summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'Sluift/sluift.cpp')
-rw-r--r--Sluift/sluift.cpp615
1 files changed, 418 insertions, 197 deletions
diff --git a/Sluift/sluift.cpp b/Sluift/sluift.cpp
index e6096a0..561f404 100644
--- a/Sluift/sluift.cpp
+++ b/Sluift/sluift.cpp
@@ -1,159 +1,287 @@
/*
- * Copyright (c) 2011-2013 Remko Tronçon
- * Licensed under the GNU General Public License v3.
- * See Documentation/Licenses/GPLv3.txt for more information.
+ * Copyright (c) 2011-2016 Isode Limited.
+ * All rights reserved.
+ * See the COPYING file for more information.
*/
#include <Sluift/sluift.h>
-#include <lua.hpp>
-
#include <string>
+
+#include <boost/assign/list_of.hpp>
#include <boost/bind.hpp>
+#include <boost/filesystem.hpp>
#include <boost/numeric/conversion/cast.hpp>
-#include <boost/assign/list_of.hpp>
-#include "Watchdog.h"
-#include <Sluift/Lua/Check.h>
-#include <Sluift/SluiftClient.h>
-#include <Sluift/globals.h>
-#include <Sluift/Lua/Exception.h>
-#include <Sluift/Lua/FunctionRegistration.h>
+#include <lua.hpp>
+
+#include <Swiften/Base/IDGenerator.h>
#include <Swiften/Base/sleep.h>
-#include <Swiften/Base/foreach.h>
+#include <Swiften/Crypto/CryptoProvider.h>
+#include <Swiften/Crypto/PlatformCryptoProvider.h>
+#include <Swiften/IDN/IDNConverter.h>
#include <Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h>
-#include <Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.h>
#include <Swiften/Serializer/PayloadSerializer.h>
-#include <Sluift/Lua/Debug.h>
+#include <Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.h>
#include <Swiften/StringCodecs/Base64.h>
#include <Swiften/StringCodecs/Hexify.h>
-#include <Swiften/Crypto/CryptoProvider.h>
-#include <Swiften/Crypto/PlatformCryptoProvider.h>
+#include <Swiften/TLS/Certificate.h>
+#include <Swiften/TLS/CertificateFactory.h>
+
+#include <Sluift/ITunesInterface.h>
+#include <Sluift/Lua/Check.h>
+#include <Sluift/Lua/Debug.h>
+#include <Sluift/Lua/Exception.h>
+#include <Sluift/Lua/FunctionRegistration.h>
+#include <Sluift/Lua/LuaUtils.h>
+#include <Sluift/LuaElementConvertor.h>
+#include <Sluift/SluiftClient.h>
+#include <Sluift/SluiftComponent.h>
+#include <Sluift/Watchdog.h>
+#include <Sluift/globals.h>
using namespace Swift;
namespace Swift {
- namespace Sluift {
- SluiftGlobals globals;
- }
+ namespace Sluift {
+ SluiftGlobals globals;
+ }
+}
+
+extern "C" const char core_lua[];
+extern "C" size_t core_lua_size;
+
+static inline bool getGlobalDebug(lua_State* L) {
+ lua_rawgeti(L, LUA_REGISTRYINDEX, Sluift::globals.moduleLibIndex);
+ lua_getfield(L, -1, "debug");
+ int result = lua_toboolean(L, -1);
+ lua_pop(L, 2);
+ return result;
}
-extern "C" const char boot_lua[];
/*******************************************************************************
* Module functions
******************************************************************************/
-SLUIFT_LUA_FUNCTION(Sluift, new_client) {
- Lua::checkString(L, 1);
- JID jid(std::string(Lua::checkString(L, 1)));
- std::string password(Lua::checkString(L, 2));
+SLUIFT_LUA_FUNCTION_WITH_HELP(
+ Sluift, new_client,
+
+ "Creates a new client.\n\nReturns a @{Client} object.\n",
+
+ "jid The JID to connect as\n"
+ "passphrase The passphrase to use\n",
- SluiftClient** client = reinterpret_cast<SluiftClient**>(lua_newuserdata(L, sizeof(SluiftClient*)));
- luaL_getmetatable(L, Lua::FunctionRegistry::getMetaTableNameForType("Client").c_str());
- lua_setmetatable(L, -2);
+ ""
+) {
+ Lua::checkString(L, 1);
+ JID jid(std::string(Lua::checkString(L, 1)));
+ std::string password(Lua::checkString(L, 2));
- *client = new SluiftClient(jid, password, &Sluift::globals.networkFactories, &Sluift::globals.eventLoop, &Sluift::globals);
- return 1;
+ SluiftClient** client = reinterpret_cast<SluiftClient**>(lua_newuserdata(L, sizeof(SluiftClient*)));
+
+ lua_rawgeti(L, LUA_REGISTRYINDEX, Sluift::globals.coreLibIndex);
+ lua_getfield(L, -1, "Client");
+ lua_setmetatable(L, -3);
+ lua_pop(L, 1);
+
+ *client = new SluiftClient(jid, password, &Sluift::globals.networkFactories, &Sluift::globals.eventLoop);
+ (*client)->setTraceEnabled(getGlobalDebug(L));
+ return 1;
}
-SLUIFT_LUA_FUNCTION(Sluift, sha1) {
- static boost::shared_ptr<CryptoProvider> crypto(PlatformCryptoProvider::create());
- if (!lua_isstring(L, 1)) {
- throw Lua::Exception("Expected string");
- }
- size_t len;
- const char* data = lua_tolstring(L, 1, &len);
- ByteArray result = crypto->getSHA1Hash(createByteArray(data, len));
- lua_pushlstring(L, reinterpret_cast<char*>(vecptr(result)), result.size());
- return 1;
+SLUIFT_LUA_FUNCTION_WITH_HELP(
+ Sluift, new_component,
+
+ "Creates a new component.\n\nReturns a @{Component} object.\n",
+
+ "jid The JID to connect as\n"
+ "passphrase The passphrase to use\n",
+
+ ""
+) {
+ Lua::checkString(L, 1);
+ JID jid(std::string(Lua::checkString(L, 1)));
+ std::string password(Lua::checkString(L, 2));
+
+ SluiftComponent** component = reinterpret_cast<SluiftComponent**>(lua_newuserdata(L, sizeof(SluiftComponent*)));
+
+ lua_rawgeti(L, LUA_REGISTRYINDEX, Sluift::globals.coreLibIndex);
+ lua_getfield(L, -1, "Component");
+ lua_setmetatable(L, -3);
+ lua_pop(L, 1);
+
+ *component = new SluiftComponent(jid, password, &Sluift::globals.networkFactories, &Sluift::globals.eventLoop);
+ (*component)->setTraceEnabled(getGlobalDebug(L));
+ return 1;
}
-SLUIFT_LUA_FUNCTION(Sluift, sleep) {
- Sluift::globals.eventLoop.runOnce();
- int timeout = Lua::checkIntNumber(L, 1);
- Watchdog watchdog(timeout, Sluift::globals.networkFactories.getTimerFactory());
- while (!watchdog.getTimedOut()) {
- Swift::sleep(boost::numeric_cast<unsigned int>(std::min(100, timeout)));
- Sluift::globals.eventLoop.runOnce();
- }
- return 0;
+SLUIFT_LUA_FUNCTION_WITH_HELP(
+ Sluift, sha1,
+ "Compute the SHA-1 hash of given data",
+ "data the data to hash",
+ ""
+) {
+ static std::shared_ptr<CryptoProvider> crypto(PlatformCryptoProvider::create());
+ if (!lua_isstring(L, 1)) {
+ throw Lua::Exception("Expected string");
+ }
+ size_t len;
+ const char* data = lua_tolstring(L, 1, &len);
+ ByteArray result = crypto->getSHA1Hash(createByteArray(data, len));
+ lua_pushlstring(L, reinterpret_cast<char*>(vecptr(result)), result.size());
+ return 1;
}
-static int sluift_index(lua_State* L) {
- try {
- std::string key(Lua::checkString(L, 2));
- if (key == "debug") {
- lua_pushboolean(L, Sluift::globals.debug);
- return 1;
- }
- else if (key == "timeout") {
- lua_pushnumber(L, Sluift::globals.timeout);
- return 1;
- }
- throw Lua::Exception("Unknown property");
- }
- catch (const std::exception& e) {
- return luaL_error(L, e.what());
- }
+SLUIFT_LUA_FUNCTION_WITH_HELP(
+ Sluift, sleep,
+ "Sleeps for the given time.",
+ "milliseconds the amount of milliseconds to sleep",
+ ""
+) {
+ Sluift::globals.eventLoop.runOnce();
+ int timeout = Lua::checkIntNumber(L, 1);
+ Watchdog watchdog(timeout, Sluift::globals.networkFactories.getTimerFactory());
+ while (!watchdog.getTimedOut()) {
+ Swift::sleep(boost::numeric_cast<unsigned int>(std::min(100, timeout)));
+ Sluift::globals.eventLoop.runOnce();
+ }
+ return 0;
}
+SLUIFT_LUA_FUNCTION_WITH_HELP(
+ Sluift, new_uuid,
+ "Generates a new UUID", "", ""
+) {
+ lua_pushstring(L, IDGenerator().generateID().c_str());
+ return 1;
+}
+
+SLUIFT_LUA_FUNCTION_WITH_HELP(
+ Sluift, from_xml,
+ "Convert a raw XML string into a structured representation.",
+ "string the string to convert",
+ ""
+) {
+ PayloadsParserTester parser;
+ if (!parser.parse(Lua::checkString(L, 1))) {
+ throw Lua::Exception("Error in XML");
+ }
+ return Sluift::globals.elementConvertor.convertToLua(L, parser.getPayload());
+}
+
+SLUIFT_LUA_FUNCTION_WITH_HELP(
+ Sluift, to_xml,
+ "Convert a structured element into XML.",
+ "element the element to convert",
+ ""
+) {
+ static FullPayloadSerializerCollection serializers;
+ std::shared_ptr<Payload> payload = std::dynamic_pointer_cast<Payload>(Sluift::globals.elementConvertor.convertFromLua(L, 1));
+ if (!payload) {
+ throw Lua::Exception("Unrecognized XML");
+ }
+ PayloadSerializer* serializer = serializers.getPayloadSerializer(payload);
+ if (!payload) {
+ throw Lua::Exception("Unrecognized XML");
+ }
+ lua_pushstring(L, serializer->serialize(payload).c_str());
+ return 1;
+}
-static int sluift_newindex(lua_State* L) {
- try {
- std::string key(Lua::checkString(L, 2));
- if (key == "debug") {
- Sluift::globals.debug = lua_toboolean(L, 3);
- }
- else if (key == "timeout") {
- Sluift::globals.timeout = Lua::checkIntNumber(L, 3);
- }
- return 0;
- }
- catch (const std::exception& e) {
- return luaL_error(L, e.what());
- }
+SLUIFT_LUA_FUNCTION_WITH_HELP(
+ Sluift, hexify,
+ "Convert binary data into hexadecimal format.",
+ "data the data to convert",
+ ""
+) {
+ if (!lua_isstring(L, 1)) {
+ throw Lua::Exception("Expected string");
+ }
+ size_t len;
+ const char* data = lua_tolstring(L, 1, &len);
+ lua_pushstring(L, Hexify::hexify(createByteArray(data, len)).c_str());
+ return 1;
}
-SLUIFT_LUA_FUNCTION(Sluift, from_xml) {
- PayloadsParserTester parser;
- if (!parser.parse(Lua::checkString(L, 1))) {
- throw Lua::Exception("Error in XML");
- }
- return Sluift::globals.elementConvertor.convertToLua(L, parser.getPayload());
+SLUIFT_LUA_FUNCTION_WITH_HELP(
+ Sluift, unhexify,
+ "Convert hexadecimal data into binary data.",
+ "data the data in hexadecimal format",
+ ""
+) {
+ if (!lua_isstring(L, 1)) {
+ throw Lua::Exception("Expected string");
+ }
+ ByteArray result = Hexify::unhexify(lua_tostring(L, 1));
+ lua_pushlstring(L, reinterpret_cast<char*>(vecptr(result)), result.size());
+ return 1;
}
-SLUIFT_LUA_FUNCTION(Sluift, to_xml) {
- static FullPayloadSerializerCollection serializers;
- boost::shared_ptr<Payload> payload = Sluift::globals.elementConvertor.convertFromLua(L, 1);
- if (!payload) {
- throw Lua::Exception("Unrecognized XML");
- }
- PayloadSerializer* serializer = serializers.getPayloadSerializer(payload);
- if (!payload) {
- throw Lua::Exception("Unrecognized XML");
- }
- lua_pushstring(L, serializer->serialize(payload).c_str());
- return 1;
+/*******************************************************************************
+ * Crypto functions
+ ******************************************************************************/
+
+SLUIFT_LUA_FUNCTION_WITH_HELP(
+ Crypto, new_certificate,
+ "Creates a new X.509 certificate from DER data.\n",
+
+ "der the DER-encoded certificate data",
+
+ "") {
+ ByteArray certData(Lua::checkByteArray(L, 1));
+ Certificate::ref cert(Sluift::globals.tlsFactories.getCertificateFactory()->createCertificateFromDER(certData));
+ lua_createtable(L, 0, 0);
+ lua_pushstring(L, cert->getSubjectName().c_str());
+ lua_setfield(L, -2, "subject_name");
+ lua_pushstring(L, Certificate::getSHA1Fingerprint(cert, Sluift::globals.networkFactories.getCryptoProvider()).c_str());
+ lua_setfield(L, -2, "sha1_fingerprint");
+
+ Lua::pushStringArray(L, cert->getCommonNames());
+ lua_setfield(L, -2, "common_names");
+
+ Lua::pushStringArray(L, cert->getSRVNames());
+ lua_setfield(L, -2, "srv_names");
+
+ Lua::pushStringArray(L, cert->getDNSNames());
+ lua_setfield(L, -2, "dns_names");
+
+ Lua::pushStringArray(L, cert->getXMPPAddresses());
+ lua_setfield(L, -2, "xmpp_addresses");
+
+ Lua::registerTableToString(L, -1);
+ return 1;
}
-SLUIFT_LUA_FUNCTION(Sluift, hexify) {
- if (!lua_isstring(L, 1)) {
- throw Lua::Exception("Expected string");
- }
- size_t len;
- const char* data = lua_tolstring(L, 1, &len);
- lua_pushstring(L, Hexify::hexify(createByteArray(data, len)).c_str());
- return 1;
+/*******************************************************************************
+ * Filesystem Functions
+ ******************************************************************************/
+
+SLUIFT_LUA_FUNCTION(FS, list) {
+ boost::filesystem::path dir(std::string(Lua::checkString(L, 1)));
+ if (!boost::filesystem::exists(dir) || !boost::filesystem::is_directory(dir)) {
+ lua_pushnil(L);
+ lua_pushstring(L, "Argument is not an existing directory");
+ return 2;
+ }
+
+ boost::filesystem::directory_iterator i(dir);
+ std::vector<boost::filesystem::path> items(
+ i, boost::filesystem::directory_iterator());
+
+ lua_createtable(L, boost::numeric_cast<int>(items.size()), 0);
+ for (size_t i = 0; i < items.size(); ++i) {
+ lua_pushstring(L, items[i].string().c_str());
+ lua_rawseti(L, -2, boost::numeric_cast<int>(i+1));
+ }
+ Lua::registerTableToString(L, -1);
+ return 1;
}
-SLUIFT_LUA_FUNCTION(Sluift, unhexify) {
- if (!lua_isstring(L, 1)) {
- throw Lua::Exception("Expected string");
- }
- ByteArray result = Hexify::unhexify(lua_tostring(L, 1));
- lua_pushlstring(L, reinterpret_cast<char*>(vecptr(result)), result.size());
- return 1;
+SLUIFT_LUA_FUNCTION(FS, is_file) {
+ boost::filesystem::path file(std::string(Lua::checkString(L, 1)));
+ lua_pushboolean(L, boost::filesystem::is_regular_file(file));
+ return 1;
}
@@ -162,32 +290,32 @@ SLUIFT_LUA_FUNCTION(Sluift, unhexify) {
******************************************************************************/
SLUIFT_LUA_FUNCTION(JID, to_bare) {
- JID jid(std::string(Lua::checkString(L, 1)));
- lua_pushstring(L, jid.toBare().toString().c_str());
- return 1;
+ JID jid(std::string(Lua::checkString(L, 1)));
+ lua_pushstring(L, jid.toBare().toString().c_str());
+ return 1;
}
SLUIFT_LUA_FUNCTION(JID, node) {
- JID jid(std::string(Lua::checkString(L, 1)));
- lua_pushstring(L, jid.getNode().c_str());
- return 1;
+ JID jid(std::string(Lua::checkString(L, 1)));
+ lua_pushstring(L, jid.getNode().c_str());
+ return 1;
}
SLUIFT_LUA_FUNCTION(JID, domain) {
- JID jid(std::string(Lua::checkString(L, 1)));
- lua_pushstring(L, jid.getDomain().c_str());
- return 1;
+ JID jid(std::string(Lua::checkString(L, 1)));
+ lua_pushstring(L, jid.getDomain().c_str());
+ return 1;
}
SLUIFT_LUA_FUNCTION(JID, resource) {
- JID jid(std::string(Lua::checkString(L, 1)));
- lua_pushstring(L, jid.getResource().c_str());
- return 1;
+ JID jid(std::string(Lua::checkString(L, 1)));
+ lua_pushstring(L, jid.getResource().c_str());
+ return 1;
}
SLUIFT_LUA_FUNCTION(JID, escape_node) {
- lua_pushstring(L, JID::getEscapedNode(Lua::checkString(L, 1)).c_str());
- return 1;
+ lua_pushstring(L, JID::getEscapedNode(Lua::checkString(L, 1)).c_str());
+ return 1;
}
/*******************************************************************************
@@ -195,86 +323,179 @@ SLUIFT_LUA_FUNCTION(JID, escape_node) {
******************************************************************************/
SLUIFT_LUA_FUNCTION(Base64, encode) {
- if (!lua_isstring(L, 1)) {
- throw Lua::Exception("Expected string");
- }
- size_t len;
- const char* data = lua_tolstring(L, 1, &len);
- lua_pushstring(L, Base64::encode(createByteArray(data, len)).c_str());
- return 1;
+ if (!lua_isstring(L, 1)) {
+ throw Lua::Exception("Expected string");
+ }
+ size_t len;
+ const char* data = lua_tolstring(L, 1, &len);
+ lua_pushstring(L, Base64::encode(createByteArray(data, len)).c_str());
+ return 1;
}
SLUIFT_LUA_FUNCTION(Base64, decode) {
- if (!lua_isstring(L, 1)) {
- throw Lua::Exception("Expected string");
- }
- ByteArray result = Base64::decode(lua_tostring(L, 1));
- lua_pushlstring(L, reinterpret_cast<char*>(vecptr(result)), result.size());
- return 1;
+ if (!lua_isstring(L, 1)) {
+ throw Lua::Exception("Expected string");
+ }
+ ByteArray result = Base64::decode(lua_tostring(L, 1));
+ lua_pushlstring(L, reinterpret_cast<char*>(vecptr(result)), result.size());
+ return 1;
+}
+
+/*******************************************************************************
+ * IDN Functions
+ ******************************************************************************/
+
+SLUIFT_LUA_FUNCTION(IDN, encode) {
+ IDNConverter* converter = Sluift::globals.networkFactories.getIDNConverter();
+ boost::optional<std::string> encoded = converter->getIDNAEncoded(Lua::checkString(L, 1));
+ if (!encoded) {
+ lua_pushnil(L);
+ lua_pushstring(L, "Error encoding domain name");
+ return 2;
+ }
+ lua_pushstring(L, encoded->c_str());
+ return 1;
+}
+
+SLUIFT_LUA_FUNCTION(IDN, stringprep) {
+ IDNConverter* converter = Sluift::globals.networkFactories.getIDNConverter();
+ IDNConverter::StringPrepProfile profile;
+ std::string profileString = Lua::checkString(L, 2);
+ if (profileString == "nameprep") {
+ profile = IDNConverter::NamePrep;
+ }
+ else if (profileString == "xmpp_nodeprep") {
+ profile = IDNConverter::XMPPNodePrep;
+ }
+ else if (profileString == "xmpp_resourceprep") {
+ profile = IDNConverter::XMPPResourcePrep;
+ }
+ else if (profileString == "saslprep") {
+ profile = IDNConverter::SASLPrep;
+ }
+ else {
+ throw Lua::Exception("Invalid profile");
+ }
+ try {
+ lua_pushstring(L, converter->getStringPrepared(Lua::checkString(L, 1), profile).c_str());
+ }
+ catch (const std::exception&) {
+ throw Lua::Exception("Error");
+ }
+ return 1;
+}
+
+/*******************************************************************************
+ * iTunes Functions
+ ******************************************************************************/
+
+#ifdef HAVE_ITUNES
+SLUIFT_LUA_FUNCTION(iTunes, get_current_track) {
+ boost::optional<ITunesInterface::Track> track = Sluift::globals.iTunes.getCurrentTrack();
+ if (!track) {
+ return 0;
+ }
+ lua_createtable(L, 0, 0);
+ lua_pushstring(L, track->artist.c_str());
+ lua_setfield(L, -2, "artist");
+ lua_pushstring(L, track->name.c_str());
+ lua_setfield(L, -2, "name");
+ lua_pushstring(L, track->album.c_str());
+ lua_setfield(L, -2, "album");
+ lua_pushinteger(L, track->trackNumber);
+ lua_setfield(L, -2, "track_number");
+ lua_pushnumber(L, track->duration);
+ lua_setfield(L, -2, "duration");
+ lua_pushinteger(L, track->rating);
+ lua_setfield(L, -2, "rating");
+ Lua::registerTableToString(L, -1);
+ Lua::registerTableEquals(L, -1);
+ return 1;
}
+#endif
/*******************************************************************************
* Module registration
******************************************************************************/
-static const luaL_reg sluift_functions[] = { {NULL, NULL} };
+static const luaL_Reg sluift_functions[] = { {nullptr, nullptr} };
SLUIFT_API int luaopen_sluift(lua_State* L) {
- // Initialize globals
- Sluift::globals.debug = false;
- Sluift::globals.timeout = -1;
-
- luaL_register(L, "sluift", sluift_functions);
-
- // Load bootstrap code
- if (luaL_loadbuffer(L, boot_lua, strlen(boot_lua), "boot.lua") != 0) {
- lua_error(L);
- }
- lua_call(L, 0, 1);
- Sluift::globals.bootIndex = luaL_ref(L, LUA_REGISTRYINDEX);
-
- // Register functions
- Lua::FunctionRegistry::getInstance().addFunctionsToTable(L, "Sluift");
- Lua::FunctionRegistry::getInstance().createFunctionTable(L, "JID");
- lua_setfield(L, -2, "jid");
- Lua::FunctionRegistry::getInstance().createFunctionTable(L, "Base64");
- lua_setfield(L, -2, "base64");
-
- // Register convenience functions
- lua_rawgeti(L, LUA_REGISTRYINDEX, Sluift::globals.bootIndex);
- lua_getfield(L, -1, "tprint");
- lua_setfield(L, -3, "tprint");
- lua_pop(L, 1);
-
- lua_rawgeti(L, LUA_REGISTRYINDEX, Sluift::globals.bootIndex);
- lua_getfield(L, -1, "disco");
- lua_setfield(L, -3, "disco");
- lua_pop(L, 1);
-
- // Set read only
- lua_createtable(L, 0, 0);
- lua_pushcclosure(L, sluift_index, 0);
- lua_setfield(L, -2, "__index");
- lua_pushcclosure(L, sluift_newindex, 0);
- lua_setfield(L, -2, "__newindex");
- lua_setmetatable(L, -2);
-
- // Load client metatable
- std::vector<std::string> tables = boost::assign::list_of("Client");
- foreach (const std::string& table, tables) {
- Lua::FunctionRegistry::getInstance().registerTypeMetaTable(L, table);
- luaL_getmetatable(L, Lua::FunctionRegistry::getMetaTableNameForType(table).c_str());
- lua_rawgeti(L, LUA_REGISTRYINDEX, Sluift::globals.bootIndex);
- lua_getfield(L, -1, table.c_str());
- if (!lua_isnil(L, -1)) {
- for (lua_pushnil(L); lua_next(L, -2); ) {
- lua_pushvalue(L, -2);
- lua_pushvalue(L, -2);
- lua_settable(L, -7);
- lua_pop(L, 1);
- }
- }
- lua_pop(L, 2);
- }
- return 1;
+ // Initialize & store the module table
+ luaL_register(L, lua_tostring(L, 1), sluift_functions);
+ lua_pushinteger(L, -1);
+ lua_setfield(L, -2, "timeout");
+ lua_pushboolean(L, 0);
+ lua_setfield(L, -2, "debug");
+
+ lua_pushvalue(L, -1);
+ Sluift::globals.moduleLibIndex = luaL_ref(L, LUA_REGISTRYINDEX);
+
+ // Load core lib code
+ if (luaL_loadbuffer(L, core_lua, core_lua_size, "core.lua") != 0) {
+ lua_error(L);
+ }
+ lua_pushvalue(L, -2);
+ lua_call(L, 1, 1);
+ Sluift::globals.coreLibIndex = luaL_ref(L, LUA_REGISTRYINDEX);
+
+ // Register functions
+ Lua::FunctionRegistry::getInstance().addFunctionsToTable(L, "Sluift");
+ Lua::FunctionRegistry::getInstance().createFunctionTable(L, "JID");
+ lua_setfield(L, -2, "jid");
+ Lua::FunctionRegistry::getInstance().createFunctionTable(L, "Base64");
+ lua_setfield(L, -2, "base64");
+ Lua::FunctionRegistry::getInstance().createFunctionTable(L, "IDN");
+ lua_setfield(L, -2, "idn");
+ Lua::FunctionRegistry::getInstance().createFunctionTable(L, "Crypto");
+ lua_setfield(L, -2, "crypto");
+ Lua::FunctionRegistry::getInstance().createFunctionTable(L, "FS");
+ lua_setfield(L, -2, "fs");
+#ifdef HAVE_ITUNES
+ Lua::FunctionRegistry::getInstance().createFunctionTable(L, "iTunes");
+ lua_setfield(L, -2, "itunes");
+#endif
+
+ // Register convenience functions
+ lua_rawgeti(L, LUA_REGISTRYINDEX, Sluift::globals.coreLibIndex);
+ std::vector<std::string> coreLibExports = boost::assign::list_of
+ ("tprint")("disco")("help")("get_help")("copy")("with")("read_file")("create_form");
+ for (const auto& coreLibExport : coreLibExports) {
+ lua_getfield(L, -1, coreLibExport.c_str());
+ lua_setfield(L, -3, coreLibExport.c_str());
+ }
+ lua_pop(L, 1);
+
+ // Load client metatable
+ lua_rawgeti(L, LUA_REGISTRYINDEX, Sluift::globals.coreLibIndex);
+ std::vector<std::string> tables = boost::assign::list_of("Client");
+ for (const auto& table : tables) {
+ lua_getfield(L, -1, table.c_str());
+ Lua::FunctionRegistry::getInstance().addFunctionsToTable(L, table);
+ lua_pop(L, 1);
+ }
+ lua_pop(L, 1);
+
+ // Load component metatable
+ lua_rawgeti(L, LUA_REGISTRYINDEX, Sluift::globals.coreLibIndex);
+ std::vector<std::string> comp_tables = boost::assign::list_of("Component");
+ for (const auto& table : comp_tables) {
+ lua_getfield(L, -1, table.c_str());
+ Lua::FunctionRegistry::getInstance().addFunctionsToTable(L, table);
+ lua_pop(L, 1);
+ }
+ lua_pop(L, 1);
+
+ // Register documentation for all elements
+ for (auto&& convertor : Sluift::globals.elementConvertor.getConvertors()) {
+ boost::optional<LuaElementConvertor::Documentation> documentation = convertor->getDocumentation();
+ if (documentation) {
+ Lua::registerClassHelp(L, documentation->className, documentation->description);
+ }
+ }
+
+ // Register global documentation
+ Lua::registerExtraHelp(L, -1, "sluift");
+
+ return 1;
}