diff options
Diffstat (limited to 'Sluift')
210 files changed, 12261 insertions, 5526 deletions
diff --git a/Sluift/.gitignore b/Sluift/.gitignore index e5fd1e5..4e4c2a4 100644 --- a/Sluift/.gitignore +++ b/Sluift/.gitignore @@ -1,7 +1,9 @@ lua.c +Version.h sluift_dll.cpp sluift dll.c -boot.c +core.c +iTunes.h dll/ exe/ diff --git a/Sluift/ClientHelpers.cpp b/Sluift/ClientHelpers.cpp deleted file mode 100644 index 8e07112..0000000 --- a/Sluift/ClientHelpers.cpp +++ /dev/null @@ -1,50 +0,0 @@ -/* - * 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 deleted file mode 100644 index eb78ba6..0000000 --- a/Sluift/ClientHelpers.h +++ /dev/null @@ -1,18 +0,0 @@ -/* - * 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/Completer.cpp b/Sluift/Completer.cpp new file mode 100644 index 0000000..2ef491e --- /dev/null +++ b/Sluift/Completer.cpp @@ -0,0 +1,12 @@ +/* + * Copyright (c) 2013 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Sluift/Completer.h> + +using namespace Swift; + +Completer::~Completer() { +} diff --git a/Sluift/Completer.h b/Sluift/Completer.h new file mode 100644 index 0000000..564c647 --- /dev/null +++ b/Sluift/Completer.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2013 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <string> +#include <vector> + +namespace Swift { + class Completer { + public: + virtual ~Completer(); + + virtual std::vector<std::string> getCompletions(const std::string& buffer, int start, int end) = 0; + }; +} diff --git a/Sluift/Console.cpp b/Sluift/Console.cpp new file mode 100644 index 0000000..ef0b1a4 --- /dev/null +++ b/Sluift/Console.cpp @@ -0,0 +1,283 @@ +/* + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Sluift/Console.h> + +#include <cctype> +#include <iostream> +#include <stdexcept> + +#include <boost/algorithm/string/predicate.hpp> +#include <boost/lexical_cast.hpp> +#include <boost/numeric/conversion/cast.hpp> +#include <boost/optional.hpp> + +#include <lua.hpp> + +#include <Sluift/Lua/LuaUtils.h> +#include <Sluift/Terminal.h> +#include <Sluift/tokenize.h> + +using namespace Swift; + +/** + * This function is called by pcall() when an error happens. + * Adds the backtrace to the error message. + */ +static int traceback(lua_State* L) { + if (!lua_isstring(L, 1)) { + return 1; + } + lua_getglobal(L, "debug"); + if (!lua_istable(L, -1)) { + lua_pop(L, 1); + return 1; + } + lua_getfield(L, -1, "traceback"); + if (!lua_isfunction(L, -1)) { + lua_pop(L, 2); + return 1; + } + lua_pushvalue(L, 1); + lua_pushinteger(L, 2); + lua_call(L, 2, 1); + return 1; +} + + +Console::Console(lua_State* L, Terminal* terminal) : L(L), terminal(terminal), previousNumberOfReturnArguments(0) { + terminal->setCompleter(this); +} + +Console::~Console() { +} + +void Console::run() { + while (true) { + lua_settop(L, 0); + try { + if (!readCommand()) { + return; + } + int result = call(L, 0, true); + if (result != 0) { + throw std::runtime_error(getErrorMessage()); + } + + // Clear the previous results + for (int i = 0; i < previousNumberOfReturnArguments; ++i) { + lua_pushnil(L); + lua_setglobal(L, ("_" + boost::lexical_cast<std::string>(i+1)).c_str()); + } + + // Store the results + for (int i = 0; i < lua_gettop(L); ++i) { + lua_pushvalue(L, i+1); + lua_setglobal(L, ("_" + boost::lexical_cast<std::string>(i+1)).c_str()); + } + previousNumberOfReturnArguments = lua_gettop(L); + + // Print results + if (lua_gettop(L) > 0) { + lua_getglobal(L, "print"); + lua_insert(L, 1); + if (lua_pcall(L, lua_gettop(L)-1, 0, 0) != 0) { + throw std::runtime_error("Error calling 'print': " + getErrorMessage()); + } + } + } + catch (const std::exception& e) { + terminal->printError(e.what()); + } + } + +} + +int Console::tryLoadCommand(const std::string& originalCommand) { + std::string command = originalCommand; + + // Replace '=' by 'return' (for compatibility with Lua console) + if (boost::algorithm::starts_with(command, "=")) { + command = "return " + command.substr(1); + } + + std::string commandAsExpression = "return " + command; + + // Try to load the command as an expression + if (luaL_loadbuffer(L, commandAsExpression.c_str(), commandAsExpression.size(), "=stdin") == 0) { + return 0; + } + lua_pop(L, 1); + + // Try to load the command as a regular command + return luaL_loadbuffer(L, command.c_str(), command.size(), "=stdin"); +} + +bool Console::readCommand() { + boost::optional<std::string> line = terminal->readLine(getPrompt(true)); + if (!line) { + return false; + } + std::string command = *line; + while (true) { + int result = tryLoadCommand(command); + + // Check if we need to read more + if (result == LUA_ERRSYNTAX) { + std::string errorMessage(lua_tostring(L, -1)); + if (boost::algorithm::ends_with(errorMessage, "'<eof>'")) { + lua_pop(L, 1); + + // Read another line + boost::optional<std::string> line = terminal->readLine(getPrompt(false)); + if (!line) { + return false; + } + command = command + "\n" + *line; + continue; + } + } + if (!command.empty()) { + terminal->addToHistory(command); + } + if (result != 0) { + throw std::runtime_error(getErrorMessage()); + } + return true; + } +} + +std::string Console::getErrorMessage() const { + if (lua_isnil(L, -1)) { + return "<null error>"; + } + const char* errorMessage = lua_tostring(L, -1); + return errorMessage ? errorMessage : "<error is not a string>"; +} + +int Console::call(lua_State* L, int numberOfArguments, bool keepResult) { + // Put traceback function on stack below call + int tracebackIndex = lua_gettop(L) - numberOfArguments; + lua_pushcfunction(L, traceback); + lua_insert(L, tracebackIndex); + + int result = lua_pcall(L, numberOfArguments, keepResult ? LUA_MULTRET : 0, tracebackIndex); + + // Remove traceback + lua_remove(L, tracebackIndex); + + return result; +} + +std::string Console::getPrompt(bool firstLine) const { + lua_getglobal(L,firstLine ? "_PROMPT" : "_PROMPT2"); + const char* rawPrompt = lua_tostring(L, -1); + std::string prompt; + if (rawPrompt) { + prompt = std::string(rawPrompt); + } + else { + prompt = firstLine ? "> " : ">> "; + } + lua_pop(L, 1); + return prompt; +} + +static void addMatchingTableKeys(lua_State* L, const std::string& match, std::vector<std::string>& result) { + for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) { + const char* rawKey = lua_tostring(L, -2); + if (rawKey) { + std::string key(rawKey); + if (boost::starts_with(key, match) && !(match == "" && boost::starts_with(key, "_"))) { + result.push_back(key); + } + } + } +} + +static void addMatchingTableValues(lua_State* L, const std::string& match, std::vector<std::string>& result) { + for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) { + const char* rawValue = lua_tostring(L, -1); + if (rawValue) { + std::string key(rawValue); + if (boost::starts_with(key, match) && !(match == "" && boost::starts_with(key, "_"))) { + result.push_back(key); + } + } + } +} + +std::vector<std::string> Console::getCompletions(const std::string& input, int start, int end) { + std::string prefix = input.substr(boost::numeric_cast<size_t>(start), boost::numeric_cast<size_t>(end - start)); + + std::vector<std::string> tokens; + if (end) { + tokens = Lua::tokenize(input.substr(0, boost::numeric_cast<size_t>(end))); + } + + // Don't autocomplete strings + if (!tokens.empty() && ((*tokens.rbegin())[0] == '\'' || (*tokens.rbegin())[0] == '"')) { + return std::vector<std::string>(); + } + + std::vector<std::string> context; + for (std::vector<std::string>::reverse_iterator i = tokens.rbegin(); i != tokens.rend(); ++i) { + if (std::isalpha((*i)[0]) || (*i)[0] == '_') { + if (i != tokens.rbegin()) { + context.push_back(*i); + } + } + else if (*i != "." && *i != ":") { + break; + } + } + + // Drill into context + int top = lua_gettop(L); + lua_pushglobaltable(L); + for (std::vector<std::string>::reverse_iterator i = context.rbegin(); i != context.rend(); ++i) { + if (lua_istable(L, -1) || lua_isuserdata(L, -1)) { + lua_getfield(L, -1, i->c_str()); + if (!lua_isnil(L, 1)) { + continue; + } + } + lua_settop(L, top); + return std::vector<std::string>(); + } + + // Collect all keys from the table + std::vector<std::string> result; + if (lua_istable(L, -1)) { + addMatchingTableKeys(L, prefix, result); + } + + // Collect all keys from the metatable + if (lua_getmetatable(L, -1)) { + lua_getfield(L, -1, "__index"); + if (lua_istable(L, -1)) { + addMatchingTableKeys(L, prefix, result); + } + lua_pop(L, 1); + + lua_getfield(L, -1, "_completions"); + if (lua_isfunction(L, -1)) { + lua_pushvalue(L, -3); + if (lua_pcall(L, 1, 1, 0) != 0) { + throw std::runtime_error("Error calling '_completions': " + getErrorMessage()); + } + } + if (lua_istable(L, -1)) { + addMatchingTableValues(L, prefix, result); + } + lua_pop(L, 2); + } + + lua_settop(L, top); + + return result; +} + diff --git a/Sluift/Console.h b/Sluift/Console.h new file mode 100644 index 0000000..0d5ceb0 --- /dev/null +++ b/Sluift/Console.h @@ -0,0 +1,42 @@ +/* + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <string> + +#include <boost/optional/optional.hpp> + +#include <Sluift/Completer.h> + +struct lua_State; + +namespace Swift { + class Terminal; + + class Console : public Completer { + public: + Console(lua_State* L, Terminal* terminal); + virtual ~Console() override; + + void run(); + + static int call(lua_State* L, int numberOfArguments, bool keepResult); + + private: + std::string getPrompt(bool firstLine) const; + std::string getErrorMessage() const; + bool readCommand(); + int tryLoadCommand(const std::string& command); + + virtual std::vector<std::string> getCompletions(const std::string&, int start, int end) override; + + private: + lua_State* L; + Terminal* terminal; + int previousNumberOfReturnArguments; + }; +} diff --git a/Sluift/EditlineTerminal.cpp b/Sluift/EditlineTerminal.cpp new file mode 100644 index 0000000..206ced6 --- /dev/null +++ b/Sluift/EditlineTerminal.cpp @@ -0,0 +1,101 @@ +/* + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Sluift/EditlineTerminal.h> + +#include <cassert> +#include <cstring> +#include <iostream> +#include <vector> + +#include <boost/numeric/conversion/cast.hpp> +#include <boost/optional.hpp> + +#include <editline/readline.h> + +#include <Swiften/Base/Platform.h> + +#include <Sluift/Completer.h> + +using namespace Swift; + +static EditlineTerminal* globalInstance = nullptr; + +static int completionStart = -1; +static int completionEnd = -1; + +#if defined(SWIFTEN_PLATFORM_WINDOWS) +static char* getEmptyCompletions(const char*, int) { +#else +static int getEmptyCompletions(const char*, int) { +#endif + return 0; +} + +static char* getCompletions(const char*, int state) { + rl_completion_append_character = 0; +#if RL_READLINE_VERSION >= 0x0600 + rl_completion_suppress_append = 1; +#endif + + static std::vector<std::string> completions; + if (state == 0) { + assert(globalInstance); + completions.clear(); + if (globalInstance->getCompleter()) { + completions = globalInstance->getCompleter()->getCompletions(rl_line_buffer, completionStart, completionEnd); + } + } + if (boost::numeric_cast<size_t>(state) >= completions.size()) { + return nullptr; + } + return strdup(completions[boost::numeric_cast<size_t>(state)].c_str()); +} + +static char** getAttemptedCompletions(const char* text, int start, int end) { + completionStart = start; + completionEnd = end; + return rl_completion_matches(text, getCompletions); +} + +EditlineTerminal& EditlineTerminal::getInstance() { + static EditlineTerminal instance; + globalInstance = &instance; + return instance; +} + +EditlineTerminal::EditlineTerminal() { + rl_attempted_completion_function = getAttemptedCompletions; + rl_completion_entry_function = getEmptyCompletions; // Fallback. Do nothing. +#if defined(SWIFTEN_PLATFORM_WINDOWS) + // rl_basic_word_break is a cons char[] in MinGWEditLine. + // This one seems to work, although it doesn't on OS X for some reason. + rl_completer_word_break_characters = strdup(" \t\n.:+-*/><=;|&()[]{}"); +#else + rl_basic_word_break_characters = strdup(" \t\n.:+-*/><=;|&()[]{}"); +#endif +} + +EditlineTerminal::~EditlineTerminal() { +} + +void EditlineTerminal::printError(const std::string& message) { + std::cout << message << std::endl; +} + +boost::optional<std::string> EditlineTerminal::readLine(const std::string& prompt) { + const char* line = readline(prompt.c_str()); + return line ? std::string(line) : boost::optional<std::string>(); +} + +void EditlineTerminal::addToHistory(const std::string& line) { +#if defined(SWIFTEN_PLATFORM_WINDOWS) + // MinGWEditLine copies the string, so this is safe + add_history(const_cast<char*>(line.c_str())); +#else + add_history(line.c_str()); +#endif +} diff --git a/Sluift/EditlineTerminal.h b/Sluift/EditlineTerminal.h new file mode 100644 index 0000000..8f4624b --- /dev/null +++ b/Sluift/EditlineTerminal.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <Sluift/Terminal.h> + +namespace Swift { + class EditlineTerminal : public Terminal { + public: + static EditlineTerminal& getInstance(); + + private: + EditlineTerminal(); + virtual ~EditlineTerminal() override; + + virtual boost::optional<std::string> readLine(const std::string& prompt) override; + virtual void printError(const std::string& message) override; + virtual void addToHistory(const std::string& command) override; + }; +} diff --git a/Sluift/ElementConvertors/BodyConvertor.cpp b/Sluift/ElementConvertors/BodyConvertor.cpp index a7abc1e..f6797b0 100644 --- a/Sluift/ElementConvertors/BodyConvertor.cpp +++ b/Sluift/ElementConvertors/BodyConvertor.cpp @@ -1,13 +1,15 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #include <Sluift/ElementConvertors/BodyConvertor.h> +#include <memory> + #include <lua.hpp> -#include <boost/smart_ptr/make_shared.hpp> + #include <Sluift/Lua/LuaUtils.h> using namespace Swift; @@ -18,18 +20,18 @@ BodyConvertor::BodyConvertor() : GenericLuaElementConvertor<Body>("body") { BodyConvertor::~BodyConvertor() { } -boost::shared_ptr<Body> BodyConvertor::doConvertFromLua(lua_State* L) { - boost::shared_ptr<Body> result = boost::make_shared<Body>(); - if (boost::optional<std::string> value = Lua::getStringField(L, -1, "text")) { - result->setText(*value); - } - return result; +std::shared_ptr<Body> BodyConvertor::doConvertFromLua(lua_State* L) { + std::shared_ptr<Body> result = std::make_shared<Body>(); + if (boost::optional<std::string> value = Lua::getStringField(L, -1, "text")) { + result->setText(*value); + } + return result; } -void BodyConvertor::doConvertToLua(lua_State* L, boost::shared_ptr<Body> payload) { - lua_createtable(L, 0, 0); - if (!payload->getText().empty()) { - lua_pushstring(L, payload->getText().c_str()); - lua_setfield(L, -2, "text"); - } +void BodyConvertor::doConvertToLua(lua_State* L, std::shared_ptr<Body> payload) { + lua_createtable(L, 0, 0); + if (!payload->getText().empty()) { + lua_pushstring(L, payload->getText().c_str()); + lua_setfield(L, -2, "text"); + } } diff --git a/Sluift/ElementConvertors/BodyConvertor.h b/Sluift/ElementConvertors/BodyConvertor.h index b1cd494..574fca9 100644 --- a/Sluift/ElementConvertors/BodyConvertor.h +++ b/Sluift/ElementConvertors/BodyConvertor.h @@ -1,25 +1,24 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <Swiften/Elements/Body.h> #include <Sluift/GenericLuaElementConvertor.h> -#include <Swiften/Elements/Body.h> namespace Swift { - class LuaElementConvertors; + class LuaElementConvertors; - class BodyConvertor : public GenericLuaElementConvertor<Body> { - public: - BodyConvertor(); - virtual ~BodyConvertor(); + class BodyConvertor : public GenericLuaElementConvertor<Body> { + public: + BodyConvertor(); + virtual ~BodyConvertor() override; - virtual boost::shared_ptr<Body> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE; - virtual void doConvertToLua(lua_State*, boost::shared_ptr<Body>) SWIFTEN_OVERRIDE; - }; + virtual std::shared_ptr<Body> doConvertFromLua(lua_State*) override; + virtual void doConvertToLua(lua_State*, std::shared_ptr<Body>) override; + }; } diff --git a/Sluift/ElementConvertors/CarbonsReceivedConvertor.cpp b/Sluift/ElementConvertors/CarbonsReceivedConvertor.cpp new file mode 100644 index 0000000..cfd55f3 --- /dev/null +++ b/Sluift/ElementConvertors/CarbonsReceivedConvertor.cpp @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Sluift/ElementConvertors/CarbonsReceivedConvertor.h> + +#include <memory> +#include <lua.hpp> + +#include <Swiften/Elements/Forwarded.h> + +#include <Sluift/LuaElementConvertors.h> + +using namespace Swift; + +CarbonsReceivedConvertor::CarbonsReceivedConvertor(LuaElementConvertors* convertors) : + GenericLuaElementConvertor<CarbonsReceived>("carbons_received"), + convertors(convertors) { +} + +CarbonsReceivedConvertor::~CarbonsReceivedConvertor() { +} + +std::shared_ptr<CarbonsReceived> CarbonsReceivedConvertor::doConvertFromLua(lua_State* L) { + std::shared_ptr<CarbonsReceived> result = std::make_shared<CarbonsReceived>(); + lua_getfield(L, -1, "payload"); + if (!lua_isnil(L, -1)) { + std::shared_ptr<Forwarded> payload = std::dynamic_pointer_cast<Forwarded>(convertors->convertFromLuaUntyped(L, -1, "payload")); + if (!!payload) { + result->setForwarded(payload); + } + } + lua_pop(L, 1); + return result; +} + +void CarbonsReceivedConvertor::doConvertToLua(lua_State* L, std::shared_ptr<CarbonsReceived> payload) { + lua_createtable(L, 0, 0); + if (convertors->convertToLuaUntyped(L, payload->getForwarded()) > 0) { + lua_setfield(L, -2, "payload"); + + } +} + +boost::optional<LuaElementConvertor::Documentation> CarbonsReceivedConvertor::getDocumentation() const { + return Documentation( + "CarbonsReceived", + "This table has the following fields:\n\n" + "- `payload`: @{Forwarded}\n" + ); +} diff --git a/Sluift/ElementConvertors/CarbonsReceivedConvertor.h b/Sluift/ElementConvertors/CarbonsReceivedConvertor.h new file mode 100644 index 0000000..cc4e6dc --- /dev/null +++ b/Sluift/ElementConvertors/CarbonsReceivedConvertor.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2016-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <Swiften/Elements/CarbonsReceived.h> + +#include <Sluift/GenericLuaElementConvertor.h> + +namespace Swift { + class LuaElementConvertors; + + class CarbonsReceivedConvertor : public GenericLuaElementConvertor<CarbonsReceived> { + public: + CarbonsReceivedConvertor(LuaElementConvertors* convertors); + virtual ~CarbonsReceivedConvertor() override; + + virtual std::shared_ptr<CarbonsReceived> doConvertFromLua(lua_State*) override; + virtual void doConvertToLua(lua_State*, std::shared_ptr<CarbonsReceived>) override; + virtual boost::optional<Documentation> getDocumentation() const override; + + private: + LuaElementConvertors* convertors; + }; +} + diff --git a/Sluift/ElementConvertors/CarbonsSentConvertor.cpp b/Sluift/ElementConvertors/CarbonsSentConvertor.cpp new file mode 100644 index 0000000..45851d2 --- /dev/null +++ b/Sluift/ElementConvertors/CarbonsSentConvertor.cpp @@ -0,0 +1,52 @@ +/* + * Copyright (c) 2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Sluift/ElementConvertors/CarbonsSentConvertor.h> + +#include <memory> +#include <lua.hpp> + +#include <Swiften/Elements/Forwarded.h> + +#include <Sluift/LuaElementConvertors.h> + +using namespace Swift; + +CarbonsSentConvertor::CarbonsSentConvertor(LuaElementConvertors* convertors) : + GenericLuaElementConvertor<CarbonsSent>("carbons_sent"), + convertors(convertors) { +} + +CarbonsSentConvertor::~CarbonsSentConvertor() { +} + +std::shared_ptr<CarbonsSent> CarbonsSentConvertor::doConvertFromLua(lua_State* L) { + std::shared_ptr<CarbonsSent> result = std::make_shared<CarbonsSent>(); + lua_getfield(L, -1, "payload"); + if (!lua_isnil(L, -1)) { + std::shared_ptr<Forwarded> payload = std::dynamic_pointer_cast<Forwarded>(convertors->convertFromLuaUntyped(L, -1, "payload")); + if (!!payload) { + result->setForwarded(payload); + } + } + lua_pop(L, 1); + return result; +} + +void CarbonsSentConvertor::doConvertToLua(lua_State* L, std::shared_ptr<CarbonsSent> payload) { + lua_createtable(L, 0, 0); + if (convertors->convertToLuaUntyped(L, payload->getForwarded()) > 0) { + lua_setfield(L, -2, "payload"); + } +} + +boost::optional<LuaElementConvertor::Documentation> CarbonsSentConvertor::getDocumentation() const { + return Documentation( + "CarbonsSent", + "This table has the following fields:\n\n" + "- `payload`: @{Forwarded}\n" + ); +} diff --git a/Sluift/ElementConvertors/CarbonsSentConvertor.h b/Sluift/ElementConvertors/CarbonsSentConvertor.h new file mode 100644 index 0000000..794e0ed --- /dev/null +++ b/Sluift/ElementConvertors/CarbonsSentConvertor.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2016-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <Swiften/Elements/CarbonsSent.h> + +#include <Sluift/GenericLuaElementConvertor.h> + +namespace Swift { + class LuaElementConvertors; + + class CarbonsSentConvertor : public GenericLuaElementConvertor<CarbonsSent> { + public: + CarbonsSentConvertor(LuaElementConvertors* convertors); + virtual ~CarbonsSentConvertor() override; + + virtual std::shared_ptr<CarbonsSent> doConvertFromLua(lua_State*) override; + virtual void doConvertToLua(lua_State*, std::shared_ptr<CarbonsSent>) override; + virtual boost::optional<Documentation> getDocumentation() const override; + + private: + LuaElementConvertors* convertors; + }; +} + diff --git a/Sluift/ElementConvertors/CommandConvertor.cpp b/Sluift/ElementConvertors/CommandConvertor.cpp index 7fb7b22..de7a439 100644 --- a/Sluift/ElementConvertors/CommandConvertor.cpp +++ b/Sluift/ElementConvertors/CommandConvertor.cpp @@ -1,16 +1,17 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #include <Sluift/ElementConvertors/CommandConvertor.h> -#include <lua.hpp> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> + #include <boost/numeric/conversion/cast.hpp> -#include <Swiften/Base/foreach.h> +#include <lua.hpp> + #include <Sluift/Lua/Check.h> #include <Sluift/Lua/Value.h> #include <Sluift/LuaElementConvertors.h> @@ -18,178 +19,177 @@ using namespace Swift; static Command::Action convertActionFromString(const std::string& action) { - if (action == "cancel") { return Command::Cancel; } - else if (action == "execute") { return Command::Execute; } - else if (action == "complete") { return Command::Complete; } - else if (action == "prev") { return Command::Prev; } - else if (action == "next") { return Command::Next; } - return Command::NoAction; + if (action == "cancel") { return Command::Cancel; } + else if (action == "execute") { return Command::Execute; } + else if (action == "complete") { return Command::Complete; } + else if (action == "prev") { return Command::Prev; } + else if (action == "next") { return Command::Next; } + return Command::NoAction; } static std::string convertActionToString(Command::Action action) { - switch (action) { - case Command::Cancel: return "cancel"; - case Command::Execute: return "execute"; - case Command::Complete: return "complete"; - case Command::Prev: return "prev"; - case Command::Next: return "next"; - case Command::NoAction: assert(false); return ""; - } - assert(false); - return ""; + switch (action) { + case Command::Cancel: return "cancel"; + case Command::Execute: return "execute"; + case Command::Complete: return "complete"; + case Command::Prev: return "prev"; + case Command::Next: return "next"; + case Command::NoAction: assert(false); return ""; + } + assert(false); + return ""; } -CommandConvertor::CommandConvertor(LuaElementConvertors* convertors) : - GenericLuaElementConvertor<Command>("command"), - convertors(convertors) { +CommandConvertor::CommandConvertor(LuaElementConvertors* convertors) : + GenericLuaElementConvertor<Command>("command"), + convertors(convertors) { } CommandConvertor::~CommandConvertor() { } -boost::shared_ptr<Command> CommandConvertor::doConvertFromLua(lua_State* L) { - boost::shared_ptr<Command> result = boost::make_shared<Command>(); - - lua_getfield(L, -1, "node"); - if (!lua_isnil(L, -1)) { - result->setNode(std::string(Lua::checkString(L, -1))); - } - lua_pop(L, 1); - - lua_getfield(L, -1, "session_id"); - if (!lua_isnil(L, -1)) { - result->setSessionID(std::string(Lua::checkString(L, -1))); - } - lua_pop(L, 1); - - lua_getfield(L, -1, "status"); - if (!lua_isnil(L, -1)) { - std::string statusText = Lua::checkString(L, -1); - Command::Status status = Command::NoStatus; - if (statusText == "executing") { status = Command::Executing; } - else if (statusText == "completed") { status = Command::Completed; } - else if (statusText == "canceled") { status = Command::Canceled; } - result->setStatus(status); - } - lua_pop(L, 1); - - lua_getfield(L, -1, "action"); - if (!lua_isnil(L, -1)) { - result->setAction(convertActionFromString(Lua::checkString(L, -1))); - } - lua_pop(L, 1); - - lua_getfield(L, -1, "execute_action"); - if (!lua_isnil(L, -1)) { - result->setExecuteAction(convertActionFromString(Lua::checkString(L, -1))); - } - lua_pop(L, 1); - - lua_getfield(L, -1, "available_actions"); - if (!lua_isnil(L, -1)) { - Lua::checkType(L, -1, LUA_TTABLE); - lua_pushnil(L); - for (lua_pushnil(L); lua_next(L, -2) != 0; ) { - result->addAvailableAction(convertActionFromString(Lua::checkString(L, -1))); - lua_pop(L, 1); - } - } - lua_pop(L, 1); - - lua_getfield(L, -1, "notes"); - if (!lua_isnil(L, -1)) { - Lua::checkType(L, -1, LUA_TTABLE); - lua_pushnil(L); - for (lua_pushnil(L); lua_next(L, -2) != 0; ) { - Lua::checkType(L, -1, LUA_TTABLE); - std::string note; - lua_getfield(L, -1, "note"); - if (!lua_isnil(L, -1)) { - note = Lua::checkString(L, -1); - } - lua_pop(L, 1); - - Command::Note::Type noteType = Command::Note::Info; - lua_getfield(L, -1, "type"); - if (!lua_isnil(L, -1)) { - std::string type = Lua::checkString(L, -1); - if (type == "info") { noteType = Command::Note::Info; } - else if (type == "warn") { noteType = Command::Note::Warn; } - else if (type == "error") { noteType = Command::Note::Error; } - } - lua_pop(L, 1); - - result->addNote(Command::Note(note, noteType)); - lua_pop(L, 1); - } - } - lua_pop(L, 1); - - lua_getfield(L, -1, "form"); - if (!lua_isnil(L, -1)) { - if (boost::shared_ptr<Form> form = boost::dynamic_pointer_cast<Form>(convertors->convertFromLuaUntyped(L, -1, "form"))) { - result->setForm(form); - } - } - lua_pop(L, 1); - - return result; +std::shared_ptr<Command> CommandConvertor::doConvertFromLua(lua_State* L) { + std::shared_ptr<Command> result = std::make_shared<Command>(); + + lua_getfield(L, -1, "node"); + if (!lua_isnil(L, -1)) { + result->setNode(std::string(Lua::checkString(L, -1))); + } + lua_pop(L, 1); + + lua_getfield(L, -1, "session_id"); + if (!lua_isnil(L, -1)) { + result->setSessionID(std::string(Lua::checkString(L, -1))); + } + lua_pop(L, 1); + + lua_getfield(L, -1, "status"); + if (!lua_isnil(L, -1)) { + std::string statusText = Lua::checkString(L, -1); + Command::Status status = Command::NoStatus; + if (statusText == "executing") { status = Command::Executing; } + else if (statusText == "completed") { status = Command::Completed; } + else if (statusText == "canceled") { status = Command::Canceled; } + result->setStatus(status); + } + lua_pop(L, 1); + + lua_getfield(L, -1, "action"); + if (!lua_isnil(L, -1)) { + result->setAction(convertActionFromString(Lua::checkString(L, -1))); + } + lua_pop(L, 1); + + lua_getfield(L, -1, "execute_action"); + if (!lua_isnil(L, -1)) { + result->setExecuteAction(convertActionFromString(Lua::checkString(L, -1))); + } + lua_pop(L, 1); + + lua_getfield(L, -1, "available_actions"); + if (!lua_isnil(L, -1)) { + Lua::checkType(L, -1, LUA_TTABLE); + for (lua_pushnil(L); lua_next(L, -2) != 0; ) { + result->addAvailableAction(convertActionFromString(Lua::checkString(L, -1))); + lua_pop(L, 1); + } + } + lua_pop(L, 1); + + lua_getfield(L, -1, "notes"); + if (!lua_isnil(L, -1)) { + Lua::checkType(L, -1, LUA_TTABLE); + for (lua_pushnil(L); lua_next(L, -2) != 0; ) { + Lua::checkType(L, -1, LUA_TTABLE); + std::string note; + lua_getfield(L, -1, "note"); + if (!lua_isnil(L, -1)) { + note = Lua::checkString(L, -1); + } + lua_pop(L, 1); + + Command::Note::Type noteType = Command::Note::Info; + lua_getfield(L, -1, "type"); + if (!lua_isnil(L, -1)) { + std::string type = Lua::checkString(L, -1); + if (type == "info") { noteType = Command::Note::Info; } + else if (type == "warn") { noteType = Command::Note::Warn; } + else if (type == "error") { noteType = Command::Note::Error; } + } + lua_pop(L, 1); + + result->addNote(Command::Note(note, noteType)); + lua_pop(L, 1); + } + } + lua_pop(L, 1); + + lua_getfield(L, -1, "form"); + if (!lua_isnil(L, -1)) { + if (std::shared_ptr<Form> form = std::dynamic_pointer_cast<Form>(convertors->convertFromLuaUntyped(L, -1, "form"))) { + result->setForm(form); + } + } + lua_pop(L, 1); + + return result; } -void CommandConvertor::doConvertToLua(lua_State* L, boost::shared_ptr<Command> payload) { - Lua::Table result; - if (!payload->getNode().empty()) { - result["node"] = Lua::valueRef(payload->getNode()); - } - if (!payload->getSessionID().empty()) { - result["session_id"] = Lua::valueRef(payload->getSessionID()); - } - switch (payload->getStatus()) { - case Command::Executing: result["status"] = Lua::valueRef("executing"); break; - case Command::Completed: result["status"] = Lua::valueRef("completed"); break; - case Command::Canceled: result["status"] = Lua::valueRef("canceled"); break; - case Command::NoStatus: break; - } - - if (!payload->getNotes().empty()) { - std::vector<Lua::Value> notes; - foreach (const Command::Note& note, payload->getNotes()) { - Lua::Table noteTable; - if (!note.note.empty()) { - noteTable["note"] = Lua::valueRef(note.note); - } - switch (note.type) { - case Command::Note::Info: noteTable["type"] = Lua::valueRef("info"); break; - case Command::Note::Warn: noteTable["type"] = Lua::valueRef("warn"); break; - case Command::Note::Error: noteTable["type"] = Lua::valueRef("error"); break; - } - notes.push_back(noteTable); - } - result["notes"] = Lua::valueRef(notes); - } - - if (payload->getAction() != Command::NoAction) { - result["action"] = Lua::valueRef(convertActionToString(payload->getAction())); - } - - if (payload->getExecuteAction() != Command::NoAction) { - result["execute_action"] = Lua::valueRef(convertActionToString(payload->getAction())); - } - - if (!payload->getAvailableActions().empty()) { - std::vector<Lua::Value> availableActions; - foreach (const Command::Action& action, payload->getAvailableActions()) { - if (action != Command::NoAction) { - availableActions.push_back(convertActionToString(action)); - } - } - result["available_actions"] = Lua::valueRef(availableActions); - } - - Lua::pushValue(L, result); - - if (payload->getForm()) { - convertors->convertToLuaUntyped(L, payload->getForm()); - lua_setfield(L, -2, "form"); - } +void CommandConvertor::doConvertToLua(lua_State* L, std::shared_ptr<Command> payload) { + Lua::Table result; + if (!payload->getNode().empty()) { + result["node"] = Lua::valueRef(payload->getNode()); + } + if (!payload->getSessionID().empty()) { + result["session_id"] = Lua::valueRef(payload->getSessionID()); + } + switch (payload->getStatus()) { + case Command::Executing: result["status"] = Lua::valueRef("executing"); break; + case Command::Completed: result["status"] = Lua::valueRef("completed"); break; + case Command::Canceled: result["status"] = Lua::valueRef("canceled"); break; + case Command::NoStatus: break; + } + + if (!payload->getNotes().empty()) { + std::vector<Lua::Value> notes; + for (const auto& note : payload->getNotes()) { + Lua::Table noteTable; + if (!note.note.empty()) { + noteTable["note"] = Lua::valueRef(note.note); + } + switch (note.type) { + case Command::Note::Info: noteTable["type"] = Lua::valueRef("info"); break; + case Command::Note::Warn: noteTable["type"] = Lua::valueRef("warn"); break; + case Command::Note::Error: noteTable["type"] = Lua::valueRef("error"); break; + } + notes.push_back(noteTable); + } + result["notes"] = Lua::valueRef(notes); + } + + if (payload->getAction() != Command::NoAction) { + result["action"] = Lua::valueRef(convertActionToString(payload->getAction())); + } + + if (payload->getExecuteAction() != Command::NoAction) { + result["execute_action"] = Lua::valueRef(convertActionToString(payload->getAction())); + } + + if (!payload->getAvailableActions().empty()) { + std::vector<Lua::Value> availableActions; + for (const auto& action : payload->getAvailableActions()) { + if (action != Command::NoAction) { + availableActions.push_back(convertActionToString(action)); + } + } + result["available_actions"] = Lua::valueRef(availableActions); + } + + Lua::pushValue(L, result); + + if (payload->getForm()) { + bool result = convertors->convertToLuaUntyped(L, payload->getForm()); + assert(result); + lua_setfield(L, -2, "form"); + } } diff --git a/Sluift/ElementConvertors/CommandConvertor.h b/Sluift/ElementConvertors/CommandConvertor.h index 7008b50..274eaa6 100644 --- a/Sluift/ElementConvertors/CommandConvertor.h +++ b/Sluift/ElementConvertors/CommandConvertor.h @@ -1,28 +1,27 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <Swiften/Elements/Command.h> #include <Sluift/GenericLuaElementConvertor.h> -#include <Swiften/Elements/Command.h> namespace Swift { - class LuaElementConvertors; + class LuaElementConvertors; - class CommandConvertor : public GenericLuaElementConvertor<Command> { - public: - CommandConvertor(LuaElementConvertors* convertors); - virtual ~CommandConvertor(); + class CommandConvertor : public GenericLuaElementConvertor<Command> { + public: + CommandConvertor(LuaElementConvertors* convertors); + virtual ~CommandConvertor() override; - virtual boost::shared_ptr<Command> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE; - virtual void doConvertToLua(lua_State*, boost::shared_ptr<Command>) SWIFTEN_OVERRIDE; + virtual std::shared_ptr<Command> doConvertFromLua(lua_State*) override; + virtual void doConvertToLua(lua_State*, std::shared_ptr<Command>) override; - private: - LuaElementConvertors* convertors; - }; + private: + LuaElementConvertors* convertors; + }; } diff --git a/Sluift/ElementConvertors/DOMElementConvertor.cpp b/Sluift/ElementConvertors/DOMElementConvertor.cpp index bb4256d..5e72cc8 100644 --- a/Sluift/ElementConvertors/DOMElementConvertor.cpp +++ b/Sluift/ElementConvertors/DOMElementConvertor.cpp @@ -1,157 +1,159 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #include <Sluift/ElementConvertors/DOMElementConvertor.h> -#include <iostream> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> + #include <lua.hpp> -#include <Swiften/Base/foreach.h> #include <Swiften/Elements/RawXMLPayload.h> -#include <Swiften/Serializer/PayloadSerializer.h> -#include <Sluift/Lua/Check.h> -#include <Sluift/Lua/LuaUtils.h> -#include <Swiften/Parser/XMLParserClient.h> -#include <Swiften/Parser/XMLParser.h> -#include <Swiften/Parser/AttributeMap.h> #include <Swiften/Parser/Attribute.h> +#include <Swiften/Parser/AttributeMap.h> +#include <Swiften/Parser/XMLParser.h> +#include <Swiften/Parser/XMLParserClient.h> +#include <Swiften/Serializer/PayloadSerializer.h> #include <Swiften/Serializer/XML/XMLElement.h> -#include <Swiften/Serializer/XML/XMLTextNode.h> #include <Swiften/Serializer/XML/XMLRawTextNode.h> +#include <Swiften/Serializer/XML/XMLTextNode.h> + +#include <Sluift/Lua/Check.h> #include <Sluift/Lua/Debug.h> +#include <Sluift/Lua/LuaUtils.h> using namespace Swift; namespace { - class ParserClient : public XMLParserClient { - public: - ParserClient(lua_State* L) : L(L), currentIndex(1) { - } - - virtual void handleStartElement( - const std::string& element, const std::string& ns, - const AttributeMap& attributes) SWIFTEN_OVERRIDE { - lua_pushnumber(L, currentIndex); - lua_newtable(L); - lua_pushstring(L, element.c_str()); - lua_setfield(L, -2, "tag"); - if (!ns.empty()) { - lua_pushstring(L, ns.c_str()); - lua_setfield(L, -2, "ns"); - } - if (!attributes.getEntries().empty()) { - lua_newtable(L); - int i = 1; - foreach(const AttributeMap::Entry& entry, attributes.getEntries()) { - lua_pushnumber(L, i); - lua_newtable(L); - lua_pushstring(L, entry.getAttribute().getName().c_str()); - lua_setfield(L, -2, "name"); - if (!entry.getAttribute().getNamespace().empty()) { - lua_pushstring(L, entry.getAttribute().getNamespace().c_str()); - lua_setfield(L, -2, "ns"); - } - lua_pushstring(L, entry.getValue().c_str()); - lua_setfield(L, -2, "value"); - lua_settable(L, -3); - ++i; - } - lua_setfield(L, -2, "attributes"); - } - - indexStack.push_back(currentIndex); - currentIndex = 1; - lua_newtable(L); - } - - virtual void handleEndElement( - const std::string&, const std::string&) SWIFTEN_OVERRIDE { - lua_setfield(L, -2, "children"); - lua_settable(L, -3); - currentIndex = indexStack.back(); - indexStack.pop_back(); - currentIndex++; - } - - virtual void handleCharacterData(const std::string& data) SWIFTEN_OVERRIDE { - lua_pushnumber(L, currentIndex); - lua_pushstring(L, data.c_str()); - lua_settable(L, -3); - currentIndex++; - } - - private: - lua_State* L; - std::vector<int> indexStack; - int currentIndex; - }; - - std::string serializeElement(lua_State* L) { - std::string tag; - lua_getfield(L, -1, "tag"); - if (lua_isstring(L, -1)) { - tag = lua_tostring(L, -1); - } - lua_pop(L, 1); - - std::string ns; - lua_getfield(L, -1, "ns"); - if (lua_isstring(L, -1)) { - ns = lua_tostring(L, -1); - } - lua_pop(L, 1); - - XMLElement element(tag, ns); - - lua_getfield(L, -1, "attributes"); - if (lua_istable(L, -1)) { - int index = Lua::absoluteOffset(L, -1); - for (lua_pushnil(L); lua_next(L, index) != 0; ) { - if (lua_istable(L, -1)) { - std::string attributeName; - lua_getfield(L, -1, "name"); - if (lua_isstring(L, -1)) { - attributeName = lua_tostring(L, -1); - } - lua_pop(L, 1); - - std::string attributeValue; - lua_getfield(L, -1, "value"); - if (lua_isstring(L, -1)) { - attributeValue = lua_tostring(L, -1); - } - lua_pop(L, 1); - - if (!attributeName.empty()) { - element.setAttribute(attributeName, attributeValue); - } - } - lua_pop(L, 1); // value - } - } - lua_pop(L, 1); // children - - lua_getfield(L, -1, "children"); - if (lua_istable(L, -1)) { - int index = Lua::absoluteOffset(L, -1); - for (lua_pushnil(L); lua_next(L, index) != 0; ) { - if (lua_isstring(L, -1)) { - element.addNode(boost::make_shared<XMLTextNode>(lua_tostring(L, -1))); - } - else if (lua_istable(L, -1)) { - element.addNode(boost::make_shared<XMLRawTextNode>(serializeElement(L))); - } - lua_pop(L, 1); // value - } - } - lua_pop(L, 1); // children - - return element.serialize(); - } + class ParserClient : public XMLParserClient { + public: + ParserClient(lua_State* L) : L(L), currentIndex(1) { + } + + virtual void handleStartElement( + const std::string& element, const std::string& ns, + const AttributeMap& attributes) override { + lua_checkstack(L, 6); + lua_pushnumber(L, currentIndex); + lua_newtable(L); + lua_pushstring(L, element.c_str()); + lua_setfield(L, -2, "tag"); + if (!ns.empty()) { + lua_pushstring(L, ns.c_str()); + lua_setfield(L, -2, "ns"); + } + if (!attributes.getEntries().empty()) { + lua_newtable(L); + int i = 1; + for (const auto& entry : attributes.getEntries()) { + lua_pushnumber(L, i); + lua_newtable(L); + lua_pushstring(L, entry.getAttribute().getName().c_str()); + lua_setfield(L, -2, "name"); + if (!entry.getAttribute().getNamespace().empty()) { + lua_pushstring(L, entry.getAttribute().getNamespace().c_str()); + lua_setfield(L, -2, "ns"); + } + lua_pushstring(L, entry.getValue().c_str()); + lua_setfield(L, -2, "value"); + lua_settable(L, -3); + ++i; + } + lua_setfield(L, -2, "attributes"); + } + + indexStack.push_back(currentIndex); + currentIndex = 1; + lua_newtable(L); + } + + virtual void handleEndElement( + const std::string&, const std::string&) override { + lua_setfield(L, -2, "children"); + lua_settable(L, -3); + currentIndex = indexStack.back(); + indexStack.pop_back(); + currentIndex++; + } + + virtual void handleCharacterData(const std::string& data) override { + lua_checkstack(L, 2); + lua_pushnumber(L, currentIndex); + lua_pushstring(L, data.c_str()); + lua_settable(L, -3); + currentIndex++; + } + + private: + lua_State* L; + std::vector<int> indexStack; + int currentIndex; + }; + + std::string serializeElement(lua_State* L) { + std::string tag; + lua_getfield(L, -1, "tag"); + if (lua_isstring(L, -1)) { + tag = lua_tostring(L, -1); + } + lua_pop(L, 1); + + std::string ns; + lua_getfield(L, -1, "ns"); + if (lua_isstring(L, -1)) { + ns = lua_tostring(L, -1); + } + lua_pop(L, 1); + + XMLElement element(tag, ns); + + lua_getfield(L, -1, "attributes"); + if (lua_istable(L, -1)) { + int index = Lua::absoluteOffset(L, -1); + for (lua_pushnil(L); lua_next(L, index) != 0; ) { + if (lua_istable(L, -1)) { + std::string attributeName; + lua_getfield(L, -1, "name"); + if (lua_isstring(L, -1)) { + attributeName = lua_tostring(L, -1); + } + lua_pop(L, 1); + + std::string attributeValue; + lua_getfield(L, -1, "value"); + if (lua_isstring(L, -1)) { + attributeValue = lua_tostring(L, -1); + } + lua_pop(L, 1); + + if (!attributeName.empty()) { + element.setAttribute(attributeName, attributeValue); + } + } + lua_pop(L, 1); // value + } + } + lua_pop(L, 1); // children + + lua_getfield(L, -1, "children"); + if (lua_istable(L, -1)) { + int index = Lua::absoluteOffset(L, -1); + for (lua_pushnil(L); lua_next(L, index) != 0; ) { + if (lua_isstring(L, -1)) { + element.addNode(std::make_shared<XMLTextNode>(lua_tostring(L, -1))); + } + else if (lua_istable(L, -1)) { + element.addNode(std::make_shared<XMLRawTextNode>(serializeElement(L))); + } + lua_pop(L, 1); // value + } + } + lua_pop(L, 1); // children + + return element.serialize(); + } } DOMElementConvertor::DOMElementConvertor() { @@ -160,35 +162,40 @@ DOMElementConvertor::DOMElementConvertor() { DOMElementConvertor::~DOMElementConvertor() { } -boost::shared_ptr<Payload> DOMElementConvertor::convertFromLua(lua_State* L, int index, const std::string& type) { - if (!lua_istable(L, index) || type != "dom") { - return boost::shared_ptr<Payload>(); - } - return boost::make_shared<RawXMLPayload>(serializeElement(L).c_str()); +std::shared_ptr<Element> DOMElementConvertor::convertFromLua(lua_State* L, int index, const std::string& type) { + if (!lua_istable(L, index) || type != "dom") { + return std::shared_ptr<Payload>(); + } + return std::make_shared<RawXMLPayload>(serializeElement(L).c_str()); } boost::optional<std::string> DOMElementConvertor::convertToLua( - lua_State* L, boost::shared_ptr<Payload> payload) { - // Serialize payload to XML - PayloadSerializer* serializer = serializers.getPayloadSerializer(payload); - assert(serializer); - std::string serializedPayload = serializer->serialize(payload); - - lua_newtable(L); - - // Parse the payload again - ParserClient parserClient(L); - boost::shared_ptr<XMLParser> parser(parsers.createXMLParser(&parserClient)); - bool result = parser->parse(serializedPayload); - assert(result); - - // There can only be one element, so stripping the list - lua_pushnil(L); - lua_next(L, -2); - Lua::registerTableToString(L, -1); - - lua_replace(L, -3); - lua_settop(L, -2); - - return std::string("dom"); + lua_State* L, std::shared_ptr<Element> element) { + // Serialize payload to XML + std::shared_ptr<Payload> payload = std::dynamic_pointer_cast<Payload>(element); + if (!payload) { + return boost::optional<std::string>(); + } + + PayloadSerializer* serializer = serializers.getPayloadSerializer(payload); + assert(serializer); + std::string serializedPayload = serializer->serialize(payload); + + lua_newtable(L); + + // Parse the payload again + ParserClient parserClient(L); + std::shared_ptr<XMLParser> parser(parsers.createXMLParser(&parserClient, false)); + bool result = parser->parse(serializedPayload); + assert(result); + + // There can only be one element, so stripping the list + lua_pushnil(L); + lua_next(L, -2); + Lua::registerTableToString(L, -1); + + lua_replace(L, -3); + lua_settop(L, -2); + + return std::string("dom"); } diff --git a/Sluift/ElementConvertors/DOMElementConvertor.h b/Sluift/ElementConvertors/DOMElementConvertor.h index 94d0669..dd8d79b 100644 --- a/Sluift/ElementConvertors/DOMElementConvertor.h +++ b/Sluift/ElementConvertors/DOMElementConvertor.h @@ -1,28 +1,27 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <Swiften/Parser/PlatformXMLParserFactory.h> +#include <Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.h> #include <Sluift/LuaElementConvertor.h> -#include <Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.h> -#include <Swiften/Parser/PlatformXMLParserFactory.h> namespace Swift { - class DOMElementConvertor : public LuaElementConvertor { - public: - DOMElementConvertor(); - virtual ~DOMElementConvertor(); + class DOMElementConvertor : public LuaElementConvertor { + public: + DOMElementConvertor(); + virtual ~DOMElementConvertor() override; - virtual boost::shared_ptr<Payload> convertFromLua(lua_State*, int index, const std::string& type) SWIFTEN_OVERRIDE; - virtual boost::optional<std::string> convertToLua(lua_State*, boost::shared_ptr<Payload>) SWIFTEN_OVERRIDE; + virtual std::shared_ptr<Element> convertFromLua(lua_State*, int index, const std::string& type) override; + virtual boost::optional<std::string> convertToLua(lua_State*, std::shared_ptr<Element>) override; - private: - PlatformXMLParserFactory parsers; - FullPayloadSerializerCollection serializers; - }; + private: + PlatformXMLParserFactory parsers; + FullPayloadSerializerCollection serializers; + }; } diff --git a/Sluift/ElementConvertors/DefaultElementConvertor.cpp b/Sluift/ElementConvertors/DefaultElementConvertor.cpp index 62c799b..d3d60ff 100644 --- a/Sluift/ElementConvertors/DefaultElementConvertor.cpp +++ b/Sluift/ElementConvertors/DefaultElementConvertor.cpp @@ -1,14 +1,15 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2019 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #include <Sluift/ElementConvertors/DefaultElementConvertor.h> -#include <iostream> -#include <typeinfo> #include <string> +#include <typeinfo> + +#include <Swiften/Base/Log.h> using namespace Swift; @@ -18,13 +19,13 @@ DefaultElementConvertor::DefaultElementConvertor() { DefaultElementConvertor::~DefaultElementConvertor() { } -boost::shared_ptr<Payload> DefaultElementConvertor::convertFromLua(lua_State*, int, const std::string& type) { - std::cerr << "Warning: Unable to convert type '" << type << "'" << std::endl; - return boost::shared_ptr<Payload>(); +std::shared_ptr<Element> DefaultElementConvertor::convertFromLua(lua_State*, int, const std::string& type) { + SWIFT_LOG(warning) << "Unable to convert type '" << type << "'"; + return std::shared_ptr<Element>(); } -boost::optional<std::string> DefaultElementConvertor::convertToLua(lua_State*, boost::shared_ptr<Payload>) { - // Should have been handled by the raw XML convertor - assert(false); - return NO_RESULT; +boost::optional<std::string> DefaultElementConvertor::convertToLua(lua_State*, std::shared_ptr<Element>) { + // Should have been handled by the raw XML convertor + assert(false); + return NO_RESULT; } diff --git a/Sluift/ElementConvertors/DefaultElementConvertor.h b/Sluift/ElementConvertors/DefaultElementConvertor.h index ad8fe75..dfef3e8 100644 --- a/Sluift/ElementConvertors/DefaultElementConvertor.h +++ b/Sluift/ElementConvertors/DefaultElementConvertor.h @@ -1,22 +1,20 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> - #include <Sluift/LuaElementConvertor.h> namespace Swift { - class DefaultElementConvertor : public LuaElementConvertor { - public: - DefaultElementConvertor(); - virtual ~DefaultElementConvertor(); + class DefaultElementConvertor : public LuaElementConvertor { + public: + DefaultElementConvertor(); + virtual ~DefaultElementConvertor() override; - virtual boost::shared_ptr<Payload> convertFromLua(lua_State*, int index, const std::string& type) SWIFTEN_OVERRIDE; - virtual boost::optional<std::string> convertToLua(lua_State*, boost::shared_ptr<Payload>) SWIFTEN_OVERRIDE; - }; + virtual std::shared_ptr<Element> convertFromLua(lua_State*, int index, const std::string& type) override; + virtual boost::optional<std::string> convertToLua(lua_State*, std::shared_ptr<Element>) override; + }; } diff --git a/Sluift/ElementConvertors/DelayConvertor.cpp b/Sluift/ElementConvertors/DelayConvertor.cpp new file mode 100644 index 0000000..f23e137 --- /dev/null +++ b/Sluift/ElementConvertors/DelayConvertor.cpp @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2014-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Sluift/ElementConvertors/DelayConvertor.h> + +#include <memory> + +#include <boost/numeric/conversion/cast.hpp> + +#include <lua.hpp> + +#include <Swiften/Base/DateTime.h> + +#include <Sluift/Lua/Check.h> + +using namespace Swift; + +DelayConvertor::DelayConvertor() : GenericLuaElementConvertor<Delay>("delay") { +} + +DelayConvertor::~DelayConvertor() { +} + +std::shared_ptr<Delay> DelayConvertor::doConvertFromLua(lua_State* L) { + std::shared_ptr<Delay> result = std::make_shared<Delay>(); + lua_getfield(L, -1, "stamp"); + if (lua_isstring(L, -1)) { + result->setStamp(stringToDateTime(lua_tostring(L, -1))); + } + lua_pop(L, 1); + + lua_getfield(L, -1, "from"); + if (lua_isstring(L, -1)) { + result->setFrom(lua_tostring(L, -1)); + } + lua_pop(L, 1); + return result; +} + +void DelayConvertor::doConvertToLua(lua_State* L, std::shared_ptr<Delay> payload) { + lua_createtable(L, 0, 0); + if (payload->getFrom()) { + lua_pushstring(L, (*payload->getFrom()).toString().c_str()); + lua_setfield(L, -2, "from"); + } + lua_pushstring(L, dateTimeToString(payload->getStamp()).c_str()); + lua_setfield(L, -2, "stamp"); +} diff --git a/Sluift/ElementConvertors/DelayConvertor.h b/Sluift/ElementConvertors/DelayConvertor.h new file mode 100644 index 0000000..ad340da --- /dev/null +++ b/Sluift/ElementConvertors/DelayConvertor.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2014-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <Swiften/Elements/Delay.h> + +#include <Sluift/GenericLuaElementConvertor.h> + +namespace Swift { + class DelayConvertor : public GenericLuaElementConvertor<Delay> { + public: + DelayConvertor(); + virtual ~DelayConvertor() override; + + virtual std::shared_ptr<Delay> doConvertFromLua(lua_State*) override; + virtual void doConvertToLua(lua_State*, std::shared_ptr<Delay>) override; + }; +} diff --git a/Sluift/ElementConvertors/DiscoInfoConvertor.cpp b/Sluift/ElementConvertors/DiscoInfoConvertor.cpp index ac0cf2e..a528211 100644 --- a/Sluift/ElementConvertors/DiscoInfoConvertor.cpp +++ b/Sluift/ElementConvertors/DiscoInfoConvertor.cpp @@ -1,101 +1,144 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #include <Sluift/ElementConvertors/DiscoInfoConvertor.h> -#include <lua.hpp> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> + #include <boost/numeric/conversion/cast.hpp> + +#include <lua.hpp> + +#include <Swiften/Elements/Form.h> +#include <Sluift/LuaElementConvertors.h> #include <Sluift/Lua/LuaUtils.h> using namespace Swift; -DiscoInfoConvertor::DiscoInfoConvertor() : GenericLuaElementConvertor<DiscoInfo>("disco_info") { +DiscoInfoConvertor::DiscoInfoConvertor(LuaElementConvertors* convertors) : + GenericLuaElementConvertor<DiscoInfo>("disco_info"), + convertors(convertors) { } DiscoInfoConvertor::~DiscoInfoConvertor() { } -boost::shared_ptr<DiscoInfo> DiscoInfoConvertor::doConvertFromLua(lua_State* L) { - boost::shared_ptr<DiscoInfo> result = boost::make_shared<DiscoInfo>(); - if (boost::optional<std::string> value = Lua::getStringField(L, -1, "node")) { - result->setNode(*value); - } - - lua_getfield(L, -1, "identities"); - if (lua_istable(L, -1)) { - for (lua_pushnil(L); lua_next(L, -2); ) { - result->addIdentity(DiscoInfo::Identity( - Lua::getStringField(L, -1, "name").get_value_or(""), - Lua::getStringField(L, -1, "category").get_value_or("client"), - Lua::getStringField(L, -1, "type").get_value_or("pc"), - Lua::getStringField(L, -1, "language").get_value_or(""))); - lua_pop(L, 1); - } - } - lua_pop(L, 1); - - lua_getfield(L, -1, "features"); - if (lua_istable(L, -1)) { - for (lua_pushnil(L); lua_next(L, -2); ) { - if (lua_isstring(L, -1)) { - result->addFeature(lua_tostring(L, -1)); - } - lua_pop(L, 1); - } - } - lua_pop(L, 1); - - // TODO: Extension - - return result; +std::shared_ptr<DiscoInfo> DiscoInfoConvertor::doConvertFromLua(lua_State* L) { + std::shared_ptr<DiscoInfo> result = std::make_shared<DiscoInfo>(); + if (boost::optional<std::string> value = Lua::getStringField(L, -1, "node")) { + result->setNode(*value); + } + + lua_getfield(L, -1, "identities"); + if (lua_istable(L, -1)) { + for (lua_pushnil(L); lua_next(L, -2); ) { + result->addIdentity(DiscoInfo::Identity( + Lua::getStringField(L, -1, "name").get_value_or(""), + Lua::getStringField(L, -1, "category").get_value_or("client"), + Lua::getStringField(L, -1, "type").get_value_or("pc"), + Lua::getStringField(L, -1, "language").get_value_or(""))); + lua_pop(L, 1); + } + } + lua_pop(L, 1); + + lua_getfield(L, -1, "features"); + if (lua_istable(L, -1)) { + for (lua_pushnil(L); lua_next(L, -2); ) { + if (lua_isstring(L, -1)) { + result->addFeature(lua_tostring(L, -1)); + } + lua_pop(L, 1); + } + } + lua_pop(L, 1); + + lua_getfield(L, -1, "extensions"); + if (lua_istable(L, -1)) { + for (lua_pushnil(L); lua_next(L, -2); ) { + std::shared_ptr<Form> form = std::dynamic_pointer_cast<Form>(convertors->convertFromLuaUntyped(L, -1, "form")); + if (!!form) { + result->addExtension(form); + } + lua_pop(L, 1); + } + } + lua_pop(L, 1); + + return result; +} + +void DiscoInfoConvertor::doConvertToLua(lua_State* L, std::shared_ptr<DiscoInfo> payload) { + lua_newtable(L); + if (!payload->getNode().empty()) { + lua_pushstring(L, payload->getNode().c_str()); + lua_setfield(L, -2, "node"); + } + + const std::vector<DiscoInfo::Identity>& identities = payload->getIdentities(); + if (!identities.empty()) { + lua_createtable(L, boost::numeric_cast<int>(identities.size()), 0); + for (size_t i = 0; i < identities.size(); ++i) { + lua_createtable(L, 0, 0); + if (!identities[i].getName().empty()) { + lua_pushstring(L, identities[i].getName().c_str()); + lua_setfield(L, -2, "name"); + } + if (!identities[i].getCategory().empty()) { + lua_pushstring(L, identities[i].getCategory().c_str()); + lua_setfield(L, -2, "category"); + } + if (!identities[i].getType().empty()) { + lua_pushstring(L, identities[i].getType().c_str()); + lua_setfield(L, -2, "type"); + } + if (!identities[i].getLanguage().empty()) { + lua_pushstring(L, identities[i].getLanguage().c_str()); + lua_setfield(L, -2, "language"); + } + lua_rawseti(L, -2, boost::numeric_cast<int>(i+1)); + } + lua_setfield(L, -2, "identities"); + } + + const std::vector<std::string>& features = payload->getFeatures(); + if (!features.empty()) { + lua_createtable(L, boost::numeric_cast<int>(features.size()), 0); + for (size_t i = 0; i < features.size(); ++i) { + lua_pushstring(L, features[i].c_str()); + lua_rawseti(L, -2, boost::numeric_cast<int>(i+1)); + } + lua_setfield(L, -2, "features"); + } + + const std::vector<Form::ref>& extensions = payload->getExtensions(); + if (!extensions.empty()) { + lua_createtable(L, boost::numeric_cast<int>(extensions.size()), 0); + for (size_t i = 0; i < extensions.size(); ++i) { + if (convertors->convertToLuaUntyped(L, extensions[i]) > 0) { + lua_rawseti(L, -2, boost::numeric_cast<int>(i+1)); + } + } + lua_setfield(L, -2, "extensions"); + } } -void DiscoInfoConvertor::doConvertToLua(lua_State* L, boost::shared_ptr<DiscoInfo> payload) { - lua_newtable(L); - if (!payload->getNode().empty()) { - lua_pushstring(L, payload->getNode().c_str()); - lua_setfield(L, -2, "node"); - } - - const std::vector<DiscoInfo::Identity>& identities = payload->getIdentities(); - if (!identities.empty()) { - lua_createtable(L, boost::numeric_cast<int>(identities.size()), 0); - for (size_t i = 0; i < identities.size(); ++i) { - lua_createtable(L, 0, 0); - if (!identities[i].getName().empty()) { - lua_pushstring(L, identities[i].getName().c_str()); - lua_setfield(L, -2, "name"); - } - if (!identities[i].getCategory().empty()) { - lua_pushstring(L, identities[i].getCategory().c_str()); - lua_setfield(L, -2, "category"); - } - if (!identities[i].getType().empty()) { - lua_pushstring(L, identities[i].getType().c_str()); - lua_setfield(L, -2, "type"); - } - if (!identities[i].getLanguage().empty()) { - lua_pushstring(L, identities[i].getLanguage().c_str()); - lua_setfield(L, -2, "language"); - } - lua_rawseti(L, -2, boost::numeric_cast<int>(i+1)); - } - lua_setfield(L, -2, "identities"); - } - - const std::vector<std::string>& features = payload->getFeatures(); - if (!features.empty()) { - lua_createtable(L, boost::numeric_cast<int>(features.size()), 0); - for (size_t i = 0; i < features.size(); ++i) { - lua_pushstring(L, features[i].c_str()); - lua_rawseti(L, -2, boost::numeric_cast<int>(i+1)); - } - lua_setfield(L, -2, "features"); - } - - // TODO: Extension +boost::optional<LuaElementConvertor::Documentation> DiscoInfoConvertor::getDocumentation() const { + return Documentation( + "DiscoInfo", + "Represents `disco#info` service discovery data.\n\n" + "This table has the following structure:\n\n" + "- `node`: string\n" + "- `identities`: array(table)\n" + " - `name`: string\n" + " - `category`: string\n" + " - `type`: string\n" + " - `language`: string\n" + "- `features`: array(string)\n" + "- `extensions`: array(table)\n" + "- `form`: string @{Form} (Optional)\n" + ); } diff --git a/Sluift/ElementConvertors/DiscoInfoConvertor.h b/Sluift/ElementConvertors/DiscoInfoConvertor.h index 7a2270e..b0e0849 100644 --- a/Sluift/ElementConvertors/DiscoInfoConvertor.h +++ b/Sluift/ElementConvertors/DiscoInfoConvertor.h @@ -1,23 +1,28 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <Swiften/Elements/DiscoInfo.h> #include <Sluift/GenericLuaElementConvertor.h> -#include <Swiften/Elements/DiscoInfo.h> namespace Swift { - class DiscoInfoConvertor : public GenericLuaElementConvertor<DiscoInfo> { - public: - DiscoInfoConvertor(); - virtual ~DiscoInfoConvertor(); + class LuaElementConvertors; + + class DiscoInfoConvertor : public GenericLuaElementConvertor<DiscoInfo> { + public: + DiscoInfoConvertor(LuaElementConvertors* convertors); + virtual ~DiscoInfoConvertor() override; + + virtual std::shared_ptr<DiscoInfo> doConvertFromLua(lua_State*) override; + virtual void doConvertToLua(lua_State*, std::shared_ptr<DiscoInfo>) override; + virtual boost::optional<Documentation> getDocumentation() const override; - virtual boost::shared_ptr<DiscoInfo> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE; - virtual void doConvertToLua(lua_State*, boost::shared_ptr<DiscoInfo>) SWIFTEN_OVERRIDE; - }; + private: + LuaElementConvertors* convertors; + }; } diff --git a/Sluift/ElementConvertors/DiscoItemsConvertor.cpp b/Sluift/ElementConvertors/DiscoItemsConvertor.cpp index 9049912..c15a0f8 100644 --- a/Sluift/ElementConvertors/DiscoItemsConvertor.cpp +++ b/Sluift/ElementConvertors/DiscoItemsConvertor.cpp @@ -1,14 +1,17 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #include <Sluift/ElementConvertors/DiscoItemsConvertor.h> -#include <lua.hpp> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> + #include <boost/numeric/conversion/cast.hpp> + +#include <lua.hpp> + #include <Sluift/Lua/LuaUtils.h> using namespace Swift; @@ -19,50 +22,50 @@ DiscoItemsConvertor::DiscoItemsConvertor() : GenericLuaElementConvertor<DiscoIte DiscoItemsConvertor::~DiscoItemsConvertor() { } -boost::shared_ptr<DiscoItems> DiscoItemsConvertor::doConvertFromLua(lua_State* L) { - boost::shared_ptr<DiscoItems> result = boost::make_shared<DiscoItems>(); - if (boost::optional<std::string> value = Lua::getStringField(L, -1, "node")) { - result->setNode(*value); - } - lua_getfield(L, -1, "items"); - if (lua_istable(L, -1)) { - for (lua_pushnil(L); lua_next(L, -2); ) { - result->addItem(DiscoItems::Item( - Lua::getStringField(L, -1, "name").get_value_or(""), - JID(Lua::getStringField(L, -1, "jid").get_value_or("")), - Lua::getStringField(L, -1, "node").get_value_or(""))); - lua_pop(L, 1); - } - } - lua_pop(L, 1); - return result; +std::shared_ptr<DiscoItems> DiscoItemsConvertor::doConvertFromLua(lua_State* L) { + std::shared_ptr<DiscoItems> result = std::make_shared<DiscoItems>(); + if (boost::optional<std::string> value = Lua::getStringField(L, -1, "node")) { + result->setNode(*value); + } + lua_getfield(L, -1, "items"); + if (lua_istable(L, -1)) { + for (lua_pushnil(L); lua_next(L, -2); ) { + result->addItem(DiscoItems::Item( + Lua::getStringField(L, -1, "name").get_value_or(""), + JID(Lua::getStringField(L, -1, "jid").get_value_or("")), + Lua::getStringField(L, -1, "node").get_value_or(""))); + lua_pop(L, 1); + } + } + lua_pop(L, 1); + return result; } -void DiscoItemsConvertor::doConvertToLua(lua_State* L, boost::shared_ptr<DiscoItems> payload) { - lua_newtable(L); - if (!payload->getNode().empty()) { - lua_pushstring(L, payload->getNode().c_str()); - lua_setfield(L, -2, "node"); - } - const std::vector<DiscoItems::Item>& items = payload->getItems(); - if (!items.empty()) { - lua_createtable(L, boost::numeric_cast<int>(items.size()), 0); - for (size_t i = 0; i < items.size(); ++i) { - lua_createtable(L, 0, 0); - if (!items[i].getName().empty()) { - lua_pushstring(L, items[i].getName().c_str()); - lua_setfield(L, -2, "name"); - } - if (!items[i].getNode().empty()) { - lua_pushstring(L, items[i].getNode().c_str()); - lua_setfield(L, -2, "node"); - } - if (items[i].getJID().isValid()) { - lua_pushstring(L, items[i].getJID().toString().c_str()); - lua_setfield(L, -2, "jid"); - } - lua_rawseti(L, -2, boost::numeric_cast<int>(i+1)); - } - lua_setfield(L, -2, "items"); - } +void DiscoItemsConvertor::doConvertToLua(lua_State* L, std::shared_ptr<DiscoItems> payload) { + lua_newtable(L); + if (!payload->getNode().empty()) { + lua_pushstring(L, payload->getNode().c_str()); + lua_setfield(L, -2, "node"); + } + const std::vector<DiscoItems::Item>& items = payload->getItems(); + if (!items.empty()) { + lua_createtable(L, boost::numeric_cast<int>(items.size()), 0); + for (size_t i = 0; i < items.size(); ++i) { + lua_createtable(L, 0, 0); + if (!items[i].getName().empty()) { + lua_pushstring(L, items[i].getName().c_str()); + lua_setfield(L, -2, "name"); + } + if (!items[i].getNode().empty()) { + lua_pushstring(L, items[i].getNode().c_str()); + lua_setfield(L, -2, "node"); + } + if (items[i].getJID().isValid()) { + lua_pushstring(L, items[i].getJID().toString().c_str()); + lua_setfield(L, -2, "jid"); + } + lua_rawseti(L, -2, boost::numeric_cast<int>(i+1)); + } + lua_setfield(L, -2, "items"); + } } diff --git a/Sluift/ElementConvertors/DiscoItemsConvertor.h b/Sluift/ElementConvertors/DiscoItemsConvertor.h index 8972a84..98dcb5c 100644 --- a/Sluift/ElementConvertors/DiscoItemsConvertor.h +++ b/Sluift/ElementConvertors/DiscoItemsConvertor.h @@ -1,23 +1,22 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <Swiften/Elements/DiscoItems.h> #include <Sluift/GenericLuaElementConvertor.h> -#include <Swiften/Elements/DiscoItems.h> namespace Swift { - class DiscoItemsConvertor : public GenericLuaElementConvertor<DiscoItems> { - public: - DiscoItemsConvertor(); - virtual ~DiscoItemsConvertor(); + class DiscoItemsConvertor : public GenericLuaElementConvertor<DiscoItems> { + public: + DiscoItemsConvertor(); + virtual ~DiscoItemsConvertor() override; - virtual boost::shared_ptr<DiscoItems> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE; - virtual void doConvertToLua(lua_State*, boost::shared_ptr<DiscoItems>) SWIFTEN_OVERRIDE; - }; + virtual std::shared_ptr<DiscoItems> doConvertFromLua(lua_State*) override; + virtual void doConvertToLua(lua_State*, std::shared_ptr<DiscoItems>) override; + }; } diff --git a/Sluift/ElementConvertors/ElementConvertors.ipp b/Sluift/ElementConvertors/ElementConvertors.ipp index b7b9166..a81c9cf 100644 --- a/Sluift/ElementConvertors/ElementConvertors.ipp +++ b/Sluift/ElementConvertors/ElementConvertors.ipp @@ -1,81 +1,87 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#include <Sluift/ElementConvertors/PubSubRetractConvertor.h> +#include <Sluift/ElementConvertors/IsodeIQDelegationConvertor.h> +#include <Sluift/ElementConvertors/PubSubAffiliationConvertor.h> #include <Sluift/ElementConvertors/PubSubAffiliationsConvertor.h> -#include <Sluift/ElementConvertors/PubSubPublishConvertor.h> -#include <Sluift/ElementConvertors/PubSubItemsConvertor.h> -#include <Sluift/ElementConvertors/PubSubOwnerRedirectConvertor.h> -#include <Sluift/ElementConvertors/PubSubEventRedirectConvertor.h> #include <Sluift/ElementConvertors/PubSubConfigureConvertor.h> -#include <Sluift/ElementConvertors/PubSubEventDisassociateConvertor.h> -#include <Sluift/ElementConvertors/PubSubOwnerAffiliationsConvertor.h> -#include <Sluift/ElementConvertors/PubSubOwnerConfigureConvertor.h> -#include <Sluift/ElementConvertors/UserLocationConvertor.h> -#include <Sluift/ElementConvertors/PubSubSubscribeOptionsConvertor.h> -#include <Sluift/ElementConvertors/PubSubOwnerSubscriptionsConvertor.h> +#include <Sluift/ElementConvertors/PubSubCreateConvertor.h> #include <Sluift/ElementConvertors/PubSubDefaultConvertor.h> +#include <Sluift/ElementConvertors/PubSubEventAssociateConvertor.h> #include <Sluift/ElementConvertors/PubSubEventCollectionConvertor.h> -#include <Sluift/ElementConvertors/PubSubEventSubscriptionConvertor.h> -#include <Sluift/ElementConvertors/PubSubEventRetractConvertor.h> -#include <Sluift/ElementConvertors/PubSubItemConvertor.h> -#include <Sluift/ElementConvertors/PubSubUnsubscribeConvertor.h> +#include <Sluift/ElementConvertors/PubSubEventConfigurationConvertor.h> #include <Sluift/ElementConvertors/PubSubEventDeleteConvertor.h> -#include <Sluift/ElementConvertors/PubSubCreateConvertor.h> -#include <Sluift/ElementConvertors/PubSubOwnerPurgeConvertor.h> +#include <Sluift/ElementConvertors/PubSubEventDisassociateConvertor.h> +#include <Sluift/ElementConvertors/PubSubEventItemConvertor.h> #include <Sluift/ElementConvertors/PubSubEventItemsConvertor.h> +#include <Sluift/ElementConvertors/PubSubEventPurgeConvertor.h> +#include <Sluift/ElementConvertors/PubSubEventRedirectConvertor.h> +#include <Sluift/ElementConvertors/PubSubEventRetractConvertor.h> +#include <Sluift/ElementConvertors/PubSubEventSubscriptionConvertor.h> +#include <Sluift/ElementConvertors/PubSubItemConvertor.h> +#include <Sluift/ElementConvertors/PubSubItemsConvertor.h> #include <Sluift/ElementConvertors/PubSubOptionsConvertor.h> -#include <Sluift/ElementConvertors/PubSubEventItemConvertor.h> -#include <Sluift/ElementConvertors/PubSubOwnerSubscriptionConvertor.h> #include <Sluift/ElementConvertors/PubSubOwnerAffiliationConvertor.h> -#include <Sluift/ElementConvertors/PubSubEventPurgeConvertor.h> -#include <Sluift/ElementConvertors/PubSubAffiliationConvertor.h> -#include <Sluift/ElementConvertors/PubSubSubscribeConvertor.h> -#include <Sluift/ElementConvertors/PubSubOwnerDeleteConvertor.h> +#include <Sluift/ElementConvertors/PubSubOwnerAffiliationsConvertor.h> +#include <Sluift/ElementConvertors/PubSubOwnerConfigureConvertor.h> #include <Sluift/ElementConvertors/PubSubOwnerDefaultConvertor.h> -#include <Sluift/ElementConvertors/PubSubSubscriptionsConvertor.h> -#include <Sluift/ElementConvertors/PubSubEventAssociateConvertor.h> +#include <Sluift/ElementConvertors/PubSubOwnerDeleteConvertor.h> +#include <Sluift/ElementConvertors/PubSubOwnerPurgeConvertor.h> +#include <Sluift/ElementConvertors/PubSubOwnerRedirectConvertor.h> +#include <Sluift/ElementConvertors/PubSubOwnerSubscriptionConvertor.h> +#include <Sluift/ElementConvertors/PubSubOwnerSubscriptionsConvertor.h> +#include <Sluift/ElementConvertors/PubSubPublishConvertor.h> +#include <Sluift/ElementConvertors/PubSubRetractConvertor.h> +#include <Sluift/ElementConvertors/PubSubSubscribeConvertor.h> +#include <Sluift/ElementConvertors/PubSubSubscribeOptionsConvertor.h> #include <Sluift/ElementConvertors/PubSubSubscriptionConvertor.h> -#include <Sluift/ElementConvertors/PubSubEventConfigurationConvertor.h> +#include <Sluift/ElementConvertors/PubSubSubscriptionsConvertor.h> +#include <Sluift/ElementConvertors/PubSubUnsubscribeConvertor.h> +#include <Sluift/ElementConvertors/SecurityLabelConvertor.h> +#include <Sluift/ElementConvertors/UserLocationConvertor.h> +#include <Sluift/ElementConvertors/UserTuneConvertor.h> void LuaElementConvertors::registerConvertors() { - convertors.push_back(boost::make_shared<PubSubRetractConvertor>(this)); - convertors.push_back(boost::make_shared<PubSubAffiliationsConvertor>(this)); - convertors.push_back(boost::make_shared<PubSubPublishConvertor>(this)); - convertors.push_back(boost::make_shared<PubSubItemsConvertor>(this)); - convertors.push_back(boost::make_shared<PubSubOwnerRedirectConvertor>(this)); - convertors.push_back(boost::make_shared<PubSubEventRedirectConvertor>(this)); - convertors.push_back(boost::make_shared<PubSubConfigureConvertor>(this)); - convertors.push_back(boost::make_shared<PubSubEventDisassociateConvertor>(this)); - convertors.push_back(boost::make_shared<PubSubOwnerAffiliationsConvertor>(this)); - convertors.push_back(boost::make_shared<PubSubOwnerConfigureConvertor>(this)); - convertors.push_back(boost::make_shared<UserLocationConvertor>(this)); - convertors.push_back(boost::make_shared<PubSubSubscribeOptionsConvertor>(this)); - convertors.push_back(boost::make_shared<PubSubOwnerSubscriptionsConvertor>(this)); - convertors.push_back(boost::make_shared<PubSubDefaultConvertor>(this)); - convertors.push_back(boost::make_shared<PubSubEventCollectionConvertor>(this)); - convertors.push_back(boost::make_shared<PubSubEventSubscriptionConvertor>(this)); - convertors.push_back(boost::make_shared<PubSubEventRetractConvertor>(this)); - convertors.push_back(boost::make_shared<PubSubItemConvertor>(this)); - convertors.push_back(boost::make_shared<PubSubUnsubscribeConvertor>(this)); - convertors.push_back(boost::make_shared<PubSubEventDeleteConvertor>(this)); - convertors.push_back(boost::make_shared<PubSubCreateConvertor>(this)); - convertors.push_back(boost::make_shared<PubSubOwnerPurgeConvertor>(this)); - convertors.push_back(boost::make_shared<PubSubEventItemsConvertor>(this)); - convertors.push_back(boost::make_shared<PubSubOptionsConvertor>(this)); - convertors.push_back(boost::make_shared<PubSubEventItemConvertor>(this)); - convertors.push_back(boost::make_shared<PubSubOwnerSubscriptionConvertor>(this)); - convertors.push_back(boost::make_shared<PubSubOwnerAffiliationConvertor>(this)); - convertors.push_back(boost::make_shared<PubSubEventPurgeConvertor>(this)); - convertors.push_back(boost::make_shared<PubSubAffiliationConvertor>(this)); - convertors.push_back(boost::make_shared<PubSubSubscribeConvertor>(this)); - convertors.push_back(boost::make_shared<PubSubOwnerDeleteConvertor>(this)); - convertors.push_back(boost::make_shared<PubSubOwnerDefaultConvertor>(this)); - convertors.push_back(boost::make_shared<PubSubSubscriptionsConvertor>(this)); - convertors.push_back(boost::make_shared<PubSubEventAssociateConvertor>(this)); - convertors.push_back(boost::make_shared<PubSubSubscriptionConvertor>(this)); - convertors.push_back(boost::make_shared<PubSubEventConfigurationConvertor>(this)); + convertors.push_back(std::make_shared<PubSubRetractConvertor>(this)); + convertors.push_back(std::make_shared<PubSubAffiliationsConvertor>(this)); + convertors.push_back(std::make_shared<PubSubPublishConvertor>(this)); + convertors.push_back(std::make_shared<PubSubItemsConvertor>(this)); + convertors.push_back(std::make_shared<PubSubOwnerRedirectConvertor>()); + convertors.push_back(std::make_shared<PubSubEventRedirectConvertor>()); + convertors.push_back(std::make_shared<UserTuneConvertor>()); + convertors.push_back(std::make_shared<PubSubConfigureConvertor>(this)); + convertors.push_back(std::make_shared<PubSubEventDisassociateConvertor>()); + convertors.push_back(std::make_shared<PubSubOwnerAffiliationsConvertor>(this)); + convertors.push_back(std::make_shared<PubSubOwnerConfigureConvertor>(this)); + convertors.push_back(std::make_shared<UserLocationConvertor>()); + convertors.push_back(std::make_shared<PubSubSubscribeOptionsConvertor>()); + convertors.push_back(std::make_shared<PubSubOwnerSubscriptionsConvertor>(this)); + convertors.push_back(std::make_shared<PubSubDefaultConvertor>()); + convertors.push_back(std::make_shared<PubSubEventCollectionConvertor>(this)); + convertors.push_back(std::make_shared<PubSubEventSubscriptionConvertor>()); + convertors.push_back(std::make_shared<PubSubEventRetractConvertor>()); + convertors.push_back(std::make_shared<PubSubItemConvertor>(this)); + convertors.push_back(std::make_shared<PubSubUnsubscribeConvertor>()); + convertors.push_back(std::make_shared<PubSubEventDeleteConvertor>(this)); + convertors.push_back(std::make_shared<PubSubCreateConvertor>(this)); + convertors.push_back(std::make_shared<PubSubOwnerPurgeConvertor>()); + convertors.push_back(std::make_shared<PubSubEventItemsConvertor>(this)); + convertors.push_back(std::make_shared<PubSubOptionsConvertor>(this)); + convertors.push_back(std::make_shared<PubSubEventItemConvertor>(this)); + convertors.push_back(std::make_shared<PubSubOwnerSubscriptionConvertor>()); + convertors.push_back(std::make_shared<IsodeIQDelegationConvertor>(this)); + convertors.push_back(std::make_shared<PubSubOwnerAffiliationConvertor>()); + convertors.push_back(std::make_shared<PubSubEventPurgeConvertor>()); + convertors.push_back(std::make_shared<PubSubAffiliationConvertor>()); + convertors.push_back(std::make_shared<PubSubSubscribeConvertor>(this)); + convertors.push_back(std::make_shared<PubSubOwnerDeleteConvertor>(this)); + convertors.push_back(std::make_shared<PubSubOwnerDefaultConvertor>(this)); + convertors.push_back(std::make_shared<PubSubSubscriptionsConvertor>(this)); + convertors.push_back(std::make_shared<PubSubEventAssociateConvertor>()); + convertors.push_back(std::make_shared<PubSubSubscriptionConvertor>(this)); + convertors.push_back(std::make_shared<SecurityLabelConvertor>()); + convertors.push_back(std::make_shared<PubSubEventConfigurationConvertor>(this)); } diff --git a/Sluift/ElementConvertors/FormConvertor.cpp b/Sluift/ElementConvertors/FormConvertor.cpp index e44ca3e..245e0f9 100644 --- a/Sluift/ElementConvertors/FormConvertor.cpp +++ b/Sluift/ElementConvertors/FormConvertor.cpp @@ -1,345 +1,343 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #include <Sluift/ElementConvertors/FormConvertor.h> -#include <lua.hpp> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> +#include <sstream> + +#include <boost/assign/list_of.hpp> #include <boost/numeric/conversion/cast.hpp> + +#include <lua.hpp> + #include <Sluift/Lua/Check.h> #include <Sluift/Lua/Value.h> -#include <Swiften/Base/foreach.h> -#include <boost/assign/list_of.hpp> -#include <sstream> using namespace Swift; namespace { - int formIndex(lua_State* L) { - lua_getfield(L, 1, "fields"); - if (lua_type(L, -1) != LUA_TTABLE) { - return 0; - } - int index = Lua::absoluteOffset(L, -1); - lua_pushnil(L); - for (lua_pushnil(L); lua_next(L, index) != 0; ) { - lua_getfield(L, -1, "name"); - if (lua_equal(L, -1, 2)) { - lua_pop(L, 1); - return 1; - } - lua_pop(L, 2); - } - return 0; - } - - int formNewIndex(lua_State* L) { - lua_getfield(L, 1, "fields"); - bool foundField = false; - if (lua_type(L, -1) == LUA_TTABLE) { - for (lua_pushnil(L); lua_next(L, -2) != 0; ) { - lua_getfield(L, -1, "name"); - if (lua_equal(L, -1, 2)) { - lua_pushvalue(L, 3); - lua_setfield(L, -3, "value"); - foundField = true; - lua_pop(L, 3); - break; - } - lua_pop(L, 2); - } - } - lua_pop(L, 1); - - if (!foundField) { - lua_pushvalue(L, 2); - lua_pushvalue(L, 3); - lua_rawset(L, 1); - } - return 0; - } - - Lua::Table convertFieldToLua(boost::shared_ptr<FormField> field) { - Lua::Table luaField = boost::assign::map_list_of("name", Lua::valueRef(field->getName())); - std::string type; - switch (field->getType()) { - case FormField::UnknownType: type = ""; break; - case FormField::BooleanType: type = "boolean"; break; - case FormField::FixedType: type = "fixed"; break; - case FormField::HiddenType: type = "hidden"; break; - case FormField::ListSingleType: type = "list-single"; break; - case FormField::TextMultiType: type = "text-multi"; break; - case FormField::TextPrivateType: type = "text-private"; break; - case FormField::TextSingleType: type = "text-single"; break; - case FormField::JIDSingleType: type = "jid-single"; break; - case FormField::JIDMultiType: type = "jid-multi"; break; - case FormField::ListMultiType: type = "list-multi"; break; - } - if (!type.empty()) { - luaField["type"] = Lua::valueRef(type); - } - if (!field->getLabel().empty()) { - luaField["label"] = Lua::valueRef(field->getLabel()); - } - if (field->getRequired()) { - luaField["required"] = Lua::boolRef(field->getRequired()); - } - if (!field->getDescription().empty()) { - luaField["description"] = Lua::valueRef(field->getDescription()); - } - - if (field->getType() == FormField::ListMultiType || field->getType() == FormField::JIDMultiType || field->getType() == FormField::TextMultiType) { - luaField["values"] = Lua::valueRef(Lua::Array(field->getValues().begin(), field->getValues().end())); - } - else if (field->getType() == FormField::BooleanType) { - luaField["value"] = Lua::boolRef(field->getBoolValue()); - } - else if (!field->getValues().empty()) { - luaField["value"] = Lua::valueRef(field->getValues()[0]); - } - - if (!field->getOptions().empty()) { - Lua::Array options; - foreach(const FormField::Option& option, field->getOptions()) { - Lua::Table luaOption = boost::assign::map_list_of - ("label", Lua::valueRef(option.label)) - ("value", Lua::valueRef(option.value)); - options.push_back(luaOption); - } - luaField["options"] = valueRef(options); - } - return luaField; - } - - Lua::Array convertFieldListToLua(const std::vector< boost::shared_ptr<FormField> >& fieldList) { - Lua::Array fields; - foreach(boost::shared_ptr<FormField> field, fieldList) { - fields.push_back(convertFieldToLua(field)); - } - return fields; - } - - - boost::shared_ptr<FormField> convertFieldFromLua(lua_State* L) { - boost::shared_ptr<FormField> result = boost::make_shared<FormField>(); - FormField::Type fieldType = FormField::UnknownType; - boost::optional<std::string> type = Lua::getStringField(L, -1, "type"); - if (type) { - if (*type == "boolean") { - fieldType = FormField::BooleanType; - } - if (*type == "fixed") { - fieldType = FormField::FixedType; - } - if (*type == "hidden") { - fieldType = FormField::HiddenType; - } - if (*type == "list-single") { - fieldType = FormField::ListSingleType; - } - if (*type == "text-multi") { - fieldType = FormField::TextMultiType; - } - if (*type == "text-private") { - fieldType = FormField::TextPrivateType; - } - if (*type == "text-single") { - fieldType = FormField::TextSingleType; - } - if (*type == "jid-single") { - fieldType = FormField::JIDSingleType; - } - if (*type == "jid-multi") { - fieldType = FormField::JIDMultiType; - } - if (*type == "list-multi") { - fieldType = FormField::ListMultiType; - } - } - result->setType(fieldType); - if (boost::optional<std::string> name = Lua::getStringField(L, -1, "name")) { - result->setName(*name); - } - if (boost::optional<std::string> description = Lua::getStringField(L, -1, "description")) { - result->setDescription(*description); - } - if (boost::optional<std::string> label = Lua::getStringField(L, -1, "label")) { - result->setLabel(*label); - } - if (boost::optional<bool> required = Lua::getBooleanField(L, -1, "required")) { - result->setRequired(*required); - } - if (boost::optional<std::string> value = Lua::getStringField(L, -1, "value")) { - result->addValue(*value); - } - else if (boost::optional<bool> value = Lua::getBooleanField(L, -1, "value")) { - result->setBoolValue(*value); - } - else { - lua_getfield(L, -1, "values"); - if (lua_istable(L, -1)) { - for (lua_pushnil(L); lua_next(L, -2); ) { - if (lua_isstring(L, -1)) { - result->addValue(lua_tostring(L, -1)); - } - lua_pop(L, 1); - } - } - lua_pop(L, 1); - } - lua_getfield(L, -1, "options"); - if (lua_istable(L, -1)) { - for (lua_pushnil(L); lua_next(L, -2); ) { - if (lua_istable(L, -1)) { - FormField::Option option("", ""); - if (boost::optional<std::string> value = Lua::getStringField(L, -1, "value")) { - option.value = *value; - } - if (boost::optional<std::string> label = Lua::getStringField(L, -1, "label")) { - option.label = *label; - } - result->addOption(option); - } - lua_pop(L, 1); - } - } - lua_pop(L, 1); - return result; - } - - std::vector< boost::shared_ptr<FormField> > convertFieldListFromLua(lua_State* L) { - std::vector< boost::shared_ptr<FormField> > result; - for (lua_pushnil(L); lua_next(L, -2);) { - result.push_back(convertFieldFromLua(L)); - lua_pop(L, 1); - } - return result; - } - - boost::shared_ptr<Form> convertFormFromLua(lua_State* L) { - boost::shared_ptr<Form> result = boost::make_shared<Form>(); - if (boost::optional<std::string> title = Lua::getStringField(L, -1, "title")) { - result->setTitle(*title); - } - if (boost::optional<std::string> instructions = Lua::getStringField(L, -1, "instructions")) { - result->setInstructions(*instructions); - } - if (boost::optional<std::string> type = Lua::getStringField(L, -1, "type")) { - Form::Type formType = Form::FormType; - if (*type == "submit") { - formType = Form::SubmitType; - } - else if (*type == "cancel") { - formType = Form::CancelType; - } - else if (*type == "result") { - formType = Form::ResultType; - } - result->setType(formType); - } - - lua_getfield(L, -1, "fields"); - if (lua_istable(L, -1)) { - foreach (boost::shared_ptr<FormField> formField, convertFieldListFromLua(L)) { - result->addField(formField); - } - } - lua_pop(L, 1); - - lua_getfield(L, -1, "reported_fields"); - if (lua_istable(L, -1)) { - foreach (boost::shared_ptr<FormField> formField, convertFieldListFromLua(L)) { - result->addReportedField(formField); - } - } - lua_pop(L, 1); - - lua_getfield(L, -1, "items"); - if (lua_istable(L, -1)) { - for (lua_pushnil(L); lua_next(L, -2);) { - result->addItem(convertFieldListFromLua(L)); - lua_pop(L, 1); - } - } - lua_pop(L, 1); - - return result; - } - - void convertFormToLua(lua_State* L, boost::shared_ptr<Form> payload) { - std::string type; - switch (payload->getType()) { - case Form::FormType: type = "form"; break; - case Form::SubmitType: type = "submit"; break; - case Form::CancelType: type = "cancel"; break; - case Form::ResultType: type = "result"; break; - } - - Lua::Table result = boost::assign::map_list_of("type", Lua::valueRef(type)); - if (!payload->getTitle().empty()) { - result["title"] = Lua::valueRef(payload->getTitle()); - } - if (!payload->getInstructions().empty()) { - result["instructions"] = Lua::valueRef(payload->getInstructions()); - } - if (!payload->getFields().empty()) { - result["fields"] = valueRef(convertFieldListToLua(payload->getFields())); - } - if (!payload->getReportedFields().empty()) { - result["reported_fields"] = valueRef(convertFieldListToLua(payload->getReportedFields())); - } - - if (!payload->getItems().empty()) { - Lua::Array luaItems; - foreach(const Form::FormItem& item, payload->getItems()) { - if (!item.empty()) { - luaItems.push_back(convertFieldListToLua(item)); - } - } - result["items"] = valueRef(luaItems); - } - - Lua::pushValue(L, result); - - lua_newtable(L); - lua_pushcfunction(L, formIndex); - lua_setfield(L, -2, "__index"); - lua_pushcfunction(L, formNewIndex); - lua_setfield(L, -2, "__newindex"); - lua_setmetatable(L, -2); - } - - int createSubmission(lua_State* L) { - boost::shared_ptr<Form> form = convertFormFromLua(L); - - // Remove all redundant elements - form->setInstructions(""); - form->setTitle(""); - form->clearItems(); - form->clearReportedFields(); - std::vector< boost::shared_ptr<FormField> > fields(form->getFields()); - form->clearFields(); - foreach (boost::shared_ptr<FormField> field, fields) { - if (field->getType() == FormField::FixedType) { - continue; - } - field->clearOptions(); - field->setLabel(""); - field->setType(FormField::UnknownType); - field->setDescription(""); - form->addField(field); - } - form->setType(Form::SubmitType); - - // Convert back - convertFormToLua(L, form); - Lua::registerTableToString(L, -1); - - return 1; - } + int formIndex(lua_State* L) { + lua_getfield(L, 1, "fields"); + if (lua_type(L, -1) != LUA_TTABLE) { + return 0; + } + int index = Lua::absoluteOffset(L, -1); + lua_pushnil(L); + for (lua_pushnil(L); lua_next(L, index) != 0; ) { + lua_getfield(L, -1, "name"); + if (lua_compare(L, -1, 2, LUA_OPEQ)) { + lua_pop(L, 1); + return 1; + } + lua_pop(L, 2); + } + return 0; + } + + int formNewIndex(lua_State* L) { + lua_getfield(L, 1, "fields"); + bool foundField = false; + if (lua_type(L, -1) == LUA_TTABLE) { + for (lua_pushnil(L); lua_next(L, -2) != 0; ) { + lua_getfield(L, -1, "name"); + if (lua_compare(L, -1, 2, LUA_OPEQ)) { + lua_pushvalue(L, 3); + lua_setfield(L, -3, "value"); + foundField = true; + lua_pop(L, 3); + break; + } + lua_pop(L, 2); + } + } + lua_pop(L, 1); + + if (!foundField) { + lua_pushvalue(L, 2); + lua_pushvalue(L, 3); + lua_rawset(L, 1); + } + return 0; + } + + Lua::Table convertFieldToLua(std::shared_ptr<FormField> field) { + Lua::Table luaField = boost::assign::map_list_of("name", Lua::valueRef(field->getName())); + std::string type; + switch (field->getType()) { + case FormField::UnknownType: type = ""; break; + case FormField::BooleanType: type = "boolean"; break; + case FormField::FixedType: type = "fixed"; break; + case FormField::HiddenType: type = "hidden"; break; + case FormField::ListSingleType: type = "list-single"; break; + case FormField::TextMultiType: type = "text-multi"; break; + case FormField::TextPrivateType: type = "text-private"; break; + case FormField::TextSingleType: type = "text-single"; break; + case FormField::JIDSingleType: type = "jid-single"; break; + case FormField::JIDMultiType: type = "jid-multi"; break; + case FormField::ListMultiType: type = "list-multi"; break; + } + if (!type.empty()) { + luaField["type"] = Lua::valueRef(type); + } + if (!field->getLabel().empty()) { + luaField["label"] = Lua::valueRef(field->getLabel()); + } + if (field->getRequired()) { + luaField["required"] = Lua::boolRef(field->getRequired()); + } + if (!field->getDescription().empty()) { + luaField["description"] = Lua::valueRef(field->getDescription()); + } + if (field->getType() == FormField::BooleanType) { + luaField["value"] = Lua::boolRef(field->getBoolValue()); + } + else if (field->getValues().size() > 1) { + luaField["value"] = Lua::valueRef(Lua::Array(field->getValues().begin(), field->getValues().end())); + } + else if (field->getValues().size() == 1) { + luaField["value"] = Lua::valueRef(field->getValues()[0]); + } + if (!field->getOptions().empty()) { + Lua::Array options; + for (const auto& option : field->getOptions()) { + Lua::Table luaOption = boost::assign::map_list_of + ("label", Lua::valueRef(option.label)) + ("value", Lua::valueRef(option.value)); + options.push_back(luaOption); + } + luaField["options"] = valueRef(options); + } + return luaField; + } + + Lua::Array convertFieldListToLua(const std::vector< std::shared_ptr<FormField> >& fieldList) { + Lua::Array fields; + for (auto&& field : fieldList) { + fields.push_back(convertFieldToLua(field)); + } + return fields; + } + + + std::shared_ptr<FormField> convertFieldFromLua(lua_State* L) { + std::shared_ptr<FormField> result = std::make_shared<FormField>(); + FormField::Type fieldType = FormField::UnknownType; + boost::optional<std::string> type = Lua::getStringField(L, -1, "type"); + if (type) { + if (*type == "boolean") { + fieldType = FormField::BooleanType; + } + if (*type == "fixed") { + fieldType = FormField::FixedType; + } + if (*type == "hidden") { + fieldType = FormField::HiddenType; + } + if (*type == "list-single") { + fieldType = FormField::ListSingleType; + } + if (*type == "text-multi") { + fieldType = FormField::TextMultiType; + } + if (*type == "text-private") { + fieldType = FormField::TextPrivateType; + } + if (*type == "text-single") { + fieldType = FormField::TextSingleType; + } + if (*type == "jid-single") { + fieldType = FormField::JIDSingleType; + } + if (*type == "jid-multi") { + fieldType = FormField::JIDMultiType; + } + if (*type == "list-multi") { + fieldType = FormField::ListMultiType; + } + } + result->setType(fieldType); + if (boost::optional<std::string> name = Lua::getStringField(L, -1, "name")) { + result->setName(*name); + } + if (boost::optional<std::string> description = Lua::getStringField(L, -1, "description")) { + result->setDescription(*description); + } + if (boost::optional<std::string> label = Lua::getStringField(L, -1, "label")) { + result->setLabel(*label); + } + if (boost::optional<bool> required = Lua::getBooleanField(L, -1, "required")) { + result->setRequired(*required); + } + if (boost::optional<std::string> value = Lua::getStringField(L, -1, "value")) { + result->addValue(*value); + } + else if (boost::optional<bool> value = Lua::getBooleanField(L, -1, "value")) { + result->setBoolValue(*value); + } + else { + lua_getfield(L, -1, "value"); + if (lua_istable(L, -1)) { + for (lua_pushnil(L); lua_next(L, -2); ) { + if (lua_isstring(L, -1)) { + result->addValue(lua_tostring(L, -1)); + } + lua_pop(L, 1); + } + } + lua_pop(L, 1); + } + lua_getfield(L, -1, "options"); + if (lua_istable(L, -1)) { + for (lua_pushnil(L); lua_next(L, -2); ) { + if (lua_istable(L, -1)) { + FormField::Option option("", ""); + if (boost::optional<std::string> value = Lua::getStringField(L, -1, "value")) { + option.value = *value; + } + if (boost::optional<std::string> label = Lua::getStringField(L, -1, "label")) { + option.label = *label; + } + result->addOption(option); + } + lua_pop(L, 1); + } + } + lua_pop(L, 1); + return result; + } + + std::vector< std::shared_ptr<FormField> > convertFieldListFromLua(lua_State* L) { + std::vector< std::shared_ptr<FormField> > result; + for (lua_pushnil(L); lua_next(L, -2);) { + result.push_back(convertFieldFromLua(L)); + lua_pop(L, 1); + } + return result; + } + + std::shared_ptr<Form> convertFormFromLua(lua_State* L) { + std::shared_ptr<Form> result = std::make_shared<Form>(); + if (boost::optional<std::string> title = Lua::getStringField(L, -1, "title")) { + result->setTitle(*title); + } + if (boost::optional<std::string> instructions = Lua::getStringField(L, -1, "instructions")) { + result->setInstructions(*instructions); + } + if (boost::optional<std::string> type = Lua::getStringField(L, -1, "type")) { + Form::Type formType = Form::FormType; + if (*type == "submit") { + formType = Form::SubmitType; + } + else if (*type == "cancel") { + formType = Form::CancelType; + } + else if (*type == "result") { + formType = Form::ResultType; + } + result->setType(formType); + } + + lua_getfield(L, -1, "fields"); + if (lua_istable(L, -1)) { + for (auto&& formField : convertFieldListFromLua(L)) { + result->addField(formField); + } + } + lua_pop(L, 1); + + lua_getfield(L, -1, "reported_fields"); + if (lua_istable(L, -1)) { + for (auto&& formField : convertFieldListFromLua(L)) { + result->addReportedField(formField); + } + } + lua_pop(L, 1); + + lua_getfield(L, -1, "items"); + if (lua_istable(L, -1)) { + for (lua_pushnil(L); lua_next(L, -2);) { + result->addItem(convertFieldListFromLua(L)); + lua_pop(L, 1); + } + } + lua_pop(L, 1); + + return result; + } + + void convertFormToLua(lua_State* L, std::shared_ptr<Form> payload) { + std::string type; + switch (payload->getType()) { + case Form::FormType: type = "form"; break; + case Form::SubmitType: type = "submit"; break; + case Form::CancelType: type = "cancel"; break; + case Form::ResultType: type = "result"; break; + } + + Lua::Table result = boost::assign::map_list_of("type", Lua::valueRef(type)); + if (!payload->getTitle().empty()) { + result["title"] = Lua::valueRef(payload->getTitle()); + } + if (!payload->getInstructions().empty()) { + result["instructions"] = Lua::valueRef(payload->getInstructions()); + } + result["fields"] = valueRef(convertFieldListToLua(payload->getFields())); + if (!payload->getReportedFields().empty()) { + result["reported_fields"] = valueRef(convertFieldListToLua(payload->getReportedFields())); + } + + if (!payload->getItems().empty()) { + Lua::Array luaItems; + for (const auto& item : payload->getItems()) { + if (!item.empty()) { + luaItems.push_back(convertFieldListToLua(item)); + } + } + result["items"] = valueRef(luaItems); + } + + Lua::pushValue(L, result); + + lua_newtable(L); + lua_pushcfunction(L, formIndex); + lua_setfield(L, -2, "__index"); + lua_pushcfunction(L, formNewIndex); + lua_setfield(L, -2, "__newindex"); + lua_setmetatable(L, -2); + } + + int createSubmission(lua_State* L) { + std::shared_ptr<Form> form = convertFormFromLua(L); + + // Remove all redundant elements + form->setInstructions(""); + form->setTitle(""); + form->clearItems(); + form->clearReportedFields(); + std::vector< std::shared_ptr<FormField> > fields(form->getFields()); + form->clearFields(); + for (auto&& field : fields) { + if (field->getType() == FormField::FixedType) { + continue; + } + field->clearOptions(); + field->setLabel(""); + field->setType(FormField::UnknownType); + field->setDescription(""); + form->addField(field); + } + form->setType(Form::SubmitType); + + // Convert back + convertFormToLua(L, form); + Lua::registerTableToString(L, -1); + + return 1; + } } FormConvertor::FormConvertor() : GenericLuaElementConvertor<Form>("form") { @@ -348,14 +346,14 @@ FormConvertor::FormConvertor() : GenericLuaElementConvertor<Form>("form") { FormConvertor::~FormConvertor() { } -boost::shared_ptr<Form> FormConvertor::doConvertFromLua(lua_State* L) { - return convertFormFromLua(L); +std::shared_ptr<Form> FormConvertor::doConvertFromLua(lua_State* L) { + return convertFormFromLua(L); } -void FormConvertor::doConvertToLua(lua_State* L, boost::shared_ptr<Form> payload) { - convertFormToLua(L, payload); +void FormConvertor::doConvertToLua(lua_State* L, std::shared_ptr<Form> payload) { + convertFormToLua(L, payload); - lua_pushstring(L, "create_submission"); - lua_pushcfunction(L, createSubmission); - lua_rawset(L, -3); + lua_pushstring(L, "create_submission"); + lua_pushcfunction(L, createSubmission); + lua_rawset(L, -3); } diff --git a/Sluift/ElementConvertors/FormConvertor.h b/Sluift/ElementConvertors/FormConvertor.h index eaccf74..8ca20cc 100644 --- a/Sluift/ElementConvertors/FormConvertor.h +++ b/Sluift/ElementConvertors/FormConvertor.h @@ -1,23 +1,22 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <Swiften/Elements/Form.h> #include <Sluift/GenericLuaElementConvertor.h> -#include <Swiften/Elements/Form.h> namespace Swift { - class FormConvertor : public GenericLuaElementConvertor<Form> { - public: - FormConvertor(); - virtual ~FormConvertor(); + class FormConvertor : public GenericLuaElementConvertor<Form> { + public: + FormConvertor(); + virtual ~FormConvertor() override; - virtual boost::shared_ptr<Form> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE; - virtual void doConvertToLua(lua_State*, boost::shared_ptr<Form>) SWIFTEN_OVERRIDE; - }; + virtual std::shared_ptr<Form> doConvertFromLua(lua_State*) override; + virtual void doConvertToLua(lua_State*, std::shared_ptr<Form>) override; + }; } diff --git a/Sluift/ElementConvertors/ForwardedConvertor.cpp b/Sluift/ElementConvertors/ForwardedConvertor.cpp new file mode 100644 index 0000000..b353eea --- /dev/null +++ b/Sluift/ElementConvertors/ForwardedConvertor.cpp @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2014-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Sluift/ElementConvertors/ForwardedConvertor.h> + +#include <memory> + +#include <boost/numeric/conversion/cast.hpp> + +#include <lua.hpp> + +#include <Swiften/Elements/Delay.h> +#include <Swiften/Elements/IQ.h> +#include <Swiften/Elements/Message.h> +#include <Swiften/Elements/Presence.h> + +#include <Sluift/LuaElementConvertors.h> + +using namespace Swift; + +ForwardedConvertor::ForwardedConvertor(LuaElementConvertors* convertors) : + GenericLuaElementConvertor<Forwarded>("forwarded"), + convertors(convertors) { +} + +ForwardedConvertor::~ForwardedConvertor() { +} + +std::shared_ptr<Forwarded> ForwardedConvertor::doConvertFromLua(lua_State* L) { + std::shared_ptr<Forwarded> result = std::make_shared<Forwarded>(); + lua_getfield(L, -1, "delay"); + if (!lua_isnil(L, -1)) { + std::shared_ptr<Delay> delay = std::dynamic_pointer_cast<Delay>(convertors->convertFromLuaUntyped(L, -1, "delay")); + if (!!delay) { + result->setDelay(delay); + } + } + lua_pop(L, 1); + lua_getfield(L, -1, "stanza"); + if (!lua_isnil(L, -1)) { + std::shared_ptr<Stanza> stanza = std::dynamic_pointer_cast<Stanza>(convertors->convertFromLua(L, -1)); + if (!!stanza) { + result->setStanza(stanza); + } + lua_pop(L, 1); + return result; + } + return result; +} + +void ForwardedConvertor::doConvertToLua(lua_State* L, std::shared_ptr<Forwarded> payload) { + lua_createtable(L, 0, 0); + if (convertors->convertToLuaUntyped(L, payload->getDelay()) > 0) { + lua_setfield(L, -2, "delay"); + } + std::shared_ptr<Stanza> stanza = payload->getStanza(); + if (!!stanza) { + if (convertors->convertToLua(L, stanza) > 0) { + lua_setfield(L, -2, "stanza"); + } + } +} + +boost::optional<LuaElementConvertor::Documentation> ForwardedConvertor::getDocumentation() const { + return Documentation( + "Forwarded", + "This table has the following fields:\n\n" + "- `delay`: @{Delay} (Optional)\n" + "- `stanza`: @{Stanza} (Optional)\n" + ); +} diff --git a/Sluift/ElementConvertors/ForwardedConvertor.h b/Sluift/ElementConvertors/ForwardedConvertor.h new file mode 100644 index 0000000..32d29e6 --- /dev/null +++ b/Sluift/ElementConvertors/ForwardedConvertor.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2014-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <Swiften/Elements/Forwarded.h> + +#include <Sluift/GenericLuaElementConvertor.h> + +namespace Swift { + class LuaElementConvertors; + + class ForwardedConvertor : public GenericLuaElementConvertor<Forwarded> { + public: + ForwardedConvertor(LuaElementConvertors* convertors); + virtual ~ForwardedConvertor() override; + + virtual std::shared_ptr<Forwarded> doConvertFromLua(lua_State*) override; + virtual void doConvertToLua(lua_State*, std::shared_ptr<Forwarded>) override; + virtual boost::optional<Documentation> getDocumentation() const override; + + private: + LuaElementConvertors* convertors; + }; +} + diff --git a/Sluift/ElementConvertors/IQConvertor.cpp b/Sluift/ElementConvertors/IQConvertor.cpp new file mode 100644 index 0000000..67a4a2a --- /dev/null +++ b/Sluift/ElementConvertors/IQConvertor.cpp @@ -0,0 +1,75 @@ +/* + * Copyright (c) 2014-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Sluift/ElementConvertors/IQConvertor.h> + +#include <memory> + +#include <lua.hpp> + +#include <Sluift/LuaElementConvertors.h> + +using namespace Swift; + +IQConvertor::IQConvertor(LuaElementConvertors* convertors) : + StanzaConvertor<IQ>("iq"), + convertors(convertors) { +} + +IQConvertor::~IQConvertor() { +} + +std::shared_ptr<IQ> IQConvertor::doConvertFromLua(lua_State* L) { + std::shared_ptr<IQ> result = getStanza(L, convertors); + lua_getfield(L, -1, "type"); + if (lua_isstring(L, -1)) { + result->setType(IQConvertor::convertIQTypeFromString(lua_tostring(L, -1))); + } + lua_pop(L, 1); + return result; +} + +void IQConvertor::doConvertToLua(lua_State* L, std::shared_ptr<IQ> stanza) { + pushStanza(L, stanza, convertors); + const std::string type = IQConvertor::convertIQTypeToString(stanza->getType()); + lua_pushstring(L, type.c_str()); + lua_setfield(L, -2, "type"); +} + +boost::optional<LuaElementConvertor::Documentation> IQConvertor::getDocumentation() const { + return Documentation( + "IQ", + "This table has the following fields:\n\n" + "- `type`: string\n" + "- `id`: string\n" + "- `from`: string\n" + "- `to`: string\n" + "- `payloads`: array<@{Payload}>\n" + ); +} + +std::string IQConvertor::convertIQTypeToString(IQ::Type type) { + switch (type) { + case IQ::Get: return "get"; + case IQ::Set: return "set"; + case IQ::Result: return "result"; + case IQ::Error: return "error"; + } + assert(false); + return ""; +} + +IQ::Type IQConvertor::convertIQTypeFromString(const std::string& type) { + if (type == "get") { + return IQ::Get; + } + else if (type == "set") { + return IQ::Set; + } + else { + throw Lua::Exception("Illegal query type: '" + type + "'"); + } +} diff --git a/Sluift/ElementConvertors/IQConvertor.h b/Sluift/ElementConvertors/IQConvertor.h new file mode 100644 index 0000000..6ccaa46 --- /dev/null +++ b/Sluift/ElementConvertors/IQConvertor.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2014-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <Swiften/Elements/IQ.h> + +#include <Sluift/ElementConvertors/StanzaConvertor.h> + +namespace Swift { + class LuaElementConvertors; + + class IQConvertor : public StanzaConvertor<IQ> { + public: + IQConvertor(LuaElementConvertors* convertors); + virtual ~IQConvertor() override; + + virtual std::shared_ptr<IQ> doConvertFromLua(lua_State*) override; + virtual void doConvertToLua(lua_State*, std::shared_ptr<IQ>) override; + + virtual boost::optional<Documentation> getDocumentation() const override; + + static std::string convertIQTypeToString(IQ::Type type); + static IQ::Type convertIQTypeFromString(const std::string& type); + + private: + LuaElementConvertors* convertors; + }; +} + diff --git a/Sluift/ElementConvertors/IsodeIQDelegationConvertor.cpp b/Sluift/ElementConvertors/IsodeIQDelegationConvertor.cpp new file mode 100644 index 0000000..56b4a80 --- /dev/null +++ b/Sluift/ElementConvertors/IsodeIQDelegationConvertor.cpp @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2014-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Sluift/ElementConvertors/IsodeIQDelegationConvertor.h> + +#include <memory> + +#include <lua.hpp> + +#include <Sluift/LuaElementConvertors.h> + +using namespace Swift; + +IsodeIQDelegationConvertor::IsodeIQDelegationConvertor(LuaElementConvertors* convertors) : + GenericLuaElementConvertor<IsodeIQDelegation>("isode_iq_delegation"), + convertors(convertors) { +} + +IsodeIQDelegationConvertor::~IsodeIQDelegationConvertor() { +} + +std::shared_ptr<IsodeIQDelegation> IsodeIQDelegationConvertor::doConvertFromLua(lua_State* L) { + std::shared_ptr<IsodeIQDelegation> result = std::make_shared<IsodeIQDelegation>(); + lua_getfield(L, -1, "forward"); + if (!lua_isnil(L, -1)) { + if (std::shared_ptr<Forwarded> payload = std::dynamic_pointer_cast<Forwarded>(convertors->convertFromLuaUntyped(L, -1, "forwarded"))) { + result->setForward(payload); + } + } + lua_pop(L, 1); + return result; +} + +void IsodeIQDelegationConvertor::doConvertToLua(lua_State* L, std::shared_ptr<IsodeIQDelegation> payload) { + lua_createtable(L, 0, 0); + if (convertors->convertToLuaUntyped(L, payload->getForward()) > 0) { + lua_setfield(L, -2, "forward"); + } +} + +boost::optional<LuaElementConvertor::Documentation> IsodeIQDelegationConvertor::getDocumentation() const { + return Documentation( + "IsodeIQDelegation", + "This table has the following fields:\n\n" + "- `forward`: @{Forwarded}\n" + ); +} diff --git a/Sluift/ElementConvertors/IsodeIQDelegationConvertor.h b/Sluift/ElementConvertors/IsodeIQDelegationConvertor.h new file mode 100644 index 0000000..f573b13 --- /dev/null +++ b/Sluift/ElementConvertors/IsodeIQDelegationConvertor.h @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2014-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <Swiften/Elements/IsodeIQDelegation.h> + +#include <Sluift/GenericLuaElementConvertor.h> + +namespace Swift { + class LuaElementConvertors; + + class IsodeIQDelegationConvertor : public GenericLuaElementConvertor<IsodeIQDelegation> { + public: + IsodeIQDelegationConvertor(LuaElementConvertors* convertors); + virtual ~IsodeIQDelegationConvertor() override; + + virtual std::shared_ptr<IsodeIQDelegation> doConvertFromLua(lua_State*) override; + virtual void doConvertToLua(lua_State*, std::shared_ptr<IsodeIQDelegation>) override; + virtual boost::optional<Documentation> getDocumentation() const override; + + private: + LuaElementConvertors* convertors; + }; +} diff --git a/Sluift/ElementConvertors/MAMFinConvertor.cpp b/Sluift/ElementConvertors/MAMFinConvertor.cpp new file mode 100644 index 0000000..4fb8201 --- /dev/null +++ b/Sluift/ElementConvertors/MAMFinConvertor.cpp @@ -0,0 +1,81 @@ +/* + * Copyright (c) 2014-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Sluift/ElementConvertors/MAMFinConvertor.h> + +#include <memory> + +#include <boost/numeric/conversion/cast.hpp> + +#include <lua.hpp> + +#include <Swiften/Elements/ResultSet.h> + +#include <Sluift/LuaElementConvertors.h> + +using namespace Swift; + +MAMFinConvertor::MAMFinConvertor(LuaElementConvertors* convertors) : + GenericLuaElementConvertor<MAMFin>("mam_fin"), + convertors(convertors) { +} + +MAMFinConvertor::~MAMFinConvertor() { +} + +std::shared_ptr<MAMFin> MAMFinConvertor::doConvertFromLua(lua_State* L) { + std::shared_ptr<MAMFin> result = std::make_shared<MAMFin>(); + lua_getfield(L, -1, "query_id"); + if (lua_isstring(L, -1)) { + result->setQueryID(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "complete"); + if (lua_isboolean(L, -1)) { + result->setComplete(lua_toboolean(L, -1) != 0); + } + lua_pop(L, 1); + lua_getfield(L, -1, "stable"); + if (!lua_isnil(L, -1)) { + result->setStable(lua_toboolean(L, -1) != 0); + } + lua_pop(L, 1); + lua_getfield(L, -1, "result_set"); + if (!lua_isnil(L, -1)) { + std::shared_ptr<ResultSet> resultSet = std::dynamic_pointer_cast<ResultSet>(convertors->convertFromLuaUntyped(L, -1, "result_set")); + if (!!resultSet) { + result->setResultSet(resultSet); + } + } + lua_pop(L, 1); + return result; +} + +void MAMFinConvertor::doConvertToLua(lua_State* L, std::shared_ptr<MAMFin> payload) { + lua_createtable(L, 0, 0); + if (payload->getQueryID()) { + lua_pushstring(L, (*payload->getQueryID()).c_str()); + lua_setfield(L, -2, "query_id"); + } + lua_pushboolean(L, payload->isComplete()); + lua_setfield(L, -2, "complete"); + lua_pushboolean(L, payload->isStable()); + lua_setfield(L, -2, "stable"); + if (convertors->convertToLuaUntyped(L, payload->getResultSet()) > 0) { + lua_setfield(L, -2, "result_set"); + } +} + +boost::optional<LuaElementConvertor::Documentation> MAMFinConvertor::getDocumentation() const { + return Documentation( + "MAMFin", + "This table has the following fields:\n\n" + "- `query_id`: string (Optional)\n" + "- `complete`: boolean (Optional)\n" + "- `stable`: boolean (Optional)\n" + "- `result_set`: @{ResultSet} (Optional)\n" + ); +} diff --git a/Sluift/ElementConvertors/MAMFinConvertor.h b/Sluift/ElementConvertors/MAMFinConvertor.h new file mode 100644 index 0000000..6e5d58c --- /dev/null +++ b/Sluift/ElementConvertors/MAMFinConvertor.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2014-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <Swiften/Elements/MAMFin.h> + +#include <Sluift/GenericLuaElementConvertor.h> + +namespace Swift { + class LuaElementConvertors; + + class MAMFinConvertor : public GenericLuaElementConvertor<MAMFin> { + public: + MAMFinConvertor(LuaElementConvertors* convertors); + virtual ~MAMFinConvertor() override; + + virtual std::shared_ptr<MAMFin> doConvertFromLua(lua_State*) override; + virtual void doConvertToLua(lua_State*, std::shared_ptr<MAMFin>) override; + virtual boost::optional<Documentation> getDocumentation() const override; + + private: + LuaElementConvertors* convertors; + }; +} + diff --git a/Sluift/ElementConvertors/MAMQueryConvertor.cpp b/Sluift/ElementConvertors/MAMQueryConvertor.cpp new file mode 100644 index 0000000..52337ce --- /dev/null +++ b/Sluift/ElementConvertors/MAMQueryConvertor.cpp @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2014-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Sluift/ElementConvertors/MAMQueryConvertor.h> + +#include <memory> + +#include <boost/numeric/conversion/cast.hpp> + +#include <lua.hpp> + +#include <Swiften/Elements/Form.h> +#include <Swiften/Elements/ResultSet.h> + +#include <Sluift/LuaElementConvertors.h> + +using namespace Swift; + +MAMQueryConvertor::MAMQueryConvertor(LuaElementConvertors* convertors) : + GenericLuaElementConvertor<MAMQuery>("mam"), + convertors(convertors) { +} + +MAMQueryConvertor::~MAMQueryConvertor() { +} + +std::shared_ptr<MAMQuery> MAMQueryConvertor::doConvertFromLua(lua_State* L) { + std::shared_ptr<MAMQuery> result = std::make_shared<MAMQuery>(); + lua_getfield(L, -1, "query_id"); + if (lua_isstring(L, -1)) { + result->setQueryID(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "node"); + if (lua_isstring(L, -1)) { + result->setNode(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "form"); + if (!lua_isnil(L, -1)) { + std::shared_ptr<Form> form = std::dynamic_pointer_cast<Form>(convertors->convertFromLuaUntyped(L, -1, "form")); + if (!!form) { + result->setForm(form); + } + } + lua_pop(L, 1); + lua_getfield(L, -1, "result_set"); + if (!lua_isnil(L, -1)) { + std::shared_ptr<ResultSet> resultSet = std::dynamic_pointer_cast<ResultSet>(convertors->convertFromLuaUntyped(L, -1, "result_set")); + if (!!resultSet) { + result->setResultSet(resultSet); + } + } + lua_pop(L, 1); + return result; +} + +void MAMQueryConvertor::doConvertToLua(lua_State* L, std::shared_ptr<MAMQuery> payload) { + lua_createtable(L, 0, 0); + if (payload->getQueryID()) { + lua_pushstring(L, (*payload->getQueryID()).c_str()); + lua_setfield(L, -2, "query_id"); + } + if (payload->getNode()) { + lua_pushstring(L, (*payload->getNode()).c_str()); + lua_setfield(L, -2, "node"); + } + if (convertors->convertToLuaUntyped(L, payload->getForm()) > 0) { + lua_setfield(L, -2, "form"); + } + if (convertors->convertToLuaUntyped(L, payload->getResultSet()) > 0) { + lua_setfield(L, -2, "result_set"); + } +} + +boost::optional<LuaElementConvertor::Documentation> MAMQueryConvertor::getDocumentation() const { + return Documentation( + "MAMQuery", + "This table has the following fields:\n\n" + "- `query_id`: string (Optional)\n" + "- `node`: string (Optional)\n" + "- `form`: string @{Form} (Optional)\n" + "- `result_set`: @{ResultSet} (Optional)\n" + ); +} diff --git a/Sluift/ElementConvertors/MAMQueryConvertor.h b/Sluift/ElementConvertors/MAMQueryConvertor.h new file mode 100644 index 0000000..3e9d387 --- /dev/null +++ b/Sluift/ElementConvertors/MAMQueryConvertor.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2014-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <Swiften/Elements/MAMQuery.h> + +#include <Sluift/GenericLuaElementConvertor.h> + +namespace Swift { + class LuaElementConvertors; + + class MAMQueryConvertor : public GenericLuaElementConvertor<MAMQuery> { + public: + MAMQueryConvertor(LuaElementConvertors* convertors); + virtual ~MAMQueryConvertor() override; + + virtual std::shared_ptr<MAMQuery> doConvertFromLua(lua_State*) override; + virtual void doConvertToLua(lua_State*, std::shared_ptr<MAMQuery>) override; + virtual boost::optional<Documentation> getDocumentation() const override; + + private: + LuaElementConvertors* convertors; + }; +} + diff --git a/Sluift/ElementConvertors/MAMResultConvertor.cpp b/Sluift/ElementConvertors/MAMResultConvertor.cpp new file mode 100644 index 0000000..25b4c39 --- /dev/null +++ b/Sluift/ElementConvertors/MAMResultConvertor.cpp @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2014-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Sluift/ElementConvertors/MAMResultConvertor.h> + +#include <memory> + +#include <boost/numeric/conversion/cast.hpp> + +#include <lua.hpp> + +#include <Swiften/Elements/Forwarded.h> + +#include <Sluift/LuaElementConvertors.h> + +using namespace Swift; + +MAMResultConvertor::MAMResultConvertor(LuaElementConvertors* convertors) : + GenericLuaElementConvertor<MAMResult>("mam_result"), + convertors(convertors) { +} + +MAMResultConvertor::~MAMResultConvertor() { +} + +std::shared_ptr<MAMResult> MAMResultConvertor::doConvertFromLua(lua_State* L) { + std::shared_ptr<MAMResult> result = std::make_shared<MAMResult>(); + lua_getfield(L, -1, "payload"); + if (!lua_isnil(L, -1)) { + std::shared_ptr<Forwarded> payload = std::dynamic_pointer_cast<Forwarded>(convertors->convertFromLuaUntyped(L, -1, "payload")); + if (!!payload) { + result->setPayload(payload); + } + } + lua_pop(L, 1); + lua_getfield(L, -1, "id"); + if (lua_isstring(L, -1)) { + result->setID(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "query_id"); + if (lua_isstring(L, -1)) { + result->setQueryID(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + return result; +} + +void MAMResultConvertor::doConvertToLua(lua_State* L, std::shared_ptr<MAMResult> payload) { + lua_createtable(L, 0, 0); + if (convertors->convertToLuaUntyped(L, payload->getPayload()) > 0) { + lua_setfield(L, -2, "payload"); + } + lua_pushstring(L, payload->getID().c_str()); + lua_setfield(L, -2, "id"); + if (payload->getQueryID()) { + lua_pushstring(L, (*payload->getQueryID()).c_str()); + lua_setfield(L, -2, "query_id"); + } +} + +boost::optional<LuaElementConvertor::Documentation> MAMResultConvertor::getDocumentation() const { + return Documentation( + "MAMResult", + "This table has the following fields:\n\n" + "- `payload`: @{Forwarded}\n" + "- `id`: string\n" + "- `query_id`: string (Optional)\n" + ); +} diff --git a/Sluift/ElementConvertors/MAMResultConvertor.h b/Sluift/ElementConvertors/MAMResultConvertor.h new file mode 100644 index 0000000..cd1d27d --- /dev/null +++ b/Sluift/ElementConvertors/MAMResultConvertor.h @@ -0,0 +1,29 @@ +/* + * Copyright (c) 2014-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <Swiften/Elements/MAMResult.h> + +#include <Sluift/GenericLuaElementConvertor.h> + +namespace Swift { + class LuaElementConvertors; + + class MAMResultConvertor : public GenericLuaElementConvertor<MAMResult> { + public: + MAMResultConvertor(LuaElementConvertors* convertors); + virtual ~MAMResultConvertor() override; + + virtual std::shared_ptr<MAMResult> doConvertFromLua(lua_State*) override; + virtual void doConvertToLua(lua_State*, std::shared_ptr<MAMResult>) override; + virtual boost::optional<Documentation> getDocumentation() const override; + + private: + LuaElementConvertors* convertors; + }; +} + diff --git a/Sluift/ElementConvertors/MessageConvertor.cpp b/Sluift/ElementConvertors/MessageConvertor.cpp new file mode 100644 index 0000000..b7bf286 --- /dev/null +++ b/Sluift/ElementConvertors/MessageConvertor.cpp @@ -0,0 +1,85 @@ +/* + * Copyright (c) 2014-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Sluift/ElementConvertors/MessageConvertor.h> + +#include <memory> + +#include <lua.hpp> + +#include <Sluift/LuaElementConvertors.h> + +using namespace Swift; + +MessageConvertor::MessageConvertor(LuaElementConvertors* convertors) : + StanzaConvertor<Message>("message"), + convertors(convertors) { +} + +MessageConvertor::~MessageConvertor() { +} + +std::shared_ptr<Message> MessageConvertor::doConvertFromLua(lua_State* L) { + std::shared_ptr<Message> result = getStanza(L, convertors); + lua_getfield(L, -1, "type"); + if (lua_isstring(L, -1)) { + result->setType(convertMessageTypeFromString(lua_tostring(L, -1))); + } + lua_pop(L, 1); + return result; +} + +void MessageConvertor::doConvertToLua(lua_State* L, std::shared_ptr<Message> stanza) { + pushStanza(L, stanza, convertors); + const std::string type = convertMessageTypeToString(stanza->getType()); + lua_pushstring(L, type.c_str()); + lua_setfield(L, -2, "type"); +} + +boost::optional<LuaElementConvertor::Documentation> MessageConvertor::getDocumentation() const { + return Documentation( + "Message", + "This table has the following fields:\n\n" + "- `type`: string\n" + "- `id`: string\n" + "- `from`: string\n" + "- `to`: string\n" + "- `payloads`: array<@{Payload}>\n" + ); +} + +std::string MessageConvertor::convertMessageTypeToString(Message::Type type) { + switch (type) { + case Message::Normal: return "normal"; + case Message::Chat: return "chat"; + case Message::Error: return "error"; + case Message::Groupchat: return "groupchat"; + case Message::Headline: return "headline"; + } + assert(false); + return ""; +} + +Message::Type MessageConvertor::convertMessageTypeFromString(const std::string& type) { + if (type == "normal") { + return Message::Normal; + } + else if (type == "chat") { + return Message::Chat; + } + else if (type == "error") { + return Message::Error; + } + else if (type == "groupchat") { + return Message::Groupchat; + } + else if (type == "headline") { + return Message::Headline; + } + else { + throw Lua::Exception("Illegal message type: '" + type + "'"); + } +} diff --git a/Sluift/ElementConvertors/MessageConvertor.h b/Sluift/ElementConvertors/MessageConvertor.h new file mode 100644 index 0000000..723e1b1 --- /dev/null +++ b/Sluift/ElementConvertors/MessageConvertor.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2014-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <Swiften/Elements/Message.h> + +#include <Sluift/ElementConvertors/StanzaConvertor.h> + +namespace Swift { + class LuaElementConvertors; + + class MessageConvertor : public StanzaConvertor<Message> { + public: + MessageConvertor(LuaElementConvertors* convertors); + virtual ~MessageConvertor() override; + + virtual std::shared_ptr<Message> doConvertFromLua(lua_State*) override; + virtual void doConvertToLua(lua_State*, std::shared_ptr<Message>) override; + + virtual boost::optional<Documentation> getDocumentation() const override; + + static std::string convertMessageTypeToString(Message::Type type); + static Message::Type convertMessageTypeFromString(const std::string& type); + + private: + LuaElementConvertors* convertors; + }; +} + diff --git a/Sluift/ElementConvertors/PresenceConvertor.cpp b/Sluift/ElementConvertors/PresenceConvertor.cpp new file mode 100644 index 0000000..abfac77 --- /dev/null +++ b/Sluift/ElementConvertors/PresenceConvertor.cpp @@ -0,0 +1,97 @@ +/* + * Copyright (c) 2014-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Sluift/ElementConvertors/PresenceConvertor.h> + +#include <memory> + +#include <lua.hpp> + +#include <Sluift/LuaElementConvertors.h> + +using namespace Swift; + +PresenceConvertor::PresenceConvertor(LuaElementConvertors* convertors) : + StanzaConvertor<Presence>("presence"), + convertors(convertors) { +} + +PresenceConvertor::~PresenceConvertor() { +} + +std::shared_ptr<Presence> PresenceConvertor::doConvertFromLua(lua_State* L) { + std::shared_ptr<Presence> result = getStanza(L, convertors); + lua_getfield(L, -1, "type"); + if (lua_isstring(L, -1)) { + result->setType(convertPresenceTypeFromString(lua_tostring(L, -1))); + } + lua_pop(L, 1); + return result; +} + +void PresenceConvertor::doConvertToLua(lua_State* L, std::shared_ptr<Presence> stanza) { + pushStanza(L, stanza, convertors); + const std::string type = convertPresenceTypeToString(stanza->getType()); + lua_pushstring(L, type.c_str()); + lua_setfield(L, -2, "type"); +} + +boost::optional<LuaElementConvertor::Documentation> PresenceConvertor::getDocumentation() const { + return Documentation( + "Presence", + "This table has the following fields:\n\n" + "- `type`: string\n" + "- `id`: string\n" + "- `from`: string\n" + "- `to`: string\n" + "- `payloads`: array<@{Payload}>\n" + ); +} + +std::string PresenceConvertor::convertPresenceTypeToString(Presence::Type type) { + switch (type) { + case Presence::Available: return "available"; + case Presence::Error: return "error"; + case Presence::Probe: return "probe"; + case Presence::Subscribe: return "subscribe"; + case Presence::Subscribed: return "subscribed"; + case Presence::Unavailable: return "unavailable"; + case Presence::Unsubscribe: return "unsubscribe"; + case Presence::Unsubscribed: return "unsubscribed"; + } + assert(false); + return ""; +} + +Presence::Type PresenceConvertor::convertPresenceTypeFromString(const std::string& type) { + if (type == "available") { + return Presence::Available; + } + else if (type == "error") { + return Presence::Error; + } + else if (type == "probe") { + return Presence::Probe; + } + else if (type == "subscribe") { + return Presence::Subscribe; + } + else if (type == "subscribed") { + return Presence::Subscribed; + } + else if (type == "unavailable") { + return Presence::Unavailable; + } + else if (type == "unsubscribe") { + return Presence::Unsubscribe; + } + else if (type == "unsubscribed") { + return Presence::Unsubscribed; + } + else { + throw Lua::Exception("Illegal presence type: '" + type + "'"); + } +} diff --git a/Sluift/ElementConvertors/PresenceConvertor.h b/Sluift/ElementConvertors/PresenceConvertor.h new file mode 100644 index 0000000..b13398d --- /dev/null +++ b/Sluift/ElementConvertors/PresenceConvertor.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2014-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <Swiften/Elements/Presence.h> + +#include <Sluift/ElementConvertors/StanzaConvertor.h> + +namespace Swift { + class LuaElementConvertors; + + class PresenceConvertor : public StanzaConvertor<Presence> { + public: + PresenceConvertor(LuaElementConvertors* convertors); + virtual ~PresenceConvertor() override; + + virtual std::shared_ptr<Presence> doConvertFromLua(lua_State*) override; + virtual void doConvertToLua(lua_State*, std::shared_ptr<Presence>) override; + + virtual boost::optional<Documentation> getDocumentation() const override; + + static std::string convertPresenceTypeToString(Presence::Type type); + static Presence::Type convertPresenceTypeFromString(const std::string& type); + + private: + LuaElementConvertors* convertors; + }; +} + diff --git a/Sluift/ElementConvertors/PubSubAffiliationConvertor.cpp b/Sluift/ElementConvertors/PubSubAffiliationConvertor.cpp index 3d40be9..62a2b60 100644 --- a/Sluift/ElementConvertors/PubSubAffiliationConvertor.cpp +++ b/Sluift/ElementConvertors/PubSubAffiliationConvertor.cpp @@ -1,64 +1,88 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #include <Sluift/ElementConvertors/PubSubAffiliationConvertor.h> -#include <lua.hpp> -#include <boost/smart_ptr/make_shared.hpp> - - - +#include <memory> -#pragma clang diagnostic ignored "-Wunused-private-field" +#include <lua.hpp> using namespace Swift; -PubSubAffiliationConvertor::PubSubAffiliationConvertor(LuaElementConvertors* convertors) : - GenericLuaElementConvertor<PubSubAffiliation>("pubsub_affiliation"), - convertors(convertors) { +PubSubAffiliationConvertor::PubSubAffiliationConvertor() : + GenericLuaElementConvertor<PubSubAffiliation>("pubsub_affiliation") { } PubSubAffiliationConvertor::~PubSubAffiliationConvertor() { } -boost::shared_ptr<PubSubAffiliation> PubSubAffiliationConvertor::doConvertFromLua(lua_State* L) { - boost::shared_ptr<PubSubAffiliation> result = boost::make_shared<PubSubAffiliation>(); - lua_getfield(L, -1, "node"); - if (lua_isstring(L, -1)) { - result->setNode(std::string(lua_tostring(L, -1))); - } - lua_pop(L, 1); - lua_getfield(L, -1, "type"); - lua_pop(L, 1); - return result; +std::shared_ptr<PubSubAffiliation> PubSubAffiliationConvertor::doConvertFromLua(lua_State* L) { + std::shared_ptr<PubSubAffiliation> result = std::make_shared<PubSubAffiliation>(); + lua_getfield(L, -1, "node"); + if (lua_isstring(L, -1)) { + result->setNode(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "type"); + if (lua_isstring(L, -1)) { + if (std::string(lua_tostring(L, -1)) == "none") { + result->setType(PubSubAffiliation::None); + } + if (std::string(lua_tostring(L, -1)) == "member") { + result->setType(PubSubAffiliation::Member); + } + if (std::string(lua_tostring(L, -1)) == "outcast") { + result->setType(PubSubAffiliation::Outcast); + } + if (std::string(lua_tostring(L, -1)) == "owner") { + result->setType(PubSubAffiliation::Owner); + } + if (std::string(lua_tostring(L, -1)) == "publisher") { + result->setType(PubSubAffiliation::Publisher); + } + if (std::string(lua_tostring(L, -1)) == "publish_only") { + result->setType(PubSubAffiliation::PublishOnly); + } + } + lua_pop(L, 1); + return result; +} + +void PubSubAffiliationConvertor::doConvertToLua(lua_State* L, std::shared_ptr<PubSubAffiliation> payload) { + lua_createtable(L, 0, 0); + lua_pushstring(L, payload->getNode().c_str()); + lua_setfield(L, -2, "node"); + switch (payload->getType()) { + case PubSubAffiliation::None: + lua_pushstring(L, "none"); + break; + case PubSubAffiliation::Member: + lua_pushstring(L, "member"); + break; + case PubSubAffiliation::Outcast: + lua_pushstring(L, "outcast"); + break; + case PubSubAffiliation::Owner: + lua_pushstring(L, "owner"); + break; + case PubSubAffiliation::Publisher: + lua_pushstring(L, "publisher"); + break; + case PubSubAffiliation::PublishOnly: + lua_pushstring(L, "publish_only"); + break; + } + lua_setfield(L, -2, "type"); } -void PubSubAffiliationConvertor::doConvertToLua(lua_State* L, boost::shared_ptr<PubSubAffiliation> payload) { - lua_createtable(L, 0, 0); - lua_pushstring(L, payload->getNode().c_str()); - lua_setfield(L, -2, "node"); - switch (payload->getType()) { - case PubSubAffiliation::None: - lua_pushstring(L, "none"); - break; - case PubSubAffiliation::Member: - lua_pushstring(L, "member"); - break; - case PubSubAffiliation::Outcast: - lua_pushstring(L, "outcast"); - break; - case PubSubAffiliation::Owner: - lua_pushstring(L, "owner"); - break; - case PubSubAffiliation::Publisher: - lua_pushstring(L, "publisher"); - break; - case PubSubAffiliation::PublishOnly: - lua_pushstring(L, "publish_only"); - break; - } - lua_setfield(L, -2, "type"); +boost::optional<LuaElementConvertor::Documentation> PubSubAffiliationConvertor::getDocumentation() const { + return Documentation( + "PubSubAffiliation", + "This table has the following fields:\n\n" + "- `node`: string\n" + "- `type`: `\"none\"`, `\"member\"`, `\"outcast\"`, `\"owner\"`, `\"publisher\"`, or `\"publish_only\"`\n" + ); } diff --git a/Sluift/ElementConvertors/PubSubAffiliationConvertor.h b/Sluift/ElementConvertors/PubSubAffiliationConvertor.h index 632a8d7..1b5cd60 100644 --- a/Sluift/ElementConvertors/PubSubAffiliationConvertor.h +++ b/Sluift/ElementConvertors/PubSubAffiliationConvertor.h @@ -1,28 +1,25 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <Swiften/Elements/PubSubAffiliation.h> #include <Sluift/GenericLuaElementConvertor.h> -#include <Swiften/Elements/PubSubAffiliation.h> namespace Swift { - class LuaElementConvertors; - - class PubSubAffiliationConvertor : public GenericLuaElementConvertor<PubSubAffiliation> { - public: - PubSubAffiliationConvertor(LuaElementConvertors* convertors); - virtual ~PubSubAffiliationConvertor(); + class LuaElementConvertors; - virtual boost::shared_ptr<PubSubAffiliation> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE; - virtual void doConvertToLua(lua_State*, boost::shared_ptr<PubSubAffiliation>) SWIFTEN_OVERRIDE; + class PubSubAffiliationConvertor : public GenericLuaElementConvertor<PubSubAffiliation> { + public: + PubSubAffiliationConvertor(); + virtual ~PubSubAffiliationConvertor() override; - private: - LuaElementConvertors* convertors; - }; + virtual std::shared_ptr<PubSubAffiliation> doConvertFromLua(lua_State*) override; + virtual void doConvertToLua(lua_State*, std::shared_ptr<PubSubAffiliation>) override; + virtual boost::optional<Documentation> getDocumentation() const override; + }; } diff --git a/Sluift/ElementConvertors/PubSubAffiliationsConvertor.cpp b/Sluift/ElementConvertors/PubSubAffiliationsConvertor.cpp index 9f34235..8f8a660 100644 --- a/Sluift/ElementConvertors/PubSubAffiliationsConvertor.cpp +++ b/Sluift/ElementConvertors/PubSubAffiliationsConvertor.cpp @@ -1,70 +1,78 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #include <Sluift/ElementConvertors/PubSubAffiliationsConvertor.h> -#include <lua.hpp> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> + #include <boost/numeric/conversion/cast.hpp> -#include <Sluift/LuaElementConvertors.h> -#include <Swiften/Base/foreach.h> +#include <lua.hpp> -#pragma clang diagnostic ignored "-Wunused-private-field" +#include <Sluift/LuaElementConvertors.h> using namespace Swift; -PubSubAffiliationsConvertor::PubSubAffiliationsConvertor(LuaElementConvertors* convertors) : - GenericLuaElementConvertor<PubSubAffiliations>("pubsub_affiliations"), - convertors(convertors) { +PubSubAffiliationsConvertor::PubSubAffiliationsConvertor(LuaElementConvertors* convertors) : + GenericLuaElementConvertor<PubSubAffiliations>("pubsub_affiliations"), + convertors(convertors) { } PubSubAffiliationsConvertor::~PubSubAffiliationsConvertor() { } -boost::shared_ptr<PubSubAffiliations> PubSubAffiliationsConvertor::doConvertFromLua(lua_State* L) { - boost::shared_ptr<PubSubAffiliations> result = boost::make_shared<PubSubAffiliations>(); - lua_getfield(L, -1, "node"); - if (lua_isstring(L, -1)) { - result->setNode(std::string(lua_tostring(L, -1))); - } - lua_pop(L, 1); - if (lua_type(L, -1) == LUA_TTABLE) { - std::vector< boost::shared_ptr<PubSubAffiliation> > items; - for(size_t i = 0; i < lua_objlen(L, -1); ++i) { - lua_pushnumber(L, i + 1); - lua_gettable(L, -2); - if (!lua_isnil(L, -1)) { - if (boost::shared_ptr<PubSubAffiliation> payload = boost::dynamic_pointer_cast<PubSubAffiliation>(convertors->convertFromLuaUntyped(L, -1, "pubsub_affiliation"))) { - items.push_back(payload); - } - } - lua_pop(L, 1); - } +std::shared_ptr<PubSubAffiliations> PubSubAffiliationsConvertor::doConvertFromLua(lua_State* L) { + std::shared_ptr<PubSubAffiliations> result = std::make_shared<PubSubAffiliations>(); + lua_getfield(L, -1, "node"); + if (lua_isstring(L, -1)) { + result->setNode(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + if (lua_type(L, -1) == LUA_TTABLE) { + std::vector< std::shared_ptr<PubSubAffiliation> > items; + for(size_t i = 0; i < lua_rawlen(L, -1); ++i) { + lua_pushnumber(L, i + 1); + lua_gettable(L, -2); + if (!lua_isnil(L, -1)) { + if (std::shared_ptr<PubSubAffiliation> payload = std::dynamic_pointer_cast<PubSubAffiliation>(convertors->convertFromLuaUntyped(L, -1, "pubsub_affiliation"))) { + items.push_back(payload); + } + } + lua_pop(L, 1); + } + + result->setAffiliations(items); + } + return result; +} - result->setAffiliations(items); - } - return result; +void PubSubAffiliationsConvertor::doConvertToLua(lua_State* L, std::shared_ptr<PubSubAffiliations> payload) { + lua_createtable(L, 0, 0); + if (payload->getNode()) { + lua_pushstring(L, (*payload->getNode()).c_str()); + lua_setfield(L, -2, "node"); + } + if (!payload->getAffiliations().empty()) { + { + int i = 0; + for (auto&& item : payload->getAffiliations()) { + if (convertors->convertToLuaUntyped(L, item) > 0) { + lua_rawseti(L, -2, boost::numeric_cast<int>(i+1)); + ++i; + } + } + } + } } -void PubSubAffiliationsConvertor::doConvertToLua(lua_State* L, boost::shared_ptr<PubSubAffiliations> payload) { - lua_createtable(L, 0, 0); - if (payload->getNode()) { - lua_pushstring(L, (*payload->getNode()).c_str()); - lua_setfield(L, -2, "node"); - } - if (!payload->getAffiliations().empty()) { - { - int i = 0; - foreach(boost::shared_ptr<PubSubAffiliation> item, payload->getAffiliations()) { - if (convertors->convertToLuaUntyped(L, item) > 0) { - lua_rawseti(L, -2, boost::numeric_cast<int>(i+1)); - ++i; - } - } - } - } +boost::optional<LuaElementConvertor::Documentation> PubSubAffiliationsConvertor::getDocumentation() const { + return Documentation( + "PubSubAffiliations", + "This table has the following fields:\n\n" + "- `node`: string (Optional)\n" + "- `affiliations`: array<@{PubSubAffiliation}>\n" + ); } diff --git a/Sluift/ElementConvertors/PubSubAffiliationsConvertor.h b/Sluift/ElementConvertors/PubSubAffiliationsConvertor.h index fb0279a..eda218b 100644 --- a/Sluift/ElementConvertors/PubSubAffiliationsConvertor.h +++ b/Sluift/ElementConvertors/PubSubAffiliationsConvertor.h @@ -1,28 +1,28 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <Swiften/Elements/PubSubAffiliations.h> #include <Sluift/GenericLuaElementConvertor.h> -#include <Swiften/Elements/PubSubAffiliations.h> namespace Swift { - class LuaElementConvertors; + class LuaElementConvertors; - class PubSubAffiliationsConvertor : public GenericLuaElementConvertor<PubSubAffiliations> { - public: - PubSubAffiliationsConvertor(LuaElementConvertors* convertors); - virtual ~PubSubAffiliationsConvertor(); + class PubSubAffiliationsConvertor : public GenericLuaElementConvertor<PubSubAffiliations> { + public: + PubSubAffiliationsConvertor(LuaElementConvertors* convertors); + virtual ~PubSubAffiliationsConvertor() override; - virtual boost::shared_ptr<PubSubAffiliations> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE; - virtual void doConvertToLua(lua_State*, boost::shared_ptr<PubSubAffiliations>) SWIFTEN_OVERRIDE; + virtual std::shared_ptr<PubSubAffiliations> doConvertFromLua(lua_State*) override; + virtual void doConvertToLua(lua_State*, std::shared_ptr<PubSubAffiliations>) override; + virtual boost::optional<Documentation> getDocumentation() const override; - private: - LuaElementConvertors* convertors; - }; + private: + LuaElementConvertors* convertors; + }; } diff --git a/Sluift/ElementConvertors/PubSubConfigureConvertor.cpp b/Sluift/ElementConvertors/PubSubConfigureConvertor.cpp index 893bc27..d8bf05d 100644 --- a/Sluift/ElementConvertors/PubSubConfigureConvertor.cpp +++ b/Sluift/ElementConvertors/PubSubConfigureConvertor.cpp @@ -1,44 +1,50 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #include <Sluift/ElementConvertors/PubSubConfigureConvertor.h> -#include <lua.hpp> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> +#include <lua.hpp> #include <Sluift/LuaElementConvertors.h> -#pragma clang diagnostic ignored "-Wunused-private-field" - using namespace Swift; -PubSubConfigureConvertor::PubSubConfigureConvertor(LuaElementConvertors* convertors) : - GenericLuaElementConvertor<PubSubConfigure>("pubsub_configure"), - convertors(convertors) { +PubSubConfigureConvertor::PubSubConfigureConvertor(LuaElementConvertors* convertors) : + GenericLuaElementConvertor<PubSubConfigure>("pubsub_configure"), + convertors(convertors) { } PubSubConfigureConvertor::~PubSubConfigureConvertor() { } -boost::shared_ptr<PubSubConfigure> PubSubConfigureConvertor::doConvertFromLua(lua_State* L) { - boost::shared_ptr<PubSubConfigure> result = boost::make_shared<PubSubConfigure>(); - lua_getfield(L, -1, "data"); - if (!lua_isnil(L, -1)) { - if (boost::shared_ptr<Form> payload = boost::dynamic_pointer_cast<Form>(convertors->convertFromLuaUntyped(L, -1, "form"))) { - result->setData(payload); - } - } - lua_pop(L, 1); - return result; +std::shared_ptr<PubSubConfigure> PubSubConfigureConvertor::doConvertFromLua(lua_State* L) { + std::shared_ptr<PubSubConfigure> result = std::make_shared<PubSubConfigure>(); + lua_getfield(L, -1, "data"); + if (!lua_isnil(L, -1)) { + if (std::shared_ptr<Form> payload = std::dynamic_pointer_cast<Form>(convertors->convertFromLuaUntyped(L, -1, "form"))) { + result->setData(payload); + } + } + lua_pop(L, 1); + return result; +} + +void PubSubConfigureConvertor::doConvertToLua(lua_State* L, std::shared_ptr<PubSubConfigure> payload) { + lua_createtable(L, 0, 0); + if (convertors->convertToLuaUntyped(L, payload->getData()) > 0) { + lua_setfield(L, -2, "data"); + } } -void PubSubConfigureConvertor::doConvertToLua(lua_State* L, boost::shared_ptr<PubSubConfigure> payload) { - lua_createtable(L, 0, 0); - if (convertors->convertToLuaUntyped(L, payload->getData()) > 0) { - lua_setfield(L, -2, "data"); - } +boost::optional<LuaElementConvertor::Documentation> PubSubConfigureConvertor::getDocumentation() const { + return Documentation( + "PubSubConfigure", + "This table has the following fields:\n\n" + "- `data`: @{Form}\n" + ); } diff --git a/Sluift/ElementConvertors/PubSubConfigureConvertor.h b/Sluift/ElementConvertors/PubSubConfigureConvertor.h index 0dd9094..f1848c2 100644 --- a/Sluift/ElementConvertors/PubSubConfigureConvertor.h +++ b/Sluift/ElementConvertors/PubSubConfigureConvertor.h @@ -1,28 +1,28 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <Swiften/Elements/PubSubConfigure.h> #include <Sluift/GenericLuaElementConvertor.h> -#include <Swiften/Elements/PubSubConfigure.h> namespace Swift { - class LuaElementConvertors; + class LuaElementConvertors; - class PubSubConfigureConvertor : public GenericLuaElementConvertor<PubSubConfigure> { - public: - PubSubConfigureConvertor(LuaElementConvertors* convertors); - virtual ~PubSubConfigureConvertor(); + class PubSubConfigureConvertor : public GenericLuaElementConvertor<PubSubConfigure> { + public: + PubSubConfigureConvertor(LuaElementConvertors* convertors); + virtual ~PubSubConfigureConvertor() override; - virtual boost::shared_ptr<PubSubConfigure> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE; - virtual void doConvertToLua(lua_State*, boost::shared_ptr<PubSubConfigure>) SWIFTEN_OVERRIDE; + virtual std::shared_ptr<PubSubConfigure> doConvertFromLua(lua_State*) override; + virtual void doConvertToLua(lua_State*, std::shared_ptr<PubSubConfigure>) override; + virtual boost::optional<Documentation> getDocumentation() const override; - private: - LuaElementConvertors* convertors; - }; + private: + LuaElementConvertors* convertors; + }; } diff --git a/Sluift/ElementConvertors/PubSubCreateConvertor.cpp b/Sluift/ElementConvertors/PubSubCreateConvertor.cpp index 64e2ee3..80553d5 100644 --- a/Sluift/ElementConvertors/PubSubCreateConvertor.cpp +++ b/Sluift/ElementConvertors/PubSubCreateConvertor.cpp @@ -1,51 +1,58 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #include <Sluift/ElementConvertors/PubSubCreateConvertor.h> -#include <lua.hpp> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> +#include <lua.hpp> #include <Sluift/LuaElementConvertors.h> -#pragma clang diagnostic ignored "-Wunused-private-field" - using namespace Swift; -PubSubCreateConvertor::PubSubCreateConvertor(LuaElementConvertors* convertors) : - GenericLuaElementConvertor<PubSubCreate>("pubsub_create"), - convertors(convertors) { +PubSubCreateConvertor::PubSubCreateConvertor(LuaElementConvertors* convertors) : + GenericLuaElementConvertor<PubSubCreate>("pubsub_create"), + convertors(convertors) { } PubSubCreateConvertor::~PubSubCreateConvertor() { } -boost::shared_ptr<PubSubCreate> PubSubCreateConvertor::doConvertFromLua(lua_State* L) { - boost::shared_ptr<PubSubCreate> result = boost::make_shared<PubSubCreate>(); - lua_getfield(L, -1, "node"); - if (lua_isstring(L, -1)) { - result->setNode(std::string(lua_tostring(L, -1))); - } - lua_pop(L, 1); - lua_getfield(L, -1, "configure"); - if (!lua_isnil(L, -1)) { - if (boost::shared_ptr<PubSubConfigure> payload = boost::dynamic_pointer_cast<PubSubConfigure>(convertors->convertFromLuaUntyped(L, -1, "pubsub_configure"))) { - result->setConfigure(payload); - } - } - lua_pop(L, 1); - return result; +std::shared_ptr<PubSubCreate> PubSubCreateConvertor::doConvertFromLua(lua_State* L) { + std::shared_ptr<PubSubCreate> result = std::make_shared<PubSubCreate>(); + lua_getfield(L, -1, "node"); + if (lua_isstring(L, -1)) { + result->setNode(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "configure"); + if (!lua_isnil(L, -1)) { + if (std::shared_ptr<PubSubConfigure> payload = std::dynamic_pointer_cast<PubSubConfigure>(convertors->convertFromLuaUntyped(L, -1, "pubsub_configure"))) { + result->setConfigure(payload); + } + } + lua_pop(L, 1); + return result; +} + +void PubSubCreateConvertor::doConvertToLua(lua_State* L, std::shared_ptr<PubSubCreate> payload) { + lua_createtable(L, 0, 0); + lua_pushstring(L, payload->getNode().c_str()); + lua_setfield(L, -2, "node"); + if (convertors->convertToLuaUntyped(L, payload->getConfigure()) > 0) { + lua_setfield(L, -2, "configure"); + } } -void PubSubCreateConvertor::doConvertToLua(lua_State* L, boost::shared_ptr<PubSubCreate> payload) { - lua_createtable(L, 0, 0); - lua_pushstring(L, payload->getNode().c_str()); - lua_setfield(L, -2, "node"); - if (convertors->convertToLuaUntyped(L, payload->getConfigure()) > 0) { - lua_setfield(L, -2, "configure"); - } +boost::optional<LuaElementConvertor::Documentation> PubSubCreateConvertor::getDocumentation() const { + return Documentation( + "PubSubCreate", + "This table has the following fields:\n\n" + "- `node`: string\n" + "- `configure`: @{PubSubConfigure}\n" + ); } diff --git a/Sluift/ElementConvertors/PubSubCreateConvertor.h b/Sluift/ElementConvertors/PubSubCreateConvertor.h index 2cb1ea6..f3b11bd 100644 --- a/Sluift/ElementConvertors/PubSubCreateConvertor.h +++ b/Sluift/ElementConvertors/PubSubCreateConvertor.h @@ -1,28 +1,28 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <Swiften/Elements/PubSubCreate.h> #include <Sluift/GenericLuaElementConvertor.h> -#include <Swiften/Elements/PubSubCreate.h> namespace Swift { - class LuaElementConvertors; + class LuaElementConvertors; - class PubSubCreateConvertor : public GenericLuaElementConvertor<PubSubCreate> { - public: - PubSubCreateConvertor(LuaElementConvertors* convertors); - virtual ~PubSubCreateConvertor(); + class PubSubCreateConvertor : public GenericLuaElementConvertor<PubSubCreate> { + public: + PubSubCreateConvertor(LuaElementConvertors* convertors); + virtual ~PubSubCreateConvertor() override; - virtual boost::shared_ptr<PubSubCreate> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE; - virtual void doConvertToLua(lua_State*, boost::shared_ptr<PubSubCreate>) SWIFTEN_OVERRIDE; + virtual std::shared_ptr<PubSubCreate> doConvertFromLua(lua_State*) override; + virtual void doConvertToLua(lua_State*, std::shared_ptr<PubSubCreate>) override; + virtual boost::optional<Documentation> getDocumentation() const override; - private: - LuaElementConvertors* convertors; - }; + private: + LuaElementConvertors* convertors; + }; } diff --git a/Sluift/ElementConvertors/PubSubDefaultConvertor.cpp b/Sluift/ElementConvertors/PubSubDefaultConvertor.cpp index 89609ed..8406913 100644 --- a/Sluift/ElementConvertors/PubSubDefaultConvertor.cpp +++ b/Sluift/ElementConvertors/PubSubDefaultConvertor.cpp @@ -1,57 +1,72 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #include <Sluift/ElementConvertors/PubSubDefaultConvertor.h> -#include <lua.hpp> -#include <boost/smart_ptr/make_shared.hpp> - - - +#include <memory> -#pragma clang diagnostic ignored "-Wunused-private-field" +#include <lua.hpp> using namespace Swift; -PubSubDefaultConvertor::PubSubDefaultConvertor(LuaElementConvertors* convertors) : - GenericLuaElementConvertor<PubSubDefault>("pubsub_default"), - convertors(convertors) { +PubSubDefaultConvertor::PubSubDefaultConvertor() : + GenericLuaElementConvertor<PubSubDefault>("pubsub_default") { } PubSubDefaultConvertor::~PubSubDefaultConvertor() { } -boost::shared_ptr<PubSubDefault> PubSubDefaultConvertor::doConvertFromLua(lua_State* L) { - boost::shared_ptr<PubSubDefault> result = boost::make_shared<PubSubDefault>(); - lua_getfield(L, -1, "node"); - if (lua_isstring(L, -1)) { - result->setNode(std::string(lua_tostring(L, -1))); - } - lua_pop(L, 1); - lua_getfield(L, -1, "type"); - lua_pop(L, 1); - return result; +std::shared_ptr<PubSubDefault> PubSubDefaultConvertor::doConvertFromLua(lua_State* L) { + std::shared_ptr<PubSubDefault> result = std::make_shared<PubSubDefault>(); + lua_getfield(L, -1, "node"); + if (lua_isstring(L, -1)) { + result->setNode(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "type"); + if (lua_isstring(L, -1)) { + if (std::string(lua_tostring(L, -1)) == "none") { + result->setType(PubSubDefault::None); + } + if (std::string(lua_tostring(L, -1)) == "collection") { + result->setType(PubSubDefault::Collection); + } + if (std::string(lua_tostring(L, -1)) == "leaf") { + result->setType(PubSubDefault::Leaf); + } + } + lua_pop(L, 1); + return result; +} + +void PubSubDefaultConvertor::doConvertToLua(lua_State* L, std::shared_ptr<PubSubDefault> payload) { + lua_createtable(L, 0, 0); + if (payload->getNode()) { + lua_pushstring(L, (*payload->getNode()).c_str()); + lua_setfield(L, -2, "node"); + } + switch (payload->getType()) { + case PubSubDefault::None: + lua_pushstring(L, "none"); + break; + case PubSubDefault::Collection: + lua_pushstring(L, "collection"); + break; + case PubSubDefault::Leaf: + lua_pushstring(L, "leaf"); + break; + } + lua_setfield(L, -2, "type"); } -void PubSubDefaultConvertor::doConvertToLua(lua_State* L, boost::shared_ptr<PubSubDefault> payload) { - lua_createtable(L, 0, 0); - if (payload->getNode()) { - lua_pushstring(L, (*payload->getNode()).c_str()); - lua_setfield(L, -2, "node"); - } - switch (payload->getType()) { - case PubSubDefault::None: - lua_pushstring(L, "none"); - break; - case PubSubDefault::Collection: - lua_pushstring(L, "collection"); - break; - case PubSubDefault::Leaf: - lua_pushstring(L, "leaf"); - break; - } - lua_setfield(L, -2, "type"); +boost::optional<LuaElementConvertor::Documentation> PubSubDefaultConvertor::getDocumentation() const { + return Documentation( + "PubSubDefault", + "This table has the following fields:\n\n" + "- `node`: string (Optional)\n" + "- `type`: `\"none\"`, `\"collection\"`, or `\"leaf\"`\n" + ); } diff --git a/Sluift/ElementConvertors/PubSubDefaultConvertor.h b/Sluift/ElementConvertors/PubSubDefaultConvertor.h index 89dd9be..1049cd4 100644 --- a/Sluift/ElementConvertors/PubSubDefaultConvertor.h +++ b/Sluift/ElementConvertors/PubSubDefaultConvertor.h @@ -1,28 +1,25 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <Swiften/Elements/PubSubDefault.h> #include <Sluift/GenericLuaElementConvertor.h> -#include <Swiften/Elements/PubSubDefault.h> namespace Swift { - class LuaElementConvertors; - - class PubSubDefaultConvertor : public GenericLuaElementConvertor<PubSubDefault> { - public: - PubSubDefaultConvertor(LuaElementConvertors* convertors); - virtual ~PubSubDefaultConvertor(); + class LuaElementConvertors; - virtual boost::shared_ptr<PubSubDefault> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE; - virtual void doConvertToLua(lua_State*, boost::shared_ptr<PubSubDefault>) SWIFTEN_OVERRIDE; + class PubSubDefaultConvertor : public GenericLuaElementConvertor<PubSubDefault> { + public: + PubSubDefaultConvertor(); + virtual ~PubSubDefaultConvertor() override; - private: - LuaElementConvertors* convertors; - }; + virtual std::shared_ptr<PubSubDefault> doConvertFromLua(lua_State*) override; + virtual void doConvertToLua(lua_State*, std::shared_ptr<PubSubDefault>) override; + virtual boost::optional<Documentation> getDocumentation() const override; + }; } diff --git a/Sluift/ElementConvertors/PubSubEventAssociateConvertor.cpp b/Sluift/ElementConvertors/PubSubEventAssociateConvertor.cpp index 2b004c8..eb025a5 100644 --- a/Sluift/ElementConvertors/PubSubEventAssociateConvertor.cpp +++ b/Sluift/ElementConvertors/PubSubEventAssociateConvertor.cpp @@ -1,41 +1,44 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #include <Sluift/ElementConvertors/PubSubEventAssociateConvertor.h> -#include <lua.hpp> -#include <boost/smart_ptr/make_shared.hpp> - - - +#include <memory> -#pragma clang diagnostic ignored "-Wunused-private-field" +#include <lua.hpp> using namespace Swift; -PubSubEventAssociateConvertor::PubSubEventAssociateConvertor(LuaElementConvertors* convertors) : - GenericLuaElementConvertor<PubSubEventAssociate>("pubsub_event_associate"), - convertors(convertors) { +PubSubEventAssociateConvertor::PubSubEventAssociateConvertor() : + GenericLuaElementConvertor<PubSubEventAssociate>("pubsub_event_associate") { } PubSubEventAssociateConvertor::~PubSubEventAssociateConvertor() { } -boost::shared_ptr<PubSubEventAssociate> PubSubEventAssociateConvertor::doConvertFromLua(lua_State* L) { - boost::shared_ptr<PubSubEventAssociate> result = boost::make_shared<PubSubEventAssociate>(); - lua_getfield(L, -1, "node"); - if (lua_isstring(L, -1)) { - result->setNode(std::string(lua_tostring(L, -1))); - } - lua_pop(L, 1); - return result; +std::shared_ptr<PubSubEventAssociate> PubSubEventAssociateConvertor::doConvertFromLua(lua_State* L) { + std::shared_ptr<PubSubEventAssociate> result = std::make_shared<PubSubEventAssociate>(); + lua_getfield(L, -1, "node"); + if (lua_isstring(L, -1)) { + result->setNode(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + return result; +} + +void PubSubEventAssociateConvertor::doConvertToLua(lua_State* L, std::shared_ptr<PubSubEventAssociate> payload) { + lua_createtable(L, 0, 0); + lua_pushstring(L, payload->getNode().c_str()); + lua_setfield(L, -2, "node"); } -void PubSubEventAssociateConvertor::doConvertToLua(lua_State* L, boost::shared_ptr<PubSubEventAssociate> payload) { - lua_createtable(L, 0, 0); - lua_pushstring(L, payload->getNode().c_str()); - lua_setfield(L, -2, "node"); +boost::optional<LuaElementConvertor::Documentation> PubSubEventAssociateConvertor::getDocumentation() const { + return Documentation( + "PubSubEventAssociate", + "This table has the following fields:\n\n" + "- `node`: string\n" + ); } diff --git a/Sluift/ElementConvertors/PubSubEventAssociateConvertor.h b/Sluift/ElementConvertors/PubSubEventAssociateConvertor.h index 60c9d28..e84460f 100644 --- a/Sluift/ElementConvertors/PubSubEventAssociateConvertor.h +++ b/Sluift/ElementConvertors/PubSubEventAssociateConvertor.h @@ -1,28 +1,25 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <Swiften/Elements/PubSubEventAssociate.h> #include <Sluift/GenericLuaElementConvertor.h> -#include <Swiften/Elements/PubSubEventAssociate.h> namespace Swift { - class LuaElementConvertors; - - class PubSubEventAssociateConvertor : public GenericLuaElementConvertor<PubSubEventAssociate> { - public: - PubSubEventAssociateConvertor(LuaElementConvertors* convertors); - virtual ~PubSubEventAssociateConvertor(); + class LuaElementConvertors; - virtual boost::shared_ptr<PubSubEventAssociate> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE; - virtual void doConvertToLua(lua_State*, boost::shared_ptr<PubSubEventAssociate>) SWIFTEN_OVERRIDE; + class PubSubEventAssociateConvertor : public GenericLuaElementConvertor<PubSubEventAssociate> { + public: + PubSubEventAssociateConvertor(); + virtual ~PubSubEventAssociateConvertor() override; - private: - LuaElementConvertors* convertors; - }; + virtual std::shared_ptr<PubSubEventAssociate> doConvertFromLua(lua_State*) override; + virtual void doConvertToLua(lua_State*, std::shared_ptr<PubSubEventAssociate>) override; + virtual boost::optional<Documentation> getDocumentation() const override; + }; } diff --git a/Sluift/ElementConvertors/PubSubEventCollectionConvertor.cpp b/Sluift/ElementConvertors/PubSubEventCollectionConvertor.cpp index d05b479..721b1b4 100644 --- a/Sluift/ElementConvertors/PubSubEventCollectionConvertor.cpp +++ b/Sluift/ElementConvertors/PubSubEventCollectionConvertor.cpp @@ -1,63 +1,71 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #include <Sluift/ElementConvertors/PubSubEventCollectionConvertor.h> -#include <lua.hpp> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> +#include <lua.hpp> #include <Sluift/LuaElementConvertors.h> -#pragma clang diagnostic ignored "-Wunused-private-field" - using namespace Swift; -PubSubEventCollectionConvertor::PubSubEventCollectionConvertor(LuaElementConvertors* convertors) : - GenericLuaElementConvertor<PubSubEventCollection>("pubsub_event_collection"), - convertors(convertors) { +PubSubEventCollectionConvertor::PubSubEventCollectionConvertor(LuaElementConvertors* convertors) : + GenericLuaElementConvertor<PubSubEventCollection>("pubsub_event_collection"), + convertors(convertors) { } PubSubEventCollectionConvertor::~PubSubEventCollectionConvertor() { } -boost::shared_ptr<PubSubEventCollection> PubSubEventCollectionConvertor::doConvertFromLua(lua_State* L) { - boost::shared_ptr<PubSubEventCollection> result = boost::make_shared<PubSubEventCollection>(); - lua_getfield(L, -1, "node"); - if (lua_isstring(L, -1)) { - result->setNode(std::string(lua_tostring(L, -1))); - } - lua_pop(L, 1); - lua_getfield(L, -1, "disassociate"); - if (!lua_isnil(L, -1)) { - if (boost::shared_ptr<PubSubEventDisassociate> payload = boost::dynamic_pointer_cast<PubSubEventDisassociate>(convertors->convertFromLuaUntyped(L, -1, "pubsub_event_disassociate"))) { - result->setDisassociate(payload); - } - } - lua_pop(L, 1); - lua_getfield(L, -1, "associate"); - if (!lua_isnil(L, -1)) { - if (boost::shared_ptr<PubSubEventAssociate> payload = boost::dynamic_pointer_cast<PubSubEventAssociate>(convertors->convertFromLuaUntyped(L, -1, "pubsub_event_associate"))) { - result->setAssociate(payload); - } - } - lua_pop(L, 1); - return result; +std::shared_ptr<PubSubEventCollection> PubSubEventCollectionConvertor::doConvertFromLua(lua_State* L) { + std::shared_ptr<PubSubEventCollection> result = std::make_shared<PubSubEventCollection>(); + lua_getfield(L, -1, "node"); + if (lua_isstring(L, -1)) { + result->setNode(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "disassociate"); + if (!lua_isnil(L, -1)) { + if (std::shared_ptr<PubSubEventDisassociate> payload = std::dynamic_pointer_cast<PubSubEventDisassociate>(convertors->convertFromLuaUntyped(L, -1, "pubsub_event_disassociate"))) { + result->setDisassociate(payload); + } + } + lua_pop(L, 1); + lua_getfield(L, -1, "associate"); + if (!lua_isnil(L, -1)) { + if (std::shared_ptr<PubSubEventAssociate> payload = std::dynamic_pointer_cast<PubSubEventAssociate>(convertors->convertFromLuaUntyped(L, -1, "pubsub_event_associate"))) { + result->setAssociate(payload); + } + } + lua_pop(L, 1); + return result; +} + +void PubSubEventCollectionConvertor::doConvertToLua(lua_State* L, std::shared_ptr<PubSubEventCollection> payload) { + lua_createtable(L, 0, 0); + if (payload->getNode()) { + lua_pushstring(L, (*payload->getNode()).c_str()); + lua_setfield(L, -2, "node"); + } + if (convertors->convertToLuaUntyped(L, payload->getDisassociate()) > 0) { + lua_setfield(L, -2, "disassociate"); + } + if (convertors->convertToLuaUntyped(L, payload->getAssociate()) > 0) { + lua_setfield(L, -2, "associate"); + } } -void PubSubEventCollectionConvertor::doConvertToLua(lua_State* L, boost::shared_ptr<PubSubEventCollection> payload) { - lua_createtable(L, 0, 0); - if (payload->getNode()) { - lua_pushstring(L, (*payload->getNode()).c_str()); - lua_setfield(L, -2, "node"); - } - if (convertors->convertToLuaUntyped(L, payload->getDisassociate()) > 0) { - lua_setfield(L, -2, "disassociate"); - } - if (convertors->convertToLuaUntyped(L, payload->getAssociate()) > 0) { - lua_setfield(L, -2, "associate"); - } +boost::optional<LuaElementConvertor::Documentation> PubSubEventCollectionConvertor::getDocumentation() const { + return Documentation( + "PubSubEventCollection", + "This table has the following fields:\n\n" + "- `node`: string (Optional)\n" + "- `disassociate`: @{PubSubEventDisassociate}\n" + "- `associate`: @{PubSubEventAssociate}\n" + ); } diff --git a/Sluift/ElementConvertors/PubSubEventCollectionConvertor.h b/Sluift/ElementConvertors/PubSubEventCollectionConvertor.h index eed2541..cab3b97 100644 --- a/Sluift/ElementConvertors/PubSubEventCollectionConvertor.h +++ b/Sluift/ElementConvertors/PubSubEventCollectionConvertor.h @@ -1,28 +1,28 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <Swiften/Elements/PubSubEventCollection.h> #include <Sluift/GenericLuaElementConvertor.h> -#include <Swiften/Elements/PubSubEventCollection.h> namespace Swift { - class LuaElementConvertors; + class LuaElementConvertors; - class PubSubEventCollectionConvertor : public GenericLuaElementConvertor<PubSubEventCollection> { - public: - PubSubEventCollectionConvertor(LuaElementConvertors* convertors); - virtual ~PubSubEventCollectionConvertor(); + class PubSubEventCollectionConvertor : public GenericLuaElementConvertor<PubSubEventCollection> { + public: + PubSubEventCollectionConvertor(LuaElementConvertors* convertors); + virtual ~PubSubEventCollectionConvertor() override; - virtual boost::shared_ptr<PubSubEventCollection> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE; - virtual void doConvertToLua(lua_State*, boost::shared_ptr<PubSubEventCollection>) SWIFTEN_OVERRIDE; + virtual std::shared_ptr<PubSubEventCollection> doConvertFromLua(lua_State*) override; + virtual void doConvertToLua(lua_State*, std::shared_ptr<PubSubEventCollection>) override; + virtual boost::optional<Documentation> getDocumentation() const override; - private: - LuaElementConvertors* convertors; - }; + private: + LuaElementConvertors* convertors; + }; } diff --git a/Sluift/ElementConvertors/PubSubEventConfigurationConvertor.cpp b/Sluift/ElementConvertors/PubSubEventConfigurationConvertor.cpp index ecdf145..828a010 100644 --- a/Sluift/ElementConvertors/PubSubEventConfigurationConvertor.cpp +++ b/Sluift/ElementConvertors/PubSubEventConfigurationConvertor.cpp @@ -1,51 +1,58 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #include <Sluift/ElementConvertors/PubSubEventConfigurationConvertor.h> -#include <lua.hpp> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> +#include <lua.hpp> #include <Sluift/LuaElementConvertors.h> -#pragma clang diagnostic ignored "-Wunused-private-field" - using namespace Swift; -PubSubEventConfigurationConvertor::PubSubEventConfigurationConvertor(LuaElementConvertors* convertors) : - GenericLuaElementConvertor<PubSubEventConfiguration>("pubsub_event_configuration"), - convertors(convertors) { +PubSubEventConfigurationConvertor::PubSubEventConfigurationConvertor(LuaElementConvertors* convertors) : + GenericLuaElementConvertor<PubSubEventConfiguration>("pubsub_event_configuration"), + convertors(convertors) { } PubSubEventConfigurationConvertor::~PubSubEventConfigurationConvertor() { } -boost::shared_ptr<PubSubEventConfiguration> PubSubEventConfigurationConvertor::doConvertFromLua(lua_State* L) { - boost::shared_ptr<PubSubEventConfiguration> result = boost::make_shared<PubSubEventConfiguration>(); - lua_getfield(L, -1, "node"); - if (lua_isstring(L, -1)) { - result->setNode(std::string(lua_tostring(L, -1))); - } - lua_pop(L, 1); - lua_getfield(L, -1, "data"); - if (!lua_isnil(L, -1)) { - if (boost::shared_ptr<Form> payload = boost::dynamic_pointer_cast<Form>(convertors->convertFromLuaUntyped(L, -1, "form"))) { - result->setData(payload); - } - } - lua_pop(L, 1); - return result; +std::shared_ptr<PubSubEventConfiguration> PubSubEventConfigurationConvertor::doConvertFromLua(lua_State* L) { + std::shared_ptr<PubSubEventConfiguration> result = std::make_shared<PubSubEventConfiguration>(); + lua_getfield(L, -1, "node"); + if (lua_isstring(L, -1)) { + result->setNode(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "data"); + if (!lua_isnil(L, -1)) { + if (std::shared_ptr<Form> payload = std::dynamic_pointer_cast<Form>(convertors->convertFromLuaUntyped(L, -1, "form"))) { + result->setData(payload); + } + } + lua_pop(L, 1); + return result; +} + +void PubSubEventConfigurationConvertor::doConvertToLua(lua_State* L, std::shared_ptr<PubSubEventConfiguration> payload) { + lua_createtable(L, 0, 0); + lua_pushstring(L, payload->getNode().c_str()); + lua_setfield(L, -2, "node"); + if (convertors->convertToLuaUntyped(L, payload->getData()) > 0) { + lua_setfield(L, -2, "data"); + } } -void PubSubEventConfigurationConvertor::doConvertToLua(lua_State* L, boost::shared_ptr<PubSubEventConfiguration> payload) { - lua_createtable(L, 0, 0); - lua_pushstring(L, payload->getNode().c_str()); - lua_setfield(L, -2, "node"); - if (convertors->convertToLuaUntyped(L, payload->getData()) > 0) { - lua_setfield(L, -2, "data"); - } +boost::optional<LuaElementConvertor::Documentation> PubSubEventConfigurationConvertor::getDocumentation() const { + return Documentation( + "PubSubEventConfiguration", + "This table has the following fields:\n\n" + "- `node`: string\n" + "- `data`: @{Form}\n" + ); } diff --git a/Sluift/ElementConvertors/PubSubEventConfigurationConvertor.h b/Sluift/ElementConvertors/PubSubEventConfigurationConvertor.h index 4347ebc..c2d82a5 100644 --- a/Sluift/ElementConvertors/PubSubEventConfigurationConvertor.h +++ b/Sluift/ElementConvertors/PubSubEventConfigurationConvertor.h @@ -1,28 +1,28 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <Swiften/Elements/PubSubEventConfiguration.h> #include <Sluift/GenericLuaElementConvertor.h> -#include <Swiften/Elements/PubSubEventConfiguration.h> namespace Swift { - class LuaElementConvertors; + class LuaElementConvertors; - class PubSubEventConfigurationConvertor : public GenericLuaElementConvertor<PubSubEventConfiguration> { - public: - PubSubEventConfigurationConvertor(LuaElementConvertors* convertors); - virtual ~PubSubEventConfigurationConvertor(); + class PubSubEventConfigurationConvertor : public GenericLuaElementConvertor<PubSubEventConfiguration> { + public: + PubSubEventConfigurationConvertor(LuaElementConvertors* convertors); + virtual ~PubSubEventConfigurationConvertor() override; - virtual boost::shared_ptr<PubSubEventConfiguration> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE; - virtual void doConvertToLua(lua_State*, boost::shared_ptr<PubSubEventConfiguration>) SWIFTEN_OVERRIDE; + virtual std::shared_ptr<PubSubEventConfiguration> doConvertFromLua(lua_State*) override; + virtual void doConvertToLua(lua_State*, std::shared_ptr<PubSubEventConfiguration>) override; + virtual boost::optional<Documentation> getDocumentation() const override; - private: - LuaElementConvertors* convertors; - }; + private: + LuaElementConvertors* convertors; + }; } diff --git a/Sluift/ElementConvertors/PubSubEventConvertor.cpp b/Sluift/ElementConvertors/PubSubEventConvertor.cpp index 46d870a..da7c849 100644 --- a/Sluift/ElementConvertors/PubSubEventConvertor.cpp +++ b/Sluift/ElementConvertors/PubSubEventConvertor.cpp @@ -1,37 +1,35 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #include <Sluift/ElementConvertors/PubSubEventConvertor.h> -#include <lua.hpp> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> +#include <lua.hpp> #include <Sluift/LuaElementConvertors.h> -#pragma clang diagnostic ignored "-Wunused-private-field" - using namespace Swift; -PubSubEventConvertor::PubSubEventConvertor(LuaElementConvertors* convertors) : - GenericLuaElementConvertor<PubSubEvent>("pubsub_event"), - convertors(convertors) { +PubSubEventConvertor::PubSubEventConvertor(LuaElementConvertors* convertors) : + GenericLuaElementConvertor<PubSubEvent>("pubsub_event"), + convertors(convertors) { } PubSubEventConvertor::~PubSubEventConvertor() { } -boost::shared_ptr<PubSubEvent> PubSubEventConvertor::doConvertFromLua(lua_State* L) { - boost::shared_ptr<PubSubEvent> result = boost::make_shared<PubSubEvent>(); - if (boost::shared_ptr<PubSubEventPayload> payload = boost::dynamic_pointer_cast<PubSubEventPayload>(convertors->convertFromLua(L, -1))) { - result->setPayload(payload); - } - return result; +std::shared_ptr<PubSubEvent> PubSubEventConvertor::doConvertFromLua(lua_State* L) { + std::shared_ptr<PubSubEvent> result = std::make_shared<PubSubEvent>(); + if (std::shared_ptr<PubSubEventPayload> payload = std::dynamic_pointer_cast<PubSubEventPayload>(convertors->convertFromLua(L, -1))) { + result->setPayload(payload); + } + return result; } -void PubSubEventConvertor::doConvertToLua(lua_State* L, boost::shared_ptr<PubSubEvent> event) { - convertors->convertToLua(L, event->getPayload()); +void PubSubEventConvertor::doConvertToLua(lua_State* L, std::shared_ptr<PubSubEvent> event) { + convertors->convertToLua(L, event->getPayload()); } diff --git a/Sluift/ElementConvertors/PubSubEventConvertor.h b/Sluift/ElementConvertors/PubSubEventConvertor.h index 8250fc4..b116c68 100644 --- a/Sluift/ElementConvertors/PubSubEventConvertor.h +++ b/Sluift/ElementConvertors/PubSubEventConvertor.h @@ -1,28 +1,27 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <Swiften/Elements/PubSubEvent.h> #include <Sluift/GenericLuaElementConvertor.h> -#include <Swiften/Elements/PubSubEvent.h> namespace Swift { - class LuaElementConvertors; + class LuaElementConvertors; - class PubSubEventConvertor : public GenericLuaElementConvertor<PubSubEvent> { - public: - PubSubEventConvertor(LuaElementConvertors* convertors); - virtual ~PubSubEventConvertor(); + class PubSubEventConvertor : public GenericLuaElementConvertor<PubSubEvent> { + public: + PubSubEventConvertor(LuaElementConvertors* convertors); + virtual ~PubSubEventConvertor() override; - virtual boost::shared_ptr<PubSubEvent> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE; - virtual void doConvertToLua(lua_State*, boost::shared_ptr<PubSubEvent>) SWIFTEN_OVERRIDE; + virtual std::shared_ptr<PubSubEvent> doConvertFromLua(lua_State*) override; + virtual void doConvertToLua(lua_State*, std::shared_ptr<PubSubEvent>) override; - private: - LuaElementConvertors* convertors; - }; + private: + LuaElementConvertors* convertors; + }; } diff --git a/Sluift/ElementConvertors/PubSubEventDeleteConvertor.cpp b/Sluift/ElementConvertors/PubSubEventDeleteConvertor.cpp index b03f22a..06fb3a2 100644 --- a/Sluift/ElementConvertors/PubSubEventDeleteConvertor.cpp +++ b/Sluift/ElementConvertors/PubSubEventDeleteConvertor.cpp @@ -1,51 +1,58 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #include <Sluift/ElementConvertors/PubSubEventDeleteConvertor.h> -#include <lua.hpp> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> +#include <lua.hpp> #include <Sluift/LuaElementConvertors.h> -#pragma clang diagnostic ignored "-Wunused-private-field" - using namespace Swift; -PubSubEventDeleteConvertor::PubSubEventDeleteConvertor(LuaElementConvertors* convertors) : - GenericLuaElementConvertor<PubSubEventDelete>("pubsub_event_delete"), - convertors(convertors) { +PubSubEventDeleteConvertor::PubSubEventDeleteConvertor(LuaElementConvertors* convertors) : + GenericLuaElementConvertor<PubSubEventDelete>("pubsub_event_delete"), + convertors(convertors) { } PubSubEventDeleteConvertor::~PubSubEventDeleteConvertor() { } -boost::shared_ptr<PubSubEventDelete> PubSubEventDeleteConvertor::doConvertFromLua(lua_State* L) { - boost::shared_ptr<PubSubEventDelete> result = boost::make_shared<PubSubEventDelete>(); - lua_getfield(L, -1, "node"); - if (lua_isstring(L, -1)) { - result->setNode(std::string(lua_tostring(L, -1))); - } - lua_pop(L, 1); - lua_getfield(L, -1, "redirects"); - if (!lua_isnil(L, -1)) { - if (boost::shared_ptr<PubSubEventRedirect> payload = boost::dynamic_pointer_cast<PubSubEventRedirect>(convertors->convertFromLuaUntyped(L, -1, "pubsub_event_redirect"))) { - result->setRedirects(payload); - } - } - lua_pop(L, 1); - return result; +std::shared_ptr<PubSubEventDelete> PubSubEventDeleteConvertor::doConvertFromLua(lua_State* L) { + std::shared_ptr<PubSubEventDelete> result = std::make_shared<PubSubEventDelete>(); + lua_getfield(L, -1, "node"); + if (lua_isstring(L, -1)) { + result->setNode(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "redirects"); + if (!lua_isnil(L, -1)) { + if (std::shared_ptr<PubSubEventRedirect> payload = std::dynamic_pointer_cast<PubSubEventRedirect>(convertors->convertFromLuaUntyped(L, -1, "pubsub_event_redirect"))) { + result->setRedirects(payload); + } + } + lua_pop(L, 1); + return result; +} + +void PubSubEventDeleteConvertor::doConvertToLua(lua_State* L, std::shared_ptr<PubSubEventDelete> payload) { + lua_createtable(L, 0, 0); + lua_pushstring(L, payload->getNode().c_str()); + lua_setfield(L, -2, "node"); + if (convertors->convertToLuaUntyped(L, payload->getRedirects()) > 0) { + lua_setfield(L, -2, "redirects"); + } } -void PubSubEventDeleteConvertor::doConvertToLua(lua_State* L, boost::shared_ptr<PubSubEventDelete> payload) { - lua_createtable(L, 0, 0); - lua_pushstring(L, payload->getNode().c_str()); - lua_setfield(L, -2, "node"); - if (convertors->convertToLuaUntyped(L, payload->getRedirects()) > 0) { - lua_setfield(L, -2, "redirects"); - } +boost::optional<LuaElementConvertor::Documentation> PubSubEventDeleteConvertor::getDocumentation() const { + return Documentation( + "PubSubEventDelete", + "This table has the following fields:\n\n" + "- `node`: string\n" + "- `redirects`: @{PubSubEventRedirect}\n" + ); } diff --git a/Sluift/ElementConvertors/PubSubEventDeleteConvertor.h b/Sluift/ElementConvertors/PubSubEventDeleteConvertor.h index a0cfd3d..66c706f 100644 --- a/Sluift/ElementConvertors/PubSubEventDeleteConvertor.h +++ b/Sluift/ElementConvertors/PubSubEventDeleteConvertor.h @@ -1,28 +1,28 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <Swiften/Elements/PubSubEventDelete.h> #include <Sluift/GenericLuaElementConvertor.h> -#include <Swiften/Elements/PubSubEventDelete.h> namespace Swift { - class LuaElementConvertors; + class LuaElementConvertors; - class PubSubEventDeleteConvertor : public GenericLuaElementConvertor<PubSubEventDelete> { - public: - PubSubEventDeleteConvertor(LuaElementConvertors* convertors); - virtual ~PubSubEventDeleteConvertor(); + class PubSubEventDeleteConvertor : public GenericLuaElementConvertor<PubSubEventDelete> { + public: + PubSubEventDeleteConvertor(LuaElementConvertors* convertors); + virtual ~PubSubEventDeleteConvertor() override; - virtual boost::shared_ptr<PubSubEventDelete> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE; - virtual void doConvertToLua(lua_State*, boost::shared_ptr<PubSubEventDelete>) SWIFTEN_OVERRIDE; + virtual std::shared_ptr<PubSubEventDelete> doConvertFromLua(lua_State*) override; + virtual void doConvertToLua(lua_State*, std::shared_ptr<PubSubEventDelete>) override; + virtual boost::optional<Documentation> getDocumentation() const override; - private: - LuaElementConvertors* convertors; - }; + private: + LuaElementConvertors* convertors; + }; } diff --git a/Sluift/ElementConvertors/PubSubEventDisassociateConvertor.cpp b/Sluift/ElementConvertors/PubSubEventDisassociateConvertor.cpp index ccd8c6e..0ada5ce 100644 --- a/Sluift/ElementConvertors/PubSubEventDisassociateConvertor.cpp +++ b/Sluift/ElementConvertors/PubSubEventDisassociateConvertor.cpp @@ -1,41 +1,44 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #include <Sluift/ElementConvertors/PubSubEventDisassociateConvertor.h> -#include <lua.hpp> -#include <boost/smart_ptr/make_shared.hpp> - - - +#include <memory> -#pragma clang diagnostic ignored "-Wunused-private-field" +#include <lua.hpp> using namespace Swift; -PubSubEventDisassociateConvertor::PubSubEventDisassociateConvertor(LuaElementConvertors* convertors) : - GenericLuaElementConvertor<PubSubEventDisassociate>("pubsub_event_disassociate"), - convertors(convertors) { +PubSubEventDisassociateConvertor::PubSubEventDisassociateConvertor() : + GenericLuaElementConvertor<PubSubEventDisassociate>("pubsub_event_disassociate") { } PubSubEventDisassociateConvertor::~PubSubEventDisassociateConvertor() { } -boost::shared_ptr<PubSubEventDisassociate> PubSubEventDisassociateConvertor::doConvertFromLua(lua_State* L) { - boost::shared_ptr<PubSubEventDisassociate> result = boost::make_shared<PubSubEventDisassociate>(); - lua_getfield(L, -1, "node"); - if (lua_isstring(L, -1)) { - result->setNode(std::string(lua_tostring(L, -1))); - } - lua_pop(L, 1); - return result; +std::shared_ptr<PubSubEventDisassociate> PubSubEventDisassociateConvertor::doConvertFromLua(lua_State* L) { + std::shared_ptr<PubSubEventDisassociate> result = std::make_shared<PubSubEventDisassociate>(); + lua_getfield(L, -1, "node"); + if (lua_isstring(L, -1)) { + result->setNode(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + return result; +} + +void PubSubEventDisassociateConvertor::doConvertToLua(lua_State* L, std::shared_ptr<PubSubEventDisassociate> payload) { + lua_createtable(L, 0, 0); + lua_pushstring(L, payload->getNode().c_str()); + lua_setfield(L, -2, "node"); } -void PubSubEventDisassociateConvertor::doConvertToLua(lua_State* L, boost::shared_ptr<PubSubEventDisassociate> payload) { - lua_createtable(L, 0, 0); - lua_pushstring(L, payload->getNode().c_str()); - lua_setfield(L, -2, "node"); +boost::optional<LuaElementConvertor::Documentation> PubSubEventDisassociateConvertor::getDocumentation() const { + return Documentation( + "PubSubEventDisassociate", + "This table has the following fields:\n\n" + "- `node`: string\n" + ); } diff --git a/Sluift/ElementConvertors/PubSubEventDisassociateConvertor.h b/Sluift/ElementConvertors/PubSubEventDisassociateConvertor.h index 90c8232..17f9ae9 100644 --- a/Sluift/ElementConvertors/PubSubEventDisassociateConvertor.h +++ b/Sluift/ElementConvertors/PubSubEventDisassociateConvertor.h @@ -1,28 +1,25 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <Swiften/Elements/PubSubEventDisassociate.h> #include <Sluift/GenericLuaElementConvertor.h> -#include <Swiften/Elements/PubSubEventDisassociate.h> namespace Swift { - class LuaElementConvertors; - - class PubSubEventDisassociateConvertor : public GenericLuaElementConvertor<PubSubEventDisassociate> { - public: - PubSubEventDisassociateConvertor(LuaElementConvertors* convertors); - virtual ~PubSubEventDisassociateConvertor(); + class LuaElementConvertors; - virtual boost::shared_ptr<PubSubEventDisassociate> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE; - virtual void doConvertToLua(lua_State*, boost::shared_ptr<PubSubEventDisassociate>) SWIFTEN_OVERRIDE; + class PubSubEventDisassociateConvertor : public GenericLuaElementConvertor<PubSubEventDisassociate> { + public: + PubSubEventDisassociateConvertor(); + virtual ~PubSubEventDisassociateConvertor() override; - private: - LuaElementConvertors* convertors; - }; + virtual std::shared_ptr<PubSubEventDisassociate> doConvertFromLua(lua_State*) override; + virtual void doConvertToLua(lua_State*, std::shared_ptr<PubSubEventDisassociate>) override; + virtual boost::optional<Documentation> getDocumentation() const override; + }; } diff --git a/Sluift/ElementConvertors/PubSubEventItemConvertor.cpp b/Sluift/ElementConvertors/PubSubEventItemConvertor.cpp index fab4bff..19ab09a 100644 --- a/Sluift/ElementConvertors/PubSubEventItemConvertor.cpp +++ b/Sluift/ElementConvertors/PubSubEventItemConvertor.cpp @@ -1,92 +1,102 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #include <Sluift/ElementConvertors/PubSubEventItemConvertor.h> -#include <lua.hpp> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> + #include <boost/numeric/conversion/cast.hpp> -#include <Sluift/LuaElementConvertors.h> -#include <Swiften/Base/foreach.h> +#include <lua.hpp> -#pragma clang diagnostic ignored "-Wunused-private-field" +#include <Sluift/LuaElementConvertors.h> using namespace Swift; -PubSubEventItemConvertor::PubSubEventItemConvertor(LuaElementConvertors* convertors) : - GenericLuaElementConvertor<PubSubEventItem>("pubsub_event_item"), - convertors(convertors) { +PubSubEventItemConvertor::PubSubEventItemConvertor(LuaElementConvertors* convertors) : + GenericLuaElementConvertor<PubSubEventItem>("pubsub_event_item"), + convertors(convertors) { } PubSubEventItemConvertor::~PubSubEventItemConvertor() { } -boost::shared_ptr<PubSubEventItem> PubSubEventItemConvertor::doConvertFromLua(lua_State* L) { - boost::shared_ptr<PubSubEventItem> result = boost::make_shared<PubSubEventItem>(); - lua_getfield(L, -1, "node"); - if (lua_isstring(L, -1)) { - result->setNode(std::string(lua_tostring(L, -1))); - } - lua_pop(L, 1); - lua_getfield(L, -1, "publisher"); - if (lua_isstring(L, -1)) { - result->setPublisher(std::string(lua_tostring(L, -1))); - } - lua_pop(L, 1); - lua_getfield(L, -1, "data"); - if (lua_type(L, -1) == LUA_TTABLE) { - std::vector< boost::shared_ptr<Payload> > items; - for(size_t i = 0; i < lua_objlen(L, -1); ++i) { - lua_pushnumber(L, i + 1); - lua_gettable(L, -2); - if (!lua_isnil(L, -1)) { - if (boost::shared_ptr<Payload> payload = convertors->convertFromLua(L, -1)) { - items.push_back(payload); - } - } - lua_pop(L, 1); - } +std::shared_ptr<PubSubEventItem> PubSubEventItemConvertor::doConvertFromLua(lua_State* L) { + std::shared_ptr<PubSubEventItem> result = std::make_shared<PubSubEventItem>(); + lua_getfield(L, -1, "node"); + if (lua_isstring(L, -1)) { + result->setNode(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "publisher"); + if (lua_isstring(L, -1)) { + result->setPublisher(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "data"); + if (lua_type(L, -1) == LUA_TTABLE) { + std::vector< std::shared_ptr<Payload> > items; + for(size_t i = 0; i < lua_rawlen(L, -1); ++i) { + lua_pushnumber(L, i + 1); + lua_gettable(L, -2); + if (!lua_isnil(L, -1)) { + if (std::shared_ptr<Payload> payload = std::dynamic_pointer_cast<Payload>(convertors->convertFromLua(L, -1))) { + items.push_back(payload); + } + } + lua_pop(L, 1); + } + + result->setData(items); + } + lua_pop(L, 1); + lua_getfield(L, -1, "id"); + if (lua_isstring(L, -1)) { + result->setID(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + return result; +} - result->setData(items); - } - lua_pop(L, 1); - lua_getfield(L, -1, "id"); - if (lua_isstring(L, -1)) { - result->setID(std::string(lua_tostring(L, -1))); - } - lua_pop(L, 1); - return result; +void PubSubEventItemConvertor::doConvertToLua(lua_State* L, std::shared_ptr<PubSubEventItem> payload) { + lua_createtable(L, 0, 0); + if (payload->getNode()) { + lua_pushstring(L, (*payload->getNode()).c_str()); + lua_setfield(L, -2, "node"); + } + if (payload->getPublisher()) { + lua_pushstring(L, (*payload->getPublisher()).c_str()); + lua_setfield(L, -2, "publisher"); + } + if (!payload->getData().empty()) { + lua_createtable(L, boost::numeric_cast<int>(payload->getData().size()), 0); + { + int i = 0; + for (auto&& item : payload->getData()) { + if (convertors->convertToLua(L, item) > 0) { + lua_rawseti(L, -2, boost::numeric_cast<int>(i+1)); + ++i; + } + } + } + lua_setfield(L, -2, "data"); + } + if (payload->getID()) { + lua_pushstring(L, (*payload->getID()).c_str()); + lua_setfield(L, -2, "id"); + } } -void PubSubEventItemConvertor::doConvertToLua(lua_State* L, boost::shared_ptr<PubSubEventItem> payload) { - lua_createtable(L, 0, 0); - if (payload->getNode()) { - lua_pushstring(L, (*payload->getNode()).c_str()); - lua_setfield(L, -2, "node"); - } - if (payload->getPublisher()) { - lua_pushstring(L, (*payload->getPublisher()).c_str()); - lua_setfield(L, -2, "publisher"); - } - if (!payload->getData().empty()) { - lua_createtable(L, boost::numeric_cast<int>(payload->getData().size()), 0); - { - int i = 0; - foreach(boost::shared_ptr<Payload> item, payload->getData()) { - if (convertors->convertToLua(L, item) > 0) { - lua_rawseti(L, -2, boost::numeric_cast<int>(i+1)); - ++i; - } - } - } - lua_setfield(L, -2, "data"); - } - if (payload->getID()) { - lua_pushstring(L, (*payload->getID()).c_str()); - lua_setfield(L, -2, "id"); - } +boost::optional<LuaElementConvertor::Documentation> PubSubEventItemConvertor::getDocumentation() const { + return Documentation( + "PubSubEventItem", + "This table has the following fields:\n\n" + "- `node`: string (Optional)\n" + "- `publisher`: string (Optional)\n" + "- `data`: array<element (table)>\n" + "- `id`: string (Optional)\n" + ); } diff --git a/Sluift/ElementConvertors/PubSubEventItemConvertor.h b/Sluift/ElementConvertors/PubSubEventItemConvertor.h index 340602a..9e29ce8 100644 --- a/Sluift/ElementConvertors/PubSubEventItemConvertor.h +++ b/Sluift/ElementConvertors/PubSubEventItemConvertor.h @@ -1,28 +1,28 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <Swiften/Elements/PubSubEventItem.h> #include <Sluift/GenericLuaElementConvertor.h> -#include <Swiften/Elements/PubSubEventItem.h> namespace Swift { - class LuaElementConvertors; + class LuaElementConvertors; - class PubSubEventItemConvertor : public GenericLuaElementConvertor<PubSubEventItem> { - public: - PubSubEventItemConvertor(LuaElementConvertors* convertors); - virtual ~PubSubEventItemConvertor(); + class PubSubEventItemConvertor : public GenericLuaElementConvertor<PubSubEventItem> { + public: + PubSubEventItemConvertor(LuaElementConvertors* convertors); + virtual ~PubSubEventItemConvertor() override; - virtual boost::shared_ptr<PubSubEventItem> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE; - virtual void doConvertToLua(lua_State*, boost::shared_ptr<PubSubEventItem>) SWIFTEN_OVERRIDE; + virtual std::shared_ptr<PubSubEventItem> doConvertFromLua(lua_State*) override; + virtual void doConvertToLua(lua_State*, std::shared_ptr<PubSubEventItem>) override; + virtual boost::optional<Documentation> getDocumentation() const override; - private: - LuaElementConvertors* convertors; - }; + private: + LuaElementConvertors* convertors; + }; } diff --git a/Sluift/ElementConvertors/PubSubEventItemsConvertor.cpp b/Sluift/ElementConvertors/PubSubEventItemsConvertor.cpp index 9996cc6..66f798e 100644 --- a/Sluift/ElementConvertors/PubSubEventItemsConvertor.cpp +++ b/Sluift/ElementConvertors/PubSubEventItemsConvertor.cpp @@ -1,102 +1,111 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #include <Sluift/ElementConvertors/PubSubEventItemsConvertor.h> -#include <lua.hpp> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> + #include <boost/numeric/conversion/cast.hpp> -#include <Sluift/LuaElementConvertors.h> -#include <Swiften/Base/foreach.h> +#include <lua.hpp> -#pragma clang diagnostic ignored "-Wunused-private-field" +#include <Sluift/LuaElementConvertors.h> using namespace Swift; -PubSubEventItemsConvertor::PubSubEventItemsConvertor(LuaElementConvertors* convertors) : - GenericLuaElementConvertor<PubSubEventItems>("pubsub_event_items"), - convertors(convertors) { +PubSubEventItemsConvertor::PubSubEventItemsConvertor(LuaElementConvertors* convertors) : + GenericLuaElementConvertor<PubSubEventItems>("pubsub_event_items"), + convertors(convertors) { } PubSubEventItemsConvertor::~PubSubEventItemsConvertor() { } -boost::shared_ptr<PubSubEventItems> PubSubEventItemsConvertor::doConvertFromLua(lua_State* L) { - boost::shared_ptr<PubSubEventItems> result = boost::make_shared<PubSubEventItems>(); - lua_getfield(L, -1, "node"); - if (lua_isstring(L, -1)) { - result->setNode(std::string(lua_tostring(L, -1))); - } - lua_pop(L, 1); - lua_getfield(L, -1, "items"); - if (lua_type(L, -1) == LUA_TTABLE) { - std::vector< boost::shared_ptr<PubSubEventItem> > items; - for(size_t i = 0; i < lua_objlen(L, -1); ++i) { - lua_pushnumber(L, i + 1); - lua_gettable(L, -2); - if (!lua_isnil(L, -1)) { - if (boost::shared_ptr<PubSubEventItem> payload = boost::dynamic_pointer_cast<PubSubEventItem>(convertors->convertFromLuaUntyped(L, -1, "pubsub_event_item"))) { - items.push_back(payload); - } - } - lua_pop(L, 1); - } +std::shared_ptr<PubSubEventItems> PubSubEventItemsConvertor::doConvertFromLua(lua_State* L) { + std::shared_ptr<PubSubEventItems> result = std::make_shared<PubSubEventItems>(); + lua_getfield(L, -1, "node"); + if (lua_isstring(L, -1)) { + result->setNode(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "items"); + if (lua_type(L, -1) == LUA_TTABLE) { + std::vector< std::shared_ptr<PubSubEventItem> > items; + for(size_t i = 0; i < lua_rawlen(L, -1); ++i) { + lua_pushnumber(L, i + 1); + lua_gettable(L, -2); + if (!lua_isnil(L, -1)) { + if (std::shared_ptr<PubSubEventItem> payload = std::dynamic_pointer_cast<PubSubEventItem>(convertors->convertFromLuaUntyped(L, -1, "pubsub_event_item"))) { + items.push_back(payload); + } + } + lua_pop(L, 1); + } + + result->setItems(items); + } + lua_pop(L, 1); + lua_getfield(L, -1, "retracts"); + if (lua_type(L, -1) == LUA_TTABLE) { + std::vector< std::shared_ptr<PubSubEventRetract> > items; + for(size_t i = 0; i < lua_rawlen(L, -1); ++i) { + lua_pushnumber(L, i + 1); + lua_gettable(L, -2); + if (!lua_isnil(L, -1)) { + if (std::shared_ptr<PubSubEventRetract> payload = std::dynamic_pointer_cast<PubSubEventRetract>(convertors->convertFromLuaUntyped(L, -1, "pubsub_event_retract"))) { + items.push_back(payload); + } + } + lua_pop(L, 1); + } - result->setItems(items); - } - lua_pop(L, 1); - lua_getfield(L, -1, "retracts"); - if (lua_type(L, -1) == LUA_TTABLE) { - std::vector< boost::shared_ptr<PubSubEventRetract> > items; - for(size_t i = 0; i < lua_objlen(L, -1); ++i) { - lua_pushnumber(L, i + 1); - lua_gettable(L, -2); - if (!lua_isnil(L, -1)) { - if (boost::shared_ptr<PubSubEventRetract> payload = boost::dynamic_pointer_cast<PubSubEventRetract>(convertors->convertFromLuaUntyped(L, -1, "pubsub_event_retract"))) { - items.push_back(payload); - } - } - lua_pop(L, 1); - } + result->setRetracts(items); + } + lua_pop(L, 1); + return result; +} - result->setRetracts(items); - } - lua_pop(L, 1); - return result; +void PubSubEventItemsConvertor::doConvertToLua(lua_State* L, std::shared_ptr<PubSubEventItems> payload) { + lua_createtable(L, 0, 0); + lua_pushstring(L, payload->getNode().c_str()); + lua_setfield(L, -2, "node"); + if (!payload->getItems().empty()) { + lua_createtable(L, boost::numeric_cast<int>(payload->getItems().size()), 0); + { + int i = 0; + for (auto&& item : payload->getItems()) { + if (convertors->convertToLuaUntyped(L, item) > 0) { + lua_rawseti(L, -2, boost::numeric_cast<int>(i+1)); + ++i; + } + } + } + lua_setfield(L, -2, "items"); + } + if (!payload->getRetracts().empty()) { + lua_createtable(L, boost::numeric_cast<int>(payload->getRetracts().size()), 0); + { + int i = 0; + for (auto&& item : payload->getRetracts()) { + if (convertors->convertToLuaUntyped(L, item) > 0) { + lua_rawseti(L, -2, boost::numeric_cast<int>(i+1)); + ++i; + } + } + } + lua_setfield(L, -2, "retracts"); + } } -void PubSubEventItemsConvertor::doConvertToLua(lua_State* L, boost::shared_ptr<PubSubEventItems> payload) { - lua_createtable(L, 0, 0); - lua_pushstring(L, payload->getNode().c_str()); - lua_setfield(L, -2, "node"); - if (!payload->getItems().empty()) { - lua_createtable(L, boost::numeric_cast<int>(payload->getItems().size()), 0); - { - int i = 0; - foreach(boost::shared_ptr<PubSubEventItem> item, payload->getItems()) { - if (convertors->convertToLuaUntyped(L, item) > 0) { - lua_rawseti(L, -2, boost::numeric_cast<int>(i+1)); - ++i; - } - } - } - lua_setfield(L, -2, "items"); - } - if (!payload->getRetracts().empty()) { - lua_createtable(L, boost::numeric_cast<int>(payload->getRetracts().size()), 0); - { - int i = 0; - foreach(boost::shared_ptr<PubSubEventRetract> item, payload->getRetracts()) { - if (convertors->convertToLuaUntyped(L, item) > 0) { - lua_rawseti(L, -2, boost::numeric_cast<int>(i+1)); - ++i; - } - } - } - lua_setfield(L, -2, "retracts"); - } +boost::optional<LuaElementConvertor::Documentation> PubSubEventItemsConvertor::getDocumentation() const { + return Documentation( + "PubSubEventItems", + "This table has the following fields:\n\n" + "- `node`: string\n" + "- `items`: array<@{PubSubEventItem}>\n" + "- `retracts`: array<@{PubSubEventRetract}>\n" + ); } diff --git a/Sluift/ElementConvertors/PubSubEventItemsConvertor.h b/Sluift/ElementConvertors/PubSubEventItemsConvertor.h index 9adbf15..8f7e3fe 100644 --- a/Sluift/ElementConvertors/PubSubEventItemsConvertor.h +++ b/Sluift/ElementConvertors/PubSubEventItemsConvertor.h @@ -1,28 +1,28 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <Swiften/Elements/PubSubEventItems.h> #include <Sluift/GenericLuaElementConvertor.h> -#include <Swiften/Elements/PubSubEventItems.h> namespace Swift { - class LuaElementConvertors; + class LuaElementConvertors; - class PubSubEventItemsConvertor : public GenericLuaElementConvertor<PubSubEventItems> { - public: - PubSubEventItemsConvertor(LuaElementConvertors* convertors); - virtual ~PubSubEventItemsConvertor(); + class PubSubEventItemsConvertor : public GenericLuaElementConvertor<PubSubEventItems> { + public: + PubSubEventItemsConvertor(LuaElementConvertors* convertors); + virtual ~PubSubEventItemsConvertor() override; - virtual boost::shared_ptr<PubSubEventItems> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE; - virtual void doConvertToLua(lua_State*, boost::shared_ptr<PubSubEventItems>) SWIFTEN_OVERRIDE; + virtual std::shared_ptr<PubSubEventItems> doConvertFromLua(lua_State*) override; + virtual void doConvertToLua(lua_State*, std::shared_ptr<PubSubEventItems>) override; + virtual boost::optional<Documentation> getDocumentation() const override; - private: - LuaElementConvertors* convertors; - }; + private: + LuaElementConvertors* convertors; + }; } diff --git a/Sluift/ElementConvertors/PubSubEventPurgeConvertor.cpp b/Sluift/ElementConvertors/PubSubEventPurgeConvertor.cpp index e389fcf..223eedd 100644 --- a/Sluift/ElementConvertors/PubSubEventPurgeConvertor.cpp +++ b/Sluift/ElementConvertors/PubSubEventPurgeConvertor.cpp @@ -1,41 +1,44 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #include <Sluift/ElementConvertors/PubSubEventPurgeConvertor.h> -#include <lua.hpp> -#include <boost/smart_ptr/make_shared.hpp> - - - +#include <memory> -#pragma clang diagnostic ignored "-Wunused-private-field" +#include <lua.hpp> using namespace Swift; -PubSubEventPurgeConvertor::PubSubEventPurgeConvertor(LuaElementConvertors* convertors) : - GenericLuaElementConvertor<PubSubEventPurge>("pubsub_event_purge"), - convertors(convertors) { +PubSubEventPurgeConvertor::PubSubEventPurgeConvertor() : + GenericLuaElementConvertor<PubSubEventPurge>("pubsub_event_purge") { } PubSubEventPurgeConvertor::~PubSubEventPurgeConvertor() { } -boost::shared_ptr<PubSubEventPurge> PubSubEventPurgeConvertor::doConvertFromLua(lua_State* L) { - boost::shared_ptr<PubSubEventPurge> result = boost::make_shared<PubSubEventPurge>(); - lua_getfield(L, -1, "node"); - if (lua_isstring(L, -1)) { - result->setNode(std::string(lua_tostring(L, -1))); - } - lua_pop(L, 1); - return result; +std::shared_ptr<PubSubEventPurge> PubSubEventPurgeConvertor::doConvertFromLua(lua_State* L) { + std::shared_ptr<PubSubEventPurge> result = std::make_shared<PubSubEventPurge>(); + lua_getfield(L, -1, "node"); + if (lua_isstring(L, -1)) { + result->setNode(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + return result; +} + +void PubSubEventPurgeConvertor::doConvertToLua(lua_State* L, std::shared_ptr<PubSubEventPurge> payload) { + lua_createtable(L, 0, 0); + lua_pushstring(L, payload->getNode().c_str()); + lua_setfield(L, -2, "node"); } -void PubSubEventPurgeConvertor::doConvertToLua(lua_State* L, boost::shared_ptr<PubSubEventPurge> payload) { - lua_createtable(L, 0, 0); - lua_pushstring(L, payload->getNode().c_str()); - lua_setfield(L, -2, "node"); +boost::optional<LuaElementConvertor::Documentation> PubSubEventPurgeConvertor::getDocumentation() const { + return Documentation( + "PubSubEventPurge", + "This table has the following fields:\n\n" + "- `node`: string\n" + ); } diff --git a/Sluift/ElementConvertors/PubSubEventPurgeConvertor.h b/Sluift/ElementConvertors/PubSubEventPurgeConvertor.h index d94aa36..1c2cdbb 100644 --- a/Sluift/ElementConvertors/PubSubEventPurgeConvertor.h +++ b/Sluift/ElementConvertors/PubSubEventPurgeConvertor.h @@ -1,28 +1,25 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <Swiften/Elements/PubSubEventPurge.h> #include <Sluift/GenericLuaElementConvertor.h> -#include <Swiften/Elements/PubSubEventPurge.h> namespace Swift { - class LuaElementConvertors; - - class PubSubEventPurgeConvertor : public GenericLuaElementConvertor<PubSubEventPurge> { - public: - PubSubEventPurgeConvertor(LuaElementConvertors* convertors); - virtual ~PubSubEventPurgeConvertor(); + class LuaElementConvertors; - virtual boost::shared_ptr<PubSubEventPurge> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE; - virtual void doConvertToLua(lua_State*, boost::shared_ptr<PubSubEventPurge>) SWIFTEN_OVERRIDE; + class PubSubEventPurgeConvertor : public GenericLuaElementConvertor<PubSubEventPurge> { + public: + PubSubEventPurgeConvertor(); + virtual ~PubSubEventPurgeConvertor() override; - private: - LuaElementConvertors* convertors; - }; + virtual std::shared_ptr<PubSubEventPurge> doConvertFromLua(lua_State*) override; + virtual void doConvertToLua(lua_State*, std::shared_ptr<PubSubEventPurge>) override; + virtual boost::optional<Documentation> getDocumentation() const override; + }; } diff --git a/Sluift/ElementConvertors/PubSubEventRedirectConvertor.cpp b/Sluift/ElementConvertors/PubSubEventRedirectConvertor.cpp index 6e128da..673b320 100644 --- a/Sluift/ElementConvertors/PubSubEventRedirectConvertor.cpp +++ b/Sluift/ElementConvertors/PubSubEventRedirectConvertor.cpp @@ -1,41 +1,44 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #include <Sluift/ElementConvertors/PubSubEventRedirectConvertor.h> -#include <lua.hpp> -#include <boost/smart_ptr/make_shared.hpp> - - - +#include <memory> -#pragma clang diagnostic ignored "-Wunused-private-field" +#include <lua.hpp> using namespace Swift; -PubSubEventRedirectConvertor::PubSubEventRedirectConvertor(LuaElementConvertors* convertors) : - GenericLuaElementConvertor<PubSubEventRedirect>("pubsub_event_redirect"), - convertors(convertors) { +PubSubEventRedirectConvertor::PubSubEventRedirectConvertor() : + GenericLuaElementConvertor<PubSubEventRedirect>("pubsub_event_redirect") { } PubSubEventRedirectConvertor::~PubSubEventRedirectConvertor() { } -boost::shared_ptr<PubSubEventRedirect> PubSubEventRedirectConvertor::doConvertFromLua(lua_State* L) { - boost::shared_ptr<PubSubEventRedirect> result = boost::make_shared<PubSubEventRedirect>(); - lua_getfield(L, -1, "uri"); - if (lua_isstring(L, -1)) { - result->setURI(std::string(lua_tostring(L, -1))); - } - lua_pop(L, 1); - return result; +std::shared_ptr<PubSubEventRedirect> PubSubEventRedirectConvertor::doConvertFromLua(lua_State* L) { + std::shared_ptr<PubSubEventRedirect> result = std::make_shared<PubSubEventRedirect>(); + lua_getfield(L, -1, "uri"); + if (lua_isstring(L, -1)) { + result->setURI(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + return result; +} + +void PubSubEventRedirectConvertor::doConvertToLua(lua_State* L, std::shared_ptr<PubSubEventRedirect> payload) { + lua_createtable(L, 0, 0); + lua_pushstring(L, payload->getURI().c_str()); + lua_setfield(L, -2, "uri"); } -void PubSubEventRedirectConvertor::doConvertToLua(lua_State* L, boost::shared_ptr<PubSubEventRedirect> payload) { - lua_createtable(L, 0, 0); - lua_pushstring(L, payload->getURI().c_str()); - lua_setfield(L, -2, "uri"); +boost::optional<LuaElementConvertor::Documentation> PubSubEventRedirectConvertor::getDocumentation() const { + return Documentation( + "PubSubEventRedirect", + "This table has the following fields:\n\n" + "- `uri`: string\n" + ); } diff --git a/Sluift/ElementConvertors/PubSubEventRedirectConvertor.h b/Sluift/ElementConvertors/PubSubEventRedirectConvertor.h index 4904102..a61cb79 100644 --- a/Sluift/ElementConvertors/PubSubEventRedirectConvertor.h +++ b/Sluift/ElementConvertors/PubSubEventRedirectConvertor.h @@ -1,28 +1,25 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <Swiften/Elements/PubSubEventRedirect.h> #include <Sluift/GenericLuaElementConvertor.h> -#include <Swiften/Elements/PubSubEventRedirect.h> namespace Swift { - class LuaElementConvertors; - - class PubSubEventRedirectConvertor : public GenericLuaElementConvertor<PubSubEventRedirect> { - public: - PubSubEventRedirectConvertor(LuaElementConvertors* convertors); - virtual ~PubSubEventRedirectConvertor(); + class LuaElementConvertors; - virtual boost::shared_ptr<PubSubEventRedirect> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE; - virtual void doConvertToLua(lua_State*, boost::shared_ptr<PubSubEventRedirect>) SWIFTEN_OVERRIDE; + class PubSubEventRedirectConvertor : public GenericLuaElementConvertor<PubSubEventRedirect> { + public: + PubSubEventRedirectConvertor(); + virtual ~PubSubEventRedirectConvertor() override; - private: - LuaElementConvertors* convertors; - }; + virtual std::shared_ptr<PubSubEventRedirect> doConvertFromLua(lua_State*) override; + virtual void doConvertToLua(lua_State*, std::shared_ptr<PubSubEventRedirect>) override; + virtual boost::optional<Documentation> getDocumentation() const override; + }; } diff --git a/Sluift/ElementConvertors/PubSubEventRetractConvertor.cpp b/Sluift/ElementConvertors/PubSubEventRetractConvertor.cpp index aed29a0..5981922 100644 --- a/Sluift/ElementConvertors/PubSubEventRetractConvertor.cpp +++ b/Sluift/ElementConvertors/PubSubEventRetractConvertor.cpp @@ -1,41 +1,44 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #include <Sluift/ElementConvertors/PubSubEventRetractConvertor.h> -#include <lua.hpp> -#include <boost/smart_ptr/make_shared.hpp> - - - +#include <memory> -#pragma clang diagnostic ignored "-Wunused-private-field" +#include <lua.hpp> using namespace Swift; -PubSubEventRetractConvertor::PubSubEventRetractConvertor(LuaElementConvertors* convertors) : - GenericLuaElementConvertor<PubSubEventRetract>("pubsub_event_retract"), - convertors(convertors) { +PubSubEventRetractConvertor::PubSubEventRetractConvertor() : + GenericLuaElementConvertor<PubSubEventRetract>("pubsub_event_retract") { } PubSubEventRetractConvertor::~PubSubEventRetractConvertor() { } -boost::shared_ptr<PubSubEventRetract> PubSubEventRetractConvertor::doConvertFromLua(lua_State* L) { - boost::shared_ptr<PubSubEventRetract> result = boost::make_shared<PubSubEventRetract>(); - lua_getfield(L, -1, "id"); - if (lua_isstring(L, -1)) { - result->setID(std::string(lua_tostring(L, -1))); - } - lua_pop(L, 1); - return result; +std::shared_ptr<PubSubEventRetract> PubSubEventRetractConvertor::doConvertFromLua(lua_State* L) { + std::shared_ptr<PubSubEventRetract> result = std::make_shared<PubSubEventRetract>(); + lua_getfield(L, -1, "id"); + if (lua_isstring(L, -1)) { + result->setID(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + return result; +} + +void PubSubEventRetractConvertor::doConvertToLua(lua_State* L, std::shared_ptr<PubSubEventRetract> payload) { + lua_createtable(L, 0, 0); + lua_pushstring(L, payload->getID().c_str()); + lua_setfield(L, -2, "id"); } -void PubSubEventRetractConvertor::doConvertToLua(lua_State* L, boost::shared_ptr<PubSubEventRetract> payload) { - lua_createtable(L, 0, 0); - lua_pushstring(L, payload->getID().c_str()); - lua_setfield(L, -2, "id"); +boost::optional<LuaElementConvertor::Documentation> PubSubEventRetractConvertor::getDocumentation() const { + return Documentation( + "PubSubEventRetract", + "This table has the following fields:\n\n" + "- `id`: string\n" + ); } diff --git a/Sluift/ElementConvertors/PubSubEventRetractConvertor.h b/Sluift/ElementConvertors/PubSubEventRetractConvertor.h index 7a7c0f9..f437ad5 100644 --- a/Sluift/ElementConvertors/PubSubEventRetractConvertor.h +++ b/Sluift/ElementConvertors/PubSubEventRetractConvertor.h @@ -1,28 +1,25 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <Swiften/Elements/PubSubEventRetract.h> #include <Sluift/GenericLuaElementConvertor.h> -#include <Swiften/Elements/PubSubEventRetract.h> namespace Swift { - class LuaElementConvertors; - - class PubSubEventRetractConvertor : public GenericLuaElementConvertor<PubSubEventRetract> { - public: - PubSubEventRetractConvertor(LuaElementConvertors* convertors); - virtual ~PubSubEventRetractConvertor(); + class LuaElementConvertors; - virtual boost::shared_ptr<PubSubEventRetract> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE; - virtual void doConvertToLua(lua_State*, boost::shared_ptr<PubSubEventRetract>) SWIFTEN_OVERRIDE; + class PubSubEventRetractConvertor : public GenericLuaElementConvertor<PubSubEventRetract> { + public: + PubSubEventRetractConvertor(); + virtual ~PubSubEventRetractConvertor() override; - private: - LuaElementConvertors* convertors; - }; + virtual std::shared_ptr<PubSubEventRetract> doConvertFromLua(lua_State*) override; + virtual void doConvertToLua(lua_State*, std::shared_ptr<PubSubEventRetract>) override; + virtual boost::optional<Documentation> getDocumentation() const override; + }; } diff --git a/Sluift/ElementConvertors/PubSubEventSubscriptionConvertor.cpp b/Sluift/ElementConvertors/PubSubEventSubscriptionConvertor.cpp index 68cb34a..cab78d4 100644 --- a/Sluift/ElementConvertors/PubSubEventSubscriptionConvertor.cpp +++ b/Sluift/ElementConvertors/PubSubEventSubscriptionConvertor.cpp @@ -1,81 +1,104 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #include <Sluift/ElementConvertors/PubSubEventSubscriptionConvertor.h> -#include <lua.hpp> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> +#include <lua.hpp> #include <Swiften/Base/DateTime.h> -#pragma clang diagnostic ignored "-Wunused-private-field" - using namespace Swift; -PubSubEventSubscriptionConvertor::PubSubEventSubscriptionConvertor(LuaElementConvertors* convertors) : - GenericLuaElementConvertor<PubSubEventSubscription>("pubsub_event_subscription"), - convertors(convertors) { +PubSubEventSubscriptionConvertor::PubSubEventSubscriptionConvertor() : + GenericLuaElementConvertor<PubSubEventSubscription>("pubsub_event_subscription") { } PubSubEventSubscriptionConvertor::~PubSubEventSubscriptionConvertor() { } -boost::shared_ptr<PubSubEventSubscription> PubSubEventSubscriptionConvertor::doConvertFromLua(lua_State* L) { - boost::shared_ptr<PubSubEventSubscription> result = boost::make_shared<PubSubEventSubscription>(); - lua_getfield(L, -1, "node"); - if (lua_isstring(L, -1)) { - result->setNode(std::string(lua_tostring(L, -1))); - } - lua_pop(L, 1); - lua_getfield(L, -1, "jid"); - if (lua_isstring(L, -1)) { - result->setJID(JID(std::string(lua_tostring(L, -1)))); - } - lua_pop(L, 1); - lua_getfield(L, -1, "subscription"); - lua_pop(L, 1); - lua_getfield(L, -1, "subscriptionid"); - if (lua_isstring(L, -1)) { - result->setSubscriptionID(std::string(lua_tostring(L, -1))); - } - lua_pop(L, 1); - lua_getfield(L, -1, "expiry"); - if (lua_isstring(L, -1)) { - result->setExpiry(stringToDateTime(std::string(lua_tostring(L, -1)))); - } - lua_pop(L, 1); - return result; +std::shared_ptr<PubSubEventSubscription> PubSubEventSubscriptionConvertor::doConvertFromLua(lua_State* L) { + std::shared_ptr<PubSubEventSubscription> result = std::make_shared<PubSubEventSubscription>(); + lua_getfield(L, -1, "node"); + if (lua_isstring(L, -1)) { + result->setNode(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "jid"); + if (lua_isstring(L, -1)) { + result->setJID(JID(std::string(lua_tostring(L, -1)))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "subscription"); + if (lua_isstring(L, -1)) { + if (std::string(lua_tostring(L, -1)) == "none") { + result->setSubscription(PubSubEventSubscription::None); + } + if (std::string(lua_tostring(L, -1)) == "pending") { + result->setSubscription(PubSubEventSubscription::Pending); + } + if (std::string(lua_tostring(L, -1)) == "subscribed") { + result->setSubscription(PubSubEventSubscription::Subscribed); + } + if (std::string(lua_tostring(L, -1)) == "unconfigured") { + result->setSubscription(PubSubEventSubscription::Unconfigured); + } + } + lua_pop(L, 1); + lua_getfield(L, -1, "subscription_id"); + if (lua_isstring(L, -1)) { + result->setSubscriptionID(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "expiry"); + if (lua_isstring(L, -1)) { + result->setExpiry(stringToDateTime(std::string(lua_tostring(L, -1)))); + } + lua_pop(L, 1); + return result; +} + +void PubSubEventSubscriptionConvertor::doConvertToLua(lua_State* L, std::shared_ptr<PubSubEventSubscription> payload) { + lua_createtable(L, 0, 0); + lua_pushstring(L, payload->getNode().c_str()); + lua_setfield(L, -2, "node"); + lua_pushstring(L, payload->getJID().toString().c_str()); + lua_setfield(L, -2, "jid"); + switch (payload->getSubscription()) { + case PubSubEventSubscription::None: + lua_pushstring(L, "none"); + break; + case PubSubEventSubscription::Pending: + lua_pushstring(L, "pending"); + break; + case PubSubEventSubscription::Subscribed: + lua_pushstring(L, "subscribed"); + break; + case PubSubEventSubscription::Unconfigured: + lua_pushstring(L, "unconfigured"); + break; + } + lua_setfield(L, -2, "subscription"); + if (payload->getSubscriptionID()) { + lua_pushstring(L, (*payload->getSubscriptionID()).c_str()); + lua_setfield(L, -2, "subscription_id"); + } + lua_pushstring(L, dateTimeToString(payload->getExpiry()).c_str()); + lua_setfield(L, -2, "expiry"); } -void PubSubEventSubscriptionConvertor::doConvertToLua(lua_State* L, boost::shared_ptr<PubSubEventSubscription> payload) { - lua_createtable(L, 0, 0); - lua_pushstring(L, payload->getNode().c_str()); - lua_setfield(L, -2, "node"); - lua_pushstring(L, payload->getJID().toString().c_str()); - lua_setfield(L, -2, "jid"); - switch (payload->getSubscription()) { - case PubSubEventSubscription::None: - lua_pushstring(L, "none"); - break; - case PubSubEventSubscription::Pending: - lua_pushstring(L, "pending"); - break; - case PubSubEventSubscription::Subscribed: - lua_pushstring(L, "subscribed"); - break; - case PubSubEventSubscription::Unconfigured: - lua_pushstring(L, "unconfigured"); - break; - } - lua_setfield(L, -2, "subscription"); - if (payload->getSubscriptionID()) { - lua_pushstring(L, (*payload->getSubscriptionID()).c_str()); - lua_setfield(L, -2, "subscriptionid"); - } - lua_pushstring(L, dateTimeToString(payload->getExpiry()).c_str()); - lua_setfield(L, -2, "expiry"); +boost::optional<LuaElementConvertor::Documentation> PubSubEventSubscriptionConvertor::getDocumentation() const { + return Documentation( + "PubSubEventSubscription", + "This table has the following fields:\n\n" + "- `node`: string\n" + "- `jid`: jid (string)\n" + "- `subscription`: `\"none\"`, `\"pending\"`, `\"subscribed\"`, or `\"unconfigured\"`\n" + "- `subscription_id`: string (Optional)\n" + "- `expiry`: datetime (string)\n" + ); } diff --git a/Sluift/ElementConvertors/PubSubEventSubscriptionConvertor.h b/Sluift/ElementConvertors/PubSubEventSubscriptionConvertor.h index fa04fb7..61d1f21 100644 --- a/Sluift/ElementConvertors/PubSubEventSubscriptionConvertor.h +++ b/Sluift/ElementConvertors/PubSubEventSubscriptionConvertor.h @@ -1,28 +1,25 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <Swiften/Elements/PubSubEventSubscription.h> #include <Sluift/GenericLuaElementConvertor.h> -#include <Swiften/Elements/PubSubEventSubscription.h> namespace Swift { - class LuaElementConvertors; - - class PubSubEventSubscriptionConvertor : public GenericLuaElementConvertor<PubSubEventSubscription> { - public: - PubSubEventSubscriptionConvertor(LuaElementConvertors* convertors); - virtual ~PubSubEventSubscriptionConvertor(); + class LuaElementConvertors; - virtual boost::shared_ptr<PubSubEventSubscription> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE; - virtual void doConvertToLua(lua_State*, boost::shared_ptr<PubSubEventSubscription>) SWIFTEN_OVERRIDE; + class PubSubEventSubscriptionConvertor : public GenericLuaElementConvertor<PubSubEventSubscription> { + public: + PubSubEventSubscriptionConvertor(); + virtual ~PubSubEventSubscriptionConvertor() override; - private: - LuaElementConvertors* convertors; - }; + virtual std::shared_ptr<PubSubEventSubscription> doConvertFromLua(lua_State*) override; + virtual void doConvertToLua(lua_State*, std::shared_ptr<PubSubEventSubscription>) override; + virtual boost::optional<Documentation> getDocumentation() const override; + }; } diff --git a/Sluift/ElementConvertors/PubSubItemConvertor.cpp b/Sluift/ElementConvertors/PubSubItemConvertor.cpp index e06065b..b46419a 100644 --- a/Sluift/ElementConvertors/PubSubItemConvertor.cpp +++ b/Sluift/ElementConvertors/PubSubItemConvertor.cpp @@ -1,72 +1,80 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #include <Sluift/ElementConvertors/PubSubItemConvertor.h> -#include <lua.hpp> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> + #include <boost/numeric/conversion/cast.hpp> -#include <Sluift/LuaElementConvertors.h> -#include <Swiften/Base/foreach.h> +#include <lua.hpp> -#pragma clang diagnostic ignored "-Wunused-private-field" +#include <Sluift/LuaElementConvertors.h> using namespace Swift; -PubSubItemConvertor::PubSubItemConvertor(LuaElementConvertors* convertors) : - GenericLuaElementConvertor<PubSubItem>("pubsub_item"), - convertors(convertors) { +PubSubItemConvertor::PubSubItemConvertor(LuaElementConvertors* convertors) : + GenericLuaElementConvertor<PubSubItem>("pubsub_item"), + convertors(convertors) { } PubSubItemConvertor::~PubSubItemConvertor() { } -boost::shared_ptr<PubSubItem> PubSubItemConvertor::doConvertFromLua(lua_State* L) { - boost::shared_ptr<PubSubItem> result = boost::make_shared<PubSubItem>(); - lua_getfield(L, -1, "data"); - if (lua_type(L, -1) == LUA_TTABLE) { - std::vector< boost::shared_ptr<Payload> > items; - for(size_t i = 0; i < lua_objlen(L, -1); ++i) { - lua_pushnumber(L, i + 1); - lua_gettable(L, -2); - if (!lua_isnil(L, -1)) { - if (boost::shared_ptr<Payload> payload = convertors->convertFromLua(L, -1)) { - items.push_back(payload); - } - } - lua_pop(L, 1); - } +std::shared_ptr<PubSubItem> PubSubItemConvertor::doConvertFromLua(lua_State* L) { + std::shared_ptr<PubSubItem> result = std::make_shared<PubSubItem>(); + lua_getfield(L, -1, "data"); + if (lua_type(L, -1) == LUA_TTABLE) { + std::vector< std::shared_ptr<Payload> > items; + for(size_t i = 0; i < lua_rawlen(L, -1); ++i) { + lua_pushnumber(L, i + 1); + lua_gettable(L, -2); + if (!lua_isnil(L, -1)) { + if (std::shared_ptr<Payload> payload = std::dynamic_pointer_cast<Payload>(convertors->convertFromLua(L, -1))) { + items.push_back(payload); + } + } + lua_pop(L, 1); + } + + result->setData(items); + } + lua_pop(L, 1); + lua_getfield(L, -1, "id"); + if (lua_isstring(L, -1)) { + result->setID(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + return result; +} - result->setData(items); - } - lua_pop(L, 1); - lua_getfield(L, -1, "id"); - if (lua_isstring(L, -1)) { - result->setID(std::string(lua_tostring(L, -1))); - } - lua_pop(L, 1); - return result; +void PubSubItemConvertor::doConvertToLua(lua_State* L, std::shared_ptr<PubSubItem> payload) { + lua_createtable(L, 0, 0); + if (!payload->getData().empty()) { + lua_createtable(L, boost::numeric_cast<int>(payload->getData().size()), 0); + { + int i = 0; + for (auto&& item : payload->getData()) { + if (convertors->convertToLua(L, item) > 0) { + lua_rawseti(L, -2, boost::numeric_cast<int>(i+1)); + ++i; + } + } + } + lua_setfield(L, -2, "data"); + } + lua_pushstring(L, payload->getID().c_str()); + lua_setfield(L, -2, "id"); } -void PubSubItemConvertor::doConvertToLua(lua_State* L, boost::shared_ptr<PubSubItem> payload) { - lua_createtable(L, 0, 0); - if (!payload->getData().empty()) { - lua_createtable(L, boost::numeric_cast<int>(payload->getData().size()), 0); - { - int i = 0; - foreach(boost::shared_ptr<Payload> item, payload->getData()) { - if (convertors->convertToLua(L, item) > 0) { - lua_rawseti(L, -2, boost::numeric_cast<int>(i+1)); - ++i; - } - } - } - lua_setfield(L, -2, "data"); - } - lua_pushstring(L, payload->getID().c_str()); - lua_setfield(L, -2, "id"); +boost::optional<LuaElementConvertor::Documentation> PubSubItemConvertor::getDocumentation() const { + return Documentation( + "PubSubItem", + "This table has the following fields:\n\n" + "- `data`: array<element (table)>\n" + "- `id`: string\n" + ); } diff --git a/Sluift/ElementConvertors/PubSubItemConvertor.h b/Sluift/ElementConvertors/PubSubItemConvertor.h index 176e1c4..87c3809 100644 --- a/Sluift/ElementConvertors/PubSubItemConvertor.h +++ b/Sluift/ElementConvertors/PubSubItemConvertor.h @@ -1,28 +1,28 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <Swiften/Elements/PubSubItem.h> #include <Sluift/GenericLuaElementConvertor.h> -#include <Swiften/Elements/PubSubItem.h> namespace Swift { - class LuaElementConvertors; + class LuaElementConvertors; - class PubSubItemConvertor : public GenericLuaElementConvertor<PubSubItem> { - public: - PubSubItemConvertor(LuaElementConvertors* convertors); - virtual ~PubSubItemConvertor(); + class PubSubItemConvertor : public GenericLuaElementConvertor<PubSubItem> { + public: + PubSubItemConvertor(LuaElementConvertors* convertors); + virtual ~PubSubItemConvertor() override; - virtual boost::shared_ptr<PubSubItem> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE; - virtual void doConvertToLua(lua_State*, boost::shared_ptr<PubSubItem>) SWIFTEN_OVERRIDE; + virtual std::shared_ptr<PubSubItem> doConvertFromLua(lua_State*) override; + virtual void doConvertToLua(lua_State*, std::shared_ptr<PubSubItem>) override; + virtual boost::optional<Documentation> getDocumentation() const override; - private: - LuaElementConvertors* convertors; - }; + private: + LuaElementConvertors* convertors; + }; } diff --git a/Sluift/ElementConvertors/PubSubItemsConvertor.cpp b/Sluift/ElementConvertors/PubSubItemsConvertor.cpp index 5ecb72e..0bb8eb9 100644 --- a/Sluift/ElementConvertors/PubSubItemsConvertor.cpp +++ b/Sluift/ElementConvertors/PubSubItemsConvertor.cpp @@ -1,86 +1,96 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #include <Sluift/ElementConvertors/PubSubItemsConvertor.h> -#include <lua.hpp> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> + #include <boost/numeric/conversion/cast.hpp> -#include <Sluift/LuaElementConvertors.h> -#include <Swiften/Base/foreach.h> +#include <lua.hpp> -#pragma clang diagnostic ignored "-Wunused-private-field" +#include <Sluift/LuaElementConvertors.h> using namespace Swift; -PubSubItemsConvertor::PubSubItemsConvertor(LuaElementConvertors* convertors) : - GenericLuaElementConvertor<PubSubItems>("pubsub_items"), - convertors(convertors) { +PubSubItemsConvertor::PubSubItemsConvertor(LuaElementConvertors* convertors) : + GenericLuaElementConvertor<PubSubItems>("pubsub_items"), + convertors(convertors) { } PubSubItemsConvertor::~PubSubItemsConvertor() { } -boost::shared_ptr<PubSubItems> PubSubItemsConvertor::doConvertFromLua(lua_State* L) { - boost::shared_ptr<PubSubItems> result = boost::make_shared<PubSubItems>(); - lua_getfield(L, -1, "node"); - if (lua_isstring(L, -1)) { - result->setNode(std::string(lua_tostring(L, -1))); - } - lua_pop(L, 1); - if (lua_type(L, -1) == LUA_TTABLE) { - std::vector< boost::shared_ptr<PubSubItem> > items; - for(size_t i = 0; i < lua_objlen(L, -1); ++i) { - lua_pushnumber(L, i + 1); - lua_gettable(L, -2); - if (!lua_isnil(L, -1)) { - if (boost::shared_ptr<PubSubItem> payload = boost::dynamic_pointer_cast<PubSubItem>(convertors->convertFromLuaUntyped(L, -1, "pubsub_item"))) { - items.push_back(payload); - } - } - lua_pop(L, 1); - } +std::shared_ptr<PubSubItems> PubSubItemsConvertor::doConvertFromLua(lua_State* L) { + std::shared_ptr<PubSubItems> result = std::make_shared<PubSubItems>(); + lua_getfield(L, -1, "node"); + if (lua_isstring(L, -1)) { + result->setNode(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + if (lua_type(L, -1) == LUA_TTABLE) { + std::vector< std::shared_ptr<PubSubItem> > items; + for(size_t i = 0; i < lua_rawlen(L, -1); ++i) { + lua_pushnumber(L, i + 1); + lua_gettable(L, -2); + if (!lua_isnil(L, -1)) { + if (std::shared_ptr<PubSubItem> payload = std::dynamic_pointer_cast<PubSubItem>(convertors->convertFromLuaUntyped(L, -1, "pubsub_item"))) { + items.push_back(payload); + } + } + lua_pop(L, 1); + } + + result->setItems(items); + } + lua_getfield(L, -1, "maximum_items"); + if (lua_isnumber(L, -1)) { + result->setMaximumItems(boost::numeric_cast<unsigned int>(lua_tonumber(L, -1))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "subscription_id"); + if (lua_isstring(L, -1)) { + result->setSubscriptionID(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + return result; +} - result->setItems(items); - } - lua_getfield(L, -1, "maximum_items"); - if (lua_isnumber(L, -1)) { - result->setMaximumItems(boost::numeric_cast<unsigned int>(lua_tonumber(L, -1))); - } - lua_pop(L, 1); - lua_getfield(L, -1, "subscriptionid"); - if (lua_isstring(L, -1)) { - result->setSubscriptionID(std::string(lua_tostring(L, -1))); - } - lua_pop(L, 1); - return result; +void PubSubItemsConvertor::doConvertToLua(lua_State* L, std::shared_ptr<PubSubItems> payload) { + lua_createtable(L, 0, 0); + lua_pushstring(L, payload->getNode().c_str()); + lua_setfield(L, -2, "node"); + if (!payload->getItems().empty()) { + { + int i = 0; + for (auto&& item : payload->getItems()) { + if (convertors->convertToLuaUntyped(L, item) > 0) { + lua_rawseti(L, -2, boost::numeric_cast<int>(i+1)); + ++i; + } + } + } + } + if (payload->getMaximumItems()) { + lua_pushnumber(L, (*payload->getMaximumItems())); + lua_setfield(L, -2, "maximum_items"); + } + if (payload->getSubscriptionID()) { + lua_pushstring(L, (*payload->getSubscriptionID()).c_str()); + lua_setfield(L, -2, "subscription_id"); + } } -void PubSubItemsConvertor::doConvertToLua(lua_State* L, boost::shared_ptr<PubSubItems> payload) { - lua_createtable(L, 0, 0); - lua_pushstring(L, payload->getNode().c_str()); - lua_setfield(L, -2, "node"); - if (!payload->getItems().empty()) { - { - int i = 0; - foreach(boost::shared_ptr<PubSubItem> item, payload->getItems()) { - if (convertors->convertToLuaUntyped(L, item) > 0) { - lua_rawseti(L, -2, boost::numeric_cast<int>(i+1)); - ++i; - } - } - } - } - if (payload->getMaximumItems()) { - lua_pushnumber(L, (*payload->getMaximumItems())); - lua_setfield(L, -2, "maximum_items"); - } - if (payload->getSubscriptionID()) { - lua_pushstring(L, (*payload->getSubscriptionID()).c_str()); - lua_setfield(L, -2, "subscriptionid"); - } +boost::optional<LuaElementConvertor::Documentation> PubSubItemsConvertor::getDocumentation() const { + return Documentation( + "PubSubItems", + "This table has the following fields:\n\n" + "- `node`: string\n" + "- `items`: array<@{PubSubItem}>\n" + "- `maximum_items`: number (Optional)\n" + "- `subscription_id`: string (Optional)\n" + ); } diff --git a/Sluift/ElementConvertors/PubSubItemsConvertor.h b/Sluift/ElementConvertors/PubSubItemsConvertor.h index 9978806..9e0f73a 100644 --- a/Sluift/ElementConvertors/PubSubItemsConvertor.h +++ b/Sluift/ElementConvertors/PubSubItemsConvertor.h @@ -1,28 +1,28 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <Swiften/Elements/PubSubItems.h> #include <Sluift/GenericLuaElementConvertor.h> -#include <Swiften/Elements/PubSubItems.h> namespace Swift { - class LuaElementConvertors; + class LuaElementConvertors; - class PubSubItemsConvertor : public GenericLuaElementConvertor<PubSubItems> { - public: - PubSubItemsConvertor(LuaElementConvertors* convertors); - virtual ~PubSubItemsConvertor(); + class PubSubItemsConvertor : public GenericLuaElementConvertor<PubSubItems> { + public: + PubSubItemsConvertor(LuaElementConvertors* convertors); + virtual ~PubSubItemsConvertor() override; - virtual boost::shared_ptr<PubSubItems> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE; - virtual void doConvertToLua(lua_State*, boost::shared_ptr<PubSubItems>) SWIFTEN_OVERRIDE; + virtual std::shared_ptr<PubSubItems> doConvertFromLua(lua_State*) override; + virtual void doConvertToLua(lua_State*, std::shared_ptr<PubSubItems>) override; + virtual boost::optional<Documentation> getDocumentation() const override; - private: - LuaElementConvertors* convertors; - }; + private: + LuaElementConvertors* convertors; + }; } diff --git a/Sluift/ElementConvertors/PubSubOptionsConvertor.cpp b/Sluift/ElementConvertors/PubSubOptionsConvertor.cpp index cc27973..3582c63 100644 --- a/Sluift/ElementConvertors/PubSubOptionsConvertor.cpp +++ b/Sluift/ElementConvertors/PubSubOptionsConvertor.cpp @@ -1,67 +1,76 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #include <Sluift/ElementConvertors/PubSubOptionsConvertor.h> -#include <lua.hpp> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> +#include <lua.hpp> #include <Sluift/LuaElementConvertors.h> -#pragma clang diagnostic ignored "-Wunused-private-field" - using namespace Swift; -PubSubOptionsConvertor::PubSubOptionsConvertor(LuaElementConvertors* convertors) : - GenericLuaElementConvertor<PubSubOptions>("pubsub_options"), - convertors(convertors) { +PubSubOptionsConvertor::PubSubOptionsConvertor(LuaElementConvertors* convertors) : + GenericLuaElementConvertor<PubSubOptions>("pubsub_options"), + convertors(convertors) { } PubSubOptionsConvertor::~PubSubOptionsConvertor() { } -boost::shared_ptr<PubSubOptions> PubSubOptionsConvertor::doConvertFromLua(lua_State* L) { - boost::shared_ptr<PubSubOptions> result = boost::make_shared<PubSubOptions>(); - lua_getfield(L, -1, "node"); - if (lua_isstring(L, -1)) { - result->setNode(std::string(lua_tostring(L, -1))); - } - lua_pop(L, 1); - lua_getfield(L, -1, "jid"); - if (lua_isstring(L, -1)) { - result->setJID(JID(std::string(lua_tostring(L, -1)))); - } - lua_pop(L, 1); - lua_getfield(L, -1, "data"); - if (!lua_isnil(L, -1)) { - if (boost::shared_ptr<Form> payload = boost::dynamic_pointer_cast<Form>(convertors->convertFromLuaUntyped(L, -1, "form"))) { - result->setData(payload); - } - } - lua_pop(L, 1); - lua_getfield(L, -1, "subscriptionid"); - if (lua_isstring(L, -1)) { - result->setSubscriptionID(std::string(lua_tostring(L, -1))); - } - lua_pop(L, 1); - return result; +std::shared_ptr<PubSubOptions> PubSubOptionsConvertor::doConvertFromLua(lua_State* L) { + std::shared_ptr<PubSubOptions> result = std::make_shared<PubSubOptions>(); + lua_getfield(L, -1, "node"); + if (lua_isstring(L, -1)) { + result->setNode(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "jid"); + if (lua_isstring(L, -1)) { + result->setJID(JID(std::string(lua_tostring(L, -1)))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "data"); + if (!lua_isnil(L, -1)) { + if (std::shared_ptr<Form> payload = std::dynamic_pointer_cast<Form>(convertors->convertFromLuaUntyped(L, -1, "form"))) { + result->setData(payload); + } + } + lua_pop(L, 1); + lua_getfield(L, -1, "subscription_id"); + if (lua_isstring(L, -1)) { + result->setSubscriptionID(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + return result; +} + +void PubSubOptionsConvertor::doConvertToLua(lua_State* L, std::shared_ptr<PubSubOptions> payload) { + lua_createtable(L, 0, 0); + lua_pushstring(L, payload->getNode().c_str()); + lua_setfield(L, -2, "node"); + lua_pushstring(L, payload->getJID().toString().c_str()); + lua_setfield(L, -2, "jid"); + if (convertors->convertToLuaUntyped(L, payload->getData()) > 0) { + lua_setfield(L, -2, "data"); + } + if (payload->getSubscriptionID()) { + lua_pushstring(L, (*payload->getSubscriptionID()).c_str()); + lua_setfield(L, -2, "subscription_id"); + } } -void PubSubOptionsConvertor::doConvertToLua(lua_State* L, boost::shared_ptr<PubSubOptions> payload) { - lua_createtable(L, 0, 0); - lua_pushstring(L, payload->getNode().c_str()); - lua_setfield(L, -2, "node"); - lua_pushstring(L, payload->getJID().toString().c_str()); - lua_setfield(L, -2, "jid"); - if (convertors->convertToLuaUntyped(L, payload->getData()) > 0) { - lua_setfield(L, -2, "data"); - } - if (payload->getSubscriptionID()) { - lua_pushstring(L, (*payload->getSubscriptionID()).c_str()); - lua_setfield(L, -2, "subscriptionid"); - } +boost::optional<LuaElementConvertor::Documentation> PubSubOptionsConvertor::getDocumentation() const { + return Documentation( + "PubSubOptions", + "This table has the following fields:\n\n" + "- `node`: string\n" + "- `jid`: jid (string)\n" + "- `data`: @{Form}\n" + "- `subscription_id`: string (Optional)\n" + ); } diff --git a/Sluift/ElementConvertors/PubSubOptionsConvertor.h b/Sluift/ElementConvertors/PubSubOptionsConvertor.h index 95a1dc8..add661a 100644 --- a/Sluift/ElementConvertors/PubSubOptionsConvertor.h +++ b/Sluift/ElementConvertors/PubSubOptionsConvertor.h @@ -1,28 +1,28 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <Swiften/Elements/PubSubOptions.h> #include <Sluift/GenericLuaElementConvertor.h> -#include <Swiften/Elements/PubSubOptions.h> namespace Swift { - class LuaElementConvertors; + class LuaElementConvertors; - class PubSubOptionsConvertor : public GenericLuaElementConvertor<PubSubOptions> { - public: - PubSubOptionsConvertor(LuaElementConvertors* convertors); - virtual ~PubSubOptionsConvertor(); + class PubSubOptionsConvertor : public GenericLuaElementConvertor<PubSubOptions> { + public: + PubSubOptionsConvertor(LuaElementConvertors* convertors); + virtual ~PubSubOptionsConvertor() override; - virtual boost::shared_ptr<PubSubOptions> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE; - virtual void doConvertToLua(lua_State*, boost::shared_ptr<PubSubOptions>) SWIFTEN_OVERRIDE; + virtual std::shared_ptr<PubSubOptions> doConvertFromLua(lua_State*) override; + virtual void doConvertToLua(lua_State*, std::shared_ptr<PubSubOptions>) override; + virtual boost::optional<Documentation> getDocumentation() const override; - private: - LuaElementConvertors* convertors; - }; + private: + LuaElementConvertors* convertors; + }; } diff --git a/Sluift/ElementConvertors/PubSubOwnerAffiliationConvertor.cpp b/Sluift/ElementConvertors/PubSubOwnerAffiliationConvertor.cpp index d7edaf4..15a800b 100644 --- a/Sluift/ElementConvertors/PubSubOwnerAffiliationConvertor.cpp +++ b/Sluift/ElementConvertors/PubSubOwnerAffiliationConvertor.cpp @@ -1,64 +1,88 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #include <Sluift/ElementConvertors/PubSubOwnerAffiliationConvertor.h> -#include <lua.hpp> -#include <boost/smart_ptr/make_shared.hpp> - - - +#include <memory> -#pragma clang diagnostic ignored "-Wunused-private-field" +#include <lua.hpp> using namespace Swift; -PubSubOwnerAffiliationConvertor::PubSubOwnerAffiliationConvertor(LuaElementConvertors* convertors) : - GenericLuaElementConvertor<PubSubOwnerAffiliation>("pubsub_owner_affiliation"), - convertors(convertors) { +PubSubOwnerAffiliationConvertor::PubSubOwnerAffiliationConvertor() : + GenericLuaElementConvertor<PubSubOwnerAffiliation>("pubsub_owner_affiliation") { } PubSubOwnerAffiliationConvertor::~PubSubOwnerAffiliationConvertor() { } -boost::shared_ptr<PubSubOwnerAffiliation> PubSubOwnerAffiliationConvertor::doConvertFromLua(lua_State* L) { - boost::shared_ptr<PubSubOwnerAffiliation> result = boost::make_shared<PubSubOwnerAffiliation>(); - lua_getfield(L, -1, "jid"); - if (lua_isstring(L, -1)) { - result->setJID(JID(std::string(lua_tostring(L, -1)))); - } - lua_pop(L, 1); - lua_getfield(L, -1, "type"); - lua_pop(L, 1); - return result; +std::shared_ptr<PubSubOwnerAffiliation> PubSubOwnerAffiliationConvertor::doConvertFromLua(lua_State* L) { + std::shared_ptr<PubSubOwnerAffiliation> result = std::make_shared<PubSubOwnerAffiliation>(); + lua_getfield(L, -1, "jid"); + if (lua_isstring(L, -1)) { + result->setJID(JID(std::string(lua_tostring(L, -1)))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "type"); + if (lua_isstring(L, -1)) { + if (std::string(lua_tostring(L, -1)) == "none") { + result->setType(PubSubOwnerAffiliation::None); + } + if (std::string(lua_tostring(L, -1)) == "member") { + result->setType(PubSubOwnerAffiliation::Member); + } + if (std::string(lua_tostring(L, -1)) == "outcast") { + result->setType(PubSubOwnerAffiliation::Outcast); + } + if (std::string(lua_tostring(L, -1)) == "owner") { + result->setType(PubSubOwnerAffiliation::Owner); + } + if (std::string(lua_tostring(L, -1)) == "publisher") { + result->setType(PubSubOwnerAffiliation::Publisher); + } + if (std::string(lua_tostring(L, -1)) == "publish_only") { + result->setType(PubSubOwnerAffiliation::PublishOnly); + } + } + lua_pop(L, 1); + return result; +} + +void PubSubOwnerAffiliationConvertor::doConvertToLua(lua_State* L, std::shared_ptr<PubSubOwnerAffiliation> payload) { + lua_createtable(L, 0, 0); + lua_pushstring(L, payload->getJID().toString().c_str()); + lua_setfield(L, -2, "jid"); + switch (payload->getType()) { + case PubSubOwnerAffiliation::None: + lua_pushstring(L, "none"); + break; + case PubSubOwnerAffiliation::Member: + lua_pushstring(L, "member"); + break; + case PubSubOwnerAffiliation::Outcast: + lua_pushstring(L, "outcast"); + break; + case PubSubOwnerAffiliation::Owner: + lua_pushstring(L, "owner"); + break; + case PubSubOwnerAffiliation::Publisher: + lua_pushstring(L, "publisher"); + break; + case PubSubOwnerAffiliation::PublishOnly: + lua_pushstring(L, "publish_only"); + break; + } + lua_setfield(L, -2, "type"); } -void PubSubOwnerAffiliationConvertor::doConvertToLua(lua_State* L, boost::shared_ptr<PubSubOwnerAffiliation> payload) { - lua_createtable(L, 0, 0); - lua_pushstring(L, payload->getJID().toString().c_str()); - lua_setfield(L, -2, "jid"); - switch (payload->getType()) { - case PubSubOwnerAffiliation::None: - lua_pushstring(L, "none"); - break; - case PubSubOwnerAffiliation::Member: - lua_pushstring(L, "member"); - break; - case PubSubOwnerAffiliation::Outcast: - lua_pushstring(L, "outcast"); - break; - case PubSubOwnerAffiliation::Owner: - lua_pushstring(L, "owner"); - break; - case PubSubOwnerAffiliation::Publisher: - lua_pushstring(L, "publisher"); - break; - case PubSubOwnerAffiliation::PublishOnly: - lua_pushstring(L, "publish_only"); - break; - } - lua_setfield(L, -2, "type"); +boost::optional<LuaElementConvertor::Documentation> PubSubOwnerAffiliationConvertor::getDocumentation() const { + return Documentation( + "PubSubOwnerAffiliation", + "This table has the following fields:\n\n" + "- `jid`: jid (string)\n" + "- `type`: `\"none\"`, `\"member\"`, `\"outcast\"`, `\"owner\"`, `\"publisher\"`, or `\"publish_only\"`\n" + ); } diff --git a/Sluift/ElementConvertors/PubSubOwnerAffiliationConvertor.h b/Sluift/ElementConvertors/PubSubOwnerAffiliationConvertor.h index 72bfaa1..92b001b 100644 --- a/Sluift/ElementConvertors/PubSubOwnerAffiliationConvertor.h +++ b/Sluift/ElementConvertors/PubSubOwnerAffiliationConvertor.h @@ -1,28 +1,25 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <Swiften/Elements/PubSubOwnerAffiliation.h> #include <Sluift/GenericLuaElementConvertor.h> -#include <Swiften/Elements/PubSubOwnerAffiliation.h> namespace Swift { - class LuaElementConvertors; - - class PubSubOwnerAffiliationConvertor : public GenericLuaElementConvertor<PubSubOwnerAffiliation> { - public: - PubSubOwnerAffiliationConvertor(LuaElementConvertors* convertors); - virtual ~PubSubOwnerAffiliationConvertor(); + class LuaElementConvertors; - virtual boost::shared_ptr<PubSubOwnerAffiliation> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE; - virtual void doConvertToLua(lua_State*, boost::shared_ptr<PubSubOwnerAffiliation>) SWIFTEN_OVERRIDE; + class PubSubOwnerAffiliationConvertor : public GenericLuaElementConvertor<PubSubOwnerAffiliation> { + public: + PubSubOwnerAffiliationConvertor(); + virtual ~PubSubOwnerAffiliationConvertor() override; - private: - LuaElementConvertors* convertors; - }; + virtual std::shared_ptr<PubSubOwnerAffiliation> doConvertFromLua(lua_State*) override; + virtual void doConvertToLua(lua_State*, std::shared_ptr<PubSubOwnerAffiliation>) override; + virtual boost::optional<Documentation> getDocumentation() const override; + }; } diff --git a/Sluift/ElementConvertors/PubSubOwnerAffiliationsConvertor.cpp b/Sluift/ElementConvertors/PubSubOwnerAffiliationsConvertor.cpp index bee8539..9ca76fc 100644 --- a/Sluift/ElementConvertors/PubSubOwnerAffiliationsConvertor.cpp +++ b/Sluift/ElementConvertors/PubSubOwnerAffiliationsConvertor.cpp @@ -1,68 +1,76 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #include <Sluift/ElementConvertors/PubSubOwnerAffiliationsConvertor.h> -#include <lua.hpp> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> + #include <boost/numeric/conversion/cast.hpp> -#include <Sluift/LuaElementConvertors.h> -#include <Swiften/Base/foreach.h> +#include <lua.hpp> -#pragma clang diagnostic ignored "-Wunused-private-field" +#include <Sluift/LuaElementConvertors.h> using namespace Swift; -PubSubOwnerAffiliationsConvertor::PubSubOwnerAffiliationsConvertor(LuaElementConvertors* convertors) : - GenericLuaElementConvertor<PubSubOwnerAffiliations>("pubsub_owner_affiliations"), - convertors(convertors) { +PubSubOwnerAffiliationsConvertor::PubSubOwnerAffiliationsConvertor(LuaElementConvertors* convertors) : + GenericLuaElementConvertor<PubSubOwnerAffiliations>("pubsub_owner_affiliations"), + convertors(convertors) { } PubSubOwnerAffiliationsConvertor::~PubSubOwnerAffiliationsConvertor() { } -boost::shared_ptr<PubSubOwnerAffiliations> PubSubOwnerAffiliationsConvertor::doConvertFromLua(lua_State* L) { - boost::shared_ptr<PubSubOwnerAffiliations> result = boost::make_shared<PubSubOwnerAffiliations>(); - lua_getfield(L, -1, "node"); - if (lua_isstring(L, -1)) { - result->setNode(std::string(lua_tostring(L, -1))); - } - lua_pop(L, 1); - if (lua_type(L, -1) == LUA_TTABLE) { - std::vector< boost::shared_ptr<PubSubOwnerAffiliation> > items; - for(size_t i = 0; i < lua_objlen(L, -1); ++i) { - lua_pushnumber(L, i + 1); - lua_gettable(L, -2); - if (!lua_isnil(L, -1)) { - if (boost::shared_ptr<PubSubOwnerAffiliation> payload = boost::dynamic_pointer_cast<PubSubOwnerAffiliation>(convertors->convertFromLuaUntyped(L, -1, "pubsub_owner_affiliation"))) { - items.push_back(payload); - } - } - lua_pop(L, 1); - } +std::shared_ptr<PubSubOwnerAffiliations> PubSubOwnerAffiliationsConvertor::doConvertFromLua(lua_State* L) { + std::shared_ptr<PubSubOwnerAffiliations> result = std::make_shared<PubSubOwnerAffiliations>(); + lua_getfield(L, -1, "node"); + if (lua_isstring(L, -1)) { + result->setNode(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + if (lua_type(L, -1) == LUA_TTABLE) { + std::vector< std::shared_ptr<PubSubOwnerAffiliation> > items; + for(size_t i = 0; i < lua_rawlen(L, -1); ++i) { + lua_pushnumber(L, i + 1); + lua_gettable(L, -2); + if (!lua_isnil(L, -1)) { + if (std::shared_ptr<PubSubOwnerAffiliation> payload = std::dynamic_pointer_cast<PubSubOwnerAffiliation>(convertors->convertFromLuaUntyped(L, -1, "pubsub_owner_affiliation"))) { + items.push_back(payload); + } + } + lua_pop(L, 1); + } + + result->setAffiliations(items); + } + return result; +} - result->setAffiliations(items); - } - return result; +void PubSubOwnerAffiliationsConvertor::doConvertToLua(lua_State* L, std::shared_ptr<PubSubOwnerAffiliations> payload) { + lua_createtable(L, 0, 0); + lua_pushstring(L, payload->getNode().c_str()); + lua_setfield(L, -2, "node"); + if (!payload->getAffiliations().empty()) { + { + int i = 0; + for (auto&& item : payload->getAffiliations()) { + if (convertors->convertToLuaUntyped(L, item) > 0) { + lua_rawseti(L, -2, boost::numeric_cast<int>(i+1)); + ++i; + } + } + } + } } -void PubSubOwnerAffiliationsConvertor::doConvertToLua(lua_State* L, boost::shared_ptr<PubSubOwnerAffiliations> payload) { - lua_createtable(L, 0, 0); - lua_pushstring(L, payload->getNode().c_str()); - lua_setfield(L, -2, "node"); - if (!payload->getAffiliations().empty()) { - { - int i = 0; - foreach(boost::shared_ptr<PubSubOwnerAffiliation> item, payload->getAffiliations()) { - if (convertors->convertToLuaUntyped(L, item) > 0) { - lua_rawseti(L, -2, boost::numeric_cast<int>(i+1)); - ++i; - } - } - } - } +boost::optional<LuaElementConvertor::Documentation> PubSubOwnerAffiliationsConvertor::getDocumentation() const { + return Documentation( + "PubSubOwnerAffiliations", + "This table has the following fields:\n\n" + "- `node`: string\n" + "- `affiliations`: array<@{PubSubOwnerAffiliation}>\n" + ); } diff --git a/Sluift/ElementConvertors/PubSubOwnerAffiliationsConvertor.h b/Sluift/ElementConvertors/PubSubOwnerAffiliationsConvertor.h index 377e108..f0c45a3 100644 --- a/Sluift/ElementConvertors/PubSubOwnerAffiliationsConvertor.h +++ b/Sluift/ElementConvertors/PubSubOwnerAffiliationsConvertor.h @@ -1,28 +1,28 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <Swiften/Elements/PubSubOwnerAffiliations.h> #include <Sluift/GenericLuaElementConvertor.h> -#include <Swiften/Elements/PubSubOwnerAffiliations.h> namespace Swift { - class LuaElementConvertors; + class LuaElementConvertors; - class PubSubOwnerAffiliationsConvertor : public GenericLuaElementConvertor<PubSubOwnerAffiliations> { - public: - PubSubOwnerAffiliationsConvertor(LuaElementConvertors* convertors); - virtual ~PubSubOwnerAffiliationsConvertor(); + class PubSubOwnerAffiliationsConvertor : public GenericLuaElementConvertor<PubSubOwnerAffiliations> { + public: + PubSubOwnerAffiliationsConvertor(LuaElementConvertors* convertors); + virtual ~PubSubOwnerAffiliationsConvertor() override; - virtual boost::shared_ptr<PubSubOwnerAffiliations> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE; - virtual void doConvertToLua(lua_State*, boost::shared_ptr<PubSubOwnerAffiliations>) SWIFTEN_OVERRIDE; + virtual std::shared_ptr<PubSubOwnerAffiliations> doConvertFromLua(lua_State*) override; + virtual void doConvertToLua(lua_State*, std::shared_ptr<PubSubOwnerAffiliations>) override; + virtual boost::optional<Documentation> getDocumentation() const override; - private: - LuaElementConvertors* convertors; - }; + private: + LuaElementConvertors* convertors; + }; } diff --git a/Sluift/ElementConvertors/PubSubOwnerConfigureConvertor.cpp b/Sluift/ElementConvertors/PubSubOwnerConfigureConvertor.cpp index 87505e1..d179152 100644 --- a/Sluift/ElementConvertors/PubSubOwnerConfigureConvertor.cpp +++ b/Sluift/ElementConvertors/PubSubOwnerConfigureConvertor.cpp @@ -1,53 +1,60 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #include <Sluift/ElementConvertors/PubSubOwnerConfigureConvertor.h> -#include <lua.hpp> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> +#include <lua.hpp> #include <Sluift/LuaElementConvertors.h> -#pragma clang diagnostic ignored "-Wunused-private-field" - using namespace Swift; -PubSubOwnerConfigureConvertor::PubSubOwnerConfigureConvertor(LuaElementConvertors* convertors) : - GenericLuaElementConvertor<PubSubOwnerConfigure>("pubsub_owner_configure"), - convertors(convertors) { +PubSubOwnerConfigureConvertor::PubSubOwnerConfigureConvertor(LuaElementConvertors* convertors) : + GenericLuaElementConvertor<PubSubOwnerConfigure>("pubsub_owner_configure"), + convertors(convertors) { } PubSubOwnerConfigureConvertor::~PubSubOwnerConfigureConvertor() { } -boost::shared_ptr<PubSubOwnerConfigure> PubSubOwnerConfigureConvertor::doConvertFromLua(lua_State* L) { - boost::shared_ptr<PubSubOwnerConfigure> result = boost::make_shared<PubSubOwnerConfigure>(); - lua_getfield(L, -1, "node"); - if (lua_isstring(L, -1)) { - result->setNode(std::string(lua_tostring(L, -1))); - } - lua_pop(L, 1); - lua_getfield(L, -1, "data"); - if (!lua_isnil(L, -1)) { - if (boost::shared_ptr<Form> payload = boost::dynamic_pointer_cast<Form>(convertors->convertFromLuaUntyped(L, -1, "form"))) { - result->setData(payload); - } - } - lua_pop(L, 1); - return result; +std::shared_ptr<PubSubOwnerConfigure> PubSubOwnerConfigureConvertor::doConvertFromLua(lua_State* L) { + std::shared_ptr<PubSubOwnerConfigure> result = std::make_shared<PubSubOwnerConfigure>(); + lua_getfield(L, -1, "node"); + if (lua_isstring(L, -1)) { + result->setNode(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "data"); + if (!lua_isnil(L, -1)) { + if (std::shared_ptr<Form> payload = std::dynamic_pointer_cast<Form>(convertors->convertFromLuaUntyped(L, -1, "form"))) { + result->setData(payload); + } + } + lua_pop(L, 1); + return result; +} + +void PubSubOwnerConfigureConvertor::doConvertToLua(lua_State* L, std::shared_ptr<PubSubOwnerConfigure> payload) { + lua_createtable(L, 0, 0); + if (payload->getNode()) { + lua_pushstring(L, (*payload->getNode()).c_str()); + lua_setfield(L, -2, "node"); + } + if (convertors->convertToLuaUntyped(L, payload->getData()) > 0) { + lua_setfield(L, -2, "data"); + } } -void PubSubOwnerConfigureConvertor::doConvertToLua(lua_State* L, boost::shared_ptr<PubSubOwnerConfigure> payload) { - lua_createtable(L, 0, 0); - if (payload->getNode()) { - lua_pushstring(L, (*payload->getNode()).c_str()); - lua_setfield(L, -2, "node"); - } - if (convertors->convertToLuaUntyped(L, payload->getData()) > 0) { - lua_setfield(L, -2, "data"); - } +boost::optional<LuaElementConvertor::Documentation> PubSubOwnerConfigureConvertor::getDocumentation() const { + return Documentation( + "PubSubOwnerConfigure", + "This table has the following fields:\n\n" + "- `node`: string (Optional)\n" + "- `data`: @{Form}\n" + ); } diff --git a/Sluift/ElementConvertors/PubSubOwnerConfigureConvertor.h b/Sluift/ElementConvertors/PubSubOwnerConfigureConvertor.h index 83b1153..9f0ed9f 100644 --- a/Sluift/ElementConvertors/PubSubOwnerConfigureConvertor.h +++ b/Sluift/ElementConvertors/PubSubOwnerConfigureConvertor.h @@ -1,28 +1,28 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <Swiften/Elements/PubSubOwnerConfigure.h> #include <Sluift/GenericLuaElementConvertor.h> -#include <Swiften/Elements/PubSubOwnerConfigure.h> namespace Swift { - class LuaElementConvertors; + class LuaElementConvertors; - class PubSubOwnerConfigureConvertor : public GenericLuaElementConvertor<PubSubOwnerConfigure> { - public: - PubSubOwnerConfigureConvertor(LuaElementConvertors* convertors); - virtual ~PubSubOwnerConfigureConvertor(); + class PubSubOwnerConfigureConvertor : public GenericLuaElementConvertor<PubSubOwnerConfigure> { + public: + PubSubOwnerConfigureConvertor(LuaElementConvertors* convertors); + virtual ~PubSubOwnerConfigureConvertor() override; - virtual boost::shared_ptr<PubSubOwnerConfigure> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE; - virtual void doConvertToLua(lua_State*, boost::shared_ptr<PubSubOwnerConfigure>) SWIFTEN_OVERRIDE; + virtual std::shared_ptr<PubSubOwnerConfigure> doConvertFromLua(lua_State*) override; + virtual void doConvertToLua(lua_State*, std::shared_ptr<PubSubOwnerConfigure>) override; + virtual boost::optional<Documentation> getDocumentation() const override; - private: - LuaElementConvertors* convertors; - }; + private: + LuaElementConvertors* convertors; + }; } diff --git a/Sluift/ElementConvertors/PubSubOwnerDefaultConvertor.cpp b/Sluift/ElementConvertors/PubSubOwnerDefaultConvertor.cpp index 17612cc..b2ff3de 100644 --- a/Sluift/ElementConvertors/PubSubOwnerDefaultConvertor.cpp +++ b/Sluift/ElementConvertors/PubSubOwnerDefaultConvertor.cpp @@ -1,44 +1,50 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #include <Sluift/ElementConvertors/PubSubOwnerDefaultConvertor.h> -#include <lua.hpp> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> +#include <lua.hpp> #include <Sluift/LuaElementConvertors.h> -#pragma clang diagnostic ignored "-Wunused-private-field" - using namespace Swift; -PubSubOwnerDefaultConvertor::PubSubOwnerDefaultConvertor(LuaElementConvertors* convertors) : - GenericLuaElementConvertor<PubSubOwnerDefault>("pubsub_owner_default"), - convertors(convertors) { +PubSubOwnerDefaultConvertor::PubSubOwnerDefaultConvertor(LuaElementConvertors* convertors) : + GenericLuaElementConvertor<PubSubOwnerDefault>("pubsub_owner_default"), + convertors(convertors) { } PubSubOwnerDefaultConvertor::~PubSubOwnerDefaultConvertor() { } -boost::shared_ptr<PubSubOwnerDefault> PubSubOwnerDefaultConvertor::doConvertFromLua(lua_State* L) { - boost::shared_ptr<PubSubOwnerDefault> result = boost::make_shared<PubSubOwnerDefault>(); - lua_getfield(L, -1, "data"); - if (!lua_isnil(L, -1)) { - if (boost::shared_ptr<Form> payload = boost::dynamic_pointer_cast<Form>(convertors->convertFromLuaUntyped(L, -1, "form"))) { - result->setData(payload); - } - } - lua_pop(L, 1); - return result; +std::shared_ptr<PubSubOwnerDefault> PubSubOwnerDefaultConvertor::doConvertFromLua(lua_State* L) { + std::shared_ptr<PubSubOwnerDefault> result = std::make_shared<PubSubOwnerDefault>(); + lua_getfield(L, -1, "data"); + if (!lua_isnil(L, -1)) { + if (std::shared_ptr<Form> payload = std::dynamic_pointer_cast<Form>(convertors->convertFromLuaUntyped(L, -1, "form"))) { + result->setData(payload); + } + } + lua_pop(L, 1); + return result; +} + +void PubSubOwnerDefaultConvertor::doConvertToLua(lua_State* L, std::shared_ptr<PubSubOwnerDefault> payload) { + lua_createtable(L, 0, 0); + if (convertors->convertToLuaUntyped(L, payload->getData()) > 0) { + lua_setfield(L, -2, "data"); + } } -void PubSubOwnerDefaultConvertor::doConvertToLua(lua_State* L, boost::shared_ptr<PubSubOwnerDefault> payload) { - lua_createtable(L, 0, 0); - if (convertors->convertToLuaUntyped(L, payload->getData()) > 0) { - lua_setfield(L, -2, "data"); - } +boost::optional<LuaElementConvertor::Documentation> PubSubOwnerDefaultConvertor::getDocumentation() const { + return Documentation( + "PubSubOwnerDefault", + "This table has the following fields:\n\n" + "- `data`: @{Form}\n" + ); } diff --git a/Sluift/ElementConvertors/PubSubOwnerDefaultConvertor.h b/Sluift/ElementConvertors/PubSubOwnerDefaultConvertor.h index 3a0f8ee..ab4a25b 100644 --- a/Sluift/ElementConvertors/PubSubOwnerDefaultConvertor.h +++ b/Sluift/ElementConvertors/PubSubOwnerDefaultConvertor.h @@ -1,28 +1,28 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <Swiften/Elements/PubSubOwnerDefault.h> #include <Sluift/GenericLuaElementConvertor.h> -#include <Swiften/Elements/PubSubOwnerDefault.h> namespace Swift { - class LuaElementConvertors; + class LuaElementConvertors; - class PubSubOwnerDefaultConvertor : public GenericLuaElementConvertor<PubSubOwnerDefault> { - public: - PubSubOwnerDefaultConvertor(LuaElementConvertors* convertors); - virtual ~PubSubOwnerDefaultConvertor(); + class PubSubOwnerDefaultConvertor : public GenericLuaElementConvertor<PubSubOwnerDefault> { + public: + PubSubOwnerDefaultConvertor(LuaElementConvertors* convertors); + virtual ~PubSubOwnerDefaultConvertor() override; - virtual boost::shared_ptr<PubSubOwnerDefault> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE; - virtual void doConvertToLua(lua_State*, boost::shared_ptr<PubSubOwnerDefault>) SWIFTEN_OVERRIDE; + virtual std::shared_ptr<PubSubOwnerDefault> doConvertFromLua(lua_State*) override; + virtual void doConvertToLua(lua_State*, std::shared_ptr<PubSubOwnerDefault>) override; + virtual boost::optional<Documentation> getDocumentation() const override; - private: - LuaElementConvertors* convertors; - }; + private: + LuaElementConvertors* convertors; + }; } diff --git a/Sluift/ElementConvertors/PubSubOwnerDeleteConvertor.cpp b/Sluift/ElementConvertors/PubSubOwnerDeleteConvertor.cpp index f67ed1e..3733d74 100644 --- a/Sluift/ElementConvertors/PubSubOwnerDeleteConvertor.cpp +++ b/Sluift/ElementConvertors/PubSubOwnerDeleteConvertor.cpp @@ -1,51 +1,58 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #include <Sluift/ElementConvertors/PubSubOwnerDeleteConvertor.h> -#include <lua.hpp> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> +#include <lua.hpp> #include <Sluift/LuaElementConvertors.h> -#pragma clang diagnostic ignored "-Wunused-private-field" - using namespace Swift; -PubSubOwnerDeleteConvertor::PubSubOwnerDeleteConvertor(LuaElementConvertors* convertors) : - GenericLuaElementConvertor<PubSubOwnerDelete>("pubsub_owner_delete"), - convertors(convertors) { +PubSubOwnerDeleteConvertor::PubSubOwnerDeleteConvertor(LuaElementConvertors* convertors) : + GenericLuaElementConvertor<PubSubOwnerDelete>("pubsub_owner_delete"), + convertors(convertors) { } PubSubOwnerDeleteConvertor::~PubSubOwnerDeleteConvertor() { } -boost::shared_ptr<PubSubOwnerDelete> PubSubOwnerDeleteConvertor::doConvertFromLua(lua_State* L) { - boost::shared_ptr<PubSubOwnerDelete> result = boost::make_shared<PubSubOwnerDelete>(); - lua_getfield(L, -1, "node"); - if (lua_isstring(L, -1)) { - result->setNode(std::string(lua_tostring(L, -1))); - } - lua_pop(L, 1); - lua_getfield(L, -1, "redirect"); - if (!lua_isnil(L, -1)) { - if (boost::shared_ptr<PubSubOwnerRedirect> payload = boost::dynamic_pointer_cast<PubSubOwnerRedirect>(convertors->convertFromLuaUntyped(L, -1, "pubsub_owner_redirect"))) { - result->setRedirect(payload); - } - } - lua_pop(L, 1); - return result; +std::shared_ptr<PubSubOwnerDelete> PubSubOwnerDeleteConvertor::doConvertFromLua(lua_State* L) { + std::shared_ptr<PubSubOwnerDelete> result = std::make_shared<PubSubOwnerDelete>(); + lua_getfield(L, -1, "node"); + if (lua_isstring(L, -1)) { + result->setNode(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "redirect"); + if (!lua_isnil(L, -1)) { + if (std::shared_ptr<PubSubOwnerRedirect> payload = std::dynamic_pointer_cast<PubSubOwnerRedirect>(convertors->convertFromLuaUntyped(L, -1, "pubsub_owner_redirect"))) { + result->setRedirect(payload); + } + } + lua_pop(L, 1); + return result; +} + +void PubSubOwnerDeleteConvertor::doConvertToLua(lua_State* L, std::shared_ptr<PubSubOwnerDelete> payload) { + lua_createtable(L, 0, 0); + lua_pushstring(L, payload->getNode().c_str()); + lua_setfield(L, -2, "node"); + if (convertors->convertToLuaUntyped(L, payload->getRedirect()) > 0) { + lua_setfield(L, -2, "redirect"); + } } -void PubSubOwnerDeleteConvertor::doConvertToLua(lua_State* L, boost::shared_ptr<PubSubOwnerDelete> payload) { - lua_createtable(L, 0, 0); - lua_pushstring(L, payload->getNode().c_str()); - lua_setfield(L, -2, "node"); - if (convertors->convertToLuaUntyped(L, payload->getRedirect()) > 0) { - lua_setfield(L, -2, "redirect"); - } +boost::optional<LuaElementConvertor::Documentation> PubSubOwnerDeleteConvertor::getDocumentation() const { + return Documentation( + "PubSubOwnerDelete", + "This table has the following fields:\n\n" + "- `node`: string\n" + "- `redirect`: @{PubSubOwnerRedirect}\n" + ); } diff --git a/Sluift/ElementConvertors/PubSubOwnerDeleteConvertor.h b/Sluift/ElementConvertors/PubSubOwnerDeleteConvertor.h index 7475e9c..8c44b5c 100644 --- a/Sluift/ElementConvertors/PubSubOwnerDeleteConvertor.h +++ b/Sluift/ElementConvertors/PubSubOwnerDeleteConvertor.h @@ -1,28 +1,28 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <Swiften/Elements/PubSubOwnerDelete.h> #include <Sluift/GenericLuaElementConvertor.h> -#include <Swiften/Elements/PubSubOwnerDelete.h> namespace Swift { - class LuaElementConvertors; + class LuaElementConvertors; - class PubSubOwnerDeleteConvertor : public GenericLuaElementConvertor<PubSubOwnerDelete> { - public: - PubSubOwnerDeleteConvertor(LuaElementConvertors* convertors); - virtual ~PubSubOwnerDeleteConvertor(); + class PubSubOwnerDeleteConvertor : public GenericLuaElementConvertor<PubSubOwnerDelete> { + public: + PubSubOwnerDeleteConvertor(LuaElementConvertors* convertors); + virtual ~PubSubOwnerDeleteConvertor() override; - virtual boost::shared_ptr<PubSubOwnerDelete> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE; - virtual void doConvertToLua(lua_State*, boost::shared_ptr<PubSubOwnerDelete>) SWIFTEN_OVERRIDE; + virtual std::shared_ptr<PubSubOwnerDelete> doConvertFromLua(lua_State*) override; + virtual void doConvertToLua(lua_State*, std::shared_ptr<PubSubOwnerDelete>) override; + virtual boost::optional<Documentation> getDocumentation() const override; - private: - LuaElementConvertors* convertors; - }; + private: + LuaElementConvertors* convertors; + }; } diff --git a/Sluift/ElementConvertors/PubSubOwnerPurgeConvertor.cpp b/Sluift/ElementConvertors/PubSubOwnerPurgeConvertor.cpp index a060db9..98c6355 100644 --- a/Sluift/ElementConvertors/PubSubOwnerPurgeConvertor.cpp +++ b/Sluift/ElementConvertors/PubSubOwnerPurgeConvertor.cpp @@ -1,41 +1,44 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #include <Sluift/ElementConvertors/PubSubOwnerPurgeConvertor.h> -#include <lua.hpp> -#include <boost/smart_ptr/make_shared.hpp> - - - +#include <memory> -#pragma clang diagnostic ignored "-Wunused-private-field" +#include <lua.hpp> using namespace Swift; -PubSubOwnerPurgeConvertor::PubSubOwnerPurgeConvertor(LuaElementConvertors* convertors) : - GenericLuaElementConvertor<PubSubOwnerPurge>("pubsub_owner_purge"), - convertors(convertors) { +PubSubOwnerPurgeConvertor::PubSubOwnerPurgeConvertor() : + GenericLuaElementConvertor<PubSubOwnerPurge>("pubsub_owner_purge") { } PubSubOwnerPurgeConvertor::~PubSubOwnerPurgeConvertor() { } -boost::shared_ptr<PubSubOwnerPurge> PubSubOwnerPurgeConvertor::doConvertFromLua(lua_State* L) { - boost::shared_ptr<PubSubOwnerPurge> result = boost::make_shared<PubSubOwnerPurge>(); - lua_getfield(L, -1, "node"); - if (lua_isstring(L, -1)) { - result->setNode(std::string(lua_tostring(L, -1))); - } - lua_pop(L, 1); - return result; +std::shared_ptr<PubSubOwnerPurge> PubSubOwnerPurgeConvertor::doConvertFromLua(lua_State* L) { + std::shared_ptr<PubSubOwnerPurge> result = std::make_shared<PubSubOwnerPurge>(); + lua_getfield(L, -1, "node"); + if (lua_isstring(L, -1)) { + result->setNode(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + return result; +} + +void PubSubOwnerPurgeConvertor::doConvertToLua(lua_State* L, std::shared_ptr<PubSubOwnerPurge> payload) { + lua_createtable(L, 0, 0); + lua_pushstring(L, payload->getNode().c_str()); + lua_setfield(L, -2, "node"); } -void PubSubOwnerPurgeConvertor::doConvertToLua(lua_State* L, boost::shared_ptr<PubSubOwnerPurge> payload) { - lua_createtable(L, 0, 0); - lua_pushstring(L, payload->getNode().c_str()); - lua_setfield(L, -2, "node"); +boost::optional<LuaElementConvertor::Documentation> PubSubOwnerPurgeConvertor::getDocumentation() const { + return Documentation( + "PubSubOwnerPurge", + "This table has the following fields:\n\n" + "- `node`: string\n" + ); } diff --git a/Sluift/ElementConvertors/PubSubOwnerPurgeConvertor.h b/Sluift/ElementConvertors/PubSubOwnerPurgeConvertor.h index 34c979b..b2cb565 100644 --- a/Sluift/ElementConvertors/PubSubOwnerPurgeConvertor.h +++ b/Sluift/ElementConvertors/PubSubOwnerPurgeConvertor.h @@ -1,28 +1,25 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <Swiften/Elements/PubSubOwnerPurge.h> #include <Sluift/GenericLuaElementConvertor.h> -#include <Swiften/Elements/PubSubOwnerPurge.h> namespace Swift { - class LuaElementConvertors; - - class PubSubOwnerPurgeConvertor : public GenericLuaElementConvertor<PubSubOwnerPurge> { - public: - PubSubOwnerPurgeConvertor(LuaElementConvertors* convertors); - virtual ~PubSubOwnerPurgeConvertor(); + class LuaElementConvertors; - virtual boost::shared_ptr<PubSubOwnerPurge> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE; - virtual void doConvertToLua(lua_State*, boost::shared_ptr<PubSubOwnerPurge>) SWIFTEN_OVERRIDE; + class PubSubOwnerPurgeConvertor : public GenericLuaElementConvertor<PubSubOwnerPurge> { + public: + PubSubOwnerPurgeConvertor(); + virtual ~PubSubOwnerPurgeConvertor() override; - private: - LuaElementConvertors* convertors; - }; + virtual std::shared_ptr<PubSubOwnerPurge> doConvertFromLua(lua_State*) override; + virtual void doConvertToLua(lua_State*, std::shared_ptr<PubSubOwnerPurge>) override; + virtual boost::optional<Documentation> getDocumentation() const override; + }; } diff --git a/Sluift/ElementConvertors/PubSubOwnerRedirectConvertor.cpp b/Sluift/ElementConvertors/PubSubOwnerRedirectConvertor.cpp index d11df72..8fc20d2 100644 --- a/Sluift/ElementConvertors/PubSubOwnerRedirectConvertor.cpp +++ b/Sluift/ElementConvertors/PubSubOwnerRedirectConvertor.cpp @@ -1,41 +1,44 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #include <Sluift/ElementConvertors/PubSubOwnerRedirectConvertor.h> -#include <lua.hpp> -#include <boost/smart_ptr/make_shared.hpp> - - - +#include <memory> -#pragma clang diagnostic ignored "-Wunused-private-field" +#include <lua.hpp> using namespace Swift; -PubSubOwnerRedirectConvertor::PubSubOwnerRedirectConvertor(LuaElementConvertors* convertors) : - GenericLuaElementConvertor<PubSubOwnerRedirect>("pubsub_owner_redirect"), - convertors(convertors) { +PubSubOwnerRedirectConvertor::PubSubOwnerRedirectConvertor() : + GenericLuaElementConvertor<PubSubOwnerRedirect>("pubsub_owner_redirect") { } PubSubOwnerRedirectConvertor::~PubSubOwnerRedirectConvertor() { } -boost::shared_ptr<PubSubOwnerRedirect> PubSubOwnerRedirectConvertor::doConvertFromLua(lua_State* L) { - boost::shared_ptr<PubSubOwnerRedirect> result = boost::make_shared<PubSubOwnerRedirect>(); - lua_getfield(L, -1, "uri"); - if (lua_isstring(L, -1)) { - result->setURI(std::string(lua_tostring(L, -1))); - } - lua_pop(L, 1); - return result; +std::shared_ptr<PubSubOwnerRedirect> PubSubOwnerRedirectConvertor::doConvertFromLua(lua_State* L) { + std::shared_ptr<PubSubOwnerRedirect> result = std::make_shared<PubSubOwnerRedirect>(); + lua_getfield(L, -1, "uri"); + if (lua_isstring(L, -1)) { + result->setURI(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + return result; +} + +void PubSubOwnerRedirectConvertor::doConvertToLua(lua_State* L, std::shared_ptr<PubSubOwnerRedirect> payload) { + lua_createtable(L, 0, 0); + lua_pushstring(L, payload->getURI().c_str()); + lua_setfield(L, -2, "uri"); } -void PubSubOwnerRedirectConvertor::doConvertToLua(lua_State* L, boost::shared_ptr<PubSubOwnerRedirect> payload) { - lua_createtable(L, 0, 0); - lua_pushstring(L, payload->getURI().c_str()); - lua_setfield(L, -2, "uri"); +boost::optional<LuaElementConvertor::Documentation> PubSubOwnerRedirectConvertor::getDocumentation() const { + return Documentation( + "PubSubOwnerRedirect", + "This table has the following fields:\n\n" + "- `uri`: string\n" + ); } diff --git a/Sluift/ElementConvertors/PubSubOwnerRedirectConvertor.h b/Sluift/ElementConvertors/PubSubOwnerRedirectConvertor.h index fc1ddce..433303f 100644 --- a/Sluift/ElementConvertors/PubSubOwnerRedirectConvertor.h +++ b/Sluift/ElementConvertors/PubSubOwnerRedirectConvertor.h @@ -1,28 +1,25 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <Swiften/Elements/PubSubOwnerRedirect.h> #include <Sluift/GenericLuaElementConvertor.h> -#include <Swiften/Elements/PubSubOwnerRedirect.h> namespace Swift { - class LuaElementConvertors; - - class PubSubOwnerRedirectConvertor : public GenericLuaElementConvertor<PubSubOwnerRedirect> { - public: - PubSubOwnerRedirectConvertor(LuaElementConvertors* convertors); - virtual ~PubSubOwnerRedirectConvertor(); + class LuaElementConvertors; - virtual boost::shared_ptr<PubSubOwnerRedirect> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE; - virtual void doConvertToLua(lua_State*, boost::shared_ptr<PubSubOwnerRedirect>) SWIFTEN_OVERRIDE; + class PubSubOwnerRedirectConvertor : public GenericLuaElementConvertor<PubSubOwnerRedirect> { + public: + PubSubOwnerRedirectConvertor(); + virtual ~PubSubOwnerRedirectConvertor() override; - private: - LuaElementConvertors* convertors; - }; + virtual std::shared_ptr<PubSubOwnerRedirect> doConvertFromLua(lua_State*) override; + virtual void doConvertToLua(lua_State*, std::shared_ptr<PubSubOwnerRedirect>) override; + virtual boost::optional<Documentation> getDocumentation() const override; + }; } diff --git a/Sluift/ElementConvertors/PubSubOwnerSubscriptionConvertor.cpp b/Sluift/ElementConvertors/PubSubOwnerSubscriptionConvertor.cpp index 0216874..e0b3687 100644 --- a/Sluift/ElementConvertors/PubSubOwnerSubscriptionConvertor.cpp +++ b/Sluift/ElementConvertors/PubSubOwnerSubscriptionConvertor.cpp @@ -1,58 +1,76 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #include <Sluift/ElementConvertors/PubSubOwnerSubscriptionConvertor.h> -#include <lua.hpp> -#include <boost/smart_ptr/make_shared.hpp> - - - +#include <memory> -#pragma clang diagnostic ignored "-Wunused-private-field" +#include <lua.hpp> using namespace Swift; -PubSubOwnerSubscriptionConvertor::PubSubOwnerSubscriptionConvertor(LuaElementConvertors* convertors) : - GenericLuaElementConvertor<PubSubOwnerSubscription>("pubsub_owner_subscription"), - convertors(convertors) { +PubSubOwnerSubscriptionConvertor::PubSubOwnerSubscriptionConvertor() : + GenericLuaElementConvertor<PubSubOwnerSubscription>("pubsub_owner_subscription") { } PubSubOwnerSubscriptionConvertor::~PubSubOwnerSubscriptionConvertor() { } -boost::shared_ptr<PubSubOwnerSubscription> PubSubOwnerSubscriptionConvertor::doConvertFromLua(lua_State* L) { - boost::shared_ptr<PubSubOwnerSubscription> result = boost::make_shared<PubSubOwnerSubscription>(); - lua_getfield(L, -1, "jid"); - if (lua_isstring(L, -1)) { - result->setJID(JID(std::string(lua_tostring(L, -1)))); - } - lua_pop(L, 1); - lua_getfield(L, -1, "subscription"); - lua_pop(L, 1); - return result; +std::shared_ptr<PubSubOwnerSubscription> PubSubOwnerSubscriptionConvertor::doConvertFromLua(lua_State* L) { + std::shared_ptr<PubSubOwnerSubscription> result = std::make_shared<PubSubOwnerSubscription>(); + lua_getfield(L, -1, "jid"); + if (lua_isstring(L, -1)) { + result->setJID(JID(std::string(lua_tostring(L, -1)))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "subscription"); + if (lua_isstring(L, -1)) { + if (std::string(lua_tostring(L, -1)) == "none") { + result->setSubscription(PubSubOwnerSubscription::None); + } + if (std::string(lua_tostring(L, -1)) == "pending") { + result->setSubscription(PubSubOwnerSubscription::Pending); + } + if (std::string(lua_tostring(L, -1)) == "subscribed") { + result->setSubscription(PubSubOwnerSubscription::Subscribed); + } + if (std::string(lua_tostring(L, -1)) == "unconfigured") { + result->setSubscription(PubSubOwnerSubscription::Unconfigured); + } + } + lua_pop(L, 1); + return result; +} + +void PubSubOwnerSubscriptionConvertor::doConvertToLua(lua_State* L, std::shared_ptr<PubSubOwnerSubscription> payload) { + lua_createtable(L, 0, 0); + lua_pushstring(L, payload->getJID().toString().c_str()); + lua_setfield(L, -2, "jid"); + switch (payload->getSubscription()) { + case PubSubOwnerSubscription::None: + lua_pushstring(L, "none"); + break; + case PubSubOwnerSubscription::Pending: + lua_pushstring(L, "pending"); + break; + case PubSubOwnerSubscription::Subscribed: + lua_pushstring(L, "subscribed"); + break; + case PubSubOwnerSubscription::Unconfigured: + lua_pushstring(L, "unconfigured"); + break; + } + lua_setfield(L, -2, "subscription"); } -void PubSubOwnerSubscriptionConvertor::doConvertToLua(lua_State* L, boost::shared_ptr<PubSubOwnerSubscription> payload) { - lua_createtable(L, 0, 0); - lua_pushstring(L, payload->getJID().toString().c_str()); - lua_setfield(L, -2, "jid"); - switch (payload->getSubscription()) { - case PubSubOwnerSubscription::None: - lua_pushstring(L, "none"); - break; - case PubSubOwnerSubscription::Pending: - lua_pushstring(L, "pending"); - break; - case PubSubOwnerSubscription::Subscribed: - lua_pushstring(L, "subscribed"); - break; - case PubSubOwnerSubscription::Unconfigured: - lua_pushstring(L, "unconfigured"); - break; - } - lua_setfield(L, -2, "subscription"); +boost::optional<LuaElementConvertor::Documentation> PubSubOwnerSubscriptionConvertor::getDocumentation() const { + return Documentation( + "PubSubOwnerSubscription", + "This table has the following fields:\n\n" + "- `jid`: jid (string)\n" + "- `subscription`: `\"none\"`, `\"pending\"`, `\"subscribed\"`, or `\"unconfigured\"`\n" + ); } diff --git a/Sluift/ElementConvertors/PubSubOwnerSubscriptionConvertor.h b/Sluift/ElementConvertors/PubSubOwnerSubscriptionConvertor.h index ca80c82..bf054b3 100644 --- a/Sluift/ElementConvertors/PubSubOwnerSubscriptionConvertor.h +++ b/Sluift/ElementConvertors/PubSubOwnerSubscriptionConvertor.h @@ -1,28 +1,25 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <Swiften/Elements/PubSubOwnerSubscription.h> #include <Sluift/GenericLuaElementConvertor.h> -#include <Swiften/Elements/PubSubOwnerSubscription.h> namespace Swift { - class LuaElementConvertors; - - class PubSubOwnerSubscriptionConvertor : public GenericLuaElementConvertor<PubSubOwnerSubscription> { - public: - PubSubOwnerSubscriptionConvertor(LuaElementConvertors* convertors); - virtual ~PubSubOwnerSubscriptionConvertor(); + class LuaElementConvertors; - virtual boost::shared_ptr<PubSubOwnerSubscription> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE; - virtual void doConvertToLua(lua_State*, boost::shared_ptr<PubSubOwnerSubscription>) SWIFTEN_OVERRIDE; + class PubSubOwnerSubscriptionConvertor : public GenericLuaElementConvertor<PubSubOwnerSubscription> { + public: + PubSubOwnerSubscriptionConvertor(); + virtual ~PubSubOwnerSubscriptionConvertor() override; - private: - LuaElementConvertors* convertors; - }; + virtual std::shared_ptr<PubSubOwnerSubscription> doConvertFromLua(lua_State*) override; + virtual void doConvertToLua(lua_State*, std::shared_ptr<PubSubOwnerSubscription>) override; + virtual boost::optional<Documentation> getDocumentation() const override; + }; } diff --git a/Sluift/ElementConvertors/PubSubOwnerSubscriptionsConvertor.cpp b/Sluift/ElementConvertors/PubSubOwnerSubscriptionsConvertor.cpp index 045cf12..3530efe 100644 --- a/Sluift/ElementConvertors/PubSubOwnerSubscriptionsConvertor.cpp +++ b/Sluift/ElementConvertors/PubSubOwnerSubscriptionsConvertor.cpp @@ -1,68 +1,76 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #include <Sluift/ElementConvertors/PubSubOwnerSubscriptionsConvertor.h> -#include <lua.hpp> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> + #include <boost/numeric/conversion/cast.hpp> -#include <Sluift/LuaElementConvertors.h> -#include <Swiften/Base/foreach.h> +#include <lua.hpp> -#pragma clang diagnostic ignored "-Wunused-private-field" +#include <Sluift/LuaElementConvertors.h> using namespace Swift; -PubSubOwnerSubscriptionsConvertor::PubSubOwnerSubscriptionsConvertor(LuaElementConvertors* convertors) : - GenericLuaElementConvertor<PubSubOwnerSubscriptions>("pubsub_owner_subscriptions"), - convertors(convertors) { +PubSubOwnerSubscriptionsConvertor::PubSubOwnerSubscriptionsConvertor(LuaElementConvertors* convertors) : + GenericLuaElementConvertor<PubSubOwnerSubscriptions>("pubsub_owner_subscriptions"), + convertors(convertors) { } PubSubOwnerSubscriptionsConvertor::~PubSubOwnerSubscriptionsConvertor() { } -boost::shared_ptr<PubSubOwnerSubscriptions> PubSubOwnerSubscriptionsConvertor::doConvertFromLua(lua_State* L) { - boost::shared_ptr<PubSubOwnerSubscriptions> result = boost::make_shared<PubSubOwnerSubscriptions>(); - lua_getfield(L, -1, "node"); - if (lua_isstring(L, -1)) { - result->setNode(std::string(lua_tostring(L, -1))); - } - lua_pop(L, 1); - if (lua_type(L, -1) == LUA_TTABLE) { - std::vector< boost::shared_ptr<PubSubOwnerSubscription> > items; - for(size_t i = 0; i < lua_objlen(L, -1); ++i) { - lua_pushnumber(L, i + 1); - lua_gettable(L, -2); - if (!lua_isnil(L, -1)) { - if (boost::shared_ptr<PubSubOwnerSubscription> payload = boost::dynamic_pointer_cast<PubSubOwnerSubscription>(convertors->convertFromLuaUntyped(L, -1, "pubsub_owner_subscription"))) { - items.push_back(payload); - } - } - lua_pop(L, 1); - } +std::shared_ptr<PubSubOwnerSubscriptions> PubSubOwnerSubscriptionsConvertor::doConvertFromLua(lua_State* L) { + std::shared_ptr<PubSubOwnerSubscriptions> result = std::make_shared<PubSubOwnerSubscriptions>(); + lua_getfield(L, -1, "node"); + if (lua_isstring(L, -1)) { + result->setNode(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + if (lua_type(L, -1) == LUA_TTABLE) { + std::vector< std::shared_ptr<PubSubOwnerSubscription> > items; + for(size_t i = 0; i < lua_rawlen(L, -1); ++i) { + lua_pushnumber(L, i + 1); + lua_gettable(L, -2); + if (!lua_isnil(L, -1)) { + if (std::shared_ptr<PubSubOwnerSubscription> payload = std::dynamic_pointer_cast<PubSubOwnerSubscription>(convertors->convertFromLuaUntyped(L, -1, "pubsub_owner_subscription"))) { + items.push_back(payload); + } + } + lua_pop(L, 1); + } + + result->setSubscriptions(items); + } + return result; +} - result->setSubscriptions(items); - } - return result; +void PubSubOwnerSubscriptionsConvertor::doConvertToLua(lua_State* L, std::shared_ptr<PubSubOwnerSubscriptions> payload) { + lua_createtable(L, 0, 0); + lua_pushstring(L, payload->getNode().c_str()); + lua_setfield(L, -2, "node"); + if (!payload->getSubscriptions().empty()) { + { + int i = 0; + for (auto&& item : payload->getSubscriptions()) { + if (convertors->convertToLuaUntyped(L, item) > 0) { + lua_rawseti(L, -2, boost::numeric_cast<int>(i+1)); + ++i; + } + } + } + } } -void PubSubOwnerSubscriptionsConvertor::doConvertToLua(lua_State* L, boost::shared_ptr<PubSubOwnerSubscriptions> payload) { - lua_createtable(L, 0, 0); - lua_pushstring(L, payload->getNode().c_str()); - lua_setfield(L, -2, "node"); - if (!payload->getSubscriptions().empty()) { - { - int i = 0; - foreach(boost::shared_ptr<PubSubOwnerSubscription> item, payload->getSubscriptions()) { - if (convertors->convertToLuaUntyped(L, item) > 0) { - lua_rawseti(L, -2, boost::numeric_cast<int>(i+1)); - ++i; - } - } - } - } +boost::optional<LuaElementConvertor::Documentation> PubSubOwnerSubscriptionsConvertor::getDocumentation() const { + return Documentation( + "PubSubOwnerSubscriptions", + "This table has the following fields:\n\n" + "- `node`: string\n" + "- `subscriptions`: array<@{PubSubOwnerSubscription}>\n" + ); } diff --git a/Sluift/ElementConvertors/PubSubOwnerSubscriptionsConvertor.h b/Sluift/ElementConvertors/PubSubOwnerSubscriptionsConvertor.h index 2e12c93..2e3f9be 100644 --- a/Sluift/ElementConvertors/PubSubOwnerSubscriptionsConvertor.h +++ b/Sluift/ElementConvertors/PubSubOwnerSubscriptionsConvertor.h @@ -1,28 +1,28 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <Swiften/Elements/PubSubOwnerSubscriptions.h> #include <Sluift/GenericLuaElementConvertor.h> -#include <Swiften/Elements/PubSubOwnerSubscriptions.h> namespace Swift { - class LuaElementConvertors; + class LuaElementConvertors; - class PubSubOwnerSubscriptionsConvertor : public GenericLuaElementConvertor<PubSubOwnerSubscriptions> { - public: - PubSubOwnerSubscriptionsConvertor(LuaElementConvertors* convertors); - virtual ~PubSubOwnerSubscriptionsConvertor(); + class PubSubOwnerSubscriptionsConvertor : public GenericLuaElementConvertor<PubSubOwnerSubscriptions> { + public: + PubSubOwnerSubscriptionsConvertor(LuaElementConvertors* convertors); + virtual ~PubSubOwnerSubscriptionsConvertor() override; - virtual boost::shared_ptr<PubSubOwnerSubscriptions> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE; - virtual void doConvertToLua(lua_State*, boost::shared_ptr<PubSubOwnerSubscriptions>) SWIFTEN_OVERRIDE; + virtual std::shared_ptr<PubSubOwnerSubscriptions> doConvertFromLua(lua_State*) override; + virtual void doConvertToLua(lua_State*, std::shared_ptr<PubSubOwnerSubscriptions>) override; + virtual boost::optional<Documentation> getDocumentation() const override; - private: - LuaElementConvertors* convertors; - }; + private: + LuaElementConvertors* convertors; + }; } diff --git a/Sluift/ElementConvertors/PubSubPublishConvertor.cpp b/Sluift/ElementConvertors/PubSubPublishConvertor.cpp index 880d9fc..d8a2742 100644 --- a/Sluift/ElementConvertors/PubSubPublishConvertor.cpp +++ b/Sluift/ElementConvertors/PubSubPublishConvertor.cpp @@ -1,72 +1,80 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #include <Sluift/ElementConvertors/PubSubPublishConvertor.h> -#include <lua.hpp> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> + #include <boost/numeric/conversion/cast.hpp> -#include <Sluift/LuaElementConvertors.h> -#include <Swiften/Base/foreach.h> +#include <lua.hpp> -#pragma clang diagnostic ignored "-Wunused-private-field" +#include <Sluift/LuaElementConvertors.h> using namespace Swift; -PubSubPublishConvertor::PubSubPublishConvertor(LuaElementConvertors* convertors) : - GenericLuaElementConvertor<PubSubPublish>("pubsub_publish"), - convertors(convertors) { +PubSubPublishConvertor::PubSubPublishConvertor(LuaElementConvertors* convertors) : + GenericLuaElementConvertor<PubSubPublish>("pubsub_publish"), + convertors(convertors) { } PubSubPublishConvertor::~PubSubPublishConvertor() { } -boost::shared_ptr<PubSubPublish> PubSubPublishConvertor::doConvertFromLua(lua_State* L) { - boost::shared_ptr<PubSubPublish> result = boost::make_shared<PubSubPublish>(); - lua_getfield(L, -1, "node"); - if (lua_isstring(L, -1)) { - result->setNode(std::string(lua_tostring(L, -1))); - } - lua_pop(L, 1); - lua_getfield(L, -1, "items"); - if (lua_type(L, -1) == LUA_TTABLE) { - std::vector< boost::shared_ptr<PubSubItem> > items; - for(size_t i = 0; i < lua_objlen(L, -1); ++i) { - lua_pushnumber(L, i + 1); - lua_gettable(L, -2); - if (!lua_isnil(L, -1)) { - if (boost::shared_ptr<PubSubItem> payload = boost::dynamic_pointer_cast<PubSubItem>(convertors->convertFromLuaUntyped(L, -1, "pubsub_item"))) { - items.push_back(payload); - } - } - lua_pop(L, 1); - } +std::shared_ptr<PubSubPublish> PubSubPublishConvertor::doConvertFromLua(lua_State* L) { + std::shared_ptr<PubSubPublish> result = std::make_shared<PubSubPublish>(); + lua_getfield(L, -1, "node"); + if (lua_isstring(L, -1)) { + result->setNode(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "items"); + if (lua_type(L, -1) == LUA_TTABLE) { + std::vector< std::shared_ptr<PubSubItem> > items; + for(size_t i = 0; i < lua_rawlen(L, -1); ++i) { + lua_pushnumber(L, i + 1); + lua_gettable(L, -2); + if (!lua_isnil(L, -1)) { + if (std::shared_ptr<PubSubItem> payload = std::dynamic_pointer_cast<PubSubItem>(convertors->convertFromLuaUntyped(L, -1, "pubsub_item"))) { + items.push_back(payload); + } + } + lua_pop(L, 1); + } + + result->setItems(items); + } + lua_pop(L, 1); + return result; +} - result->setItems(items); - } - lua_pop(L, 1); - return result; +void PubSubPublishConvertor::doConvertToLua(lua_State* L, std::shared_ptr<PubSubPublish> payload) { + lua_createtable(L, 0, 0); + lua_pushstring(L, payload->getNode().c_str()); + lua_setfield(L, -2, "node"); + if (!payload->getItems().empty()) { + lua_createtable(L, boost::numeric_cast<int>(payload->getItems().size()), 0); + { + int i = 0; + for (auto&& item : payload->getItems()) { + if (convertors->convertToLuaUntyped(L, item) > 0) { + lua_rawseti(L, -2, boost::numeric_cast<int>(i+1)); + ++i; + } + } + } + lua_setfield(L, -2, "items"); + } } -void PubSubPublishConvertor::doConvertToLua(lua_State* L, boost::shared_ptr<PubSubPublish> payload) { - lua_createtable(L, 0, 0); - lua_pushstring(L, payload->getNode().c_str()); - lua_setfield(L, -2, "node"); - if (!payload->getItems().empty()) { - lua_createtable(L, boost::numeric_cast<int>(payload->getItems().size()), 0); - { - int i = 0; - foreach(boost::shared_ptr<PubSubItem> item, payload->getItems()) { - if (convertors->convertToLuaUntyped(L, item) > 0) { - lua_rawseti(L, -2, boost::numeric_cast<int>(i+1)); - ++i; - } - } - } - lua_setfield(L, -2, "items"); - } +boost::optional<LuaElementConvertor::Documentation> PubSubPublishConvertor::getDocumentation() const { + return Documentation( + "PubSubPublish", + "This table has the following fields:\n\n" + "- `node`: string\n" + "- `items`: array<@{PubSubItem}>\n" + ); } diff --git a/Sluift/ElementConvertors/PubSubPublishConvertor.h b/Sluift/ElementConvertors/PubSubPublishConvertor.h index 4415566..ae28f14 100644 --- a/Sluift/ElementConvertors/PubSubPublishConvertor.h +++ b/Sluift/ElementConvertors/PubSubPublishConvertor.h @@ -1,28 +1,28 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <Swiften/Elements/PubSubPublish.h> #include <Sluift/GenericLuaElementConvertor.h> -#include <Swiften/Elements/PubSubPublish.h> namespace Swift { - class LuaElementConvertors; + class LuaElementConvertors; - class PubSubPublishConvertor : public GenericLuaElementConvertor<PubSubPublish> { - public: - PubSubPublishConvertor(LuaElementConvertors* convertors); - virtual ~PubSubPublishConvertor(); + class PubSubPublishConvertor : public GenericLuaElementConvertor<PubSubPublish> { + public: + PubSubPublishConvertor(LuaElementConvertors* convertors); + virtual ~PubSubPublishConvertor() override; - virtual boost::shared_ptr<PubSubPublish> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE; - virtual void doConvertToLua(lua_State*, boost::shared_ptr<PubSubPublish>) SWIFTEN_OVERRIDE; + virtual std::shared_ptr<PubSubPublish> doConvertFromLua(lua_State*) override; + virtual void doConvertToLua(lua_State*, std::shared_ptr<PubSubPublish>) override; + virtual boost::optional<Documentation> getDocumentation() const override; - private: - LuaElementConvertors* convertors; - }; + private: + LuaElementConvertors* convertors; + }; } diff --git a/Sluift/ElementConvertors/PubSubRetractConvertor.cpp b/Sluift/ElementConvertors/PubSubRetractConvertor.cpp index 61ca3df..c27ad7d 100644 --- a/Sluift/ElementConvertors/PubSubRetractConvertor.cpp +++ b/Sluift/ElementConvertors/PubSubRetractConvertor.cpp @@ -1,79 +1,90 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #include <Sluift/ElementConvertors/PubSubRetractConvertor.h> -#include <lua.hpp> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> + #include <boost/numeric/conversion/cast.hpp> -#include <Sluift/LuaElementConvertors.h> -#include <Swiften/Base/foreach.h> +#include <lua.hpp> -#pragma clang diagnostic ignored "-Wunused-private-field" +#include <Sluift/LuaElementConvertors.h> using namespace Swift; -PubSubRetractConvertor::PubSubRetractConvertor(LuaElementConvertors* convertors) : - GenericLuaElementConvertor<PubSubRetract>("pubsub_retract"), - convertors(convertors) { +PubSubRetractConvertor::PubSubRetractConvertor(LuaElementConvertors* convertors) : + GenericLuaElementConvertor<PubSubRetract>("pubsub_retract"), + convertors(convertors) { } PubSubRetractConvertor::~PubSubRetractConvertor() { } -boost::shared_ptr<PubSubRetract> PubSubRetractConvertor::doConvertFromLua(lua_State* L) { - boost::shared_ptr<PubSubRetract> result = boost::make_shared<PubSubRetract>(); - lua_getfield(L, -1, "node"); - if (lua_isstring(L, -1)) { - result->setNode(std::string(lua_tostring(L, -1))); - } - lua_pop(L, 1); - lua_getfield(L, -1, "items"); - if (lua_type(L, -1) == LUA_TTABLE) { - std::vector< boost::shared_ptr<PubSubItem> > items; - for(size_t i = 0; i < lua_objlen(L, -1); ++i) { - lua_pushnumber(L, i + 1); - lua_gettable(L, -2); - if (!lua_isnil(L, -1)) { - if (boost::shared_ptr<PubSubItem> payload = boost::dynamic_pointer_cast<PubSubItem>(convertors->convertFromLuaUntyped(L, -1, "pubsub_item"))) { - items.push_back(payload); - } - } - lua_pop(L, 1); - } +std::shared_ptr<PubSubRetract> PubSubRetractConvertor::doConvertFromLua(lua_State* L) { + std::shared_ptr<PubSubRetract> result = std::make_shared<PubSubRetract>(); + lua_getfield(L, -1, "node"); + if (lua_isstring(L, -1)) { + result->setNode(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "items"); + if (lua_type(L, -1) == LUA_TTABLE) { + std::vector< std::shared_ptr<PubSubItem> > items; + for(size_t i = 0; i < lua_rawlen(L, -1); ++i) { + lua_pushnumber(L, i + 1); + lua_gettable(L, -2); + if (!lua_isnil(L, -1)) { + if (std::shared_ptr<PubSubItem> payload = std::dynamic_pointer_cast<PubSubItem>(convertors->convertFromLuaUntyped(L, -1, "pubsub_item"))) { + items.push_back(payload); + } + } + lua_pop(L, 1); + } + + result->setItems(items); + } + lua_pop(L, 1); + lua_getfield(L, -1, "notify"); + if (lua_isboolean(L, -1)) { + result->setNotify(lua_toboolean(L, -1)); + } + lua_pop(L, 1); + return result; +} - result->setItems(items); - } - lua_pop(L, 1); - lua_getfield(L, -1, "notify"); - if (lua_isboolean(L, -1)) { - result->setNotify(lua_toboolean(L, -1)); - } - lua_pop(L, 1); - return result; +void PubSubRetractConvertor::doConvertToLua(lua_State* L, std::shared_ptr<PubSubRetract> payload) { + lua_createtable(L, 0, 0); + lua_pushstring(L, payload->getNode().c_str()); + lua_setfield(L, -2, "node"); + if (!payload->getItems().empty()) { + lua_createtable(L, boost::numeric_cast<int>(payload->getItems().size()), 0); + { + int i = 0; + for (auto&& item : payload->getItems()) { + if (convertors->convertToLuaUntyped(L, item) > 0) { + lua_rawseti(L, -2, boost::numeric_cast<int>(i+1)); + ++i; + } + } + } + lua_setfield(L, -2, "items"); + } + if (payload->isNotify().is_initialized()) { + lua_pushboolean(L, payload->isNotify().get_value_or(false)); + lua_setfield(L, -2, "notify"); + } } -void PubSubRetractConvertor::doConvertToLua(lua_State* L, boost::shared_ptr<PubSubRetract> payload) { - lua_createtable(L, 0, 0); - lua_pushstring(L, payload->getNode().c_str()); - lua_setfield(L, -2, "node"); - if (!payload->getItems().empty()) { - lua_createtable(L, boost::numeric_cast<int>(payload->getItems().size()), 0); - { - int i = 0; - foreach(boost::shared_ptr<PubSubItem> item, payload->getItems()) { - if (convertors->convertToLuaUntyped(L, item) > 0) { - lua_rawseti(L, -2, boost::numeric_cast<int>(i+1)); - ++i; - } - } - } - lua_setfield(L, -2, "items"); - } - lua_pushboolean(L, payload->isNotify()); - lua_setfield(L, -2, "notify"); +boost::optional<LuaElementConvertor::Documentation> PubSubRetractConvertor::getDocumentation() const { + return Documentation( + "PubSubRetract", + "This table has the following fields:\n\n" + "- `node`: string\n" + "- `items`: array<@{PubSubItem}>\n" + "- `notify`: boolean\n" + ); } diff --git a/Sluift/ElementConvertors/PubSubRetractConvertor.h b/Sluift/ElementConvertors/PubSubRetractConvertor.h index 80d888b..ca15ca7 100644 --- a/Sluift/ElementConvertors/PubSubRetractConvertor.h +++ b/Sluift/ElementConvertors/PubSubRetractConvertor.h @@ -1,28 +1,28 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <Swiften/Elements/PubSubRetract.h> #include <Sluift/GenericLuaElementConvertor.h> -#include <Swiften/Elements/PubSubRetract.h> namespace Swift { - class LuaElementConvertors; + class LuaElementConvertors; - class PubSubRetractConvertor : public GenericLuaElementConvertor<PubSubRetract> { - public: - PubSubRetractConvertor(LuaElementConvertors* convertors); - virtual ~PubSubRetractConvertor(); + class PubSubRetractConvertor : public GenericLuaElementConvertor<PubSubRetract> { + public: + PubSubRetractConvertor(LuaElementConvertors* convertors); + virtual ~PubSubRetractConvertor() override; - virtual boost::shared_ptr<PubSubRetract> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE; - virtual void doConvertToLua(lua_State*, boost::shared_ptr<PubSubRetract>) SWIFTEN_OVERRIDE; + virtual std::shared_ptr<PubSubRetract> doConvertFromLua(lua_State*) override; + virtual void doConvertToLua(lua_State*, std::shared_ptr<PubSubRetract>) override; + virtual boost::optional<Documentation> getDocumentation() const override; - private: - LuaElementConvertors* convertors; - }; + private: + LuaElementConvertors* convertors; + }; } diff --git a/Sluift/ElementConvertors/PubSubSubscribeConvertor.cpp b/Sluift/ElementConvertors/PubSubSubscribeConvertor.cpp index 06d6447..bb5eb61 100644 --- a/Sluift/ElementConvertors/PubSubSubscribeConvertor.cpp +++ b/Sluift/ElementConvertors/PubSubSubscribeConvertor.cpp @@ -1,60 +1,68 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #include <Sluift/ElementConvertors/PubSubSubscribeConvertor.h> -#include <lua.hpp> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> +#include <lua.hpp> #include <Sluift/LuaElementConvertors.h> -#pragma clang diagnostic ignored "-Wunused-private-field" - using namespace Swift; -PubSubSubscribeConvertor::PubSubSubscribeConvertor(LuaElementConvertors* convertors) : - GenericLuaElementConvertor<PubSubSubscribe>("pubsub_subscribe"), - convertors(convertors) { +PubSubSubscribeConvertor::PubSubSubscribeConvertor(LuaElementConvertors* convertors) : + GenericLuaElementConvertor<PubSubSubscribe>("pubsub_subscribe"), + convertors(convertors) { } PubSubSubscribeConvertor::~PubSubSubscribeConvertor() { } -boost::shared_ptr<PubSubSubscribe> PubSubSubscribeConvertor::doConvertFromLua(lua_State* L) { - boost::shared_ptr<PubSubSubscribe> result = boost::make_shared<PubSubSubscribe>(); - lua_getfield(L, -1, "node"); - if (lua_isstring(L, -1)) { - result->setNode(std::string(lua_tostring(L, -1))); - } - lua_pop(L, 1); - lua_getfield(L, -1, "jid"); - if (lua_isstring(L, -1)) { - result->setJID(JID(std::string(lua_tostring(L, -1)))); - } - lua_pop(L, 1); - lua_getfield(L, -1, "options"); - if (!lua_isnil(L, -1)) { - if (boost::shared_ptr<PubSubOptions> payload = boost::dynamic_pointer_cast<PubSubOptions>(convertors->convertFromLuaUntyped(L, -1, "pubsub_options"))) { - result->setOptions(payload); - } - } - lua_pop(L, 1); - return result; +std::shared_ptr<PubSubSubscribe> PubSubSubscribeConvertor::doConvertFromLua(lua_State* L) { + std::shared_ptr<PubSubSubscribe> result = std::make_shared<PubSubSubscribe>(); + lua_getfield(L, -1, "node"); + if (lua_isstring(L, -1)) { + result->setNode(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "jid"); + if (lua_isstring(L, -1)) { + result->setJID(JID(std::string(lua_tostring(L, -1)))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "options"); + if (!lua_isnil(L, -1)) { + if (std::shared_ptr<PubSubOptions> payload = std::dynamic_pointer_cast<PubSubOptions>(convertors->convertFromLuaUntyped(L, -1, "pubsub_options"))) { + result->setOptions(payload); + } + } + lua_pop(L, 1); + return result; +} + +void PubSubSubscribeConvertor::doConvertToLua(lua_State* L, std::shared_ptr<PubSubSubscribe> payload) { + lua_createtable(L, 0, 0); + if (payload->getNode()) { + lua_pushstring(L, (*payload->getNode()).c_str()); + lua_setfield(L, -2, "node"); + } + lua_pushstring(L, payload->getJID().toString().c_str()); + lua_setfield(L, -2, "jid"); + if (convertors->convertToLuaUntyped(L, payload->getOptions()) > 0) { + lua_setfield(L, -2, "options"); + } } -void PubSubSubscribeConvertor::doConvertToLua(lua_State* L, boost::shared_ptr<PubSubSubscribe> payload) { - lua_createtable(L, 0, 0); - if (payload->getNode()) { - lua_pushstring(L, (*payload->getNode()).c_str()); - lua_setfield(L, -2, "node"); - } - lua_pushstring(L, payload->getJID().toString().c_str()); - lua_setfield(L, -2, "jid"); - if (convertors->convertToLuaUntyped(L, payload->getOptions()) > 0) { - lua_setfield(L, -2, "options"); - } +boost::optional<LuaElementConvertor::Documentation> PubSubSubscribeConvertor::getDocumentation() const { + return Documentation( + "PubSubSubscribe", + "This table has the following fields:\n\n" + "- `node`: string (Optional)\n" + "- `jid`: jid (string)\n" + "- `options`: @{PubSubOptions}\n" + ); } diff --git a/Sluift/ElementConvertors/PubSubSubscribeConvertor.h b/Sluift/ElementConvertors/PubSubSubscribeConvertor.h index 2073c09..5f9d224 100644 --- a/Sluift/ElementConvertors/PubSubSubscribeConvertor.h +++ b/Sluift/ElementConvertors/PubSubSubscribeConvertor.h @@ -1,28 +1,28 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <Swiften/Elements/PubSubSubscribe.h> #include <Sluift/GenericLuaElementConvertor.h> -#include <Swiften/Elements/PubSubSubscribe.h> namespace Swift { - class LuaElementConvertors; + class LuaElementConvertors; - class PubSubSubscribeConvertor : public GenericLuaElementConvertor<PubSubSubscribe> { - public: - PubSubSubscribeConvertor(LuaElementConvertors* convertors); - virtual ~PubSubSubscribeConvertor(); + class PubSubSubscribeConvertor : public GenericLuaElementConvertor<PubSubSubscribe> { + public: + PubSubSubscribeConvertor(LuaElementConvertors* convertors); + virtual ~PubSubSubscribeConvertor() override; - virtual boost::shared_ptr<PubSubSubscribe> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE; - virtual void doConvertToLua(lua_State*, boost::shared_ptr<PubSubSubscribe>) SWIFTEN_OVERRIDE; + virtual std::shared_ptr<PubSubSubscribe> doConvertFromLua(lua_State*) override; + virtual void doConvertToLua(lua_State*, std::shared_ptr<PubSubSubscribe>) override; + virtual boost::optional<Documentation> getDocumentation() const override; - private: - LuaElementConvertors* convertors; - }; + private: + LuaElementConvertors* convertors; + }; } diff --git a/Sluift/ElementConvertors/PubSubSubscribeOptionsConvertor.cpp b/Sluift/ElementConvertors/PubSubSubscribeOptionsConvertor.cpp index e8053fb..01da15f 100644 --- a/Sluift/ElementConvertors/PubSubSubscribeOptionsConvertor.cpp +++ b/Sluift/ElementConvertors/PubSubSubscribeOptionsConvertor.cpp @@ -1,41 +1,44 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #include <Sluift/ElementConvertors/PubSubSubscribeOptionsConvertor.h> -#include <lua.hpp> -#include <boost/smart_ptr/make_shared.hpp> - - - +#include <memory> -#pragma clang diagnostic ignored "-Wunused-private-field" +#include <lua.hpp> using namespace Swift; -PubSubSubscribeOptionsConvertor::PubSubSubscribeOptionsConvertor(LuaElementConvertors* convertors) : - GenericLuaElementConvertor<PubSubSubscribeOptions>("pubsub_subscribe_options"), - convertors(convertors) { +PubSubSubscribeOptionsConvertor::PubSubSubscribeOptionsConvertor() : + GenericLuaElementConvertor<PubSubSubscribeOptions>("pubsub_subscribe_options") { } PubSubSubscribeOptionsConvertor::~PubSubSubscribeOptionsConvertor() { } -boost::shared_ptr<PubSubSubscribeOptions> PubSubSubscribeOptionsConvertor::doConvertFromLua(lua_State* L) { - boost::shared_ptr<PubSubSubscribeOptions> result = boost::make_shared<PubSubSubscribeOptions>(); - lua_getfield(L, -1, "required"); - if (lua_isboolean(L, -1)) { - result->setRequired(lua_toboolean(L, -1)); - } - lua_pop(L, 1); - return result; +std::shared_ptr<PubSubSubscribeOptions> PubSubSubscribeOptionsConvertor::doConvertFromLua(lua_State* L) { + std::shared_ptr<PubSubSubscribeOptions> result = std::make_shared<PubSubSubscribeOptions>(); + lua_getfield(L, -1, "required"); + if (lua_isboolean(L, -1)) { + result->setRequired(lua_toboolean(L, -1)); + } + lua_pop(L, 1); + return result; +} + +void PubSubSubscribeOptionsConvertor::doConvertToLua(lua_State* L, std::shared_ptr<PubSubSubscribeOptions> payload) { + lua_createtable(L, 0, 0); + lua_pushboolean(L, payload->isRequired()); + lua_setfield(L, -2, "required"); } -void PubSubSubscribeOptionsConvertor::doConvertToLua(lua_State* L, boost::shared_ptr<PubSubSubscribeOptions> payload) { - lua_createtable(L, 0, 0); - lua_pushboolean(L, payload->isRequired()); - lua_setfield(L, -2, "required"); +boost::optional<LuaElementConvertor::Documentation> PubSubSubscribeOptionsConvertor::getDocumentation() const { + return Documentation( + "PubSubSubscribeOptions", + "This table has the following fields:\n\n" + "- `required`: boolean\n" + ); } diff --git a/Sluift/ElementConvertors/PubSubSubscribeOptionsConvertor.h b/Sluift/ElementConvertors/PubSubSubscribeOptionsConvertor.h index 71e1baf..d853989 100644 --- a/Sluift/ElementConvertors/PubSubSubscribeOptionsConvertor.h +++ b/Sluift/ElementConvertors/PubSubSubscribeOptionsConvertor.h @@ -1,28 +1,25 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <Swiften/Elements/PubSubSubscribeOptions.h> #include <Sluift/GenericLuaElementConvertor.h> -#include <Swiften/Elements/PubSubSubscribeOptions.h> namespace Swift { - class LuaElementConvertors; - - class PubSubSubscribeOptionsConvertor : public GenericLuaElementConvertor<PubSubSubscribeOptions> { - public: - PubSubSubscribeOptionsConvertor(LuaElementConvertors* convertors); - virtual ~PubSubSubscribeOptionsConvertor(); + class LuaElementConvertors; - virtual boost::shared_ptr<PubSubSubscribeOptions> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE; - virtual void doConvertToLua(lua_State*, boost::shared_ptr<PubSubSubscribeOptions>) SWIFTEN_OVERRIDE; + class PubSubSubscribeOptionsConvertor : public GenericLuaElementConvertor<PubSubSubscribeOptions> { + public: + PubSubSubscribeOptionsConvertor(); + virtual ~PubSubSubscribeOptionsConvertor() override; - private: - LuaElementConvertors* convertors; - }; + virtual std::shared_ptr<PubSubSubscribeOptions> doConvertFromLua(lua_State*) override; + virtual void doConvertToLua(lua_State*, std::shared_ptr<PubSubSubscribeOptions>) override; + virtual boost::optional<Documentation> getDocumentation() const override; + }; } diff --git a/Sluift/ElementConvertors/PubSubSubscriptionConvertor.cpp b/Sluift/ElementConvertors/PubSubSubscriptionConvertor.cpp index 9ec9fec..65c6474 100644 --- a/Sluift/ElementConvertors/PubSubSubscriptionConvertor.cpp +++ b/Sluift/ElementConvertors/PubSubSubscriptionConvertor.cpp @@ -1,86 +1,110 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #include <Sluift/ElementConvertors/PubSubSubscriptionConvertor.h> -#include <lua.hpp> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> +#include <lua.hpp> #include <Sluift/LuaElementConvertors.h> -#pragma clang diagnostic ignored "-Wunused-private-field" - using namespace Swift; -PubSubSubscriptionConvertor::PubSubSubscriptionConvertor(LuaElementConvertors* convertors) : - GenericLuaElementConvertor<PubSubSubscription>("pubsub_subscription"), - convertors(convertors) { +PubSubSubscriptionConvertor::PubSubSubscriptionConvertor(LuaElementConvertors* convertors) : + GenericLuaElementConvertor<PubSubSubscription>("pubsub_subscription"), + convertors(convertors) { } PubSubSubscriptionConvertor::~PubSubSubscriptionConvertor() { } -boost::shared_ptr<PubSubSubscription> PubSubSubscriptionConvertor::doConvertFromLua(lua_State* L) { - boost::shared_ptr<PubSubSubscription> result = boost::make_shared<PubSubSubscription>(); - lua_getfield(L, -1, "node"); - if (lua_isstring(L, -1)) { - result->setNode(std::string(lua_tostring(L, -1))); - } - lua_pop(L, 1); - lua_getfield(L, -1, "subscriptionid"); - if (lua_isstring(L, -1)) { - result->setSubscriptionID(std::string(lua_tostring(L, -1))); - } - lua_pop(L, 1); - lua_getfield(L, -1, "jid"); - if (lua_isstring(L, -1)) { - result->setJID(JID(std::string(lua_tostring(L, -1)))); - } - lua_pop(L, 1); - lua_getfield(L, -1, "options"); - if (!lua_isnil(L, -1)) { - if (boost::shared_ptr<PubSubSubscribeOptions> payload = boost::dynamic_pointer_cast<PubSubSubscribeOptions>(convertors->convertFromLuaUntyped(L, -1, "pubsub_subscribe_options"))) { - result->setOptions(payload); - } - } - lua_pop(L, 1); - lua_getfield(L, -1, "subscription"); - lua_pop(L, 1); - return result; +std::shared_ptr<PubSubSubscription> PubSubSubscriptionConvertor::doConvertFromLua(lua_State* L) { + std::shared_ptr<PubSubSubscription> result = std::make_shared<PubSubSubscription>(); + lua_getfield(L, -1, "node"); + if (lua_isstring(L, -1)) { + result->setNode(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "subscription_id"); + if (lua_isstring(L, -1)) { + result->setSubscriptionID(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "jid"); + if (lua_isstring(L, -1)) { + result->setJID(JID(std::string(lua_tostring(L, -1)))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "options"); + if (!lua_isnil(L, -1)) { + if (std::shared_ptr<PubSubSubscribeOptions> payload = std::dynamic_pointer_cast<PubSubSubscribeOptions>(convertors->convertFromLuaUntyped(L, -1, "pubsub_subscribe_options"))) { + result->setOptions(payload); + } + } + lua_pop(L, 1); + lua_getfield(L, -1, "subscription"); + if (lua_isstring(L, -1)) { + if (std::string(lua_tostring(L, -1)) == "none") { + result->setSubscription(PubSubSubscription::None); + } + if (std::string(lua_tostring(L, -1)) == "pending") { + result->setSubscription(PubSubSubscription::Pending); + } + if (std::string(lua_tostring(L, -1)) == "subscribed") { + result->setSubscription(PubSubSubscription::Subscribed); + } + if (std::string(lua_tostring(L, -1)) == "unconfigured") { + result->setSubscription(PubSubSubscription::Unconfigured); + } + } + lua_pop(L, 1); + return result; +} + +void PubSubSubscriptionConvertor::doConvertToLua(lua_State* L, std::shared_ptr<PubSubSubscription> payload) { + lua_createtable(L, 0, 0); + if (payload->getNode()) { + lua_pushstring(L, (*payload->getNode()).c_str()); + lua_setfield(L, -2, "node"); + } + if (payload->getSubscriptionID()) { + lua_pushstring(L, (*payload->getSubscriptionID()).c_str()); + lua_setfield(L, -2, "subscription_id"); + } + lua_pushstring(L, payload->getJID().toString().c_str()); + lua_setfield(L, -2, "jid"); + if (convertors->convertToLuaUntyped(L, payload->getOptions()) > 0) { + lua_setfield(L, -2, "options"); + } + switch (payload->getSubscription()) { + case PubSubSubscription::None: + lua_pushstring(L, "none"); + break; + case PubSubSubscription::Pending: + lua_pushstring(L, "pending"); + break; + case PubSubSubscription::Subscribed: + lua_pushstring(L, "subscribed"); + break; + case PubSubSubscription::Unconfigured: + lua_pushstring(L, "unconfigured"); + break; + } + lua_setfield(L, -2, "subscription"); } -void PubSubSubscriptionConvertor::doConvertToLua(lua_State* L, boost::shared_ptr<PubSubSubscription> payload) { - lua_createtable(L, 0, 0); - if (payload->getNode()) { - lua_pushstring(L, (*payload->getNode()).c_str()); - lua_setfield(L, -2, "node"); - } - if (payload->getSubscriptionID()) { - lua_pushstring(L, (*payload->getSubscriptionID()).c_str()); - lua_setfield(L, -2, "subscriptionid"); - } - lua_pushstring(L, payload->getJID().toString().c_str()); - lua_setfield(L, -2, "jid"); - if (convertors->convertToLuaUntyped(L, payload->getOptions()) > 0) { - lua_setfield(L, -2, "options"); - } - switch (payload->getSubscription()) { - case PubSubSubscription::None: - lua_pushstring(L, "none"); - break; - case PubSubSubscription::Pending: - lua_pushstring(L, "pending"); - break; - case PubSubSubscription::Subscribed: - lua_pushstring(L, "subscribed"); - break; - case PubSubSubscription::Unconfigured: - lua_pushstring(L, "unconfigured"); - break; - } - lua_setfield(L, -2, "subscription"); +boost::optional<LuaElementConvertor::Documentation> PubSubSubscriptionConvertor::getDocumentation() const { + return Documentation( + "PubSubSubscription", + "This table has the following fields:\n\n" + "- `node`: string (Optional)\n" + "- `subscription_id`: string (Optional)\n" + "- `jid`: jid (string)\n" + "- `options`: @{PubSubSubscribeOptions}\n" + "- `subscription`: `\"none\"`, `\"pending\"`, `\"subscribed\"`, or `\"unconfigured\"`\n" + ); } diff --git a/Sluift/ElementConvertors/PubSubSubscriptionConvertor.h b/Sluift/ElementConvertors/PubSubSubscriptionConvertor.h index 2da4930..9cad963 100644 --- a/Sluift/ElementConvertors/PubSubSubscriptionConvertor.h +++ b/Sluift/ElementConvertors/PubSubSubscriptionConvertor.h @@ -1,28 +1,28 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <Swiften/Elements/PubSubSubscription.h> #include <Sluift/GenericLuaElementConvertor.h> -#include <Swiften/Elements/PubSubSubscription.h> namespace Swift { - class LuaElementConvertors; + class LuaElementConvertors; - class PubSubSubscriptionConvertor : public GenericLuaElementConvertor<PubSubSubscription> { - public: - PubSubSubscriptionConvertor(LuaElementConvertors* convertors); - virtual ~PubSubSubscriptionConvertor(); + class PubSubSubscriptionConvertor : public GenericLuaElementConvertor<PubSubSubscription> { + public: + PubSubSubscriptionConvertor(LuaElementConvertors* convertors); + virtual ~PubSubSubscriptionConvertor() override; - virtual boost::shared_ptr<PubSubSubscription> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE; - virtual void doConvertToLua(lua_State*, boost::shared_ptr<PubSubSubscription>) SWIFTEN_OVERRIDE; + virtual std::shared_ptr<PubSubSubscription> doConvertFromLua(lua_State*) override; + virtual void doConvertToLua(lua_State*, std::shared_ptr<PubSubSubscription>) override; + virtual boost::optional<Documentation> getDocumentation() const override; - private: - LuaElementConvertors* convertors; - }; + private: + LuaElementConvertors* convertors; + }; } diff --git a/Sluift/ElementConvertors/PubSubSubscriptionsConvertor.cpp b/Sluift/ElementConvertors/PubSubSubscriptionsConvertor.cpp index 04f8da8..2325181 100644 --- a/Sluift/ElementConvertors/PubSubSubscriptionsConvertor.cpp +++ b/Sluift/ElementConvertors/PubSubSubscriptionsConvertor.cpp @@ -1,70 +1,78 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #include <Sluift/ElementConvertors/PubSubSubscriptionsConvertor.h> -#include <lua.hpp> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> + #include <boost/numeric/conversion/cast.hpp> -#include <Sluift/LuaElementConvertors.h> -#include <Swiften/Base/foreach.h> +#include <lua.hpp> -#pragma clang diagnostic ignored "-Wunused-private-field" +#include <Sluift/LuaElementConvertors.h> using namespace Swift; -PubSubSubscriptionsConvertor::PubSubSubscriptionsConvertor(LuaElementConvertors* convertors) : - GenericLuaElementConvertor<PubSubSubscriptions>("pubsub_subscriptions"), - convertors(convertors) { +PubSubSubscriptionsConvertor::PubSubSubscriptionsConvertor(LuaElementConvertors* convertors) : + GenericLuaElementConvertor<PubSubSubscriptions>("pubsub_subscriptions"), + convertors(convertors) { } PubSubSubscriptionsConvertor::~PubSubSubscriptionsConvertor() { } -boost::shared_ptr<PubSubSubscriptions> PubSubSubscriptionsConvertor::doConvertFromLua(lua_State* L) { - boost::shared_ptr<PubSubSubscriptions> result = boost::make_shared<PubSubSubscriptions>(); - lua_getfield(L, -1, "node"); - if (lua_isstring(L, -1)) { - result->setNode(std::string(lua_tostring(L, -1))); - } - lua_pop(L, 1); - if (lua_type(L, -1) == LUA_TTABLE) { - std::vector< boost::shared_ptr<PubSubSubscription> > items; - for(size_t i = 0; i < lua_objlen(L, -1); ++i) { - lua_pushnumber(L, i + 1); - lua_gettable(L, -2); - if (!lua_isnil(L, -1)) { - if (boost::shared_ptr<PubSubSubscription> payload = boost::dynamic_pointer_cast<PubSubSubscription>(convertors->convertFromLuaUntyped(L, -1, "pubsub_subscription"))) { - items.push_back(payload); - } - } - lua_pop(L, 1); - } +std::shared_ptr<PubSubSubscriptions> PubSubSubscriptionsConvertor::doConvertFromLua(lua_State* L) { + std::shared_ptr<PubSubSubscriptions> result = std::make_shared<PubSubSubscriptions>(); + lua_getfield(L, -1, "node"); + if (lua_isstring(L, -1)) { + result->setNode(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + if (lua_type(L, -1) == LUA_TTABLE) { + std::vector< std::shared_ptr<PubSubSubscription> > items; + for(size_t i = 0; i < lua_rawlen(L, -1); ++i) { + lua_pushnumber(L, i + 1); + lua_gettable(L, -2); + if (!lua_isnil(L, -1)) { + if (std::shared_ptr<PubSubSubscription> payload = std::dynamic_pointer_cast<PubSubSubscription>(convertors->convertFromLuaUntyped(L, -1, "pubsub_subscription"))) { + items.push_back(payload); + } + } + lua_pop(L, 1); + } + + result->setSubscriptions(items); + } + return result; +} - result->setSubscriptions(items); - } - return result; +void PubSubSubscriptionsConvertor::doConvertToLua(lua_State* L, std::shared_ptr<PubSubSubscriptions> payload) { + lua_createtable(L, 0, 0); + if (payload->getNode()) { + lua_pushstring(L, (*payload->getNode()).c_str()); + lua_setfield(L, -2, "node"); + } + if (!payload->getSubscriptions().empty()) { + { + int i = 0; + for (auto&& item : payload->getSubscriptions()) { + if (convertors->convertToLuaUntyped(L, item) > 0) { + lua_rawseti(L, -2, boost::numeric_cast<int>(i+1)); + ++i; + } + } + } + } } -void PubSubSubscriptionsConvertor::doConvertToLua(lua_State* L, boost::shared_ptr<PubSubSubscriptions> payload) { - lua_createtable(L, 0, 0); - if (payload->getNode()) { - lua_pushstring(L, (*payload->getNode()).c_str()); - lua_setfield(L, -2, "node"); - } - if (!payload->getSubscriptions().empty()) { - { - int i = 0; - foreach(boost::shared_ptr<PubSubSubscription> item, payload->getSubscriptions()) { - if (convertors->convertToLuaUntyped(L, item) > 0) { - lua_rawseti(L, -2, boost::numeric_cast<int>(i+1)); - ++i; - } - } - } - } +boost::optional<LuaElementConvertor::Documentation> PubSubSubscriptionsConvertor::getDocumentation() const { + return Documentation( + "PubSubSubscriptions", + "This table has the following fields:\n\n" + "- `node`: string (Optional)\n" + "- `subscriptions`: array<@{PubSubSubscription}>\n" + ); } diff --git a/Sluift/ElementConvertors/PubSubSubscriptionsConvertor.h b/Sluift/ElementConvertors/PubSubSubscriptionsConvertor.h index 7f18f64..94b4533 100644 --- a/Sluift/ElementConvertors/PubSubSubscriptionsConvertor.h +++ b/Sluift/ElementConvertors/PubSubSubscriptionsConvertor.h @@ -1,28 +1,28 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <Swiften/Elements/PubSubSubscriptions.h> #include <Sluift/GenericLuaElementConvertor.h> -#include <Swiften/Elements/PubSubSubscriptions.h> namespace Swift { - class LuaElementConvertors; + class LuaElementConvertors; - class PubSubSubscriptionsConvertor : public GenericLuaElementConvertor<PubSubSubscriptions> { - public: - PubSubSubscriptionsConvertor(LuaElementConvertors* convertors); - virtual ~PubSubSubscriptionsConvertor(); + class PubSubSubscriptionsConvertor : public GenericLuaElementConvertor<PubSubSubscriptions> { + public: + PubSubSubscriptionsConvertor(LuaElementConvertors* convertors); + virtual ~PubSubSubscriptionsConvertor() override; - virtual boost::shared_ptr<PubSubSubscriptions> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE; - virtual void doConvertToLua(lua_State*, boost::shared_ptr<PubSubSubscriptions>) SWIFTEN_OVERRIDE; + virtual std::shared_ptr<PubSubSubscriptions> doConvertFromLua(lua_State*) override; + virtual void doConvertToLua(lua_State*, std::shared_ptr<PubSubSubscriptions>) override; + virtual boost::optional<Documentation> getDocumentation() const override; - private: - LuaElementConvertors* convertors; - }; + private: + LuaElementConvertors* convertors; + }; } diff --git a/Sluift/ElementConvertors/PubSubUnsubscribeConvertor.cpp b/Sluift/ElementConvertors/PubSubUnsubscribeConvertor.cpp index 323cb29..056c84c 100644 --- a/Sluift/ElementConvertors/PubSubUnsubscribeConvertor.cpp +++ b/Sluift/ElementConvertors/PubSubUnsubscribeConvertor.cpp @@ -1,59 +1,64 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #include <Sluift/ElementConvertors/PubSubUnsubscribeConvertor.h> -#include <lua.hpp> -#include <boost/smart_ptr/make_shared.hpp> - - - +#include <memory> -#pragma clang diagnostic ignored "-Wunused-private-field" +#include <lua.hpp> using namespace Swift; -PubSubUnsubscribeConvertor::PubSubUnsubscribeConvertor(LuaElementConvertors* convertors) : - GenericLuaElementConvertor<PubSubUnsubscribe>("pubsub_unsubscribe"), - convertors(convertors) { +PubSubUnsubscribeConvertor::PubSubUnsubscribeConvertor() : + GenericLuaElementConvertor<PubSubUnsubscribe>("pubsub_unsubscribe") { } PubSubUnsubscribeConvertor::~PubSubUnsubscribeConvertor() { } -boost::shared_ptr<PubSubUnsubscribe> PubSubUnsubscribeConvertor::doConvertFromLua(lua_State* L) { - boost::shared_ptr<PubSubUnsubscribe> result = boost::make_shared<PubSubUnsubscribe>(); - lua_getfield(L, -1, "node"); - if (lua_isstring(L, -1)) { - result->setNode(std::string(lua_tostring(L, -1))); - } - lua_pop(L, 1); - lua_getfield(L, -1, "jid"); - if (lua_isstring(L, -1)) { - result->setJID(JID(std::string(lua_tostring(L, -1)))); - } - lua_pop(L, 1); - lua_getfield(L, -1, "subscriptionid"); - if (lua_isstring(L, -1)) { - result->setSubscriptionID(std::string(lua_tostring(L, -1))); - } - lua_pop(L, 1); - return result; +std::shared_ptr<PubSubUnsubscribe> PubSubUnsubscribeConvertor::doConvertFromLua(lua_State* L) { + std::shared_ptr<PubSubUnsubscribe> result = std::make_shared<PubSubUnsubscribe>(); + lua_getfield(L, -1, "node"); + if (lua_isstring(L, -1)) { + result->setNode(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "jid"); + if (lua_isstring(L, -1)) { + result->setJID(JID(std::string(lua_tostring(L, -1)))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "subscription_id"); + if (lua_isstring(L, -1)) { + result->setSubscriptionID(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + return result; +} + +void PubSubUnsubscribeConvertor::doConvertToLua(lua_State* L, std::shared_ptr<PubSubUnsubscribe> payload) { + lua_createtable(L, 0, 0); + if (payload->getNode()) { + lua_pushstring(L, (*payload->getNode()).c_str()); + lua_setfield(L, -2, "node"); + } + lua_pushstring(L, payload->getJID().toString().c_str()); + lua_setfield(L, -2, "jid"); + if (payload->getSubscriptionID()) { + lua_pushstring(L, (*payload->getSubscriptionID()).c_str()); + lua_setfield(L, -2, "subscription_id"); + } } -void PubSubUnsubscribeConvertor::doConvertToLua(lua_State* L, boost::shared_ptr<PubSubUnsubscribe> payload) { - lua_createtable(L, 0, 0); - if (payload->getNode()) { - lua_pushstring(L, (*payload->getNode()).c_str()); - lua_setfield(L, -2, "node"); - } - lua_pushstring(L, payload->getJID().toString().c_str()); - lua_setfield(L, -2, "jid"); - if (payload->getSubscriptionID()) { - lua_pushstring(L, (*payload->getSubscriptionID()).c_str()); - lua_setfield(L, -2, "subscriptionid"); - } +boost::optional<LuaElementConvertor::Documentation> PubSubUnsubscribeConvertor::getDocumentation() const { + return Documentation( + "PubSubUnsubscribe", + "This table has the following fields:\n\n" + "- `node`: string (Optional)\n" + "- `jid`: jid (string)\n" + "- `subscription_id`: string (Optional)\n" + ); } diff --git a/Sluift/ElementConvertors/PubSubUnsubscribeConvertor.h b/Sluift/ElementConvertors/PubSubUnsubscribeConvertor.h index 16d279f..f76f2b1 100644 --- a/Sluift/ElementConvertors/PubSubUnsubscribeConvertor.h +++ b/Sluift/ElementConvertors/PubSubUnsubscribeConvertor.h @@ -1,28 +1,25 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <Swiften/Elements/PubSubUnsubscribe.h> #include <Sluift/GenericLuaElementConvertor.h> -#include <Swiften/Elements/PubSubUnsubscribe.h> namespace Swift { - class LuaElementConvertors; - - class PubSubUnsubscribeConvertor : public GenericLuaElementConvertor<PubSubUnsubscribe> { - public: - PubSubUnsubscribeConvertor(LuaElementConvertors* convertors); - virtual ~PubSubUnsubscribeConvertor(); + class LuaElementConvertors; - virtual boost::shared_ptr<PubSubUnsubscribe> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE; - virtual void doConvertToLua(lua_State*, boost::shared_ptr<PubSubUnsubscribe>) SWIFTEN_OVERRIDE; + class PubSubUnsubscribeConvertor : public GenericLuaElementConvertor<PubSubUnsubscribe> { + public: + PubSubUnsubscribeConvertor(); + virtual ~PubSubUnsubscribeConvertor() override; - private: - LuaElementConvertors* convertors; - }; + virtual std::shared_ptr<PubSubUnsubscribe> doConvertFromLua(lua_State*) override; + virtual void doConvertToLua(lua_State*, std::shared_ptr<PubSubUnsubscribe>) override; + virtual boost::optional<Documentation> getDocumentation() const override; + }; } diff --git a/Sluift/ElementConvertors/RawXMLElementConvertor.cpp b/Sluift/ElementConvertors/RawXMLElementConvertor.cpp index 35a53ca..9688677 100644 --- a/Sluift/ElementConvertors/RawXMLElementConvertor.cpp +++ b/Sluift/ElementConvertors/RawXMLElementConvertor.cpp @@ -1,17 +1,18 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #include <Sluift/ElementConvertors/RawXMLElementConvertor.h> -#include <iostream> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> + #include <lua.hpp> #include <Swiften/Elements/RawXMLPayload.h> #include <Swiften/Serializer/PayloadSerializer.h> + #include <Sluift/Lua/Check.h> using namespace Swift; @@ -22,16 +23,20 @@ RawXMLElementConvertor::RawXMLElementConvertor() { RawXMLElementConvertor::~RawXMLElementConvertor() { } -boost::shared_ptr<Payload> RawXMLElementConvertor::convertFromLua(lua_State* L, int index, const std::string& type) { - if (type == "xml") { - return boost::make_shared<RawXMLPayload>(std::string(Lua::checkString(L, index))); - } - return boost::shared_ptr<Payload>(); +std::shared_ptr<Element> RawXMLElementConvertor::convertFromLua(lua_State* L, int index, const std::string& type) { + if (type == "xml") { + return std::make_shared<RawXMLPayload>(std::string(Lua::checkString(L, index))); + } + return std::shared_ptr<Payload>(); } -boost::optional<std::string> RawXMLElementConvertor::convertToLua(lua_State* L, boost::shared_ptr<Payload> payload) { - PayloadSerializer* serializer = serializers.getPayloadSerializer(payload); - assert(serializer); - lua_pushstring(L, serializer->serialize(payload).c_str()); - return std::string("xml"); +boost::optional<std::string> RawXMLElementConvertor::convertToLua(lua_State* L, std::shared_ptr<Element> element) { + std::shared_ptr<Payload> payload = std::dynamic_pointer_cast<Payload>(element); + if (!payload) { + return boost::optional<std::string>(); + } + PayloadSerializer* serializer = serializers.getPayloadSerializer(payload); + assert(serializer); + lua_pushstring(L, serializer->serialize(payload).c_str()); + return std::string("xml"); } diff --git a/Sluift/ElementConvertors/RawXMLElementConvertor.h b/Sluift/ElementConvertors/RawXMLElementConvertor.h index 6087ba0..af3625b 100644 --- a/Sluift/ElementConvertors/RawXMLElementConvertor.h +++ b/Sluift/ElementConvertors/RawXMLElementConvertor.h @@ -1,26 +1,25 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.h> #include <Sluift/LuaElementConvertor.h> -#include <Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.h> namespace Swift { - class RawXMLElementConvertor : public LuaElementConvertor { - public: - RawXMLElementConvertor(); - virtual ~RawXMLElementConvertor(); + class RawXMLElementConvertor : public LuaElementConvertor { + public: + RawXMLElementConvertor(); + virtual ~RawXMLElementConvertor() override; - virtual boost::shared_ptr<Payload> convertFromLua(lua_State*, int index, const std::string& type) SWIFTEN_OVERRIDE; - virtual boost::optional<std::string> convertToLua(lua_State*, boost::shared_ptr<Payload>) SWIFTEN_OVERRIDE; + virtual std::shared_ptr<Element> convertFromLua(lua_State*, int index, const std::string& type) override; + virtual boost::optional<std::string> convertToLua(lua_State*, std::shared_ptr<Element>) override; - private: - FullPayloadSerializerCollection serializers; - }; + private: + FullPayloadSerializerCollection serializers; + }; } diff --git a/Sluift/ElementConvertors/ResultSetConvertor.cpp b/Sluift/ElementConvertors/ResultSetConvertor.cpp new file mode 100644 index 0000000..7762a79 --- /dev/null +++ b/Sluift/ElementConvertors/ResultSetConvertor.cpp @@ -0,0 +1,116 @@ +/* + * Copyright (c) 2014-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Sluift/ElementConvertors/ResultSetConvertor.h> + +#include <memory> + +#include <boost/numeric/conversion/cast.hpp> + +#include <lua.hpp> + +using namespace Swift; + +ResultSetConvertor::ResultSetConvertor() : + GenericLuaElementConvertor<ResultSet>("result_set") { +} + +ResultSetConvertor::~ResultSetConvertor() { +} + +std::shared_ptr<ResultSet> ResultSetConvertor::doConvertFromLua(lua_State* L) { + std::shared_ptr<ResultSet> result = std::make_shared<ResultSet>(); + lua_getfield(L, -1, "max_items"); + if (lua_isstring(L, -1)) { + result->setMaxItems(boost::numeric_cast<int>(lua_tonumber(L, -1))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "count"); + if (lua_isnumber(L, -1)) { + result->setCount(boost::numeric_cast<int>(lua_tonumber(L, -1))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "index"); + if (lua_isnumber(L, -1)) { + result->setIndex(boost::numeric_cast<int>(lua_tonumber(L, -1))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "first_id_index"); + if (lua_isstring(L, -1)) { + result->setFirstIDIndex(boost::numeric_cast<int>(lua_tonumber(L, -1))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "first_id"); + if (lua_isstring(L, -1)) { + result->setFirstID(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "last_id"); + if (lua_isstring(L, -1)) { + result->setLastID(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "after"); + if (lua_isstring(L, -1)) { + result->setAfter(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "before"); + if (lua_isstring(L, -1)) { + result->setBefore(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + return result; +} + +void ResultSetConvertor::doConvertToLua(lua_State* L, std::shared_ptr<ResultSet> payload) { + lua_createtable(L, 0, 0); + if (payload->getMaxItems()) { + lua_pushnumber(L, *payload->getMaxItems()); + lua_setfield(L, -2, "max_items"); + } + if (payload->getCount()) { + lua_pushnumber(L, *payload->getCount()); + lua_setfield(L, -2, "count"); + } + if (payload->getIndex()) { + lua_pushnumber(L, *payload->getIndex()); + lua_setfield(L, -2, "index"); + } + if (payload->getFirstIDIndex()) { + lua_pushnumber(L, *payload->getFirstIDIndex()); + lua_setfield(L, -2, "first_id_index"); + } + if (payload->getFirstID()) { + lua_pushstring(L, (*payload->getFirstID()).c_str()); + lua_setfield(L, -2, "first_id"); + } + if (payload->getLastID()) { + lua_pushstring(L, (*payload->getLastID()).c_str()); + lua_setfield(L, -2, "last_id"); + } + if (payload->getAfter()) { + lua_pushstring(L, (*payload->getAfter()).c_str()); + lua_setfield(L, -2, "after"); + } + if (payload->getBefore()) { + lua_pushstring(L, (*payload->getBefore()).c_str()); + lua_setfield(L, -2, "before"); + } +} + +boost::optional<LuaElementConvertor::Documentation> ResultSetConvertor::getDocumentation() const { + return Documentation( + "ResultSet", + "This table has the following fields:\n\n" + "- `max_items`: number (Optional)\n" + "- `count`: number (Optional)\n" + "- `first_id_index`: number (Optional)\n" + "- `first_id`: string (Optional)\n" + "- `last_id`: string (Optional)\n" + "- `after`: string (Optional)\n" + ); +} diff --git a/Sluift/ElementConvertors/ResultSetConvertor.h b/Sluift/ElementConvertors/ResultSetConvertor.h new file mode 100644 index 0000000..e098605 --- /dev/null +++ b/Sluift/ElementConvertors/ResultSetConvertor.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2014-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <Swiften/Elements/ResultSet.h> + +#include <Sluift/GenericLuaElementConvertor.h> + +namespace Swift { + class LuaElementConvertors; + + class ResultSetConvertor : public GenericLuaElementConvertor<ResultSet> { + public: + ResultSetConvertor(); + virtual ~ResultSetConvertor() override; + + virtual std::shared_ptr<ResultSet> doConvertFromLua(lua_State*) override; + virtual void doConvertToLua(lua_State*, std::shared_ptr<ResultSet>) override; + virtual boost::optional<Documentation> getDocumentation() const override; + }; +} + diff --git a/Sluift/ElementConvertors/SConscript b/Sluift/ElementConvertors/SConscript index e98f7c4..0bf8022 100644 --- a/Sluift/ElementConvertors/SConscript +++ b/Sluift/ElementConvertors/SConscript @@ -2,41 +2,55 @@ Import('env') convertors = [ - env.File("PubSubRetractConvertor.cpp"), - env.File("PubSubAffiliationsConvertor.cpp"), - env.File("PubSubPublishConvertor.cpp"), - env.File("PubSubItemsConvertor.cpp"), - env.File("PubSubOwnerRedirectConvertor.cpp"), - env.File("PubSubEventRedirectConvertor.cpp"), - env.File("PubSubConfigureConvertor.cpp"), - env.File("PubSubEventDisassociateConvertor.cpp"), - env.File("PubSubOwnerAffiliationsConvertor.cpp"), - env.File("PubSubOwnerConfigureConvertor.cpp"), - env.File("UserLocationConvertor.cpp"), - env.File("PubSubSubscribeOptionsConvertor.cpp"), - env.File("PubSubOwnerSubscriptionsConvertor.cpp"), - env.File("PubSubDefaultConvertor.cpp"), - env.File("PubSubEventCollectionConvertor.cpp"), - env.File("PubSubEventSubscriptionConvertor.cpp"), - env.File("PubSubEventRetractConvertor.cpp"), - env.File("PubSubItemConvertor.cpp"), - env.File("PubSubUnsubscribeConvertor.cpp"), - env.File("PubSubEventDeleteConvertor.cpp"), - env.File("PubSubCreateConvertor.cpp"), - env.File("PubSubOwnerPurgeConvertor.cpp"), - env.File("PubSubEventItemsConvertor.cpp"), - env.File("PubSubOptionsConvertor.cpp"), - env.File("PubSubEventItemConvertor.cpp"), - env.File("PubSubOwnerSubscriptionConvertor.cpp"), - env.File("PubSubOwnerAffiliationConvertor.cpp"), - env.File("PubSubEventPurgeConvertor.cpp"), - env.File("PubSubAffiliationConvertor.cpp"), - env.File("PubSubSubscribeConvertor.cpp"), - env.File("PubSubOwnerDeleteConvertor.cpp"), - env.File("PubSubOwnerDefaultConvertor.cpp"), - env.File("PubSubSubscriptionsConvertor.cpp"), - env.File("PubSubEventAssociateConvertor.cpp"), - env.File("PubSubSubscriptionConvertor.cpp"), - env.File("PubSubEventConfigurationConvertor.cpp") + env.File("PubSubRetractConvertor.cpp"), + env.File("PubSubAffiliationsConvertor.cpp"), + env.File("PubSubPublishConvertor.cpp"), + env.File("PubSubItemsConvertor.cpp"), + env.File("PubSubOwnerRedirectConvertor.cpp"), + env.File("PubSubEventRedirectConvertor.cpp"), + env.File("UserTuneConvertor.cpp"), + env.File("PubSubConfigureConvertor.cpp"), + env.File("PubSubEventDisassociateConvertor.cpp"), + env.File("PubSubOwnerAffiliationsConvertor.cpp"), + env.File("PubSubOwnerConfigureConvertor.cpp"), + env.File("UserLocationConvertor.cpp"), + env.File("PubSubSubscribeOptionsConvertor.cpp"), + env.File("PubSubOwnerSubscriptionsConvertor.cpp"), + env.File("PubSubDefaultConvertor.cpp"), + env.File("PubSubEventCollectionConvertor.cpp"), + env.File("PubSubEventSubscriptionConvertor.cpp"), + env.File("PubSubEventRetractConvertor.cpp"), + env.File("PubSubItemConvertor.cpp"), + env.File("PubSubUnsubscribeConvertor.cpp"), + env.File("PubSubEventDeleteConvertor.cpp"), + env.File("PubSubCreateConvertor.cpp"), + env.File("PubSubOwnerPurgeConvertor.cpp"), + env.File("PubSubEventItemsConvertor.cpp"), + env.File("PubSubOptionsConvertor.cpp"), + env.File("PubSubEventItemConvertor.cpp"), + env.File("PubSubOwnerSubscriptionConvertor.cpp"), + env.File("PubSubOwnerAffiliationConvertor.cpp"), + env.File("PubSubEventPurgeConvertor.cpp"), + env.File("PubSubAffiliationConvertor.cpp"), + env.File("PubSubSubscribeConvertor.cpp"), + env.File("PubSubOwnerDeleteConvertor.cpp"), + env.File("PubSubOwnerDefaultConvertor.cpp"), + env.File("PubSubSubscriptionsConvertor.cpp"), + env.File("PubSubEventAssociateConvertor.cpp"), + env.File("PubSubSubscriptionConvertor.cpp"), + env.File("SecurityLabelConvertor.cpp"), + env.File("PubSubEventConfigurationConvertor.cpp"), + env.File("IQConvertor.cpp"), + env.File("PresenceConvertor.cpp"), + env.File("MessageConvertor.cpp"), + env.File("ResultSetConvertor.cpp"), + env.File("ForwardedConvertor.cpp"), + env.File("MAMResultConvertor.cpp"), + env.File("MAMQueryConvertor.cpp"), + env.File("MAMFinConvertor.cpp"), + env.File("CarbonsReceivedConvertor.cpp"), + env.File("CarbonsSentConvertor.cpp"), + env.File("SubjectConvertor.cpp"), + env.File("IsodeIQDelegationConvertor.cpp") ] Return('convertors') diff --git a/Sluift/ElementConvertors/SecurityLabelConvertor.cpp b/Sluift/ElementConvertors/SecurityLabelConvertor.cpp new file mode 100644 index 0000000..8bc323a --- /dev/null +++ b/Sluift/ElementConvertors/SecurityLabelConvertor.cpp @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Sluift/ElementConvertors/SecurityLabelConvertor.h> + +#include <memory> + +#include <boost/numeric/conversion/cast.hpp> + +#include <lua.hpp> + +using namespace Swift; + +SecurityLabelConvertor::SecurityLabelConvertor() : + GenericLuaElementConvertor<SecurityLabel>("security_label") { +} + +SecurityLabelConvertor::~SecurityLabelConvertor() { +} + +std::shared_ptr<SecurityLabel> SecurityLabelConvertor::doConvertFromLua(lua_State* L) { + std::shared_ptr<SecurityLabel> result = std::make_shared<SecurityLabel>(); + lua_getfield(L, -1, "equivalent_labels"); + if (lua_type(L, -1) == LUA_TTABLE) { + std::vector< std::string > items; + for(size_t i = 0; i < lua_rawlen(L, -1); ++i) { + lua_pushnumber(L, i + 1); + lua_gettable(L, -2); + if (lua_isstring(L, -1)) { + items.push_back(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + } + + result->setEquivalentLabels(items); + } + lua_pop(L, 1); + lua_getfield(L, -1, "foreground_color"); + if (lua_isstring(L, -1)) { + result->setForegroundColor(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "display_marking"); + if (lua_isstring(L, -1)) { + result->setDisplayMarking(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "background_color"); + if (lua_isstring(L, -1)) { + result->setBackgroundColor(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "label"); + if (lua_isstring(L, -1)) { + result->setLabel(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + return result; +} + +void SecurityLabelConvertor::doConvertToLua(lua_State* L, std::shared_ptr<SecurityLabel> payload) { + lua_createtable(L, 0, 0); + if (!payload->getEquivalentLabels().empty()) { + lua_createtable(L, boost::numeric_cast<int>(payload->getEquivalentLabels().size()), 0); + { + int i = 0; + for (const auto& item : payload->getEquivalentLabels()) { + lua_pushstring(L, item.c_str()); + lua_rawseti(L, -2, boost::numeric_cast<int>(i+1)); + ++i; + } + } + lua_setfield(L, -2, "equivalent_labels"); + } + lua_pushstring(L, payload->getForegroundColor().c_str()); + lua_setfield(L, -2, "foreground_color"); + lua_pushstring(L, payload->getDisplayMarking().c_str()); + lua_setfield(L, -2, "display_marking"); + lua_pushstring(L, payload->getBackgroundColor().c_str()); + lua_setfield(L, -2, "background_color"); + lua_pushstring(L, payload->getLabel().c_str()); + lua_setfield(L, -2, "label"); +} + +boost::optional<LuaElementConvertor::Documentation> SecurityLabelConvertor::getDocumentation() const { + return Documentation( + "SecurityLabel", + "This table has the following fields:\n\n" + "- `equivalent_labels`: array<string>\n" + "- `foreground_color`: string\n" + "- `display_marking`: string\n" + "- `background_color`: string\n" + "- `label`: string\n" + ); +} diff --git a/Sluift/ElementConvertors/SecurityLabelConvertor.h b/Sluift/ElementConvertors/SecurityLabelConvertor.h new file mode 100644 index 0000000..22d11ca --- /dev/null +++ b/Sluift/ElementConvertors/SecurityLabelConvertor.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2010-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <Swiften/Elements/SecurityLabel.h> + +#include <Sluift/GenericLuaElementConvertor.h> + +namespace Swift { + class LuaElementConvertors; + + class SecurityLabelConvertor : public GenericLuaElementConvertor<SecurityLabel> { + public: + SecurityLabelConvertor(); + virtual ~SecurityLabelConvertor() override; + + virtual std::shared_ptr<SecurityLabel> doConvertFromLua(lua_State*) override; + virtual void doConvertToLua(lua_State*, std::shared_ptr<SecurityLabel>) override; + virtual boost::optional<Documentation> getDocumentation() const override; + }; +} diff --git a/Sluift/ElementConvertors/SoftwareVersionConvertor.cpp b/Sluift/ElementConvertors/SoftwareVersionConvertor.cpp index 5799614..f997a45 100644 --- a/Sluift/ElementConvertors/SoftwareVersionConvertor.cpp +++ b/Sluift/ElementConvertors/SoftwareVersionConvertor.cpp @@ -1,14 +1,17 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #include <Sluift/ElementConvertors/SoftwareVersionConvertor.h> -#include <lua.hpp> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> + #include <boost/numeric/conversion/cast.hpp> + +#include <lua.hpp> + #include <Sluift/Lua/Check.h> using namespace Swift; @@ -19,32 +22,32 @@ SoftwareVersionConvertor::SoftwareVersionConvertor() : GenericLuaElementConverto SoftwareVersionConvertor::~SoftwareVersionConvertor() { } -boost::shared_ptr<SoftwareVersion> SoftwareVersionConvertor::doConvertFromLua(lua_State* L) { - boost::shared_ptr<SoftwareVersion> result = boost::make_shared<SoftwareVersion>(); - lua_getfield(L, -1, "name"); - if (!lua_isnil(L, -1)) { - result->setName(std::string(Lua::checkString(L, -1))); - } - lua_pop(L, 1); - lua_getfield(L, -1, "version"); - if (!lua_isnil(L, -1)) { - result->setVersion(std::string(Lua::checkString(L, -1))); - } - lua_pop(L, 1); - lua_getfield(L, -1, "os"); - if (!lua_isnil(L, -1)) { - result->setOS(std::string(Lua::checkString(L, -1))); - } - lua_pop(L, 1); - return result; +std::shared_ptr<SoftwareVersion> SoftwareVersionConvertor::doConvertFromLua(lua_State* L) { + std::shared_ptr<SoftwareVersion> result = std::make_shared<SoftwareVersion>(); + lua_getfield(L, -1, "name"); + if (!lua_isnil(L, -1)) { + result->setName(std::string(Lua::checkString(L, -1))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "version"); + if (!lua_isnil(L, -1)) { + result->setVersion(std::string(Lua::checkString(L, -1))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "os"); + if (!lua_isnil(L, -1)) { + result->setOS(std::string(Lua::checkString(L, -1))); + } + lua_pop(L, 1); + return result; } -void SoftwareVersionConvertor::doConvertToLua(lua_State* L, boost::shared_ptr<SoftwareVersion> payload) { - lua_createtable(L, 0, 0); - lua_pushstring(L, payload->getName().c_str()); - lua_setfield(L, -2, "name"); - lua_pushstring(L, payload->getVersion().c_str()); - lua_setfield(L, -2, "version"); - lua_pushstring(L, payload->getOS().c_str()); - lua_setfield(L, -2, "os"); +void SoftwareVersionConvertor::doConvertToLua(lua_State* L, std::shared_ptr<SoftwareVersion> payload) { + lua_createtable(L, 0, 0); + lua_pushstring(L, payload->getName().c_str()); + lua_setfield(L, -2, "name"); + lua_pushstring(L, payload->getVersion().c_str()); + lua_setfield(L, -2, "version"); + lua_pushstring(L, payload->getOS().c_str()); + lua_setfield(L, -2, "os"); } diff --git a/Sluift/ElementConvertors/SoftwareVersionConvertor.h b/Sluift/ElementConvertors/SoftwareVersionConvertor.h index 5fa3cc3..791aede 100644 --- a/Sluift/ElementConvertors/SoftwareVersionConvertor.h +++ b/Sluift/ElementConvertors/SoftwareVersionConvertor.h @@ -1,23 +1,22 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <Swiften/Elements/SoftwareVersion.h> #include <Sluift/GenericLuaElementConvertor.h> -#include <Swiften/Elements/SoftwareVersion.h> namespace Swift { - class SoftwareVersionConvertor : public GenericLuaElementConvertor<SoftwareVersion> { - public: - SoftwareVersionConvertor(); - virtual ~SoftwareVersionConvertor(); + class SoftwareVersionConvertor : public GenericLuaElementConvertor<SoftwareVersion> { + public: + SoftwareVersionConvertor(); + virtual ~SoftwareVersionConvertor() override; - virtual boost::shared_ptr<SoftwareVersion> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE; - virtual void doConvertToLua(lua_State*, boost::shared_ptr<SoftwareVersion>) SWIFTEN_OVERRIDE; - }; + virtual std::shared_ptr<SoftwareVersion> doConvertFromLua(lua_State*) override; + virtual void doConvertToLua(lua_State*, std::shared_ptr<SoftwareVersion>) override; + }; } diff --git a/Sluift/ElementConvertors/StanzaConvertor.h b/Sluift/ElementConvertors/StanzaConvertor.h new file mode 100644 index 0000000..a7b4e4e --- /dev/null +++ b/Sluift/ElementConvertors/StanzaConvertor.h @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2014-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <boost/numeric/conversion/cast.hpp> + +#include <Swiften/Elements/IQ.h> +#include <Swiften/Elements/Message.h> +#include <Swiften/Elements/Payload.h> +#include <Swiften/Elements/Presence.h> + +#include <Sluift/GenericLuaElementConvertor.h> +#include <Sluift/Lua/Exception.h> +#include <Sluift/LuaElementConvertors.h> + +namespace Swift { + template <typename T> class StanzaConvertor : public GenericLuaElementConvertor<T> { + public: + StanzaConvertor(const std::string& tag) + : GenericLuaElementConvertor<T>(tag) { + } + + virtual ~StanzaConvertor() { + } + + std::shared_ptr<T> getStanza(lua_State* L, LuaElementConvertors* convertors) { + std::shared_ptr<T> result = std::make_shared<T>(); + lua_getfield(L, -1, "id"); + if (lua_isstring(L, -1)) { + result->setID(lua_tostring(L, -1)); + } + lua_pop(L, 1); + lua_getfield(L, -1, "from"); + if (lua_isstring(L, -1)) { + result->setFrom(lua_tostring(L, -1)); + } + lua_pop(L, 1); + lua_getfield(L, -1, "to"); + if (lua_isstring(L, -1)) { + result->setTo(lua_tostring(L, -1)); + } + lua_pop(L, 1); + lua_getfield(L, -1, "payloads"); + if (lua_type(L, -1) == LUA_TTABLE) { + for(size_t i = 0; i < lua_rawlen(L, -1); ++i) { + lua_pushnumber(L, i + 1); + lua_gettable(L, -2); + if (!lua_isnil(L, -1)) { + std::shared_ptr<Payload> payload = std::dynamic_pointer_cast<Payload>(convertors->convertFromLua(L, -1)); + if (!!payload) { + result->addPayload(payload); + } + } + lua_pop(L, 1); + } + } + lua_pop(L, 1); + return result; + } + + void pushStanza(lua_State* L, const std::shared_ptr<T> stanza, LuaElementConvertors* convertors) { + lua_createtable(L, 0, 0); + lua_pushstring(L, stanza->getID().c_str()); + lua_setfield(L, -2, "id"); + lua_pushstring(L, stanza->getFrom().toString().c_str()); + lua_setfield(L, -2, "from"); + lua_pushstring(L, stanza->getTo().toString().c_str()); + lua_setfield(L, -2, "to"); + if (!stanza->getPayloads().empty()) { + lua_createtable(L, boost::numeric_cast<int>(stanza->getPayloads().size()), 0); + { + int i = 0; + for (const auto& item : stanza->getPayloads()) { + if (convertors->convertToLua(L, item) > 0) { + lua_rawseti(L, -2, boost::numeric_cast<int>(i+1)); + ++i; + } + } + } + lua_setfield(L, -2, "payloads"); + } + } + }; +} diff --git a/Sluift/ElementConvertors/StatusConvertor.cpp b/Sluift/ElementConvertors/StatusConvertor.cpp new file mode 100644 index 0000000..eed4044 --- /dev/null +++ b/Sluift/ElementConvertors/StatusConvertor.cpp @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2014-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Sluift/ElementConvertors/StatusConvertor.h> + +#include <memory> + +#include <boost/numeric/conversion/cast.hpp> + +#include <lua.hpp> + +#include <Sluift/Lua/Check.h> + +using namespace Swift; + +StatusConvertor::StatusConvertor() : GenericLuaElementConvertor<Status>("status") { +} + +StatusConvertor::~StatusConvertor() { +} + +std::shared_ptr<Status> StatusConvertor::doConvertFromLua(lua_State* L) { + std::shared_ptr<Status> result = std::make_shared<Status>(); + lua_getfield(L, -1, "text"); + if (lua_isstring(L, -1)) { + result->setText(lua_tostring(L, -1)); + } + lua_pop(L, 1); + return result; +} + +void StatusConvertor::doConvertToLua(lua_State* L, std::shared_ptr<Status> payload) { + lua_createtable(L, 0, 0); + lua_pushstring(L, payload->getText().c_str()); + lua_setfield(L, -2, "text"); +} diff --git a/Sluift/ElementConvertors/StatusConvertor.h b/Sluift/ElementConvertors/StatusConvertor.h new file mode 100644 index 0000000..994cee5 --- /dev/null +++ b/Sluift/ElementConvertors/StatusConvertor.h @@ -0,0 +1,22 @@ +/* + * Copyright (c) 2014-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <Swiften/Elements/Status.h> + +#include <Sluift/GenericLuaElementConvertor.h> + +namespace Swift { + class StatusConvertor : public GenericLuaElementConvertor<Status> { + public: + StatusConvertor(); + virtual ~StatusConvertor() override; + + virtual std::shared_ptr<Status> doConvertFromLua(lua_State*) override; + virtual void doConvertToLua(lua_State*, std::shared_ptr<Status>) override; + }; +} diff --git a/Sluift/ElementConvertors/StatusShowConvertor.cpp b/Sluift/ElementConvertors/StatusShowConvertor.cpp new file mode 100644 index 0000000..6d0a067 --- /dev/null +++ b/Sluift/ElementConvertors/StatusShowConvertor.cpp @@ -0,0 +1,77 @@ +/* + * Copyright (c) 2014-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Sluift/ElementConvertors/StatusShowConvertor.h> + +#include <memory> + +#include <boost/numeric/conversion/cast.hpp> + +#include <lua.hpp> + +#include <Sluift/Lua/Check.h> +#include <Sluift/Lua/Exception.h> + +using namespace Swift; + +StatusShowConvertor::StatusShowConvertor() : GenericLuaElementConvertor<StatusShow>("show") { +} + +StatusShowConvertor::~StatusShowConvertor() { +} + +std::shared_ptr<StatusShow> StatusShowConvertor::doConvertFromLua(lua_State* L) { + std::shared_ptr<StatusShow> result = std::make_shared<StatusShow>(); + lua_getfield(L, -1, "type"); + if (lua_isstring(L, -1)) { + result->setType(convertStatusShowTypeFromString(lua_tostring(L, -1))); + } + lua_pop(L, 1); + return result; +} + +void StatusShowConvertor::doConvertToLua(lua_State* L, std::shared_ptr<StatusShow> payload) { + lua_createtable(L, 0, 0); + const std::string show = convertStatusShowTypeToString(payload->getType()); + if (!show.empty()) { + lua_pushstring(L, show.c_str()); + lua_setfield(L, -2, "type"); + } +} + +std::string StatusShowConvertor::convertStatusShowTypeToString(const StatusShow::Type &show) { + switch (show) { + case StatusShow::Online: return "online"; + case StatusShow::FFC: return "ffc"; + case StatusShow::Away: return "away"; + case StatusShow::XA: return "xa"; + case StatusShow::DND: return "dnd"; + case StatusShow::None: return ""; + } + assert(false); + return ""; +} + +StatusShow::Type StatusShowConvertor::convertStatusShowTypeFromString(const std::string& show) { + if (show == "online") { + return StatusShow::Online; + } + else if (show == "ffc") { + return StatusShow::FFC; + } + else if (show == "away") { + return StatusShow::Away; + } + else if (show == "xa") { + return StatusShow::XA; + } + else if (show == "dnd") { + return StatusShow::DND; + } + else { + throw Lua::Exception("Illegal status show: '" + show + "'"); + } +} diff --git a/Sluift/ElementConvertors/StatusShowConvertor.h b/Sluift/ElementConvertors/StatusShowConvertor.h new file mode 100644 index 0000000..41be6b3 --- /dev/null +++ b/Sluift/ElementConvertors/StatusShowConvertor.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2014-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <Swiften/Elements/StatusShow.h> + +#include <Sluift/GenericLuaElementConvertor.h> + +namespace Swift { + class StatusShowConvertor : public GenericLuaElementConvertor<StatusShow> { + public: + StatusShowConvertor(); + virtual ~StatusShowConvertor() override; + + virtual std::shared_ptr<StatusShow> doConvertFromLua(lua_State*) override; + virtual void doConvertToLua(lua_State*, std::shared_ptr<StatusShow>) override; + + static std::string convertStatusShowTypeToString(const StatusShow::Type &show); + static StatusShow::Type convertStatusShowTypeFromString(const std::string& show); + }; +} diff --git a/Sluift/ElementConvertors/SubjectConvertor.cpp b/Sluift/ElementConvertors/SubjectConvertor.cpp new file mode 100644 index 0000000..ae03564 --- /dev/null +++ b/Sluift/ElementConvertors/SubjectConvertor.cpp @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2014-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Sluift/ElementConvertors/SubjectConvertor.h> + +#include <memory> + +#include <lua.hpp> + +#include <Sluift/Lua/LuaUtils.h> + +using namespace Swift; + +SubjectConvertor::SubjectConvertor() : GenericLuaElementConvertor<Subject>("subject") { +} + +SubjectConvertor::~SubjectConvertor() { +} + +std::shared_ptr<Subject> SubjectConvertor::doConvertFromLua(lua_State* L) { + std::shared_ptr<Subject> result = std::make_shared<Subject>(); + if (boost::optional<std::string> value = Lua::getStringField(L, -1, "text")) { + result->setText(*value); + } + return result; +} + +void SubjectConvertor::doConvertToLua(lua_State* L, std::shared_ptr<Subject> payload) { + lua_createtable(L, 0, 0); + if (!payload->getText().empty()) { + lua_pushstring(L, payload->getText().c_str()); + lua_setfield(L, -2, "text"); + } +} diff --git a/Sluift/ElementConvertors/SubjectConvertor.h b/Sluift/ElementConvertors/SubjectConvertor.h new file mode 100644 index 0000000..f8eb152 --- /dev/null +++ b/Sluift/ElementConvertors/SubjectConvertor.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2014-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <Swiften/Elements/Subject.h> + +#include <Sluift/GenericLuaElementConvertor.h> + +namespace Swift { + class LuaElementConvertors; + + class SubjectConvertor : public GenericLuaElementConvertor<Subject> { + public: + SubjectConvertor(); + virtual ~SubjectConvertor() override; + + virtual std::shared_ptr<Subject> doConvertFromLua(lua_State*) override; + virtual void doConvertToLua(lua_State*, std::shared_ptr<Subject>) override; + }; +} diff --git a/Sluift/ElementConvertors/UserLocationConvertor.cpp b/Sluift/ElementConvertors/UserLocationConvertor.cpp index 97cb288..253ca36 100644 --- a/Sluift/ElementConvertors/UserLocationConvertor.cpp +++ b/Sluift/ElementConvertors/UserLocationConvertor.cpp @@ -1,232 +1,258 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #include <Sluift/ElementConvertors/UserLocationConvertor.h> +#include <memory> + #include <lua.hpp> -#include <boost/smart_ptr/make_shared.hpp> -#include <boost/numeric/conversion/cast.hpp> #include <Swiften/Base/DateTime.h> -#pragma clang diagnostic ignored "-Wunused-private-field" - using namespace Swift; -UserLocationConvertor::UserLocationConvertor(LuaElementConvertors* convertors) : - GenericLuaElementConvertor<UserLocation>("user_location"), - convertors(convertors) { +UserLocationConvertor::UserLocationConvertor() : + GenericLuaElementConvertor<UserLocation>("user_location") { } UserLocationConvertor::~UserLocationConvertor() { } -boost::shared_ptr<UserLocation> UserLocationConvertor::doConvertFromLua(lua_State* L) { - boost::shared_ptr<UserLocation> result = boost::make_shared<UserLocation>(); - lua_getfield(L, -1, "area"); - if (lua_isstring(L, -1)) { - result->setArea(std::string(lua_tostring(L, -1))); - } - lua_pop(L, 1); - lua_getfield(L, -1, "altitude"); - if (lua_isnumber(L, -1)) { - result->setAltitude(boost::numeric_cast<float>(lua_tonumber(L, -1))); - } - lua_pop(L, 1); - lua_getfield(L, -1, "locality"); - if (lua_isstring(L, -1)) { - result->setLocality(std::string(lua_tostring(L, -1))); - } - lua_pop(L, 1); - lua_getfield(L, -1, "latitude"); - if (lua_isnumber(L, -1)) { - result->setLatitude(boost::numeric_cast<float>(lua_tonumber(L, -1))); - } - lua_pop(L, 1); - lua_getfield(L, -1, "accuracy"); - if (lua_isnumber(L, -1)) { - result->setAccuracy(boost::numeric_cast<float>(lua_tonumber(L, -1))); - } - lua_pop(L, 1); - lua_getfield(L, -1, "description"); - if (lua_isstring(L, -1)) { - result->setDescription(std::string(lua_tostring(L, -1))); - } - lua_pop(L, 1); - lua_getfield(L, -1, "country_code"); - if (lua_isstring(L, -1)) { - result->setCountryCode(std::string(lua_tostring(L, -1))); - } - lua_pop(L, 1); - lua_getfield(L, -1, "timestamp"); - if (lua_isstring(L, -1)) { - result->setTimestamp(stringToDateTime(std::string(lua_tostring(L, -1)))); - } - lua_pop(L, 1); - lua_getfield(L, -1, "floor"); - if (lua_isstring(L, -1)) { - result->setFloor(std::string(lua_tostring(L, -1))); - } - lua_pop(L, 1); - lua_getfield(L, -1, "building"); - if (lua_isstring(L, -1)) { - result->setBuilding(std::string(lua_tostring(L, -1))); - } - lua_pop(L, 1); - lua_getfield(L, -1, "room"); - if (lua_isstring(L, -1)) { - result->setRoom(std::string(lua_tostring(L, -1))); - } - lua_pop(L, 1); - lua_getfield(L, -1, "country"); - if (lua_isstring(L, -1)) { - result->setCountry(std::string(lua_tostring(L, -1))); - } - lua_pop(L, 1); - lua_getfield(L, -1, "region"); - if (lua_isstring(L, -1)) { - result->setRegion(std::string(lua_tostring(L, -1))); - } - lua_pop(L, 1); - lua_getfield(L, -1, "uri"); - if (lua_isstring(L, -1)) { - result->setURI(std::string(lua_tostring(L, -1))); - } - lua_pop(L, 1); - lua_getfield(L, -1, "longitude"); - if (lua_isnumber(L, -1)) { - result->setLongitude(boost::numeric_cast<float>(lua_tonumber(L, -1))); - } - lua_pop(L, 1); - lua_getfield(L, -1, "error"); - if (lua_isnumber(L, -1)) { - result->setError(boost::numeric_cast<float>(lua_tonumber(L, -1))); - } - lua_pop(L, 1); - lua_getfield(L, -1, "postal_code"); - if (lua_isstring(L, -1)) { - result->setPostalCode(std::string(lua_tostring(L, -1))); - } - lua_pop(L, 1); - lua_getfield(L, -1, "bearing"); - if (lua_isnumber(L, -1)) { - result->setBearing(boost::numeric_cast<float>(lua_tonumber(L, -1))); - } - lua_pop(L, 1); - lua_getfield(L, -1, "text"); - if (lua_isstring(L, -1)) { - result->setText(std::string(lua_tostring(L, -1))); - } - lua_pop(L, 1); - lua_getfield(L, -1, "datum"); - if (lua_isstring(L, -1)) { - result->setDatum(std::string(lua_tostring(L, -1))); - } - lua_pop(L, 1); - lua_getfield(L, -1, "street"); - if (lua_isstring(L, -1)) { - result->setStreet(std::string(lua_tostring(L, -1))); - } - lua_pop(L, 1); - lua_getfield(L, -1, "speed"); - if (lua_isnumber(L, -1)) { - result->setSpeed(boost::numeric_cast<float>(lua_tonumber(L, -1))); - } - lua_pop(L, 1); - return result; +std::shared_ptr<UserLocation> UserLocationConvertor::doConvertFromLua(lua_State* L) { + std::shared_ptr<UserLocation> result = std::make_shared<UserLocation>(); + lua_getfield(L, -1, "area"); + if (lua_isstring(L, -1)) { + result->setArea(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "altitude"); + if (lua_isnumber(L, -1)) { + result->setAltitude(lua_tonumber(L, -1)); + } + lua_pop(L, 1); + lua_getfield(L, -1, "locality"); + if (lua_isstring(L, -1)) { + result->setLocality(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "latitude"); + if (lua_isnumber(L, -1)) { + result->setLatitude(lua_tonumber(L, -1)); + } + lua_pop(L, 1); + lua_getfield(L, -1, "accuracy"); + if (lua_isnumber(L, -1)) { + result->setAccuracy(lua_tonumber(L, -1)); + } + lua_pop(L, 1); + lua_getfield(L, -1, "description"); + if (lua_isstring(L, -1)) { + result->setDescription(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "country_code"); + if (lua_isstring(L, -1)) { + result->setCountryCode(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "timestamp"); + if (lua_isstring(L, -1)) { + result->setTimestamp(stringToDateTime(std::string(lua_tostring(L, -1)))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "floor"); + if (lua_isstring(L, -1)) { + result->setFloor(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "building"); + if (lua_isstring(L, -1)) { + result->setBuilding(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "room"); + if (lua_isstring(L, -1)) { + result->setRoom(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "country"); + if (lua_isstring(L, -1)) { + result->setCountry(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "region"); + if (lua_isstring(L, -1)) { + result->setRegion(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "uri"); + if (lua_isstring(L, -1)) { + result->setURI(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "longitude"); + if (lua_isnumber(L, -1)) { + result->setLongitude(lua_tonumber(L, -1)); + } + lua_pop(L, 1); + lua_getfield(L, -1, "error"); + if (lua_isnumber(L, -1)) { + result->setError(lua_tonumber(L, -1)); + } + lua_pop(L, 1); + lua_getfield(L, -1, "postal_code"); + if (lua_isstring(L, -1)) { + result->setPostalCode(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "bearing"); + if (lua_isnumber(L, -1)) { + result->setBearing(lua_tonumber(L, -1)); + } + lua_pop(L, 1); + lua_getfield(L, -1, "text"); + if (lua_isstring(L, -1)) { + result->setText(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "datum"); + if (lua_isstring(L, -1)) { + result->setDatum(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "street"); + if (lua_isstring(L, -1)) { + result->setStreet(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "speed"); + if (lua_isnumber(L, -1)) { + result->setSpeed(lua_tonumber(L, -1)); + } + lua_pop(L, 1); + return result; +} + +void UserLocationConvertor::doConvertToLua(lua_State* L, std::shared_ptr<UserLocation> payload) { + lua_createtable(L, 0, 0); + if (payload->getArea()) { + lua_pushstring(L, (*payload->getArea()).c_str()); + lua_setfield(L, -2, "area"); + } + if (payload->getAltitude()) { + lua_pushnumber(L, (*payload->getAltitude())); + lua_setfield(L, -2, "altitude"); + } + if (payload->getLocality()) { + lua_pushstring(L, (*payload->getLocality()).c_str()); + lua_setfield(L, -2, "locality"); + } + if (payload->getLatitude()) { + lua_pushnumber(L, (*payload->getLatitude())); + lua_setfield(L, -2, "latitude"); + } + if (payload->getAccuracy()) { + lua_pushnumber(L, (*payload->getAccuracy())); + lua_setfield(L, -2, "accuracy"); + } + if (payload->getDescription()) { + lua_pushstring(L, (*payload->getDescription()).c_str()); + lua_setfield(L, -2, "description"); + } + if (payload->getCountryCode()) { + lua_pushstring(L, (*payload->getCountryCode()).c_str()); + lua_setfield(L, -2, "country_code"); + } + if (payload->getTimestamp()) { + lua_pushstring(L, dateTimeToString((*payload->getTimestamp())).c_str()); + lua_setfield(L, -2, "timestamp"); + } + if (payload->getFloor()) { + lua_pushstring(L, (*payload->getFloor()).c_str()); + lua_setfield(L, -2, "floor"); + } + if (payload->getBuilding()) { + lua_pushstring(L, (*payload->getBuilding()).c_str()); + lua_setfield(L, -2, "building"); + } + if (payload->getRoom()) { + lua_pushstring(L, (*payload->getRoom()).c_str()); + lua_setfield(L, -2, "room"); + } + if (payload->getCountry()) { + lua_pushstring(L, (*payload->getCountry()).c_str()); + lua_setfield(L, -2, "country"); + } + if (payload->getRegion()) { + lua_pushstring(L, (*payload->getRegion()).c_str()); + lua_setfield(L, -2, "region"); + } + if (payload->getURI()) { + lua_pushstring(L, (*payload->getURI()).c_str()); + lua_setfield(L, -2, "uri"); + } + if (payload->getLongitude()) { + lua_pushnumber(L, (*payload->getLongitude())); + lua_setfield(L, -2, "longitude"); + } + if (payload->getError()) { + lua_pushnumber(L, (*payload->getError())); + lua_setfield(L, -2, "error"); + } + if (payload->getPostalCode()) { + lua_pushstring(L, (*payload->getPostalCode()).c_str()); + lua_setfield(L, -2, "postal_code"); + } + if (payload->getBearing()) { + lua_pushnumber(L, (*payload->getBearing())); + lua_setfield(L, -2, "bearing"); + } + if (payload->getText()) { + lua_pushstring(L, (*payload->getText()).c_str()); + lua_setfield(L, -2, "text"); + } + if (payload->getDatum()) { + lua_pushstring(L, (*payload->getDatum()).c_str()); + lua_setfield(L, -2, "datum"); + } + if (payload->getStreet()) { + lua_pushstring(L, (*payload->getStreet()).c_str()); + lua_setfield(L, -2, "street"); + } + if (payload->getSpeed()) { + lua_pushnumber(L, (*payload->getSpeed())); + lua_setfield(L, -2, "speed"); + } } -void UserLocationConvertor::doConvertToLua(lua_State* L, boost::shared_ptr<UserLocation> payload) { - lua_createtable(L, 0, 0); - if (payload->getArea()) { - lua_pushstring(L, (*payload->getArea()).c_str()); - lua_setfield(L, -2, "area"); - } - if (payload->getAltitude()) { - lua_pushnumber(L, (*payload->getAltitude())); - lua_setfield(L, -2, "altitude"); - } - if (payload->getLocality()) { - lua_pushstring(L, (*payload->getLocality()).c_str()); - lua_setfield(L, -2, "locality"); - } - if (payload->getLatitude()) { - lua_pushnumber(L, (*payload->getLatitude())); - lua_setfield(L, -2, "latitude"); - } - if (payload->getAccuracy()) { - lua_pushnumber(L, (*payload->getAccuracy())); - lua_setfield(L, -2, "accuracy"); - } - if (payload->getDescription()) { - lua_pushstring(L, (*payload->getDescription()).c_str()); - lua_setfield(L, -2, "description"); - } - if (payload->getCountryCode()) { - lua_pushstring(L, (*payload->getCountryCode()).c_str()); - lua_setfield(L, -2, "country_code"); - } - if (payload->getTimestamp()) { - lua_pushstring(L, dateTimeToString((*payload->getTimestamp())).c_str()); - lua_setfield(L, -2, "timestamp"); - } - if (payload->getFloor()) { - lua_pushstring(L, (*payload->getFloor()).c_str()); - lua_setfield(L, -2, "floor"); - } - if (payload->getBuilding()) { - lua_pushstring(L, (*payload->getBuilding()).c_str()); - lua_setfield(L, -2, "building"); - } - if (payload->getRoom()) { - lua_pushstring(L, (*payload->getRoom()).c_str()); - lua_setfield(L, -2, "room"); - } - if (payload->getCountry()) { - lua_pushstring(L, (*payload->getCountry()).c_str()); - lua_setfield(L, -2, "country"); - } - if (payload->getRegion()) { - lua_pushstring(L, (*payload->getRegion()).c_str()); - lua_setfield(L, -2, "region"); - } - if (payload->getURI()) { - lua_pushstring(L, (*payload->getURI()).c_str()); - lua_setfield(L, -2, "uri"); - } - if (payload->getLongitude()) { - lua_pushnumber(L, (*payload->getLongitude())); - lua_setfield(L, -2, "longitude"); - } - if (payload->getError()) { - lua_pushnumber(L, (*payload->getError())); - lua_setfield(L, -2, "error"); - } - if (payload->getPostalCode()) { - lua_pushstring(L, (*payload->getPostalCode()).c_str()); - lua_setfield(L, -2, "postal_code"); - } - if (payload->getBearing()) { - lua_pushnumber(L, (*payload->getBearing())); - lua_setfield(L, -2, "bearing"); - } - if (payload->getText()) { - lua_pushstring(L, (*payload->getText()).c_str()); - lua_setfield(L, -2, "text"); - } - if (payload->getDatum()) { - lua_pushstring(L, (*payload->getDatum()).c_str()); - lua_setfield(L, -2, "datum"); - } - if (payload->getStreet()) { - lua_pushstring(L, (*payload->getStreet()).c_str()); - lua_setfield(L, -2, "street"); - } - if (payload->getSpeed()) { - lua_pushnumber(L, (*payload->getSpeed())); - lua_setfield(L, -2, "speed"); - } +boost::optional<LuaElementConvertor::Documentation> UserLocationConvertor::getDocumentation() const { + return Documentation( + "UserLocation", + "This table has the following fields:\n\n" + "- `area`: string (Optional)\n" + "- `altitude`: @{float} (Optional)\n" + "- `locality`: string (Optional)\n" + "- `latitude`: @{float} (Optional)\n" + "- `accuracy`: @{float} (Optional)\n" + "- `description`: string (Optional)\n" + "- `country_code`: string (Optional)\n" + "- `timestamp`: datetime (string) (Optional)\n" + "- `floor`: string (Optional)\n" + "- `building`: string (Optional)\n" + "- `room`: string (Optional)\n" + "- `country`: string (Optional)\n" + "- `region`: string (Optional)\n" + "- `uri`: string (Optional)\n" + "- `longitude`: @{float} (Optional)\n" + "- `error`: @{float} (Optional)\n" + "- `postal_code`: string (Optional)\n" + "- `bearing`: @{float} (Optional)\n" + "- `text`: string (Optional)\n" + "- `datum`: string (Optional)\n" + "- `street`: string (Optional)\n" + "- `speed`: @{float} (Optional)\n" + ); } diff --git a/Sluift/ElementConvertors/UserLocationConvertor.h b/Sluift/ElementConvertors/UserLocationConvertor.h index a5eb153..b667d2a 100644 --- a/Sluift/ElementConvertors/UserLocationConvertor.h +++ b/Sluift/ElementConvertors/UserLocationConvertor.h @@ -1,28 +1,25 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <Swiften/Elements/UserLocation.h> #include <Sluift/GenericLuaElementConvertor.h> -#include <Swiften/Elements/UserLocation.h> namespace Swift { - class LuaElementConvertors; - - class UserLocationConvertor : public GenericLuaElementConvertor<UserLocation> { - public: - UserLocationConvertor(LuaElementConvertors* convertors); - virtual ~UserLocationConvertor(); + class LuaElementConvertors; - virtual boost::shared_ptr<UserLocation> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE; - virtual void doConvertToLua(lua_State*, boost::shared_ptr<UserLocation>) SWIFTEN_OVERRIDE; + class UserLocationConvertor : public GenericLuaElementConvertor<UserLocation> { + public: + UserLocationConvertor(); + virtual ~UserLocationConvertor() override; - private: - LuaElementConvertors* convertors; - }; + virtual std::shared_ptr<UserLocation> doConvertFromLua(lua_State*) override; + virtual void doConvertToLua(lua_State*, std::shared_ptr<UserLocation>) override; + virtual boost::optional<Documentation> getDocumentation() const override; + }; } diff --git a/Sluift/ElementConvertors/UserTuneConvertor.cpp b/Sluift/ElementConvertors/UserTuneConvertor.cpp new file mode 100644 index 0000000..a9e1bee --- /dev/null +++ b/Sluift/ElementConvertors/UserTuneConvertor.cpp @@ -0,0 +1,108 @@ +/* + * Copyright (c) 2014-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Sluift/ElementConvertors/UserTuneConvertor.h> + +#include <memory> + +#include <boost/numeric/conversion/cast.hpp> + +#include <lua.hpp> + +using namespace Swift; + +UserTuneConvertor::UserTuneConvertor() : + GenericLuaElementConvertor<UserTune>("user_tune") { +} + +UserTuneConvertor::~UserTuneConvertor() { +} + +std::shared_ptr<UserTune> UserTuneConvertor::doConvertFromLua(lua_State* L) { + std::shared_ptr<UserTune> result = std::make_shared<UserTune>(); + lua_getfield(L, -1, "rating"); + if (lua_isnumber(L, -1)) { + result->setRating(boost::numeric_cast<unsigned int>(lua_tonumber(L, -1))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "title"); + if (lua_isstring(L, -1)) { + result->setTitle(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "track"); + if (lua_isstring(L, -1)) { + result->setTrack(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "artist"); + if (lua_isstring(L, -1)) { + result->setArtist(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "uri"); + if (lua_isstring(L, -1)) { + result->setURI(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "source"); + if (lua_isstring(L, -1)) { + result->setSource(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "length"); + if (lua_isnumber(L, -1)) { + result->setLength(boost::numeric_cast<unsigned int>(lua_tonumber(L, -1))); + } + lua_pop(L, 1); + return result; +} + +void UserTuneConvertor::doConvertToLua(lua_State* L, std::shared_ptr<UserTune> payload) { + lua_createtable(L, 0, 0); + if (payload->getRating()) { + lua_pushnumber(L, (*payload->getRating())); + lua_setfield(L, -2, "rating"); + } + if (payload->getTitle()) { + lua_pushstring(L, (*payload->getTitle()).c_str()); + lua_setfield(L, -2, "title"); + } + if (payload->getTrack()) { + lua_pushstring(L, (*payload->getTrack()).c_str()); + lua_setfield(L, -2, "track"); + } + if (payload->getArtist()) { + lua_pushstring(L, (*payload->getArtist()).c_str()); + lua_setfield(L, -2, "artist"); + } + if (payload->getURI()) { + lua_pushstring(L, (*payload->getURI()).c_str()); + lua_setfield(L, -2, "uri"); + } + if (payload->getSource()) { + lua_pushstring(L, (*payload->getSource()).c_str()); + lua_setfield(L, -2, "source"); + } + if (payload->getLength()) { + lua_pushnumber(L, (*payload->getLength())); + lua_setfield(L, -2, "length"); + } +} + +boost::optional<LuaElementConvertor::Documentation> UserTuneConvertor::getDocumentation() const { + return Documentation( + "UserTune", + "This table has the following fields:\n\n" + "- `rating`: number (Optional)\n" + "- `title`: string (Optional)\n" + "- `track`: string (Optional)\n" + "- `artist`: string (Optional)\n" + "- `uri`: string (Optional)\n" + "- `source`: string (Optional)\n" + "- `length`: number (Optional)\n" + ); +} diff --git a/Sluift/ElementConvertors/UserTuneConvertor.h b/Sluift/ElementConvertors/UserTuneConvertor.h new file mode 100644 index 0000000..90bda41 --- /dev/null +++ b/Sluift/ElementConvertors/UserTuneConvertor.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2014-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <Swiften/Elements/UserTune.h> + +#include <Sluift/GenericLuaElementConvertor.h> + +namespace Swift { + class LuaElementConvertors; + + class UserTuneConvertor : public GenericLuaElementConvertor<UserTune> { + public: + UserTuneConvertor(); + virtual ~UserTuneConvertor() override; + + virtual std::shared_ptr<UserTune> doConvertFromLua(lua_State*) override; + virtual void doConvertToLua(lua_State*, std::shared_ptr<UserTune>) override; + virtual boost::optional<Documentation> getDocumentation() const override; + }; +} diff --git a/Sluift/ElementConvertors/VCardConvertor.cpp b/Sluift/ElementConvertors/VCardConvertor.cpp index a1c57be..ad521b3 100644 --- a/Sluift/ElementConvertors/VCardConvertor.cpp +++ b/Sluift/ElementConvertors/VCardConvertor.cpp @@ -1,16 +1,21 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #include <Sluift/ElementConvertors/VCardConvertor.h> -#include <lua.hpp> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> + #include <boost/numeric/conversion/cast.hpp> -#include <Sluift/Lua/LuaUtils.h> + +#include <lua.hpp> + #include <Swiften/Base/ByteArray.h> +#include <Swiften/Base/DateTime.h> + +#include <Sluift/Lua/LuaUtils.h> using namespace Swift; @@ -20,27 +25,609 @@ VCardConvertor::VCardConvertor() : GenericLuaElementConvertor<VCard>("vcard") { VCardConvertor::~VCardConvertor() { } -boost::shared_ptr<VCard> VCardConvertor::doConvertFromLua(lua_State* L) { - boost::shared_ptr<VCard> result = boost::make_shared<VCard>(); - lua_getfield(L, -1, "photo"); - if (lua_isstring(L, -1)) { - size_t len; - const char* data = lua_tolstring(L, -1, &len); - result->setPhoto(createByteArray(data, len)); - } - lua_pop(L, 1); - - // TODO - - return result; +std::shared_ptr<VCard> VCardConvertor::doConvertFromLua(lua_State* L) { + std::shared_ptr<VCard> result = std::make_shared<VCard>(); + lua_getfield(L, -1, "fullname"); + if (lua_isstring(L, -1)) { + result->setFullName(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "familyname"); + if (lua_isstring(L, -1)) { + result->setFamilyName(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "givenname"); + if (lua_isstring(L, -1)) { + result->setGivenName(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "middlename"); + if (lua_isstring(L, -1)) { + result->setMiddleName(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "prefix"); + if (lua_isstring(L, -1)) { + result->setPrefix(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "suffix"); + if (lua_isstring(L, -1)) { + result->setSuffix(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "nick"); + if (lua_isstring(L, -1)) { + result->setNickname(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "description"); + if (lua_isstring(L, -1)) { + result->setDescription(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "photo"); + if (lua_isstring(L, -1)) { + size_t len; + const char* data = lua_tolstring(L, -1, &len); + result->setPhoto(createByteArray(data, len)); + } + lua_pop(L, 1); + lua_getfield(L, -1, "phototype"); + if (lua_isstring(L, -1)) { + result->setPhotoType(std::string(lua_tostring(L, -1))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "birthday"); + if (lua_isstring(L, -1)) { + result->setBirthday(stringToDateTime(std::string(lua_tostring(L, -1)))); + } + lua_pop(L, 1); + lua_getfield(L, -1, "email"); + if (lua_istable(L, -1)) { + for (lua_pushnil(L); lua_next(L, -2); ) { + VCard::EMailAddress emailAddress; + emailAddress.address = Lua::getStringField(L, -1, "address").get_value_or(""); + if (boost::optional<bool> home = Lua::getBooleanField(L, -1, "home")) { + emailAddress.isHome = *home; + } + if (boost::optional<bool> work = Lua::getBooleanField(L, -1, "work")) { + emailAddress.isWork = *work; + } + if (boost::optional<bool> internet = Lua::getBooleanField(L, -1, "internet")) { + emailAddress.isInternet = *internet; + } + if (boost::optional<bool> preferred = Lua::getBooleanField(L, -1, "preferred")) { + emailAddress.isPreferred = *preferred; + } + if (boost::optional<bool> x400 = Lua::getBooleanField(L, -1, "x400")) { + emailAddress.isX400 = *x400; + } + result->addEMailAddress(emailAddress); + lua_pop(L, 1); + } + } + lua_pop(L, 1); + lua_getfield(L, -1, "telephone"); + if (lua_istable(L, -1)) { + for (lua_pushnil(L); lua_next(L, -2); ) { + VCard::Telephone telephone; + telephone.number = Lua::getStringField(L, -1, "number").get_value_or(""); + if (boost::optional<bool> home = Lua::getBooleanField(L, -1, "home")) { + telephone.isHome = *home; + } + if (boost::optional<bool> work = Lua::getBooleanField(L, -1, "work")) { + telephone.isWork = *work; + } + if (boost::optional<bool> voice = Lua::getBooleanField(L, -1, "voice")) { + telephone.isVoice = *voice; + } + if (boost::optional<bool> fax = Lua::getBooleanField(L, -1, "fax")) { + telephone.isFax = *fax; + } + if (boost::optional<bool> pager = Lua::getBooleanField(L, -1, "pager")) { + telephone.isPager = *pager; + } + if (boost::optional<bool> msg = Lua::getBooleanField(L, -1, "msg")) { + telephone.isMSG = *msg; + } + if (boost::optional<bool> cell = Lua::getBooleanField(L, -1, "cell")) { + telephone.isCell = *cell; + } + if (boost::optional<bool> video = Lua::getBooleanField(L, -1, "video")) { + telephone.isVideo = *video; + } + if (boost::optional<bool> bbs = Lua::getBooleanField(L, -1, "bbs")) { + telephone.isBBS = *bbs; + } + if (boost::optional<bool> modem = Lua::getBooleanField(L, -1, "modem")) { + telephone.isModem = *modem; + } + if (boost::optional<bool> isdn = Lua::getBooleanField(L, -1, "isdn")) { + telephone.isISDN = *isdn; + } + if (boost::optional<bool> pcs = Lua::getBooleanField(L, -1, "pcs")) { + telephone.isPCS = *pcs; + } + if (boost::optional<bool> preferred = Lua::getBooleanField(L, -1, "preferred")) { + telephone.isPreferred = *preferred; + } + result->addTelephone(telephone); + lua_pop(L, 1); + } + } + lua_pop(L, 1); + lua_getfield(L, -1, "address"); + if (lua_istable(L, -1)) { + for (lua_pushnil(L); lua_next(L, -2); ) { + VCard::Address address; + address.poBox = Lua::getStringField(L, -1, "pobox").get_value_or(""); + address.addressExtension = Lua::getStringField(L, -1, "extension").get_value_or(""); + address.street = Lua::getStringField(L, -1, "street").get_value_or(""); + address.locality = Lua::getStringField(L, -1, "locality").get_value_or(""); + address.region = Lua::getStringField(L, -1, "region").get_value_or(""); + address.postalCode = Lua::getStringField(L, -1, "postalcode").get_value_or(""); + address.country = Lua::getStringField(L, -1, "country").get_value_or(""); + if (boost::optional<bool> home = Lua::getBooleanField(L, -1, "home")) { + address.isHome = *home; + } + if (boost::optional<bool> work = Lua::getBooleanField(L, -1, "work")) { + address.isWork = *work; + } + if (boost::optional<bool> postal = Lua::getBooleanField(L, -1, "postal")) { + address.isPostal = *postal; + } + if (boost::optional<bool> parcel = Lua::getBooleanField(L, -1, "parcel")) { + address.isParcel = *parcel; + } + if (boost::optional<bool> preferred = Lua::getBooleanField(L, -1, "preferred")) { + address.isPreferred = *preferred; + } + if (boost::optional<bool> domestic = Lua::getBooleanField(L, -1, "domestic")) { + if (*domestic) { + address.deliveryType = VCard::DomesticDelivery; + } + } + if (boost::optional<bool> international = Lua::getBooleanField(L, -1, "international")) { + if (*international) { + address.deliveryType = VCard::InternationalDelivery; + } + } + result->addAddress(address); + lua_pop(L, 1); + } + } + lua_pop(L, 1); + lua_getfield(L, -1, "addresslabel"); + if (lua_istable(L, -1)) { + for (lua_pushnil(L); lua_next(L, -2); ) { + VCard::AddressLabel addresslabel; + lua_getfield(L, -1, "lines"); + if (lua_istable(L, -1)) { + for (lua_pushnil(L); lua_next(L, -2); ) { + if (lua_isstring(L, -1)) { + addresslabel.lines.push_back(lua_tostring(L, -1)); + } + lua_pop(L, 1); + } + } + lua_pop(L, 1); + if (boost::optional<bool> home = Lua::getBooleanField(L, -1, "home")) { + addresslabel.isHome = *home; + } + if (boost::optional<bool> work = Lua::getBooleanField(L, -1, "work")) { + addresslabel.isWork = *work; + } + if (boost::optional<bool> postal = Lua::getBooleanField(L, -1, "postal")) { + addresslabel.isPostal = *postal; + } + if (boost::optional<bool> parcel = Lua::getBooleanField(L, -1, "parcel")) { + addresslabel.isParcel = *parcel; + } + if (boost::optional<bool> preferred = Lua::getBooleanField(L, -1, "preferred")) { + addresslabel.isPreferred = *preferred; + } + if (boost::optional<bool> domestic = Lua::getBooleanField(L, -1, "domestic")) { + if (*domestic) { + addresslabel.deliveryType = VCard::DomesticDelivery; + } + } + if (boost::optional<bool> international = Lua::getBooleanField(L, -1, "international")) { + if (*international) { + addresslabel.deliveryType = VCard::InternationalDelivery; + } + } + result->addAddressLabel(addresslabel); + lua_pop(L, 1); + } + } + lua_pop(L, 1); + lua_getfield(L, -1, "organization"); + if (lua_istable(L, -1)) { + for (lua_pushnil(L); lua_next(L, -2); ) { + VCard::Organization organization; + organization.name = Lua::getStringField(L, -1, "name").get_value_or(""); + lua_getfield(L, -1, "units"); + if (lua_istable(L, -1)) { + for (lua_pushnil(L); lua_next(L, -2); ) { + if (lua_isstring(L, -1)) { + organization.units.push_back(lua_tostring(L, -1)); + } + lua_pop(L, 1); + } + } + lua_pop(L, 1); + result->addOrganization(organization); + lua_pop(L, 1); + } + } + lua_pop(L, 1); + lua_getfield(L, -1, "jid"); + if (lua_istable(L, -1)) { + for (lua_pushnil(L); lua_next(L, -2); ) { + if (lua_isstring(L, -1)) { + result->addJID(lua_tostring(L, -1)); + } + lua_pop(L, 1); + } + } + lua_pop(L, 1); + lua_getfield(L, -1, "title"); + if (lua_istable(L, -1)) { + for (lua_pushnil(L); lua_next(L, -2); ) { + if (lua_isstring(L, -1)) { + result->addTitle(lua_tostring(L, -1)); + } + lua_pop(L, 1); + } + } + lua_pop(L, 1); + lua_getfield(L, -1, "role"); + if (lua_istable(L, -1)) { + for (lua_pushnil(L); lua_next(L, -2); ) { + if (lua_isstring(L, -1)) { + result->addRole(lua_tostring(L, -1)); + } + lua_pop(L, 1); } + } + lua_pop(L, 1); + lua_getfield(L, -1, "url"); + if (lua_istable(L, -1)) { + for (lua_pushnil(L); lua_next(L, -2); ) { + if (lua_isstring(L, -1)) { + result->addURL(lua_tostring(L, -1)); + } + lua_pop(L, 1); + } + } + lua_pop(L, 1); + return result; } -void VCardConvertor::doConvertToLua(lua_State* L, boost::shared_ptr<VCard> payload) { - lua_newtable(L); - if (!payload->getPhoto().empty()) { - lua_pushlstring(L, - reinterpret_cast<const char*>(vecptr(payload->getPhoto())), - payload->getPhoto().size()); - lua_setfield(L, -2, "photo"); - } +void VCardConvertor::doConvertToLua(lua_State* L, std::shared_ptr<VCard> payload) { + lua_newtable(L); + if (!payload->getFullName().empty()) { + lua_pushstring(L, payload->getFullName().c_str()); + lua_setfield(L, -2, "fullname"); + } + if (!payload->getFamilyName().empty()) { + lua_pushstring(L, payload->getFamilyName().c_str()); + lua_setfield(L, -2, "familyname"); + } + if (!payload->getGivenName().empty()) { + lua_pushstring(L, payload->getGivenName().c_str()); + lua_setfield(L, -2, "givenname"); + } + if (!payload->getMiddleName().empty()) { + lua_pushstring(L, payload->getMiddleName().c_str()); + lua_setfield(L, -2, "middlename"); + } + if (!payload->getPrefix().empty()) { + lua_pushstring(L, payload->getPrefix().c_str()); + lua_setfield(L, -2, "prefix"); + } + if (!payload->getSuffix().empty()) { + lua_pushstring(L, payload->getSuffix().c_str()); + lua_setfield(L, -2, "suffix"); + } + if (!payload->getNickname().empty()) { + lua_pushstring(L, payload->getNickname().c_str()); + lua_setfield(L, -2, "nick"); + } + if (!payload->getDescription().empty()) { + lua_pushstring(L, payload->getDescription().c_str()); + lua_setfield(L, -2, "description"); + } + if (!payload->getPhoto().empty()) { + lua_pushlstring(L, reinterpret_cast<const char*>(vecptr(payload->getPhoto())), payload->getPhoto().size()); + lua_setfield(L, -2, "photo"); + } + if (!payload->getPhotoType().empty()) { + lua_pushstring(L, payload->getPhotoType().c_str()); + lua_setfield(L, -2, "phototype"); + } + if (!payload->getBirthday().is_not_a_date_time()) { + lua_pushstring(L, dateTimeToString(payload->getBirthday()).c_str()); + lua_setfield(L, -2, "birthday"); + } + const std::vector<VCard::EMailAddress>& emails = payload->getEMailAddresses(); + if (!emails.empty()) { + lua_createtable(L, boost::numeric_cast<int>(emails.size()), 0); + for (size_t i = 0; i < emails.size(); ++i) { + lua_createtable(L, 0, 0); + if (!emails[i].address.empty()) { + lua_pushstring(L, emails[i].address.c_str()); + lua_setfield(L, -2, "address"); + } + if (emails[i].isHome) { + lua_pushboolean(L, true); + lua_setfield(L, -2, "home"); + } + if (emails[i].isWork) { + lua_pushboolean(L, true); + lua_setfield(L, -2, "work"); + } + if (emails[i].isInternet) { + lua_pushboolean(L, true); + lua_setfield(L, -2, "internet"); + } + if (emails[i].isPreferred) { + lua_pushboolean(L, true); + lua_setfield(L, -2, "preferred"); + } + if (emails[i].isX400) { + lua_pushboolean(L, true); + lua_setfield(L, -2, "x400"); + } + lua_rawseti(L, -2, boost::numeric_cast<int>(i+1)); + } + lua_setfield(L, -2, "email"); + } + const std::vector<VCard::Telephone>& telephones = payload->getTelephones(); + if (!telephones.empty()) { + lua_createtable(L, boost::numeric_cast<int>(telephones.size()), 0); + for (size_t i = 0; i < telephones.size(); ++i) { + lua_createtable(L, 0, 0); + if (!telephones[i].number.empty()) { + lua_pushstring(L, telephones[i].number.c_str()); + lua_setfield(L, -2, "number"); + } + if (telephones[i].isHome) { + lua_pushboolean(L, true); + lua_setfield(L, -2, "home"); + } + if (telephones[i].isWork) { + lua_pushboolean(L, true); + lua_setfield(L, -2, "work"); + } + if (telephones[i].isVoice) { + lua_pushboolean(L, true); + lua_setfield(L, -2, "voice"); + } + if (telephones[i].isFax) { + lua_pushboolean(L, true); + lua_setfield(L, -2, "fax"); + } + if (telephones[i].isPager) { + lua_pushboolean(L, true); + lua_setfield(L, -2, "pager"); + } + if (telephones[i].isMSG) { + lua_pushboolean(L, true); + lua_setfield(L, -2, "msg"); + } + if (telephones[i].isCell) { + lua_pushboolean(L, true); + lua_setfield(L, -2, "cell"); + } + if (telephones[i].isVideo) { + lua_pushboolean(L, true); + lua_setfield(L, -2, "video"); + } + if (telephones[i].isBBS) { + lua_pushboolean(L, true); + lua_setfield(L, -2, "bbs"); + } + if (telephones[i].isModem) { + lua_pushboolean(L, true); + lua_setfield(L, -2, "modem"); + } + if (telephones[i].isISDN) { + lua_pushboolean(L, true); + lua_setfield(L, -2, "isdn"); + } + if (telephones[i].isPCS) { + lua_pushboolean(L, true); + lua_setfield(L, -2, "pcs"); + } + if (telephones[i].isPreferred) { + lua_pushboolean(L, true); + lua_setfield(L, -2, "preferred"); + } + lua_rawseti(L, -2, boost::numeric_cast<int>(i+1)); + } + lua_setfield(L, -2, "telephone"); + } + const std::vector<VCard::Address>& addresses = payload->getAddresses(); + if (!addresses.empty()) { + lua_createtable(L, boost::numeric_cast<int>(addresses.size()), 0); + for (size_t i = 0; i < addresses.size(); ++i) { + lua_createtable(L, 0, 0); + if (!addresses[i].poBox.empty()) { + lua_pushstring(L, addresses[i].poBox.c_str()); + lua_setfield(L, -2, "pobox"); + } + if (!addresses[i].addressExtension.empty()) { + lua_pushstring(L, addresses[i].addressExtension.c_str()); + lua_setfield(L, -2, "extension"); + } + if (!addresses[i].street.empty()) { + lua_pushstring(L, addresses[i].street.c_str()); + lua_setfield(L, -2, "street"); + } + if (!addresses[i].locality.empty()) { + lua_pushstring(L, addresses[i].locality.c_str()); + lua_setfield(L, -2, "locality"); + } + if (!addresses[i].region.empty()) { + lua_pushstring(L, addresses[i].region.c_str()); + lua_setfield(L, -2, "region"); + } + if (!addresses[i].postalCode.empty()) { + lua_pushstring(L, addresses[i].postalCode.c_str()); + lua_setfield(L, -2, "postalcode"); + } + if (!addresses[i].country.empty()) { + lua_pushstring(L, addresses[i].country.c_str()); + lua_setfield(L, -2, "country"); + } + if (addresses[i].isHome) { + lua_pushboolean(L, true); + lua_setfield(L, -2, "home"); + } + if (addresses[i].isWork) { + lua_pushboolean(L, true); + lua_setfield(L, -2, "work"); + } + if (addresses[i].isPostal) { + lua_pushboolean(L, true); + lua_setfield(L, -2, "postal"); + } + if (addresses[i].isParcel) { + lua_pushboolean(L, true); + lua_setfield(L, -2, "parcel"); + } + if (addresses[i].isPreferred) { + lua_pushboolean(L, true); + lua_setfield(L, -2, "preferred"); + } + if (addresses[i].deliveryType == VCard::DomesticDelivery) { + lua_pushboolean(L, true); + lua_setfield(L, -2, "domestic"); + } + if (addresses[i].deliveryType == VCard::InternationalDelivery) { + lua_pushboolean(L, true); + lua_setfield(L, -2, "international"); + } + lua_rawseti(L, -2, boost::numeric_cast<int>(i+1)); + } + lua_setfield(L, -2, "address"); + } + const std::vector<VCard::AddressLabel>& addresslabels = payload->getAddressLabels(); + if (!addresslabels.empty()) { + lua_createtable(L, boost::numeric_cast<int>(addresslabels.size()), 0); + for (size_t i = 0; i < addresslabels.size(); ++i) { + lua_createtable(L, 0, 0); + const std::vector<std::string>& lines = addresslabels[i].lines; + if (!lines.empty()) { + lua_createtable(L, boost::numeric_cast<int>(addresslabels[i].lines.size()), 0); + for (size_t j = 0; j < lines.size(); ++j) { + if (!lines[j].empty()) { + lua_pushstring(L, lines[j].c_str()); + } + lua_rawseti(L, -2, boost::numeric_cast<int>(j+1)); + } + lua_setfield(L, -2, "lines"); + } + if (addresslabels[i].isHome) { + lua_pushboolean(L, true); + lua_setfield(L, -2, "home"); + } + if (addresslabels[i].isWork) { + lua_pushboolean(L, true); + lua_setfield(L, -2, "work"); + } + if (addresslabels[i].isPostal) { + lua_pushboolean(L, true); + lua_setfield(L, -2, "postal"); + } + if (addresslabels[i].isParcel) { + lua_pushboolean(L, true); + lua_setfield(L, -2, "parcel"); + } + if (addresslabels[i].isPreferred) { + lua_pushboolean(L, true); + lua_setfield(L, -2, "preferred"); + } + if (addresslabels[i].deliveryType == VCard::DomesticDelivery) { + lua_pushboolean(L, true); + lua_setfield(L, -2, "domestic"); + } + if (addresslabels[i].deliveryType == VCard::InternationalDelivery) { + lua_pushboolean(L, true); + lua_setfield(L, -2, "international"); + } + lua_rawseti(L, -2, boost::numeric_cast<int>(i+1)); + } + lua_setfield(L, -2, "addresslabel"); + } + const std::vector<VCard::Organization>& organizations = payload->getOrganizations(); + if (!organizations.empty()) { + lua_createtable(L, boost::numeric_cast<int>(organizations.size()), 0); + for (size_t i = 0; i < organizations.size(); ++i) { + lua_createtable(L, 0, 0); + if (!organizations[i].name.empty()) { + lua_pushstring(L, organizations[i].name.c_str()); + lua_setfield(L, -2, "name"); + } + const std::vector<std::string>& units = organizations[i].units; + if (!units.empty()) { + lua_createtable(L, boost::numeric_cast<int>(organizations[i].units.size()), 0); + for (size_t j = 0; j < units.size(); ++j) { + if (!units[j].empty()) { + lua_pushstring(L, units[j].c_str()); + } + lua_rawseti(L, -2, boost::numeric_cast<int>(j+1)); + } + lua_setfield(L, -2, "units"); + } + lua_rawseti(L, -2, boost::numeric_cast<int>(i+1)); + } + lua_setfield(L, -2, "organization"); + } + const std::vector<JID>& jids = payload->getJIDs(); + if (!jids.empty()) { + lua_createtable(L, boost::numeric_cast<int>(jids.size()), 0); + for (size_t i = 0; i < jids.size(); ++i) { + if (!jids[i].toString().empty()) { + lua_pushstring(L, jids[i].toString().c_str()); + } + lua_rawseti(L, -2, boost::numeric_cast<int>(i+1)); + } + lua_setfield(L, -2, "jid"); + } + const std::vector<std::string>& titles = payload->getTitles(); + if (!titles.empty()) { + lua_createtable(L, boost::numeric_cast<int>(titles.size()), 0); + for (size_t i = 0; i < titles.size(); ++i) { + if (!titles[i].empty()) { + lua_pushstring(L, titles[i].c_str()); + } + lua_rawseti(L, -2, boost::numeric_cast<int>(i+1)); + } + lua_setfield(L, -2, "title"); + } + const std::vector<std::string>& roles = payload->getRoles(); + if (!roles.empty()) { + lua_createtable(L, boost::numeric_cast<int>(roles.size()), 0); + for (size_t i = 0; i < roles.size(); ++i) { + if (!roles[i].empty()) { + lua_pushstring(L, roles[i].c_str()); + } + lua_rawseti(L, -2, boost::numeric_cast<int>(i+1)); + } + lua_setfield(L, -2, "role"); + } + const std::vector<std::string>& urls = payload->getURLs(); + if (!urls.empty()) { + lua_createtable(L, boost::numeric_cast<int>(urls.size()), 0); + for (size_t i = 0; i < urls.size(); ++i) { + if (!urls[i].empty()) { + lua_pushstring(L, urls[i].c_str()); + } + lua_rawseti(L, -2, boost::numeric_cast<int>(i+1)); + } + lua_setfield(L, -2, "url"); + } } diff --git a/Sluift/ElementConvertors/VCardConvertor.h b/Sluift/ElementConvertors/VCardConvertor.h index 1cf4e9f..1d59c69 100644 --- a/Sluift/ElementConvertors/VCardConvertor.h +++ b/Sluift/ElementConvertors/VCardConvertor.h @@ -1,23 +1,22 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <Swiften/Elements/VCard.h> #include <Sluift/GenericLuaElementConvertor.h> -#include <Swiften/Elements/VCard.h> namespace Swift { - class VCardConvertor : public GenericLuaElementConvertor<VCard> { - public: - VCardConvertor(); - virtual ~VCardConvertor(); + class VCardConvertor : public GenericLuaElementConvertor<VCard> { + public: + VCardConvertor(); + virtual ~VCardConvertor() override; - virtual boost::shared_ptr<VCard> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE; - virtual void doConvertToLua(lua_State*, boost::shared_ptr<VCard>) SWIFTEN_OVERRIDE; - }; + virtual std::shared_ptr<VCard> doConvertFromLua(lua_State*) override; + virtual void doConvertToLua(lua_State*, std::shared_ptr<VCard>) override; + }; } diff --git a/Sluift/ElementConvertors/VCardUpdateConvertor.cpp b/Sluift/ElementConvertors/VCardUpdateConvertor.cpp index 0010ca5..21c3d68 100644 --- a/Sluift/ElementConvertors/VCardUpdateConvertor.cpp +++ b/Sluift/ElementConvertors/VCardUpdateConvertor.cpp @@ -1,14 +1,17 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #include <Sluift/ElementConvertors/VCardUpdateConvertor.h> -#include <lua.hpp> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> + #include <boost/numeric/conversion/cast.hpp> + +#include <lua.hpp> + #include <Sluift/Lua/LuaUtils.h> using namespace Swift; @@ -19,18 +22,18 @@ VCardUpdateConvertor::VCardUpdateConvertor() : GenericLuaElementConvertor<VCardU VCardUpdateConvertor::~VCardUpdateConvertor() { } -boost::shared_ptr<VCardUpdate> VCardUpdateConvertor::doConvertFromLua(lua_State* L) { - boost::shared_ptr<VCardUpdate> result = boost::make_shared<VCardUpdate>(); - if (boost::optional<std::string> value = Lua::getStringField(L, -1, "photo_hash")) { - result->setPhotoHash(*value); - } - return result; +std::shared_ptr<VCardUpdate> VCardUpdateConvertor::doConvertFromLua(lua_State* L) { + std::shared_ptr<VCardUpdate> result = std::make_shared<VCardUpdate>(); + if (boost::optional<std::string> value = Lua::getStringField(L, -1, "photo_hash")) { + result->setPhotoHash(*value); + } + return result; } -void VCardUpdateConvertor::doConvertToLua(lua_State* L, boost::shared_ptr<VCardUpdate> payload) { - lua_newtable(L); - if (!payload->getPhotoHash().empty()) { - lua_pushstring(L, payload->getPhotoHash().c_str()); - lua_setfield(L, -2, "photo_hash"); - } +void VCardUpdateConvertor::doConvertToLua(lua_State* L, std::shared_ptr<VCardUpdate> payload) { + lua_newtable(L); + if (!payload->getPhotoHash().empty()) { + lua_pushstring(L, payload->getPhotoHash().c_str()); + lua_setfield(L, -2, "photo_hash"); + } } diff --git a/Sluift/ElementConvertors/VCardUpdateConvertor.h b/Sluift/ElementConvertors/VCardUpdateConvertor.h index e9bcd0f..19e42c6 100644 --- a/Sluift/ElementConvertors/VCardUpdateConvertor.h +++ b/Sluift/ElementConvertors/VCardUpdateConvertor.h @@ -1,23 +1,22 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <Swiften/Elements/VCardUpdate.h> #include <Sluift/GenericLuaElementConvertor.h> -#include <Swiften/Elements/VCardUpdate.h> namespace Swift { - class VCardUpdateConvertor : public GenericLuaElementConvertor<VCardUpdate> { - public: - VCardUpdateConvertor(); - virtual ~VCardUpdateConvertor(); + class VCardUpdateConvertor : public GenericLuaElementConvertor<VCardUpdate> { + public: + VCardUpdateConvertor(); + virtual ~VCardUpdateConvertor() override; - virtual boost::shared_ptr<VCardUpdate> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE; - virtual void doConvertToLua(lua_State*, boost::shared_ptr<VCardUpdate>) SWIFTEN_OVERRIDE; - }; + virtual std::shared_ptr<VCardUpdate> doConvertFromLua(lua_State*) override; + virtual void doConvertToLua(lua_State*, std::shared_ptr<VCardUpdate>) override; + }; } diff --git a/Sluift/Examples/AdHocCommands.lua b/Sluift/Examples/AdHocCommands.lua index 9e83f0c..f2f9cb4 100644 --- a/Sluift/Examples/AdHocCommands.lua +++ b/Sluift/Examples/AdHocCommands.lua @@ -1,7 +1,7 @@ --[[ - Copyright (c) 2013 Remko Tronçon - Licensed under the GNU General Public License v3. - See Documentation/Licenses/GPLv3.txt for more information. + Copyright (c) 2013 Isode Limited. + All rights reserved. + See the COPYING file for more information. --]] --[[ diff --git a/Sluift/Examples/CollectVersions.lua b/Sluift/Examples/CollectVersions.lua index 38bf6ac..42bcf86 100644 --- a/Sluift/Examples/CollectVersions.lua +++ b/Sluift/Examples/CollectVersions.lua @@ -1,8 +1,8 @@ --[[ - Copyright (c) 2010-2013 Remko Tronçon - Licensed under the GNU General Public License v3. - See Documentation/Licenses/GPLv3.txt for more information. + Copyright (c) 2010-2013 Isode Limited. + All rights reserved. + See the COPYING file for more information. This script logs into an XMPP server, and collects statistics about the server software of all contacts in your roster diff --git a/Sluift/Examples/Component.lua b/Sluift/Examples/Component.lua new file mode 100644 index 0000000..b8a71f5 --- /dev/null +++ b/Sluift/Examples/Component.lua @@ -0,0 +1,55 @@ +--[[ + Copyright (c) 2014 Edwin Mons and Isode Limited. + All rights reserved. + See the COPYING file for more information. +--]] + +--[[ + + Component example. + + This script connects to an XMPP server as a component, and listens to + messages received. + + The following environment variables are used: + * SLUIFT_COMP_DOMAIN: Component domain name + * SLUIFT_COMP_SECRET: Component secret + * SLUIFT_COMP_HOST: XMPP server host name + * SLUIFT_COMP_PORT: XMPP server component port + * SLUIFT_JID: Recipient of presence and initial message + * SLUIFT_DEBUG: Sets whether debugging should be turned on + +--]] + +require "sluift" + +sluift.debug = os.getenv("SLUIFT_DEBUG") or false + +config = { + domain = os.getenv('SLUIFT_COMP_DOMAIN'), + secret = os.getenv('SLUIFT_COMP_SECRET'), + host = os.getenv('SLUIFT_COMP_HOST'), + port = os.getenv('SLUIFT_COMP_PORT'), + jid = os.getenv('SLUIFT_JID') +} + +-- Create the component, and connect +comp = sluift.new_component(config.domain, config.secret); +comp:connect(config) + +-- Send initial presence and message +-- Assumes the remote client already has this component user on his roster +comp:send_presence{from='root@' .. config.domain, to=config.jid} +comp:send_message{from='root@' .. config.domain, to=config.jid, body='Component active'} + +-- Listen for messages, and reply if one is received +for message in comp:messages() do + print("Received a message from " .. message.from) + comp:send_message{to=message.from, from=message.to, body='I received: ' .. message['body']} + + -- Send out a ping to demonstrate we can do more than just send messages + comp:get{to=message.from, query='<ping xmlns="urn:xmpp:ping"/>'} +end + +comp:disconnect() + diff --git a/Sluift/Examples/ContactsMap.lua b/Sluift/Examples/ContactsMap.lua index d248dc7..573eb9f 100644 --- a/Sluift/Examples/ContactsMap.lua +++ b/Sluift/Examples/ContactsMap.lua @@ -1,7 +1,7 @@ --[[ - Copyright (c) 2013 Remko Tronçon - Licensed under the GNU General Public License v3. - See Documentation/Licenses/GPLv3.txt for more information. + Copyright (c) 2013 Isode Limited. + All rights reserved. + See the COPYING file for more information. --]] --[[ diff --git a/Sluift/Examples/EchoBot.lua b/Sluift/Examples/EchoBot.lua index fc495c4..81c2fa3 100644 --- a/Sluift/Examples/EchoBot.lua +++ b/Sluift/Examples/EchoBot.lua @@ -1,7 +1,7 @@ --[[ - Copyright (c) 2010-2013 Remko Tronçon - Licensed under the GNU General Public License v3. - See Documentation/Licenses/GPLv3.txt for more information. + Copyright (c) 2010-2013 Isode Limited. + All rights reserved. + See the COPYING file for more information. --]] --[[ diff --git a/Sluift/Examples/EchoBot_With.lua b/Sluift/Examples/EchoBot_With.lua new file mode 100644 index 0000000..2260deb --- /dev/null +++ b/Sluift/Examples/EchoBot_With.lua @@ -0,0 +1,32 @@ +--[[ + Copyright (c) 2010-2013 Isode Limited. + All rights reserved. + See the COPYING file for more information. +--]] + +--[[ + + Alternative version of EchoBot that uses with() + + This script logs into an XMPP server, sends initial presence, + and then waits for incoming messages, and echoes them back. + + The following environment variables are used: + * SLUIFT_JID, SWIFT_PASS: JID and password to log in with + * SLUIFT_DEBUG: Sets whether debugging should be turned on + +--]] + +require "sluift" + +sluift.debug = os.getenv("SLUIFT_DEBUG") or false + +client = sluift.new_client(os.getenv("SLUIFT_JID"), os.getenv("SLUIFT_PASS")) +sluift.with(client, function () + connect() + set_version{name = "EchoBot", version = "0.1"} + send_presence("Send me a message") + for message in messages() do + send_message{to = message["from"], body = message["body"]} + end +end) diff --git a/Sluift/Examples/Login.lua b/Sluift/Examples/Login.lua index c43b72a..1d70954 100644 --- a/Sluift/Examples/Login.lua +++ b/Sluift/Examples/Login.lua @@ -1,7 +1,7 @@ --[[ - Copyright (c) 2010-2013 Remko Tronçon - Licensed under the GNU General Public License v3. - See Documentation/Licenses/GPLv3.txt for more information. + Copyright (c) 2010-2014 Isode Limited. + All rights reserved. + See the COPYING file for more information. --]] --[[ @@ -21,7 +21,7 @@ sluift.debug = os.getenv("SLUIFT_DEBUG") or false print("Connecting " .. os.getenv("SLUIFT_JID") .. " ...") c = sluift.new_client(os.getenv("SLUIFT_JID"), os.getenv("SLUIFT_PASS")) -c:set_options({compress = false, tls = false}) +c:set_options{compress = false, tls = false} c:connect() c:send_presence("") diff --git a/Sluift/Examples/MAMRSM.lua b/Sluift/Examples/MAMRSM.lua new file mode 100644 index 0000000..c8a1e85 --- /dev/null +++ b/Sluift/Examples/MAMRSM.lua @@ -0,0 +1,23 @@ +-- A query using Result Set Management +-- Usage: ./sluift MAMRSM.lua <jid> <password> <query_dest> <max_results> + +sluift.debug = true + +c = sluift.new_client(arg[1], arg[2]) + +c:connect(); + +query = { + result_set={max_items=arg[4]} +} + +c:set_mam{mam=query, to=arg[3]} + +c:for_each_message(function(e) + if e.payloads[1].tag == 'fin' then return true end + if e.payloads[1]._type == 'mam_result' then + print(e.payloads[1].payload.stanza.payloads[1].text) + end +end) + +c:disconnect() diff --git a/Sluift/Examples/MAMRSMPage.lua b/Sluift/Examples/MAMRSMPage.lua new file mode 100644 index 0000000..cb3307c --- /dev/null +++ b/Sluift/Examples/MAMRSMPage.lua @@ -0,0 +1,36 @@ +-- A page query using Result Set Management +-- Usage: ./sluift MAMRSMPage.lua <jid> <password> <query_dest> <pages> + +sluift.debug = true + +c = sluift.new_client(arg[1], arg[2]) + +c:set_options{compress = false, tls = false} + +c:connect(); + +query = { + result_set={max_items=5} +} + +done = false +page = 0 +while not done and page < tonumber(arg[4]) do + page = page + 1 + c:set_mam{mam=query, to=arg[3]} + c:for_each_message(function(e) + if e.payloads[1].tag == 'fin' then + if e.payloads[2].last_id then + query.result_set.after = e.payloads[2].last_id + else + done = true + end + return true + end + if e.payloads[1]._type == 'mam_result' then + print(e.payloads[1].payload.stanza.payloads[1].text) + end + end) +end + +c:disconnect() diff --git a/Sluift/Examples/MAMSimple.lua b/Sluift/Examples/MAMSimple.lua new file mode 100644 index 0000000..13ab1a0 --- /dev/null +++ b/Sluift/Examples/MAMSimple.lua @@ -0,0 +1,19 @@ +-- Querying the archive for messages +-- Usage: ./sluift MAMSimple.lua <jid> <password> <query_dest> + +sluift.debug = true + +c = sluift.new_client(arg[1], arg[2]) + +c:connect(); + +c:set_mam{mam={}, to=arg[3]} + +c:for_each_message(function(e) + if e.payloads[1].tag == 'fin' then return true end + if e.payloads[1]._type == 'mam_result' then + print(e.payloads[1].payload.stanza.payloads[1].text) + end +end) + +c:disconnect() diff --git a/Sluift/Examples/MAMSupportedFields.lua b/Sluift/Examples/MAMSupportedFields.lua new file mode 100644 index 0000000..0417924 --- /dev/null +++ b/Sluift/Examples/MAMSupportedFields.lua @@ -0,0 +1,18 @@ +-- Retrieving form fields +-- Usage: ./sluift MAMSupportedFields.lua <jid> <password> + +sluift.debug = true + +c = sluift.new_client(arg[1], arg[2]) + +c:connect(); + +mam_result = c:get_mam{} + +for i=1,#mam_result.form.fields do + if mam_result.form.fields[i].type ~= "hidden" then + print("Server supports: " .. mam_result.form.fields[i].name) + end +end + +c:disconnect() diff --git a/Sluift/Examples/MAMUser.lua b/Sluift/Examples/MAMUser.lua new file mode 100644 index 0000000..e4a7c28 --- /dev/null +++ b/Sluift/Examples/MAMUser.lua @@ -0,0 +1,25 @@ +-- Querying for all messages to/from a particular JID +-- Usage: ./sluift MAMUser.lua <jid> <password> <query_dest> <query_jid> + +sluift.debug = true + +c = sluift.new_client(arg[1], arg[2]) + +c:connect(); + +fields = { + with = arg[4] +} + +query_form = sluift.create_form{fields, form_type="urn:xmpp:mam:0"} + +c:set_mam{mam={form=query_form}, to=arg[3]} + +c:for_each_message(function(e) + if e.payloads[1].tag == 'fin' then return true end + if e.payloads[1]._type == 'mam_result' then + print(e.payloads[1].payload.stanza.payloads[1].text) + end +end) + +c:disconnect() diff --git a/Sluift/Examples/PEPListener.lua b/Sluift/Examples/PEPListener.lua index f196f84..416ae52 100644 --- a/Sluift/Examples/PEPListener.lua +++ b/Sluift/Examples/PEPListener.lua @@ -1,7 +1,7 @@ --[[ - Copyright (c) 2010-2013 Remko Tronçon - Licensed under the GNU General Public License v3. - See Documentation/Licenses/GPLv3.txt for more information. + Copyright (c) 2010-2013 Isode Limited. + All rights reserved. + See the COPYING file for more information. --]] --[[ diff --git a/Sluift/Examples/RemoveUnreachableContacts.lua b/Sluift/Examples/RemoveUnreachableContacts.lua index a202e62..65d64b9 100644 --- a/Sluift/Examples/RemoveUnreachableContacts.lua +++ b/Sluift/Examples/RemoveUnreachableContacts.lua @@ -1,7 +1,7 @@ --[[ - Copyright (c) 2010-2013 Remko Tronçon - Licensed under the GNU General Public License v3. - See Documentation/Licenses/GPLv3.txt for more information. + Copyright (c) 2010-2013 Isode Limited. + All rights reserved. + See the COPYING file for more information. --]] --[[ diff --git a/Sluift/Examples/SendReference.lua b/Sluift/Examples/SendReference.lua new file mode 100644 index 0000000..2e60182 --- /dev/null +++ b/Sluift/Examples/SendReference.lua @@ -0,0 +1,74 @@ +#!/usr/bin/env sluift -- + +-- This is an example of sending a custom payload, a XEP-0372 reference in this +-- case. +-- +-- Running this requires a sluift binary somewhere in the PATH. Alternatively, +-- you can feed this to sluift, or to a Lua that has sluift.so in its library +-- path. + +require("sluift") + +DEFAULT_URI = "http://example.com/kitten.jpg" + +function usage(err) + print("Usage: SendReference.lua jid [tojid] [datauri]") + print() + print("This tool will log in as jid, and send a reference to tojid. If no tojid") + print("is provided, a message to itself is sent. The datauri defaults to") + print(DEFAULT_URI .. ", but can be overridden.") + + if err then + print("") + print("Error: " .. err) + end + os.exit(1) +end + +function get_password(prompt) + if prompt then + io.write(prompt) + end + local stty_ret = os.execute("stty -echo 2>/dev/null") + if stty_ret then + io.write("\027[8m") + end + local ok, pass = pcall(io.read, "*l") + if stty_ret then + io.write("\027[m") + else + os.execute("stty echo") + end + io.write("\n"); + if ok then + return pass + end +end + +if #arg < 1 then + usage("no jid specified") +end +jid = arg[1] +password = os.getenv("XMPP_PASSWORD") or get_password("Password: ") +tojid = #arg > 1 and arg[2] or jid +datauri = #arg > 2 and arg[3] or DEFAULT_URI + +sluift.debug = 1 +sluift.with(sluift.new_client(jid, password), function() + options = { host=os.getenv("XMPP_HOST"), port=os.getenv("XMPP_PORT") } + connect(options) + reference = { + ['_type'] = 'dom', + ['tag'] = 'reference', + ['ns'] = 'urn:xmpp:reference:0', + ['attributes'] = { + { ['name'] = 'type', ['value'] = 'data' }, + { ['name'] = 'uri', ['value'] = datauri }, + { ['name'] = 'mimeType', ['value'] = arg[4] }, + { ['name'] = 'begin', ['value'] = arg[5] }, + { ['name'] = 'end', ['value'] = arg[6] } + }, + } + send_message{to=tojid, body="Check out this data!", payloads={reference}} + disconnect() +end) diff --git a/Sluift/Examples/Tunes.lua b/Sluift/Examples/Tunes.lua new file mode 100644 index 0000000..c645583 --- /dev/null +++ b/Sluift/Examples/Tunes.lua @@ -0,0 +1,68 @@ +--[[ + Copyright (c) 2014 Isode Limited. + All rights reserved. + See the COPYING file for more information. +--]] + +--[[ + + Tune Publisher/Listener + + Publishes the currently playing tune in iTunes, and prints + the playing tunes of contacts + + The following environment variables are used: + - SLUIFT_JID, SWIFT_PASS: JID and password to log in with + - SLUIFT_DEBUG: Sets whether debugging should be turned on + +--]] + +require 'sluift' + +sluift.debug = os.getenv('SLUIFT_DEBUG') or false + +client = sluift.new_client(os.getenv('SLUIFT_JID'), os.getenv('SLUIFT_PASS')) +client:connect(function (c) + -- Send initial presence (with service discovery information) + c:set_caps_node('http://swift.im/Tunes') + c:set_disco_info{ + identities = {{name = 'Tunes'}}, + features = { + sluift.disco.features.DISCO_INFO, + sluift.disco.features.USER_TUNE .. '+notify' + }} + c:send_presence{priority = -1} + + local pubsub = c:pubsub(sluift.jid.to_bare(c:jid())) + local tunes_node = pubsub:node(sluift.disco.features.USER_TUNE) + local current_track = nil + while true do + -- Publish currently playing tune + if sluift.itunes then + local track = sluift.itunes.get_current_track() + if track ~= current_track then + tunes_node:publish{item = { + _type = 'user_tune', + title = track.name, + artist = track.artist, + track = track.track_number, + source = track.album, + length = track.length, + rating = track.rating and track.rating / 10 or nil + }} + current_track = track + end + end + + -- Print incoming events for a while + for event in c:pubsub_events{timeout = 1000} do + if event._type == 'pubsub_event_items' + and event.node == sluift.disco.features.USER_TUNE + and event.item.title then + print(event.from .. ' is playing "' + .. (event.item.artist or '<Unknown Artist>') .. ' - ' + .. event.item.title .. '"') + end + end + end +end) diff --git a/Sluift/Examples/Wonderland.lua b/Sluift/Examples/Wonderland.lua index 426ec07..5104830 100755 --- a/Sluift/Examples/Wonderland.lua +++ b/Sluift/Examples/Wonderland.lua @@ -1,7 +1,7 @@ -- --- Copyright (c) 2011 Remko Tronçon --- Licensed under the GNU General Public License v3. --- See Documentation/Licenses/GPLv3.txt for more information. +-- Copyright (c) 2011 Isode Limited. +-- All rights reserved. +-- See the COPYING file for more information. -- -- This script creates the wonderland world example. diff --git a/Sluift/GenerateDocumentation.lua b/Sluift/GenerateDocumentation.lua new file mode 100644 index 0000000..ce9c9a9 --- /dev/null +++ b/Sluift/GenerateDocumentation.lua @@ -0,0 +1,90 @@ +--[[ + Copyright (c) 2013 Isode Limited. + All rights reserved. + See the COPYING file for more information. +--]] + +require "sluift" + +local function get_anchor(...) + return table.concat({...}, "-") +end + +local function convert_links(text) + result = text:gsub("(@{(%w*)})", "[`%2`](#%2)") + return result +end + +local function add_help(help, document, class, level) + -- Collect help of children + local methods = {} + for _, method in pairs(help.methods or {}) do + local description + local method_help = sluift.get_help(method.ref) + if method_help and method_help.description then + description = method_help.synopsis + end + methods[#methods+1] = { name = method.name, description = description, ref = method.ref } + end + local fields = sluift.copy(help.fields or {}) + + table.sort(methods, function (a, b) return (a.name or "") < (b.name or "") end) + table.sort(fields, function (a, b) return (a.name or "") < (b.name or "") end) + + local classes = {} + for _, class in pairs(help.classes or {}) do + classes[#classes+1] = { name = class, description = sluift.get_help(class).synopsis } + end + + table.insert(document, convert_links(help.description or "")) + for _, p in ipairs({ + {"Parameters", help.parameters}, {"Options", help.options}, {"Fields", fields}, {"Methods", methods}}) do + if p[2] and next(p[2]) ~= nil then + table.insert(document, "\n\n" .. level .. " " .. p[1] .. "\n") + for _, parameter in ipairs(p[2]) do + parameter_name = "`" .. parameter.name .. "`" + if p[1] == "Methods" then + parameter_name = "[" .. parameter_name .. "](#" .. get_anchor(class, parameter.name) .. ")" + end + if parameter.description then + table.insert(document, "- " .. parameter_name .. ": " .. convert_links(parameter.description)) + else + table.insert(document, "- " .. parameter_name) + end + end + if p[1] == "Methods" then + for _, method in ipairs(p[2]) do + table.insert(document, "\n#### <a name=\"" .. get_anchor(class, method.name) .. "\"></a> `" .. method.name .. "`\n") + if method.ref then + add_help(sluift.get_help(method.ref) or {}, document, class, level .. "#") + end + end + end + end + end +end + +local document = {} + +table.insert(document, [[ +# Sluift + +This document describes the API of the `sluift` module. + +The entry points of Sluift are in the `sluift` module, described below. + +## `sluift` module +]]) + +help = sluift.get_help(sluift) +add_help(help, document, "sluift", "###") +for _, class in pairs(help.classes) do + class_help = sluift.get_help(class) + if class_help then + table.insert(document, "\n## <a name=\"" .. class .. "\"></a> `" .. class .. "` class\n") + add_help(class_help, document, class, "###") + end +end + +document = table.concat(document, "\n") .. "\n" +print(document) diff --git a/Sluift/GenericLuaElementConvertor.h b/Sluift/GenericLuaElementConvertor.h index afad481..4e52d9e 100644 --- a/Sluift/GenericLuaElementConvertor.h +++ b/Sluift/GenericLuaElementConvertor.h @@ -1,54 +1,54 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <lua.hpp> #include <string> -#include <Swiften/Base/Override.h> -#include <Sluift/LuaElementConvertor.h> +#include <lua.hpp> + #include <Sluift/Lua/Check.h> #include <Sluift/Lua/LuaUtils.h> +#include <Sluift/LuaElementConvertor.h> namespace Swift { - template<typename T> - class GenericLuaElementConvertor : public LuaElementConvertor { - public: - GenericLuaElementConvertor(const std::string& type) : type(type) { - } - - virtual ~GenericLuaElementConvertor() {} - - virtual boost::shared_ptr<Payload> convertFromLua(lua_State* L, int index, const std::string& payloadType) SWIFTEN_OVERRIDE { - if (payloadType == type) { - Lua::checkType(L, index, LUA_TTABLE); - lua_pushvalue(L, index); - boost::shared_ptr<Payload> result = doConvertFromLua(L); - lua_pop(L, 1); - return result; - } - return boost::shared_ptr<Payload>(); - } - - virtual boost::optional<std::string> convertToLua( - lua_State* L, boost::shared_ptr<Payload> payload) SWIFTEN_OVERRIDE { - if (boost::shared_ptr<T> actualPayload = boost::dynamic_pointer_cast<T>(payload)) { - doConvertToLua(L, actualPayload); - assert(lua_type(L, -1) == LUA_TTABLE); - return type; - } - return NO_RESULT; - } - - protected: - virtual boost::shared_ptr<T> doConvertFromLua(lua_State*) = 0; - virtual void doConvertToLua(lua_State*, boost::shared_ptr<T>) = 0; - - private: - std::string type; - }; + template<typename T> + class GenericLuaElementConvertor : public LuaElementConvertor { + public: + GenericLuaElementConvertor(const std::string& type) : type(type) { + } + + virtual ~GenericLuaElementConvertor() override {} + + virtual std::shared_ptr<Element> convertFromLua(lua_State* L, int index, const std::string& payloadType) override { + if (payloadType == type) { + Lua::checkType(L, index, LUA_TTABLE); + lua_pushvalue(L, index); + std::shared_ptr<Element> result = doConvertFromLua(L); + lua_pop(L, 1); + return result; + } + return std::shared_ptr<Element>(); + } + + virtual boost::optional<std::string> convertToLua( + lua_State* L, std::shared_ptr<Element> payload) override { + if (std::shared_ptr<T> actualPayload = std::dynamic_pointer_cast<T>(payload)) { + doConvertToLua(L, actualPayload); + assert(lua_type(L, -1) == LUA_TTABLE); + return type; + } + return NO_RESULT; + } + + protected: + virtual std::shared_ptr<T> doConvertFromLua(lua_State*) = 0; + virtual void doConvertToLua(lua_State*, std::shared_ptr<T>) = 0; + + private: + std::string type; + }; } diff --git a/Sluift/Helpers.cpp b/Sluift/Helpers.cpp new file mode 100644 index 0000000..97d14ad --- /dev/null +++ b/Sluift/Helpers.cpp @@ -0,0 +1,65 @@ +/* + * Copyright (c) 2013-2015 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Sluift/Helpers.h> + +#include <Swiften/Client/ClientError.h> +#include <Swiften/Component/ComponentError.h> + +using namespace Swift; + +std::string Swift::getErrorString(const ClientError& error) { + std::string reason = "Disconnected: "; + switch(error.getType()) { + case ClientError::UnknownError: reason += "Unknown Error"; 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::UnexpectedElementError: reason += "Unexpected response"; break; + case ClientError::DomainNameResolveError: reason += "Unable to find server"; 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::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 file or 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; +} + +std::string Swift::getErrorString(const ComponentError& error) { + std::string reason = "Disconnected: "; + switch(error.getType()) { + case ComponentError::UnknownError: reason += "Unknown Error"; break; + case ComponentError::ConnectionError: reason += "Error connecting to server"; break; + case ComponentError::ConnectionReadError: reason += "Error while receiving server data"; break; + case ComponentError::ConnectionWriteError: reason += "Error while sending data to the server"; break; + case ComponentError::XMLError: reason += "Error parsing server data"; break; + case ComponentError::AuthenticationFailedError: reason += "Login/password invalid"; break; + case ComponentError::UnexpectedElementError: reason += "Unexpected response"; break; + } + return reason; +} + diff --git a/Sluift/Helpers.h b/Sluift/Helpers.h new file mode 100644 index 0000000..41bfc97 --- /dev/null +++ b/Sluift/Helpers.h @@ -0,0 +1,19 @@ +/* + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <string> + +#include <Swiften/Base/API.h> + +namespace Swift { + class ClientError; + class ComponentError; + + std::string getErrorString(const ClientError& error); + std::string getErrorString(const ComponentError& error); +} diff --git a/Sluift/ITunesInterface.h b/Sluift/ITunesInterface.h new file mode 100644 index 0000000..d44dcb1 --- /dev/null +++ b/Sluift/ITunesInterface.h @@ -0,0 +1,40 @@ +/* + * Copyright (c) 2014-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <memory> +#include <string> + +#include <boost/optional/optional.hpp> + +#include <Swiften/Base/API.h> + +namespace Swift { + class SWIFTEN_API ITunesInterface { + public: + struct Track { + std::string name; + std::string artist; + std::string album; + long trackNumber; + double duration; + long rating; + }; + + ITunesInterface(); + virtual ~ITunesInterface(); + + boost::optional<Track> getCurrentTrack() const; + + private: + bool haveApplication() const; + + private: + struct Private; + const std::unique_ptr<Private> p; + }; +} diff --git a/Sluift/ITunesInterface.mm b/Sluift/ITunesInterface.mm new file mode 100644 index 0000000..33cf1ca --- /dev/null +++ b/Sluift/ITunesInterface.mm @@ -0,0 +1,58 @@ +/* + * Copyright (c) 2014-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Sluift/ITunesInterface.h> + +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wfour-char-constants" +#import <Sluift/iTunes.h> +#pragma clang diagnostic pop +#include <ScriptingBridge/ScriptingBridge.h> + +#include <memory> +#include <boost/optional.hpp> +#include <SwifTools/Cocoa/CocoaUtil.h> + +using namespace Swift; + +struct ITunesInterface::Private { + Private() : iTunes(nil) { + } + + iTunesApplication* iTunes; +}; + +ITunesInterface::ITunesInterface() : p(new Private()) { +} + +ITunesInterface::~ITunesInterface() { +} + +boost::optional<ITunesInterface::Track> ITunesInterface::getCurrentTrack() const { + if (!haveApplication()) { + return boost::optional<ITunesInterface::Track>(); + } + iTunesTrack* currentTrack = p->iTunes.currentTrack; + if (!currentTrack) { + return boost::optional<ITunesInterface::Track>(); + } + ITunesInterface::Track result; + result.name = ns2StdString(currentTrack.name); + result.artist = ns2StdString(currentTrack.artist); + result.album = ns2StdString(currentTrack.album); + result.trackNumber = currentTrack.trackNumber; + result.duration = currentTrack.duration; + result.rating = currentTrack.rating; + return result; +} + + +bool ITunesInterface::haveApplication() const { + if (!p->iTunes) { + p->iTunes = [SBApplication applicationWithBundleIdentifier:@"com.apple.iTunes"]; + } + return p->iTunes != nil && [p->iTunes isRunning]; +} diff --git a/Sluift/Lua/Check.cpp b/Sluift/Lua/Check.cpp index cfb726a..b956623 100644 --- a/Sluift/Lua/Check.cpp +++ b/Sluift/Lua/Check.cpp @@ -1,60 +1,68 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #include <Sluift/Lua/Check.h> -#include <boost/numeric/conversion/cast.hpp> -#include <iostream> #include <sstream> + +#include <boost/numeric/conversion/cast.hpp> + #include <lua.hpp> +#include <Swiften/Base/ByteArray.h> + #include <Sluift/Lua/Exception.h> using namespace Swift; static std::string getArgTypeError(lua_State* L, int arg, int tag) { - std::ostringstream s; - s << "Arg " << arg << ": expected " << lua_typename(L, tag) << ", got " << luaL_typename(L, arg); - return s.str(); + std::ostringstream s; + s << "Arg " << arg << ": expected " << lua_typename(L, tag) << ", got " << luaL_typename(L, arg); + return s.str(); } void Lua::checkType(lua_State* L, int arg, int type) { - if (lua_type(L, arg) != type) { - throw Lua::Exception(getArgTypeError(L, arg, type)); - } + if (lua_type(L, arg) != type) { + throw Lua::Exception(getArgTypeError(L, arg, type)); + } } int Lua::checkIntNumber(lua_State* L, int arg) { - if (!lua_isnumber(L, arg)) { - throw Lua::Exception(getArgTypeError(L, arg, LUA_TNUMBER)); - } - return boost::numeric_cast<int>(lua_tonumber(L, arg)); + if (!lua_isnumber(L, arg)) { + throw Lua::Exception(getArgTypeError(L, arg, LUA_TNUMBER)); + } + return boost::numeric_cast<int>(lua_tonumber(L, arg)); } std::string Lua::checkString(lua_State* L, int arg) { - const char *s = lua_tolstring(L, arg, NULL); - if (!s) { - throw Lua::Exception(getArgTypeError(L, arg, LUA_TSTRING)); - } - return std::string(s); + const char *s = lua_tolstring(L, arg, nullptr); + if (!s) { + throw Lua::Exception(getArgTypeError(L, arg, LUA_TSTRING)); + } + return std::string(s); +} + +ByteArray Lua::checkByteArray(lua_State* L, int arg) { + size_t len; + const char *s = lua_tolstring(L, arg, &len); + if (!s) { + throw Lua::Exception(getArgTypeError(L, arg, LUA_TSTRING)); + } + return createByteArray(s, len); } -void* Lua::checkUserDataRaw(lua_State* L, int arg, const char* tableName) { - void* userData = lua_touserdata(L, arg); - if (!userData) { - throw Lua::Exception(getArgTypeError(L, arg, LUA_TUSERDATA)); - } - if (!lua_getmetatable(L, arg)) { - throw Lua::Exception(getArgTypeError(L, arg, LUA_TUSERDATA)); - } - lua_getfield(L, LUA_REGISTRYINDEX, tableName); - if (!lua_rawequal(L, -1, -2)) { - throw Lua::Exception(getArgTypeError(L, arg, LUA_TUSERDATA)); - } - lua_pop(L, 2); - return userData; +void* Lua::checkUserDataRaw(lua_State* L, int arg) { + void* userData = lua_touserdata(L, arg); + if (!userData) { + throw Lua::Exception(getArgTypeError(L, arg, LUA_TUSERDATA)); + } + if (!lua_getmetatable(L, arg)) { + throw Lua::Exception(getArgTypeError(L, arg, LUA_TUSERDATA)); + } + lua_pop(L, 1); + return userData; } diff --git a/Sluift/Lua/Check.h b/Sluift/Lua/Check.h index a569826..61658a6 100644 --- a/Sluift/Lua/Check.h +++ b/Sluift/Lua/Check.h @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2014 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ @@ -8,19 +8,22 @@ #include <string> +#include <Swiften/Base/ByteArray.h> + struct lua_State; namespace Swift { - namespace Lua { - void checkType(lua_State* L, int arg, int type); - int checkIntNumber(lua_State* L, int arg); - std::string checkString(lua_State* L, int arg); + namespace Lua { + void checkType(lua_State* L, int arg, int type); + int checkIntNumber(lua_State* L, int arg); + std::string checkString(lua_State* L, int arg); + ByteArray checkByteArray(lua_State* L, int arg); - void* checkUserDataRaw(lua_State* L, int arg, const char* tableName); + void* checkUserDataRaw(lua_State* L, int arg); - template<typename T> - T** checkUserData(lua_State* L, int arg, const char* tableName) { - return reinterpret_cast<T**>(checkUserDataRaw(L, arg, tableName)); - } - } + template<typename T> + T** checkUserData(lua_State* L, int arg) { + return reinterpret_cast<T**>(checkUserDataRaw(L, arg)); + } + } } diff --git a/Sluift/Lua/Debug.h b/Sluift/Lua/Debug.h index 8e86b89..5f141e1 100644 --- a/Sluift/Lua/Debug.h +++ b/Sluift/Lua/Debug.h @@ -1,28 +1,29 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <lua.hpp> #include <iostream> +#include <lua.hpp> + namespace Swift { - namespace Lua { - inline void dumpStack(lua_State *L) { - for (int i = 1; i <= lua_gettop(L); i++) { - int type = lua_type(L, i); - std::cout << i << ": [" << lua_typename(L, type) << "] "; - switch (type) { - case LUA_TSTRING: std::cout << lua_tostring(L, i); break; - case LUA_TNUMBER: std::cout << lua_tonumber(L, i); break; - case LUA_TBOOLEAN: std::cout << lua_toboolean(L, i); break; - default: break; - } - std::cout << std::endl; - } - } - } + namespace Lua { + inline void dumpStack(lua_State *L) { + for (int i = 1; i <= lua_gettop(L); i++) { + int type = lua_type(L, i); + std::cout << i << ": [" << lua_typename(L, type) << "] "; + switch (type) { + case LUA_TSTRING: std::cout << lua_tostring(L, i); break; + case LUA_TNUMBER: std::cout << lua_tonumber(L, i); break; + case LUA_TBOOLEAN: std::cout << lua_toboolean(L, i); break; + default: break; + } + std::cout << std::endl; + } + } + } } diff --git a/Sluift/Lua/Exception.cpp b/Sluift/Lua/Exception.cpp index d80b9fb..a51ad10 100644 --- a/Sluift/Lua/Exception.cpp +++ b/Sluift/Lua/Exception.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ @@ -11,5 +11,5 @@ using namespace Swift::Lua; Exception::Exception(const std::string& what) : std::runtime_error(what) { } -Exception::~Exception() throw() { +Exception::~Exception() SWIFTEN_NOEXCEPT { } diff --git a/Sluift/Lua/Exception.h b/Sluift/Lua/Exception.h index 6d00d01..a8ecc5f 100644 --- a/Sluift/Lua/Exception.h +++ b/Sluift/Lua/Exception.h @@ -1,20 +1,23 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <stdexcept> +#include <Swiften/Base/API.h> + namespace Swift { - namespace Lua { - class Exception : public std::runtime_error { - public: - Exception(const std::string& what); - virtual ~Exception() throw(); - }; - } + namespace Lua { + class Exception : public std::runtime_error { + public: + Exception(const std::string& what); + SWIFTEN_DEFAULT_COPY_CONSTRUCTOR(Exception) + virtual ~Exception() SWIFTEN_NOEXCEPT; + }; + } } diff --git a/Sluift/Lua/FunctionRegistration.cpp b/Sluift/Lua/FunctionRegistration.cpp index b773952..5a6d43e 100644 --- a/Sluift/Lua/FunctionRegistration.cpp +++ b/Sluift/Lua/FunctionRegistration.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ @@ -8,8 +8,8 @@ using namespace Swift::Lua; -FunctionRegistration::FunctionRegistration(const std::string& name, lua_CFunction function, const std::string& type) { - FunctionRegistry::getInstance().addFunction(name, function, type); +FunctionRegistration::FunctionRegistration(const std::string& name, lua_CFunction function, const std::string& type, const std::string& helpDescription, const std::string& helpParameters, const std::string& helpOptions) { + FunctionRegistry::getInstance().addFunction(name, function, type, helpDescription, helpParameters, helpOptions); } FunctionRegistration::~FunctionRegistration() { diff --git a/Sluift/Lua/FunctionRegistration.h b/Sluift/Lua/FunctionRegistration.h index 0df1da1..285c3d0 100644 --- a/Sluift/Lua/FunctionRegistration.h +++ b/Sluift/Lua/FunctionRegistration.h @@ -1,36 +1,45 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <string> + +#include <lua.hpp> + #include <Swiften/Base/API.h> + #include <Sluift/Lua/FunctionRegistry.h> -#include <lua.hpp> -#include <string> namespace Swift { - namespace Lua { - class FunctionRegistration { - public: - FunctionRegistration(const std::string& name, lua_CFunction function, const std::string& type); - ~FunctionRegistration(); - }; - } + namespace Lua { + class FunctionRegistration { + public: + FunctionRegistration( + const std::string& name, lua_CFunction function, const std::string& type, + const std::string& helpDescription, const std::string& helpParameters, const std::string& helpOptions); + ~FunctionRegistration(); + }; + } } + + +#define SLUIFT_LUA_FUNCTION_WITH_HELP(TYPE, NAME, HELP_DESCRIPTION, HELP_PARAMETERS, HELP_OPTIONS) \ + static int TYPE##_##NAME(lua_State* L); \ + static int TYPE##_##NAME##_wrapper(lua_State* L); \ + static ::Swift::Lua::FunctionRegistration TYPE##_##NAME##_registration( #NAME , TYPE##_##NAME##_wrapper, #TYPE, HELP_DESCRIPTION, HELP_PARAMETERS, HELP_OPTIONS); \ + static int TYPE##_##NAME##_wrapper(lua_State* L) { \ + try { \ + return TYPE ## _ ## NAME (L); \ + } \ + catch (const std::exception& e) { \ + return luaL_error(L, e.what()); \ + } \ + } \ + static int TYPE ## _ ## NAME (lua_State* L) + #define SLUIFT_LUA_FUNCTION(TYPE, NAME) \ - static int TYPE##_##NAME(lua_State* L); \ - static int TYPE##_##NAME##_wrapper(lua_State* L); \ - static ::Swift::Lua::FunctionRegistration TYPE##_##NAME##_registration( #NAME , TYPE##_##NAME##_wrapper, #TYPE); \ - static int TYPE##_##NAME##_wrapper(lua_State* L) { \ - try { \ - return TYPE ## _ ## NAME (L); \ - } \ - catch (const std::exception& e) { \ - return luaL_error(L, e.what()); \ - } \ - } \ - static int TYPE ## _ ## NAME (lua_State* L) + SLUIFT_LUA_FUNCTION_WITH_HELP(TYPE, NAME, "", "", "") diff --git a/Sluift/Lua/FunctionRegistry.cpp b/Sluift/Lua/FunctionRegistry.cpp index 99ea096..46c6d18 100644 --- a/Sluift/Lua/FunctionRegistry.cpp +++ b/Sluift/Lua/FunctionRegistry.cpp @@ -1,12 +1,14 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #include <Sluift/Lua/FunctionRegistry.h> -#include <Swiften/Base/foreach.h> +#include <Sluift/Lua/Exception.h> +#include <Sluift/Lua/LuaUtils.h> +#include <Sluift/globals.h> using namespace Swift::Lua; @@ -17,39 +19,39 @@ FunctionRegistry::~FunctionRegistry() { } FunctionRegistry& FunctionRegistry::getInstance() { - static FunctionRegistry instance; - return instance; + static FunctionRegistry instance; + return instance; } -void FunctionRegistry::addFunction(const std::string& name, lua_CFunction function, const std::string& type) { - Registration registration; - registration.name = name; - registration.function = function; - registration.type = type; - registrations.push_back(registration); -} - -std::string FunctionRegistry::getMetaTableNameForType(const std::string& type) { - return "Sluift_" + type; -} - -void FunctionRegistry::registerTypeMetaTable(lua_State* L, const std::string& type) { - luaL_newmetatable(L, getMetaTableNameForType(type).c_str()); - lua_pushvalue(L, -1); - lua_setfield(L, -2, "__index"); - addFunctionsToTable(L, type); +void FunctionRegistry::addFunction( + const std::string& name, lua_CFunction function, const std::string& type, + const std::string& helpDescription, const std::string& helpParameters, const std::string& helpOptions) { + Registration registration; + registration.name = name; + registration.function = function; + registration.type = type; + registration.helpDescription = helpDescription; + registration.helpParameters = helpParameters; + registration.helpOptions = helpOptions; + registrations.push_back(registration); } void FunctionRegistry::createFunctionTable(lua_State* L, const std::string& type) { - lua_newtable(L); - addFunctionsToTable(L, type); + lua_newtable(L); + addFunctionsToTable(L, type); } void FunctionRegistry::addFunctionsToTable(lua_State* L, const std::string& type) { - foreach(const Registration& registration, registrations) { - if (registration.type == type) { - lua_pushcclosure(L, registration.function, 0); - lua_setfield(L, -2, registration.name.c_str()); - } - } + for (const auto& registration : registrations) { + if (registration.type == type) { + lua_pushcclosure(L, registration.function, 0); + if (!registration.helpDescription.empty()) { + Lua::registerHelp(L, -1, registration.helpDescription, registration.helpParameters, registration.helpOptions); + } + else { + Lua::registerExtraHelp(L, -1, registration.type + "." + registration.name); + } + lua_setfield(L, -2, registration.name.c_str()); + } + } } diff --git a/Sluift/Lua/FunctionRegistry.h b/Sluift/Lua/FunctionRegistry.h index e3ad620..88e15d5 100644 --- a/Sluift/Lua/FunctionRegistry.h +++ b/Sluift/Lua/FunctionRegistry.h @@ -1,46 +1,47 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> -#include <lua.hpp> #include <string> #include <vector> -namespace Swift { - namespace Lua { - class FunctionRegistry { - public: - ~FunctionRegistry(); - static FunctionRegistry& getInstance(); - - void addFunction(const std::string& name, lua_CFunction function, const std::string& type); - - static std::string getMetaTableNameForType(const std::string& type); - void registerTypeMetaTable(lua_State* L, const std::string& type); - - void createFunctionTable(lua_State* L, const std::string& type); - - /** - * Adds the functions to the table on the top of the stack. - */ - void addFunctionsToTable(lua_State* L, const std::string& type); - - private: - FunctionRegistry(); - +#include <lua.hpp> - private: - struct Registration { - std::string name; - lua_CFunction function; - std::string type; - }; - std::vector<Registration> registrations; - }; - } +namespace Swift { + namespace Lua { + class FunctionRegistry { + public: + ~FunctionRegistry(); + static FunctionRegistry& getInstance(); + + void addFunction(const std::string& name, lua_CFunction function, const std::string& type, + const std::string& helpDescription, const std::string& helpParameters, const std::string& helpOptions); + + void createFunctionTable(lua_State* L, const std::string& type); + + /** + * Adds the functions to the table on the top of the stack. + */ + void addFunctionsToTable(lua_State* L, const std::string& type); + + private: + FunctionRegistry(); + + + private: + struct Registration { + std::string name; + lua_CFunction function; + std::string type; + std::string helpDescription; + std::string helpParameters; + std::string helpOptions; + }; + std::vector<Registration> registrations; + }; + } } diff --git a/Sluift/Lua/LuaUtils.cpp b/Sluift/Lua/LuaUtils.cpp index 7052abe..c677381 100644 --- a/Sluift/Lua/LuaUtils.cpp +++ b/Sluift/Lua/LuaUtils.cpp @@ -1,19 +1,21 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #include <Sluift/Lua/LuaUtils.h> -#include <lua.hpp> - -#include <boost/scope_exit.hpp> -#include <Sluift/Lua/Exception.h> -#include <iostream> #include <cassert> #include <sstream> + +#include <boost/algorithm/string/trim.hpp> #include <boost/numeric/conversion/cast.hpp> +#include <boost/scope_exit.hpp> + +#include <lua.hpp> + +#include <Sluift/Lua/Exception.h> #include <Sluift/globals.h> using namespace Swift::Lua; @@ -21,59 +23,178 @@ using namespace Swift::Lua; static const std::string INDENT = " "; void Swift::Lua::registerTableToString(lua_State* L, int index) { - index = Lua::absoluteOffset(L, index); - lua_rawgeti(L, LUA_REGISTRYINDEX, Sluift::globals.bootIndex); - lua_getfield(L, -1, "register_table_tostring"); - lua_pushvalue(L, index); - if (lua_pcall(L, 1, 0, 0) != 0) { - throw Lua::Exception(lua_tostring(L, -1)); - } - lua_pop(L, 1); + index = Lua::absoluteOffset(L, index); + lua_rawgeti(L, LUA_REGISTRYINDEX, Sluift::globals.coreLibIndex); + lua_getfield(L, -1, "register_table_tostring"); + lua_pushvalue(L, index); + if (lua_pcall(L, 1, 0, 0) != 0) { + throw Lua::Exception(lua_tostring(L, -1)); + } + lua_pop(L, 1); +} + +void Swift::Lua::registerTableEquals(lua_State* L, int index) { + index = Lua::absoluteOffset(L, index); + lua_rawgeti(L, LUA_REGISTRYINDEX, Sluift::globals.coreLibIndex); + lua_getfield(L, -1, "register_table_equals"); + lua_pushvalue(L, index); + if (lua_pcall(L, 1, 0, 0) != 0) { + throw Lua::Exception(lua_tostring(L, -1)); + } + lua_pop(L, 1); } void Swift::Lua::registerGetByTypeIndex(lua_State* L, int index) { - index = Lua::absoluteOffset(L, index); - lua_rawgeti(L, LUA_REGISTRYINDEX, Sluift::globals.bootIndex); - lua_getfield(L, -1, "register_get_by_type_index"); - lua_pushvalue(L, index); - if (lua_pcall(L, 1, 0, 0) != 0) { - throw Lua::Exception(lua_tostring(L, -1)); - } - lua_pop(L, 1); + index = Lua::absoluteOffset(L, index); + lua_rawgeti(L, LUA_REGISTRYINDEX, Sluift::globals.coreLibIndex); + lua_getfield(L, -1, "register_get_by_type_index"); + lua_pushvalue(L, index); + if (lua_pcall(L, 1, 0, 0) != 0) { + throw Lua::Exception(lua_tostring(L, -1)); + } + lua_pop(L, 1); } boost::optional<std::string> Swift::Lua::getStringField(lua_State* L, int index, const std::string& field) { - lua_getfield(L, index, field.c_str()); - // Seems to generate warnings with some versions of CLang that i can't turn off. - // Leaving the more elegant code here, hoping we can re-enable it later (newer boost? c++11?). - // The same applies to the other get*Field functions. - //BOOST_SCOPE_EXIT(&L) { lua_pop(L,1); } BOOST_SCOPE_EXIT_END - //return lua_isstring(L, -1) ? std::string(lua_tostring(L, -1)) : boost::optional<std::string>(); - - boost::optional<std::string> result; - if (lua_isstring(L, -1)) { - result = std::string(lua_tostring(L, -1)); - } - lua_pop(L, 1); - return result; + lua_getfield(L, index, field.c_str()); + // Seems to generate warnings with some versions of CLang that i can't turn off. + // Leaving the more elegant code here, hoping we can re-enable it later (newer boost? c++11?). + // The same applies to the other get*Field functions. + //BOOST_SCOPE_EXIT(&L) { lua_pop(L,1); } BOOST_SCOPE_EXIT_END + //return lua_isstring(L, -1) ? std::string(lua_tostring(L, -1)) : boost::optional<std::string>(); + + boost::optional<std::string> result; + if (lua_isstring(L, -1)) { + result = std::string(lua_tostring(L, -1)); + } + lua_pop(L, 1); + return result; } boost::optional<bool> Swift::Lua::getBooleanField(lua_State* L, int index, const std::string& field) { - lua_getfield(L, index, field.c_str()); - boost::optional<bool> result; - if (lua_isboolean(L, -1)) { - result = lua_toboolean(L, -1); - } - lua_pop(L, 1); - return result; + lua_getfield(L, index, field.c_str()); + boost::optional<bool> result; + if (lua_isboolean(L, -1)) { + result = lua_toboolean(L, -1); + } + lua_pop(L, 1); + return result; } boost::optional<int> Swift::Lua::getIntField(lua_State* L, int index, const std::string& field) { - lua_getfield(L, index, field.c_str()); - boost::optional<int> result; - if (lua_isnumber(L, -1)) { - result = boost::numeric_cast<int>(lua_tonumber(L, -1)); - } - lua_pop(L, 1); - return result; + lua_getfield(L, index, field.c_str()); + boost::optional<int> result; + if (lua_isnumber(L, -1)) { + result = boost::numeric_cast<int>(lua_tonumber(L, -1)); + } + lua_pop(L, 1); + return result; +} + +void Swift::Lua::registerHelp(lua_State* L, int index, const std::string& description, const std::string& parameters, const std::string& options) { + index = Lua::absoluteOffset(L, index); + lua_rawgeti(L, LUA_REGISTRYINDEX, Sluift::globals.coreLibIndex); + lua_getfield(L, -1, "register_help"); + lua_pushvalue(L, index); + + lua_newtable(L); + lua_pushstring(L, description.c_str()); + lua_rawseti(L, -2, 1); + + if (!parameters.empty()) { + std::istringstream s(parameters); + lua_newtable(L); + int i = 1; + for (std::string line; std::getline(s, line); ) { + std::string trimmedLine = boost::trim_copy(line); + if (trimmedLine.empty()) { + continue; + } + size_t splitIndex = trimmedLine.find_first_of(" \t"); + std::string key; + std::string value; + if (splitIndex == std::string::npos) { + key = trimmedLine; + } + else { + key = trimmedLine.substr(0, splitIndex); + value = boost::trim_copy(trimmedLine.substr(splitIndex+1)); + } + lua_createtable(L, 2, 0); + lua_pushstring(L, key.c_str()); + lua_rawseti(L, -2, 1); + lua_pushstring(L, value.c_str()); + lua_rawseti(L, -2, 2); + + lua_rawseti(L, -2, i++); + } + lua_setfield(L, -2, "parameters"); + } + if (!options.empty()) { + std::istringstream s(options); + lua_newtable(L); + for (std::string line; std::getline(s, line); ) { + std::string trimmedLine = boost::trim_copy(line); + if (trimmedLine.empty()) { + continue; + } + size_t splitIndex = trimmedLine.find_first_of(" \t"); + std::string key; + std::string value; + if (splitIndex == std::string::npos) { + key = trimmedLine; + } + else { + key = trimmedLine.substr(0, splitIndex); + value = boost::trim_copy(trimmedLine.substr(splitIndex+1)); + } + lua_pushstring(L, value.c_str()); + lua_setfield(L, -2, key.c_str()); + } + lua_setfield(L, -2, "options"); + } + + if (lua_pcall(L, 2, 0, 0) != 0) { + throw Lua::Exception(lua_tostring(L, -1)); + } + lua_pop(L, 1); +} + +void Swift::Lua::registerClassHelp(lua_State* L, const std::string& name, const std::string& description) { + lua_rawgeti(L, LUA_REGISTRYINDEX, Sluift::globals.coreLibIndex); + lua_getfield(L, -1, "register_class_help"); + lua_pushstring(L, name.c_str()); + + lua_newtable(L); + lua_pushstring(L, description.c_str()); + lua_rawseti(L, -2, 1); + + if (lua_pcall(L, 2, 0, 0) != 0) { + throw Lua::Exception(lua_tostring(L, -1)); + } + lua_pop(L, 1); +} + +void Swift::Lua::registerExtraHelp(lua_State* L, int index, const std::string& name) { + index = Lua::absoluteOffset(L, index); + lua_rawgeti(L, LUA_REGISTRYINDEX, Sluift::globals.coreLibIndex); + lua_getfield(L, -1, "extra_help"); + lua_getfield(L, -1, name.c_str()); + if (!lua_isnil(L, -1)) { + lua_getfield(L, -3, "register_help"); + lua_pushvalue(L, index); + lua_pushvalue(L, -3); + if (lua_pcall(L, 2, 0, 0) != 0) { + throw Lua::Exception(lua_tostring(L, -1)); + } + } + lua_pop(L, 3); +} + +void Swift::Lua::pushStringArray(lua_State* L, const std::vector<std::string>& strings) { + lua_createtable(L, boost::numeric_cast<int>(strings.size()), 0); + for (size_t i = 0; i < strings.size(); ++i) { + lua_pushstring(L, strings[i].c_str()); + lua_rawseti(L, -2, boost::numeric_cast<int>(i+1)); + } } diff --git a/Sluift/Lua/LuaUtils.h b/Sluift/Lua/LuaUtils.h index bad307c..b9f5bff 100644 --- a/Sluift/Lua/LuaUtils.h +++ b/Sluift/Lua/LuaUtils.h @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ @@ -8,25 +8,51 @@ #include <lua.hpp> #include <boost/optional.hpp> +#include <string> +#include <vector> -struct lua_State; +#if LUA_VERSION_NUM < 502 +#define lua_pushglobaltable(L) lua_pushvalue(L, LUA_GLOBALSINDEX) +#define lua_compare(L,idx1,idx2,LUA_OPEQ) lua_equal(L,(idx1),(idx2)) +#define lua_rawlen(L, i) lua_objlen(L,(i)) +#endif +#if LUA_VERSION_NUM >= 503 +#undef luaL_register +#define luaL_register(L, n, l) \ + lua_getglobal( L, n ); \ + if( lua_isnil( L, -1 ) ) \ + { \ + lua_pop( L, 1 ); \ + lua_newtable( L ); \ + } \ + luaL_setfuncs( L, (l), 0 ); \ + lua_pushvalue( L, -1 ); \ + lua_setglobal( L, n ); +#endif namespace Swift { - namespace Lua { - /** - * Can be used as __tostring metamethod on a table. - */ - int convertTableToString(lua_State* L); - - void registerTableToString(lua_State* L, int index); - void registerGetByTypeIndex(lua_State* L, int index); - - inline int absoluteOffset(lua_State* L, int index) { - return index > 0 ? index : lua_gettop(L) + index + 1; - } - - boost::optional<std::string> getStringField(lua_State* L, int index, const std::string&); - boost::optional<bool> getBooleanField(lua_State* L, int index, const std::string&); - boost::optional<int> getIntField(lua_State* L, int index, const std::string&); - } + namespace Lua { + /** + * Can be used as __tostring metamethod on a table. + */ + int convertTableToString(lua_State* L); + + void registerTableToString(lua_State* L, int index); + void registerTableEquals(lua_State* L, int index); + void registerGetByTypeIndex(lua_State* L, int index); + void registerHelp(lua_State* L, int index, + const std::string& description, const std::string& parameters, const std::string& options); + void registerClassHelp(lua_State* L, const std::string& name, const std::string& description); + void registerExtraHelp(lua_State* L, int index, const std::string& name); + + inline int absoluteOffset(lua_State* L, int index) { + return index > 0 ? index : lua_gettop(L) + index + 1; + } + + boost::optional<std::string> getStringField(lua_State* L, int index, const std::string&); + boost::optional<bool> getBooleanField(lua_State* L, int index, const std::string&); + boost::optional<int> getIntField(lua_State* L, int index, const std::string&); + + void pushStringArray(lua_State* L, const std::vector<std::string>& strings); + } } diff --git a/Sluift/Lua/Value.cpp b/Sluift/Lua/Value.cpp index 4f8078e..96d954c 100644 --- a/Sluift/Lua/Value.cpp +++ b/Sluift/Lua/Value.cpp @@ -1,66 +1,66 @@ /* - * Copyright (c) 2011 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 "Value.h" +#include <Sluift/Lua/Value.h> + +#include <boost/numeric/conversion/cast.hpp> +#include <boost/variant/apply_visitor.hpp> extern "C" { - #include <lualib.h> + #include <lualib.h> } -#include <boost/variant/apply_visitor.hpp> -#include <boost/numeric/conversion/cast.hpp> -#include <Swiften/Base/foreach.h> using namespace Swift; using namespace Swift::Lua; namespace { - struct PushVisitor : public boost::static_visitor<> { - PushVisitor(lua_State* state) : state(state) { - } + struct PushVisitor : public boost::static_visitor<> { + PushVisitor(lua_State* state) : state(state) { + } - void operator()(const Nil&) const { - lua_pushnil(state); - } + void operator()(const Nil&) const { + lua_pushnil(state); + } - void operator()(const bool& b) const { - lua_pushboolean(state, b); - } + void operator()(const bool& b) const { + lua_pushboolean(state, b); + } - void operator()(const int& i) const { - lua_pushnumber(state, i); - } + void operator()(const int& i) const { + lua_pushnumber(state, i); + } - void operator()(const std::string& s) const { - lua_pushstring(state, s.c_str()); - } + void operator()(const std::string& s) const { + lua_pushstring(state, s.c_str()); + } - void operator()(const std::vector<Value>& values) const { - lua_createtable(state, boost::numeric_cast<int>(values.size()), 0); - for(size_t i = 0; i < values.size(); ++i) { - boost::apply_visitor(PushVisitor(state), values[i]); - lua_rawseti(state, -2, boost::numeric_cast<int>(i + 1)); - } - } + void operator()(const std::vector<Value>& values) const { + lua_createtable(state, boost::numeric_cast<int>(values.size()), 0); + for(size_t i = 0; i < values.size(); ++i) { + boost::apply_visitor(PushVisitor(state), values[i]); + lua_rawseti(state, -2, boost::numeric_cast<int>(i + 1)); + } + } - void operator()(const std::map<std::string, boost::shared_ptr<Value> >& table) const { - lua_createtable(state, 0, boost::numeric_cast<int>(table.size())); - for(std::map<std::string, boost::shared_ptr<Value> >::const_iterator i = table.begin(); i != table.end(); ++i) { - boost::apply_visitor(PushVisitor(state), *i->second); - lua_setfield(state, -2, i->first.c_str()); - } - } + void operator()(const std::map<std::string, std::shared_ptr<Value> >& table) const { + lua_createtable(state, 0, boost::numeric_cast<int>(table.size())); + for (const auto& i : table) { + boost::apply_visitor(PushVisitor(state), *i.second); + lua_setfield(state, -2, i.first.c_str()); + } + } - lua_State* state; - }; + lua_State* state; + }; } namespace Swift { namespace Lua { void pushValue(lua_State* state, const Value& value) { - boost::apply_visitor(PushVisitor(state), value); + boost::apply_visitor(PushVisitor(state), value); } }} diff --git a/Sluift/Lua/Value.h b/Sluift/Lua/Value.h index 55aa347..13c4a0c 100644 --- a/Sluift/Lua/Value.h +++ b/Sluift/Lua/Value.h @@ -1,60 +1,60 @@ /* - * Copyright (c) 2010-2013 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2010-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once #include <map> +#include <memory> #include <string> #include <vector> + #include <boost/variant.hpp> -#include <boost/shared_ptr.hpp> -#include <boost/smart_ptr/make_shared.hpp> struct lua_State; namespace Swift { - namespace Lua { - struct Nil {}; - - typedef boost::make_recursive_variant< - Nil, - bool, - int, - std::string, - std::vector< boost::recursive_variant_ >, - std::map<std::string, boost::shared_ptr<boost::recursive_variant_> > - >::type Value; - - typedef std::map<std::string, boost::shared_ptr<Value> > Table; - typedef std::vector<Value> Array; - - inline boost::shared_ptr<Value> nilRef() { - return boost::make_shared<Value>(Nil()); - } - - inline boost::shared_ptr<Value> valueRef(const std::string& value) { - return boost::make_shared<Value>(value); - } - - inline boost::shared_ptr<Value> intRef(int value) { - return boost::make_shared<Value>(value); - } - - inline boost::shared_ptr<Value> boolRef(bool value) { - return boost::make_shared<Value>(value); - } - - inline boost::shared_ptr<Value> valueRef(const Table& table) { - return boost::make_shared<Value>(table); - } - - inline boost::shared_ptr<Value> valueRef(const Array& array) { - return boost::make_shared<Value>(array); - } - - void pushValue(lua_State* state, const Value& value); - } + namespace Lua { + struct Nil {}; + + typedef boost::make_recursive_variant< + Nil, + bool, + int, + std::string, + std::vector< boost::recursive_variant_ >, + std::map<std::string, std::shared_ptr<boost::recursive_variant_> > + >::type Value; + + typedef std::map<std::string, std::shared_ptr<Value> > Table; + typedef std::vector<Value> Array; + + inline std::shared_ptr<Value> nilRef() { + return std::make_shared<Value>(Nil()); + } + + inline std::shared_ptr<Value> valueRef(const std::string& value) { + return std::make_shared<Value>(value); + } + + inline std::shared_ptr<Value> intRef(int value) { + return std::make_shared<Value>(value); + } + + inline std::shared_ptr<Value> boolRef(bool value) { + return std::make_shared<Value>(value); + } + + inline std::shared_ptr<Value> valueRef(const Table& table) { + return std::make_shared<Value>(table); + } + + inline std::shared_ptr<Value> valueRef(const Array& array) { + return std::make_shared<Value>(array); + } + + void pushValue(lua_State* state, const Value& value); + } } diff --git a/Sluift/LuaElementConvertor.cpp b/Sluift/LuaElementConvertor.cpp index c1d0720..176ed1f 100644 --- a/Sluift/LuaElementConvertor.cpp +++ b/Sluift/LuaElementConvertor.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ diff --git a/Sluift/LuaElementConvertor.h b/Sluift/LuaElementConvertor.h index 187ccf1..eb3a24f 100644 --- a/Sluift/LuaElementConvertor.h +++ b/Sluift/LuaElementConvertor.h @@ -1,28 +1,39 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> +#include <memory> +#include <string> -#include <boost/shared_ptr.hpp> #include <boost/optional.hpp> struct lua_State; namespace Swift { - class Payload; + class Element; - class LuaElementConvertor { - public: - static boost::optional<std::string> NO_RESULT; + class LuaElementConvertor { + public: + static boost::optional<std::string> NO_RESULT; - virtual ~LuaElementConvertor(); + struct Documentation { + Documentation(const std::string& className, const std::string& description) : + className(className), description(description) {} + std::string className; + std::string description; + }; - virtual boost::shared_ptr<Payload> convertFromLua(lua_State*, int index, const std::string& type) = 0; - virtual boost::optional<std::string> convertToLua(lua_State*, boost::shared_ptr<Payload>) = 0; - }; + virtual ~LuaElementConvertor(); + + virtual std::shared_ptr<Element> convertFromLua(lua_State*, int index, const std::string& type) = 0; + virtual boost::optional<std::string> convertToLua(lua_State*, std::shared_ptr<Element>) = 0; + + virtual boost::optional<Documentation> getDocumentation() const { + return boost::optional<Documentation>(); + } + }; } diff --git a/Sluift/LuaElementConvertors.cpp b/Sluift/LuaElementConvertors.cpp index 71957c1..db91761 100644 --- a/Sluift/LuaElementConvertors.cpp +++ b/Sluift/LuaElementConvertors.cpp @@ -1,46 +1,73 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #include <Sluift/LuaElementConvertors.h> -#include <boost/smart_ptr/make_shared.hpp> +#include <memory> -#include <Swiften/Base/foreach.h> -#include <Sluift/LuaElementConvertor.h> -#include <Sluift/ElementConvertors/RawXMLElementConvertor.h> -#include <Sluift/ElementConvertors/PubSubEventConvertor.h> +#include <Sluift/ElementConvertors/BodyConvertor.h> +#include <Sluift/ElementConvertors/CarbonsReceivedConvertor.h> +#include <Sluift/ElementConvertors/CarbonsSentConvertor.h> +#include <Sluift/ElementConvertors/CommandConvertor.h> #include <Sluift/ElementConvertors/DOMElementConvertor.h> #include <Sluift/ElementConvertors/DefaultElementConvertor.h> -#include <Sluift/ElementConvertors/DiscoItemsConvertor.h> +#include <Sluift/ElementConvertors/DelayConvertor.h> #include <Sluift/ElementConvertors/DiscoInfoConvertor.h> +#include <Sluift/ElementConvertors/DiscoItemsConvertor.h> #include <Sluift/ElementConvertors/FormConvertor.h> +#include <Sluift/ElementConvertors/ForwardedConvertor.h> +#include <Sluift/ElementConvertors/IQConvertor.h> +#include <Sluift/ElementConvertors/MAMFinConvertor.h> +#include <Sluift/ElementConvertors/MAMQueryConvertor.h> +#include <Sluift/ElementConvertors/MAMResultConvertor.h> +#include <Sluift/ElementConvertors/MessageConvertor.h> +#include <Sluift/ElementConvertors/PresenceConvertor.h> +#include <Sluift/ElementConvertors/PubSubEventConvertor.h> +#include <Sluift/ElementConvertors/RawXMLElementConvertor.h> +#include <Sluift/ElementConvertors/ResultSetConvertor.h> #include <Sluift/ElementConvertors/SoftwareVersionConvertor.h> -#include <Sluift/ElementConvertors/VCardUpdateConvertor.h> +#include <Sluift/ElementConvertors/StatusConvertor.h> +#include <Sluift/ElementConvertors/StatusShowConvertor.h> +#include <Sluift/ElementConvertors/SubjectConvertor.h> #include <Sluift/ElementConvertors/VCardConvertor.h> -#include <Sluift/ElementConvertors/BodyConvertor.h> -#include <Sluift/ElementConvertors/CommandConvertor.h> -#include <Sluift/Lua/LuaUtils.h> +#include <Sluift/ElementConvertors/VCardUpdateConvertor.h> #include <Sluift/Lua/Exception.h> +#include <Sluift/Lua/LuaUtils.h> +#include <Sluift/LuaElementConvertor.h> using namespace Swift; LuaElementConvertors::LuaElementConvertors() { - registerConvertors(); - convertors.push_back(boost::make_shared<CommandConvertor>(this)); - convertors.push_back(boost::make_shared<PubSubEventConvertor>(this)); - convertors.push_back(boost::make_shared<BodyConvertor>()); - convertors.push_back(boost::make_shared<VCardConvertor>()); - convertors.push_back(boost::make_shared<VCardUpdateConvertor>()); - convertors.push_back(boost::make_shared<FormConvertor>()); - convertors.push_back(boost::make_shared<SoftwareVersionConvertor>()); - convertors.push_back(boost::make_shared<DiscoInfoConvertor>()); - convertors.push_back(boost::make_shared<DiscoItemsConvertor>()); - convertors.push_back(boost::make_shared<DOMElementConvertor>()); - convertors.push_back(boost::make_shared<RawXMLElementConvertor>()); - convertors.push_back(boost::make_shared<DefaultElementConvertor>()); + registerConvertors(); + convertors.push_back(std::make_shared<StatusConvertor>()); + convertors.push_back(std::make_shared<StatusShowConvertor>()); + convertors.push_back(std::make_shared<DelayConvertor>()); + convertors.push_back(std::make_shared<CommandConvertor>(this)); + convertors.push_back(std::make_shared<PubSubEventConvertor>(this)); + convertors.push_back(std::make_shared<BodyConvertor>()); + convertors.push_back(std::make_shared<SubjectConvertor>()); + convertors.push_back(std::make_shared<VCardConvertor>()); + convertors.push_back(std::make_shared<VCardUpdateConvertor>()); + convertors.push_back(std::make_shared<FormConvertor>()); + convertors.push_back(std::make_shared<SoftwareVersionConvertor>()); + convertors.push_back(std::make_shared<DiscoInfoConvertor>(this)); + convertors.push_back(std::make_shared<DiscoItemsConvertor>()); + convertors.push_back(std::make_shared<IQConvertor>(this)); + convertors.push_back(std::make_shared<PresenceConvertor>(this)); + convertors.push_back(std::make_shared<MessageConvertor>(this)); + convertors.push_back(std::make_shared<ResultSetConvertor>()); + convertors.push_back(std::make_shared<ForwardedConvertor>(this)); + convertors.push_back(std::make_shared<MAMResultConvertor>(this)); + convertors.push_back(std::make_shared<MAMQueryConvertor>(this)); + convertors.push_back(std::make_shared<MAMFinConvertor>(this)); + convertors.push_back(std::make_shared<CarbonsReceivedConvertor>(this)); + convertors.push_back(std::make_shared<CarbonsSentConvertor>(this)); + convertors.push_back(std::make_shared<DOMElementConvertor>()); + convertors.push_back(std::make_shared<RawXMLElementConvertor>()); + convertors.push_back(std::make_shared<DefaultElementConvertor>()); } LuaElementConvertors::~LuaElementConvertors() { @@ -48,65 +75,65 @@ LuaElementConvertors::~LuaElementConvertors() { #include <Sluift/ElementConvertors/ElementConvertors.ipp> -boost::shared_ptr<Payload> LuaElementConvertors::convertFromLua(lua_State* L, int index) { - if (lua_isstring(L, index)) { - return convertFromLuaUntyped(L, index, "xml"); - } - else if (lua_istable(L, index)) { - lua_getfield(L, index, "_type"); - if (lua_isstring(L, -1)) { - std::string type = lua_tostring(L, -1); - lua_pop(L, 1); - return convertFromLuaUntyped(L, index, type); - } - lua_pop(L, 1); - } - throw Lua::Exception("Unable to determine type"); +std::shared_ptr<Element> LuaElementConvertors::convertFromLua(lua_State* L, int index) { + if (lua_isstring(L, index)) { + return convertFromLuaUntyped(L, index, "xml"); + } + else if (lua_istable(L, index)) { + lua_getfield(L, index, "_type"); + if (lua_isstring(L, -1)) { + std::string type = lua_tostring(L, -1); + lua_pop(L, 1); + return convertFromLuaUntyped(L, index, type); + } + lua_pop(L, 1); + } + throw Lua::Exception("Unable to determine type"); } -boost::shared_ptr<Payload> LuaElementConvertors::convertFromLuaUntyped(lua_State* L, int index, const std::string& type) { - index = Lua::absoluteOffset(L, index); - foreach (boost::shared_ptr<LuaElementConvertor> convertor, convertors) { - if (boost::shared_ptr<Payload> result = convertor->convertFromLua(L, index, type)) { - return result; - } - } - return boost::shared_ptr<Payload>(); +std::shared_ptr<Element> LuaElementConvertors::convertFromLuaUntyped(lua_State* L, int index, const std::string& type) { + index = Lua::absoluteOffset(L, index); + for (auto&& convertor : convertors) { + if (std::shared_ptr<Element> result = convertor->convertFromLua(L, index, type)) { + return result; + } + } + return std::shared_ptr<Element>(); } -int LuaElementConvertors::convertToLua(lua_State* L, boost::shared_ptr<Payload> payload) { - if (boost::optional<std::string> type = doConvertToLuaUntyped(L, payload)) { - if (lua_istable(L, -1)) { - lua_pushstring(L, type->c_str()); - lua_setfield(L, -2, "_type"); - Lua::registerTableToString(L, -1); - } - else { - assert(*type == "xml"); - } - return 1; - } - return 0; +int LuaElementConvertors::convertToLua(lua_State* L, std::shared_ptr<Element> payload) { + if (boost::optional<std::string> type = doConvertToLuaUntyped(L, payload)) { + if (lua_istable(L, -1)) { + lua_pushstring(L, type->c_str()); + lua_setfield(L, -2, "_type"); + Lua::registerTableToString(L, -1); + } + else { + assert(*type == "xml"); + } + return 1; + } + return 0; } -int LuaElementConvertors::convertToLuaUntyped(lua_State* L, boost::shared_ptr<Payload> payload) { - if (doConvertToLuaUntyped(L, payload)) { - return 1; - } - return 0; +int LuaElementConvertors::convertToLuaUntyped(lua_State* L, std::shared_ptr<Element> payload) { + if (doConvertToLuaUntyped(L, payload)) { + return 1; + } + return 0; } boost::optional<std::string> LuaElementConvertors::doConvertToLuaUntyped( - lua_State* L, boost::shared_ptr<Payload> payload) { - if (!payload) { - return LuaElementConvertor::NO_RESULT; - } - foreach (boost::shared_ptr<LuaElementConvertor> convertor, convertors) { - if (boost::optional<std::string> type = convertor->convertToLua(L, payload)) { - return *type; - } - } - return LuaElementConvertor::NO_RESULT; + lua_State* L, std::shared_ptr<Element> payload) { + if (!payload) { + return LuaElementConvertor::NO_RESULT; + } + for (auto&& convertor : convertors) { + if (boost::optional<std::string> type = convertor->convertToLua(L, payload)) { + return *type; + } + } + return LuaElementConvertor::NO_RESULT; } diff --git a/Sluift/LuaElementConvertors.h b/Sluift/LuaElementConvertors.h index 36da15a..bfcffdd 100644 --- a/Sluift/LuaElementConvertors.h +++ b/Sluift/LuaElementConvertors.h @@ -1,47 +1,50 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Base/Override.h> - +#include <memory> #include <vector> -#include <boost/shared_ptr.hpp> + #include <boost/optional.hpp> struct lua_State; namespace Swift { - class LuaElementConvertor; - class Payload; - - class LuaElementConvertors { - public: - LuaElementConvertors(); - virtual ~LuaElementConvertors(); - - boost::shared_ptr<Payload> convertFromLua(lua_State*, int index); - int convertToLua(lua_State*, boost::shared_ptr<Payload>); - - /** - * Adds a toplevel type+data table with the given type. - */ - boost::shared_ptr<Payload> convertFromLuaUntyped(lua_State*, int index, const std::string& type); - - /** - * Strips the toplevel type+data table, and only return the - * data. - */ - int convertToLuaUntyped(lua_State*, boost::shared_ptr<Payload>); - - private: - boost::optional<std::string> doConvertToLuaUntyped(lua_State*, boost::shared_ptr<Payload>); - void registerConvertors(); - - private: - std::vector< boost::shared_ptr<LuaElementConvertor> > convertors; - }; + class LuaElementConvertor; + class Element; + + class LuaElementConvertors { + public: + LuaElementConvertors(); + virtual ~LuaElementConvertors(); + + std::shared_ptr<Element> convertFromLua(lua_State*, int index); + int convertToLua(lua_State*, std::shared_ptr<Element>); + + /** + * Adds a toplevel type+data table with the given type. + */ + std::shared_ptr<Element> convertFromLuaUntyped(lua_State*, int index, const std::string& type); + + /** + * Strips the toplevel type+data table, and only return the + * data. + */ + int convertToLuaUntyped(lua_State*, std::shared_ptr<Element>); + + const std::vector< std::shared_ptr<LuaElementConvertor> >& getConvertors() const { + return convertors; + } + + private: + boost::optional<std::string> doConvertToLuaUntyped(lua_State*, std::shared_ptr<Element>); + void registerConvertors(); + + private: + std::vector< std::shared_ptr<LuaElementConvertor> > convertors; + }; } diff --git a/Sluift/Response.cpp b/Sluift/Response.cpp index 519379c..dd98a25 100644 --- a/Sluift/Response.cpp +++ b/Sluift/Response.cpp @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ @@ -8,71 +8,74 @@ #include <lua.hpp> -#include <Sluift/globals.h> #include <Swiften/Elements/ErrorPayload.h> + #include <Sluift/Lua/LuaUtils.h> +#include <Sluift/globals.h> using namespace Swift; using namespace Swift::Sluift; -static std::string getErrorString(boost::shared_ptr<ErrorPayload> error) { - // Copied from ChatControllerBase. - // TODO: Share this code; - std::string defaultMessage = "Error sending message"; - if (!error->getText().empty()) { - return error->getText(); - } - else { - switch (error->getCondition()) { - case ErrorPayload::BadRequest: return "Bad request"; - case ErrorPayload::Conflict: return "Conflict"; - case ErrorPayload::FeatureNotImplemented: return "This feature is not implemented"; - case ErrorPayload::Forbidden: return "Forbidden"; - case ErrorPayload::Gone: return "Recipient can no longer be contacted"; - case ErrorPayload::InternalServerError: return "Internal server error"; - case ErrorPayload::ItemNotFound: return "Item not found"; - case ErrorPayload::JIDMalformed: return "JID Malformed"; - case ErrorPayload::NotAcceptable: return "Message was rejected"; - case ErrorPayload::NotAllowed: return "Not allowed"; - case ErrorPayload::NotAuthorized: return "Not authorized"; - case ErrorPayload::PaymentRequired: return "Payment is required"; - case ErrorPayload::RecipientUnavailable: return "Recipient is unavailable"; - case ErrorPayload::Redirect: return "Redirect"; - case ErrorPayload::RegistrationRequired: return "Registration required"; - case ErrorPayload::RemoteServerNotFound: return "Recipient's server not found"; - case ErrorPayload::RemoteServerTimeout: return "Remote server timeout"; - case ErrorPayload::ResourceConstraint: return "The server is low on resources"; - case ErrorPayload::ServiceUnavailable: return "The service is unavailable"; - case ErrorPayload::SubscriptionRequired: return "A subscription is required"; - case ErrorPayload::UndefinedCondition: return "Undefined condition"; - case ErrorPayload::UnexpectedRequest: return "Unexpected request"; - } - } - assert(false); - return defaultMessage; +static std::string getErrorString(std::shared_ptr<ErrorPayload> error) { + // Copied from ChatControllerBase. + // TODO: Share this code; + std::string defaultMessage = "Error sending message"; + if (!error->getText().empty()) { + return error->getText(); + } + else { + switch (error->getCondition()) { + case ErrorPayload::BadRequest: return "Bad request"; + case ErrorPayload::Conflict: return "Conflict"; + case ErrorPayload::FeatureNotImplemented: return "This feature is not implemented"; + case ErrorPayload::Forbidden: return "Forbidden"; + case ErrorPayload::Gone: return "Recipient can no longer be contacted"; + case ErrorPayload::InternalServerError: return "Internal server error"; + case ErrorPayload::ItemNotFound: return "Item not found"; + case ErrorPayload::JIDMalformed: return "JID Malformed"; + case ErrorPayload::NotAcceptable: return "Message was rejected"; + case ErrorPayload::NotAllowed: return "Not allowed"; + case ErrorPayload::NotAuthorized: return "Not authorized"; + case ErrorPayload::PaymentRequired: return "Payment is required"; + case ErrorPayload::RecipientUnavailable: return "Recipient is unavailable"; + case ErrorPayload::Redirect: return "Redirect"; + case ErrorPayload::RegistrationRequired: return "Registration required"; + case ErrorPayload::RemoteServerNotFound: return "Recipient's server not found"; + case ErrorPayload::RemoteServerTimeout: return "Remote server timeout"; + case ErrorPayload::ResourceConstraint: return "The server is low on resources"; + case ErrorPayload::ServiceUnavailable: return "The service is unavailable"; + case ErrorPayload::SubscriptionRequired: return "A subscription is required"; + case ErrorPayload::UndefinedCondition: return "Undefined condition"; + case ErrorPayload::UnexpectedRequest: return "Unexpected request"; + } + } + assert(false); + return defaultMessage; } Response::~Response() { } int Response::convertToLuaResult(lua_State* L) { - if (error) { - lua_pushnil(L); - lua_pushstring(L, getErrorString(error).c_str()); - Sluift::globals.elementConvertor.convertToLuaUntyped(L, error); - Lua::registerTableToString(L, -1); - return 3; - } - else { - if (result) { - Sluift::globals.elementConvertor.convertToLuaUntyped(L, result); - Lua::registerTableToString(L, -1); - } - else { - lua_pushboolean(L, 1); - } - return 1; - } + if (error) { + lua_pushnil(L); + lua_pushstring(L, getErrorString(error).c_str()); + bool converted = Sluift::globals.elementConvertor.convertToLuaUntyped(L, error); + assert(converted); + Lua::registerTableToString(L, -1); + return 3; + } + else { + if (result) { + bool converted = Sluift::globals.elementConvertor.convertToLuaUntyped(L, result); + assert(converted); + Lua::registerTableToString(L, -1); + } + else { + lua_pushboolean(L, 1); + } + return 1; + } } diff --git a/Sluift/Response.h b/Sluift/Response.h index 1cd059a..dc35289 100644 --- a/Sluift/Response.h +++ b/Sluift/Response.h @@ -1,34 +1,36 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once -#include <Swiften/Elements/Payload.h> +#include <Swiften/Base/API.h> #include <Swiften/Elements/ErrorPayload.h> +#include <Swiften/Elements/Payload.h> struct lua_State; namespace Swift { - namespace Sluift { - struct Response { - Response(boost::shared_ptr<Payload> result, boost::shared_ptr<ErrorPayload> error) : result(result), error(error) {} - ~Response(); - - static Response withResult(boost::shared_ptr<Payload> response) { - return Response(response, boost::shared_ptr<ErrorPayload>()); - } - - static Response withError(boost::shared_ptr<ErrorPayload> error) { - return Response(boost::shared_ptr<Payload>(), error); - } - - int convertToLuaResult(lua_State* L); - - boost::shared_ptr<Payload> result; - boost::shared_ptr<ErrorPayload> error; - }; - } + namespace Sluift { + struct Response { + Response(std::shared_ptr<Payload> result, std::shared_ptr<ErrorPayload> error) : result(result), error(error) {} + SWIFTEN_DEFAULT_COPY_CONSTRUCTOR(Response) + ~Response(); + + static Response withResult(std::shared_ptr<Payload> response) { + return Response(response, std::shared_ptr<ErrorPayload>()); + } + + static Response withError(std::shared_ptr<ErrorPayload> error) { + return Response(std::shared_ptr<Payload>(), error); + } + + int convertToLuaResult(lua_State* L); + + std::shared_ptr<Payload> result; + std::shared_ptr<ErrorPayload> error; + }; + } } diff --git a/Sluift/SConscript b/Sluift/SConscript index 1a29e43..af54ece 100644 --- a/Sluift/SConscript +++ b/Sluift/SConscript @@ -1,85 +1,88 @@ import Version, os.path -Import(["env", "conf_env"]) +Import(["env"]) if env["SCONS_STAGE"] == "build" and not GetOption("help") and not env.get("HAVE_LUA", 0) : - print "Warning: Lua was not found. Sluift will not be built." - if "Sluift" in env["PROJECTS"] : - env["PROJECTS"].remove("Sluift") - + print("Warning: Lua was not found. Sluift will not be built.") + if "Sluift" in env["PROJECTS"] : + env["PROJECTS"].remove("Sluift") + elif env["SCONS_STAGE"] == "build" : - sluift_sources = [ - "Lua/Value.cpp", - "Lua/Exception.cpp", - "Lua/Check.cpp", - "Lua/FunctionRegistration.cpp", - "Lua/FunctionRegistry.cpp", - "Lua/LuaUtils.cpp", - "LuaElementConvertors.cpp", - "LuaElementConvertor.cpp", - "Response.cpp", - "ElementConvertors/BodyConvertor.cpp", - "ElementConvertors/VCardUpdateConvertor.cpp", - "ElementConvertors/PubSubEventConvertor.cpp", - "ElementConvertors/RawXMLElementConvertor.cpp", - "ElementConvertors/DOMElementConvertor.cpp", - "ElementConvertors/DefaultElementConvertor.cpp", - "ElementConvertors/DiscoInfoConvertor.cpp", - "ElementConvertors/DiscoItemsConvertor.cpp", - "ElementConvertors/FormConvertor.cpp", - "ElementConvertors/SoftwareVersionConvertor.cpp", - "ElementConvertors/VCardConvertor.cpp", - "ElementConvertors/CommandConvertor.cpp", - "ClientHelpers.cpp", - "SluiftClient.cpp", - "boot.c", - "client.cpp", - "sluift.cpp" - ] - sluift_sources += env.SConscript("ElementConvertors/SConscript") + sluift_sources = [ + "Lua/Value.cpp", + "Lua/Exception.cpp", + "Lua/Check.cpp", + "Lua/FunctionRegistration.cpp", + "Lua/FunctionRegistry.cpp", + "Lua/LuaUtils.cpp", + "LuaElementConvertors.cpp", + "LuaElementConvertor.cpp", + "Response.cpp", + "ElementConvertors/BodyConvertor.cpp", + "ElementConvertors/VCardUpdateConvertor.cpp", + "ElementConvertors/PubSubEventConvertor.cpp", + "ElementConvertors/RawXMLElementConvertor.cpp", + "ElementConvertors/DOMElementConvertor.cpp", + "ElementConvertors/DefaultElementConvertor.cpp", + "ElementConvertors/DiscoInfoConvertor.cpp", + "ElementConvertors/DiscoItemsConvertor.cpp", + "ElementConvertors/FormConvertor.cpp", + "ElementConvertors/SoftwareVersionConvertor.cpp", + "ElementConvertors/VCardConvertor.cpp", + "ElementConvertors/CommandConvertor.cpp", + "ElementConvertors/StatusConvertor.cpp", + "ElementConvertors/StatusShowConvertor.cpp", + "ElementConvertors/DelayConvertor.cpp", + "Helpers.cpp", + "SluiftClient.cpp", + "SluiftComponent.cpp", + "Watchdog.cpp", + "core.c", + "client.cpp", + "component.cpp", + "sluift.cpp" + ] + sluift_sources += env.SConscript("ElementConvertors/SConscript") + + - sluift_env = env.Clone() - sluift_env.UseFlags(env.get("LUA_FLAGS", {})) - sluift_env.UseFlags(env["SWIFTEN_FLAGS"]) - sluift_env.UseFlags(env["SWIFTEN_DEP_FLAGS"]) - if sluift_env["PLATFORM"] == "win32" : - sluift_env.Append(CPPDEFINES = ["SLUIFT_BUILD_DLL"]) + sluift_env = env.Clone() + sluift_env.UseFlags(env.get("LUA_FLAGS", {})) + sluift_env.UseFlags(env["SWIFTEN_FLAGS"]) + sluift_env.UseFlags(env["SWIFTEN_DEP_FLAGS"]) + # Support compilation on both Lua 5.1 and Lua 5.2 + sluift_env.Append(CPPDEFINES = ["LUA_COMPAT_ALL"]) + if sluift_env["PLATFORM"] == "win32" : + sluift_env.Append(CPPDEFINES = ["SLUIFT_BUILD_DLL"]) - # Generate a customized lua.c - sluift_env["SLUIFT_VERSION"] = Version.getBuildVersion(env.Dir("#").abspath, "sluift") - def patchLua(env, target, source) : - f = open(source[0].abspath, "r") - contents = f.read() - f.close() - if env["PLATFORM"] == "win32" : - key = "Z" - else : - key = "D" - contents = contents.replace("LUA_RELEASE", "\"== Sluift XMPP Console (%(version)s) == \\nPress Ctrl-%(key)s to exit\"" % {"version": source[1].get_contents(), "key" : key}) - contents = contents.replace("LUA_COPYRIGHT", "") - f = open(target[0].abspath, "w") - f.write(contents) - f.close() - sluift_env.Command("lua.c", ["#/3rdParty/Lua/src/lua.c", sluift_env.Value(sluift_env["SLUIFT_VERSION"])], env.Action(patchLua, cmdstr = "$GENCOMSTR")) + if sluift_env["PLATFORM"] == "darwin" and os.path.isdir("/Applications/iTunes.app") : + sluift_env.Append(FRAMEWORKS = ["ScriptingBridge"]) + sluift_env.Command("iTunes.h", "/Applications/iTunes.app", + "sdef ${SOURCE} | sdp -fh --basename iTunes -V 10.10 -o ${TARGET.dir}") + sluift_env.Append(CPPDEFINES = ["HAVE_ITUNES"]) + sluift_sources += ["ITunesInterface.mm"] - # Generate boot.cpp - def generate_embedded_lua(env, target, source) : - f = open(source[0].abspath, "r") - data = f.read() - f.close() - f = open(target[0].abspath, "w") - f.write('const char ' + source[0].name.replace(".", "_") + "[] = \"" + data.replace("\\", "\\\\").replace("\n", "\\n").replace('"', '\\"') + "\";") - f.close() - sluift_env.Command("boot.c", ["boot.lua"], env.Action(generate_embedded_lua, cmdstr="$GENCOMSTR")) + # Generate Version.h + version_header = "#pragma once\n\n" + version_header += "#define SLUIFT_VERSION_STRING \"" + Version.getBuildVersion(env.Dir("#").abspath, "sluift") + "\"\n" + sluift_env.WriteVal("Version.h", sluift_env.Value(version_header)) - if sluift_env.get("HAVE_READLINE", False) : - sluift_env.Append(CPPDEFINES = ["LUA_USE_READLINE"]) - sluift_env.MergeFlags(sluift_env["READLINE_FLAGS"]) + # Generate core.c + def generate_embedded_lua(env, target, source) : + f = open(source[0].abspath, "r") + data = f.read() + f.close() + f = open(target[0].abspath, "w") + f.write('#include <stddef.h>\n') + f.write('const size_t ' + source[0].name.replace(".", "_") + "_size = " + str(len(data)) + ";\n") + f.write('const char ' + source[0].name.replace(".", "_") + "[] = {" + ", ".join([str(ord(c)) for c in data]) + "};\n") + f.close() + sluift_env.Command("core.c", ["core.lua"], env.Action(generate_embedded_lua, cmdstr="$GENCOMSTR")) - sluift_env.WriteVal("dll.c", sluift_env.Value("")) + sluift_env.WriteVal("dll.c", sluift_env.Value("")) - sluift_sources = [env.File(x) for x in sluift_sources] - for sluift_variant in ['dll', 'exe'] : - SConscript(["SConscript.variant"], variant_dir = sluift_variant, - duplicate = 0, - exports = ['sluift_sources', 'sluift_variant', 'sluift_env']) + sluift_sources = [env.File(x) for x in sluift_sources] + for sluift_variant in ['dll', 'exe'] : + SConscript(["SConscript.variant"], variant_dir = sluift_variant, + duplicate = 0, + exports = ['sluift_sources', 'sluift_variant', 'sluift_env']) diff --git a/Sluift/SConscript.variant b/Sluift/SConscript.variant index 92ee493..9f56c91 100644 --- a/Sluift/SConscript.variant +++ b/Sluift/SConscript.variant @@ -6,20 +6,37 @@ Import('sluift_variant') Import('sluift_sources') if sluift_variant == 'exe' : - env["SLUIFT"] = sluift_env.Program("sluift", sluift_sources + [ - "#/Sluift/lua.c", - "#/Sluift/linit.c", - ]) - if sluift_env.get("SLUIFT_INSTALLDIR", "") : - sluift_env.Install(os.path.join(sluift_env["SLUIFT_INSTALLDIR"], "bin"), env["SLUIFT"]) + common_objects = sluift_env.StaticObject(sluift_sources) + + sluift_exe_env = sluift_env.Clone() + tokenize = sluift_exe_env.StaticObject("#/Sluift/tokenize.cpp") + exe_sources = tokenize + [ + "#/Sluift/Console.cpp", + "#/Sluift/Terminal.cpp", + "#/Sluift/StandardTerminal.cpp", + "#/Sluift/Completer.cpp", + "#/Sluift/main.cpp", + ] + + if sluift_exe_env.get("HAVE_EDITLINE", False) : + sluift_exe_env.Append(CPPDEFINES = ["HAVE_EDITLINE"]) + sluift_exe_env.MergeFlags(sluift_exe_env["EDITLINE_FLAGS"]) + exe_sources += ["#/Sluift/EditlineTerminal.cpp"] + + env["SLUIFT"] = sluift_exe_env.Program("sluift", common_objects + exe_sources) + if sluift_exe_env.get("SLUIFT_INSTALLDIR", "") : + sluift_exe_env.Install(os.path.join(sluift_exe_env["SLUIFT_INSTALLDIR"], "bin"), env["SLUIFT"]) + + # Unit tests + env.Append(UNITTEST_OBJECTS = tokenize + ["#/Sluift/UnitTest/TokenizeTest.cpp"]) else : - sluift_env["SLUIFT_DLL_SUFFIX"] = "${SHLIBSUFFIX}" - if sluift_env["PLATFORM"] == "darwin" : - sluift_env["SLUIFT_DLL_SUFFIX"] = ".so" - sluift_dll = sluift_env.SharedLibrary(sluift_env.File("sluift${SLUIFT_DLL_SUFFIX}"), - sluift_sources + ["#/Sluift/dll.c"]) - if sluift_env.get("SLUIFT_INSTALLDIR", False) and sluift_env.get("LUA_VERSION", False) : - sluift_env.Install( - os.path.join(sluift_env["SLUIFT_INSTALLDIR"], "lib", "lua", sluift_env["LUA_VERSION"]), - sluift_dll) + sluift_env["SLUIFT_DLL_SUFFIX"] = "${SHLIBSUFFIX}" + if sluift_env["PLATFORM"] == "darwin" : + sluift_env["SLUIFT_DLL_SUFFIX"] = ".so" + sluift_dll = sluift_env.SharedLibrary(sluift_env.File("sluift${SLUIFT_DLL_SUFFIX}"), + sluift_sources + ["#/Sluift/dll.c"]) + if sluift_env.get("SLUIFT_INSTALLDIR", False) and sluift_env.get("LUA_VERSION", False) : + sluift_env.Install( + os.path.join(sluift_env["SLUIFT_INSTALLDIR"], "lib", "lua", sluift_env["LUA_VERSION"]), + sluift_dll) diff --git a/Sluift/SluiftClient.cpp b/Sluift/SluiftClient.cpp index 8a8d772..99892a9 100644 --- a/Sluift/SluiftClient.cpp +++ b/Sluift/SluiftClient.cpp @@ -1,168 +1,232 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2018 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #include <Sluift/SluiftClient.h> -#include <Swiften/Client/ClientXMLTracer.h> +#include <boost/numeric/conversion/cast.hpp> + #include <Swiften/Client/Client.h> -#include <Swiften/Roster/XMPPRoster.h> -#include <Sluift/SluiftGlobals.h> -#include <Sluift/Lua/Exception.h> +#include <Swiften/Client/ClientBlockListManager.h> +#include <Swiften/Client/ClientXMLTracer.h> #include <Swiften/Elements/Message.h> +#include <Swiften/Elements/Presence.h> #include <Swiften/Elements/PubSubEvent.h> #include <Swiften/Queries/RawRequest.h> -#include <Sluift/ClientHelpers.h> -#include <Swiften/Elements/Presence.h> +#include <Swiften/Roster/XMPPRoster.h> + +#include <Sluift/Helpers.h> +#include <Sluift/Lua/Exception.h> +#include <Sluift/SluiftGlobals.h> using namespace Swift; SluiftClient::SluiftClient( - const JID& jid, - const std::string& password, - NetworkFactories* networkFactories, - SimpleEventLoop* eventLoop, - SluiftGlobals* globals) : - networkFactories(networkFactories), - eventLoop(eventLoop), - globals(globals), - tracer(NULL) { - client = new Client(jid, password, networkFactories); - client->setAlwaysTrustCertificates(); - client->onDisconnected.connect(boost::bind(&SluiftClient::handleDisconnected, this, _1)); - client->onMessageReceived.connect(boost::bind(&SluiftClient::handleIncomingMessage, this, _1)); - client->onPresenceReceived.connect(boost::bind(&SluiftClient::handleIncomingPresence, this, _1)); - client->getPubSubManager()->onEvent.connect(boost::bind(&SluiftClient::handleIncomingPubSubEvent, this, _1, _2)); - client->getRoster()->onInitialRosterPopulated.connect(boost::bind(&SluiftClient::handleInitialRosterPopulated, this)); - if (globals->debug) { - tracer = new ClientXMLTracer(client); - } + const JID& jid, + const std::string& password, + NetworkFactories* networkFactories, + SimpleEventLoop* eventLoop) : + networkFactories(networkFactories), + eventLoop(eventLoop), + tracer(nullptr) { + client = new Client(jid, password, networkFactories); + client->setAlwaysTrustCertificates(); + client->onDisconnected.connect(boost::bind(&SluiftClient::handleDisconnected, this, _1)); + client->onMessageReceived.connect(boost::bind(&SluiftClient::handleIncomingMessage, this, _1)); + client->onPresenceReceived.connect(boost::bind(&SluiftClient::handleIncomingPresence, this, _1)); + client->getPubSubManager()->onEvent.connect(boost::bind(&SluiftClient::handleIncomingPubSubEvent, this, _1, _2)); + client->getRoster()->onInitialRosterPopulated.connect(boost::bind(&SluiftClient::handleInitialRosterPopulated, this)); + client->getRoster()->onJIDAdded.connect(boost::bind(&SluiftClient::handleIncomingRosterAdd, this, _1)); + client->getRoster()->onJIDRemoved.connect(boost::bind(&SluiftClient::handleIncomingRosterRemove, this, _1)); + client->getRoster()->onJIDUpdated.connect(boost::bind(&SluiftClient::handleIncomingRosterUpdate, this, _1)); + client->getClientBlockListManager()->getBlockList()->onItemAdded.connect(boost::bind(&SluiftClient::handleIncomingBlockEvent, this, _1)); + client->getClientBlockListManager()->getBlockList()->onItemRemoved.connect(boost::bind(&SluiftClient::handleIncomingUnblockEvent, this, _1)); } SluiftClient::~SluiftClient() { - delete tracer; - delete client; + delete tracer; + delete client; } void SluiftClient::connect() { - rosterReceived = false; - disconnectedError = boost::optional<ClientError>(); - client->connect(options); -} - -void SluiftClient::connect(const std::string& host) { - rosterReceived = false; - options.manualHostname = host; - client->connect(options); -} - -void SluiftClient::waitConnected() { - Watchdog watchdog(globals->timeout, networkFactories->getTimerFactory()); - while (!watchdog.getTimedOut() && client->isActive() && !client->isAvailable()) { - eventLoop->runUntilEvents(); - } - if (watchdog.getTimedOut()) { - client->disconnect(); - throw Lua::Exception("Timeout while connecting"); - } - if (disconnectedError) { - throw Lua::Exception(getClientErrorString(*disconnectedError)); - } + if (client->isActive()) { + throw Lua::Exception("Client is already connecting or connected"); + } + rosterReceived = false; + blockListReceived = false; + disconnectedError = boost::optional<ClientError>(); + client->connect(options); +} + +void SluiftClient::setTraceEnabled(bool b) { + if (b && !tracer) { + tracer = new ClientXMLTracer(client, options.boshURL.isEmpty()? false: true); + } + else if (!b && tracer) { + delete tracer; + tracer = nullptr; + } +} + +void SluiftClient::waitConnected(int timeout) { + Watchdog watchdog(timeout, networkFactories->getTimerFactory()); + while (!watchdog.getTimedOut() && client->isActive() && !client->isAvailable()) { + eventLoop->runUntilEvents(); + } + if (watchdog.getTimedOut()) { + client->disconnect(); + throw Lua::Exception("Timeout while connecting"); + } + if (disconnectedError) { + throw Lua::Exception(getErrorString(*disconnectedError)); + } } bool SluiftClient::isConnected() const { - return client->isAvailable(); + return client->isAvailable(); } void SluiftClient::disconnect() { - client->disconnect(); - while (client->isActive()) { - eventLoop->runUntilEvents(); - } + client->disconnect(); + while (client->isActive()) { + eventLoop->runUntilEvents(); + } } void SluiftClient::setSoftwareVersion(const std::string& name, const std::string& version, const std::string& os) { - client->setSoftwareVersion(name, version, os); + client->setSoftwareVersion(name, version, os); } boost::optional<SluiftClient::Event> SluiftClient::getNextEvent( - int timeout, boost::function<bool (const Event&)> condition) { - Watchdog watchdog(timeout, networkFactories->getTimerFactory()); - while (true) { - // Look for pending events in the queue - while (!pendingEvents.empty()) { - Event event = pendingEvents.front(); - pendingEvents.pop_front(); - if (!condition || condition(event)) { - return event; - } - } + int timeout, boost::function<bool (const Event&)> condition) { + Watchdog watchdog(timeout, networkFactories->getTimerFactory()); + size_t currentIndex = 0; + while (true) { + // Look for pending events in the queue + while (currentIndex < pendingEvents.size()) { + Event event = pendingEvents[currentIndex]; + if (!condition || condition(event)) { + pendingEvents.erase( + pendingEvents.begin() + + boost::numeric_cast<int>(currentIndex)); + return event; + } + ++currentIndex; + } - // Wait for new events - while (!watchdog.getTimedOut() && pendingEvents.empty() && client->isActive()) { - eventLoop->runUntilEvents(); - } + // Wait for new events + while (!watchdog.getTimedOut() && currentIndex >= pendingEvents.size() && client->isActive()) { + eventLoop->runUntilEvents(); + } - // Finish if we're disconnected or timed out - if (watchdog.getTimedOut() || !client->isActive()) { - return boost::optional<Event>(); - } - } + // Finish if we're disconnected or timed out + if (watchdog.getTimedOut() || !client->isActive()) { + return boost::optional<Event>(); + } + } } -std::vector<XMPPRosterItem> SluiftClient::getRoster() { - if (!rosterReceived) { - // If we haven't requested it yet, request it for the first time - client->requestRoster(); - } - while (!rosterReceived) { - eventLoop->runUntilEvents(); - } - return client->getRoster()->getItems(); +std::vector<JID> SluiftClient::getBlockList(int timeout) { + Watchdog watchdog(timeout, networkFactories->getTimerFactory()); + if (!blockListReceived) { + // If we haven't requested it yet, request it for the first time + client->getClientBlockListManager()->requestBlockList(); + + // Wait for new events + while (!watchdog.getTimedOut() && client->getClientBlockListManager()->getBlockList()->getState() != BlockList::Available) { + eventLoop->runUntilEvents(); + } + + // Throw an error if we're timed out + if (watchdog.getTimedOut()) { + throw Lua::Exception("Timeout while requesting blocklist"); + } + } + blockListReceived = true; + return client->getClientBlockListManager()->getBlockList()->getItems(); +} + +std::vector<XMPPRosterItem> SluiftClient::getRoster(int timeout) { + Watchdog watchdog(timeout, networkFactories->getTimerFactory()); + if (!rosterReceived) { + // If we haven't requested it yet, request it for the first time + client->requestRoster(); + + // Wait for new events + while (!watchdog.getTimedOut() && !rosterReceived) { + eventLoop->runUntilEvents(); + } + + // Throw an error if we're timed out + if (watchdog.getTimedOut()) { + throw Lua::Exception("Timeout while requesting roster"); + } + } + return client->getRoster()->getItems(); +} + +void SluiftClient::handleIncomingMessage(std::shared_ptr<Message> stanza) { + if (stanza->getPayload<PubSubEvent>()) { + // Already handled by pubsub manager + return; + } + pendingEvents.push_back(Event(stanza)); } -void SluiftClient::handleIncomingMessage(boost::shared_ptr<Message> stanza) { - if (stanza->getPayload<PubSubEvent>()) { - // Already handled by pubsub manager - return; - } - pendingEvents.push_back(Event(stanza)); +void SluiftClient::handleIncomingPresence(std::shared_ptr<Presence> stanza) { + pendingEvents.push_back(Event(stanza)); } -void SluiftClient::handleIncomingPresence(boost::shared_ptr<Presence> stanza) { - pendingEvents.push_back(Event(stanza)); +void SluiftClient::handleIncomingPubSubEvent(const JID& from, std::shared_ptr<PubSubEventPayload> event) { + pendingEvents.push_back(Event(from, event)); } -void SluiftClient::handleIncomingPubSubEvent(const JID& from, boost::shared_ptr<PubSubEventPayload> event) { - pendingEvents.push_back(Event(from, event)); +void SluiftClient::handleIncomingBlockEvent(const JID& item) { + pendingEvents.push_back(Event(item, Event::BlockEventType)); +} + +void SluiftClient::handleIncomingUnblockEvent(const JID& item) { + pendingEvents.push_back(Event(item, Event::UnblockEventType)); } void SluiftClient::handleInitialRosterPopulated() { - rosterReceived = true; + rosterReceived = true; +} + +void SluiftClient::handleIncomingRosterAdd(const JID& item) { + pendingEvents.push_back(Event(item, Event::RosterAddType)); +} + +void SluiftClient::handleIncomingRosterRemove(const JID& item) { + pendingEvents.push_back(Event(item, Event::RosterRemoveType)); +} + +void SluiftClient::handleIncomingRosterUpdate(const JID& item) { + pendingEvents.push_back(Event(item, Event::RosterUpdateType)); } -void SluiftClient::handleRequestResponse(boost::shared_ptr<Payload> response, boost::shared_ptr<ErrorPayload> error) { - requestResponse = response; - requestError = error; - requestResponseReceived = true; +void SluiftClient::handleRequestResponse(std::shared_ptr<Payload> response, std::shared_ptr<ErrorPayload> error) { + requestResponse = response; + requestError = error; + requestResponseReceived = true; } void SluiftClient::handleDisconnected(const boost::optional<ClientError>& error) { - disconnectedError = error; + disconnectedError = error; } -Sluift::Response SluiftClient::doSendRequest(boost::shared_ptr<Request> request, int timeout) { - requestResponse.reset(); - requestError.reset(); - requestResponseReceived = false; - request->send(); +Sluift::Response SluiftClient::doSendRequest(std::shared_ptr<Request> request, int timeout) { + requestResponse.reset(); + requestError.reset(); + requestResponseReceived = false; + request->send(); - Watchdog watchdog(timeout, networkFactories->getTimerFactory()); - while (!watchdog.getTimedOut() && !requestResponseReceived) { - eventLoop->runUntilEvents(); - } - return Sluift::Response(requestResponse, watchdog.getTimedOut() ? - boost::make_shared<ErrorPayload>(ErrorPayload::RemoteServerTimeout) : requestError); + Watchdog watchdog(timeout, networkFactories->getTimerFactory()); + while (!watchdog.getTimedOut() && !requestResponseReceived) { + eventLoop->runUntilEvents(); + } + return Sluift::Response(requestResponse, watchdog.getTimedOut() ? + std::make_shared<ErrorPayload>(ErrorPayload::RemoteServerTimeout) : requestError); } diff --git a/Sluift/SluiftClient.h b/Sluift/SluiftClient.h index bedd6ba..ac4c582 100644 --- a/Sluift/SluiftClient.h +++ b/Sluift/SluiftClient.h @@ -1,133 +1,148 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2018 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ #pragma once #include <deque> -#include <boost/optional.hpp> + #include <boost/bind.hpp> #include <boost/function.hpp> +#include <boost/optional.hpp> +#include <Swiften/Client/Client.h> +#include <Swiften/Client/ClientBlockListManager.h> +#include <Swiften/Client/ClientError.h> #include <Swiften/Client/ClientOptions.h> -#include <Sluift/globals.h> #include <Swiften/Elements/IQ.h> #include <Swiften/Elements/Message.h> #include <Swiften/Elements/Presence.h> -#include <Swiften/Queries/GenericRequest.h> -#include <Swiften/Roster/XMPPRosterItem.h> -#include <Swiften/Client/ClientError.h> -#include <Swiften/Network/NetworkFactories.h> -#include <Swiften/Client/Client.h> #include <Swiften/EventLoop/SimpleEventLoop.h> -#include <Sluift/Watchdog.h> +#include <Swiften/Network/NetworkFactories.h> #include <Swiften/PubSub/PubSubManager.h> +#include <Swiften/Queries/GenericRequest.h> +#include <Swiften/Roster/XMPPRosterItem.h> + #include <Sluift/Response.h> +#include <Sluift/Watchdog.h> namespace Swift { - struct SluiftGlobals; - class ClientXMLTracer; - class Client; - class Stanza; - class Payload; - class ErrorPayload; - class JID; - - class SluiftClient { - public: - struct Event { - enum Type { - MessageType, - PresenceType, - PubSubEventType - }; - - Event(boost::shared_ptr<Message> stanza) : type(MessageType), stanza(stanza) {} - Event(boost::shared_ptr<Presence> stanza) : type(PresenceType), stanza(stanza) {} - Event(const JID& from, boost::shared_ptr<PubSubEventPayload> payload) : type(PubSubEventType), from(from), pubsubEvent(payload) {} - - Type type; - - // Message & Presence - boost::shared_ptr<Stanza> stanza; - - // PubSubEvent - JID from; - boost::shared_ptr<PubSubEventPayload> pubsubEvent; - }; - - SluiftClient( - const JID& jid, - const std::string& password, - NetworkFactories* networkFactories, - SimpleEventLoop* eventLoop, - SluiftGlobals* globals); - ~SluiftClient(); - - Client* getClient() { - return client; - } - - ClientOptions& getOptions() { - return options; - } - - void connect(); - void connect(const std::string& host); - void waitConnected(); - bool isConnected() const; - - template<typename T> - Sluift::Response sendPubSubRequest( - IQ::Type type, const JID& jid, boost::shared_ptr<T> payload, int timeout) { - return sendRequest(client->getPubSubManager()->createRequest( - type, jid, payload), timeout); - } - - template<typename REQUEST_TYPE> - Sluift::Response sendRequest(REQUEST_TYPE request, int timeout) { - boost::signals::scoped_connection c = request->onResponse.connect( - boost::bind(&SluiftClient::handleRequestResponse, this, _1, _2)); - return doSendRequest(request, timeout); - } - - template<typename REQUEST_TYPE> - Sluift::Response sendVoidRequest(REQUEST_TYPE request, int timeout) { - boost::signals::scoped_connection c = request->onResponse.connect( - boost::bind(&SluiftClient::handleRequestResponse, this, boost::shared_ptr<Payload>(), _1)); - return doSendRequest(request, timeout); - } - - void disconnect(); - void setSoftwareVersion(const std::string& name, const std::string& version, const std::string& os); - boost::optional<SluiftClient::Event> getNextEvent(int timeout, - boost::function<bool (const Event&)> condition = 0); - std::vector<XMPPRosterItem> getRoster(); - - private: - Sluift::Response doSendRequest(boost::shared_ptr<Request> request, int timeout); - - void handleIncomingMessage(boost::shared_ptr<Message> stanza); - void handleIncomingPresence(boost::shared_ptr<Presence> stanza); - void handleIncomingPubSubEvent(const JID& from, boost::shared_ptr<PubSubEventPayload> event); - void handleInitialRosterPopulated(); - void handleRequestResponse(boost::shared_ptr<Payload> response, boost::shared_ptr<ErrorPayload> error); - void handleDisconnected(const boost::optional<ClientError>& error); - - private: - NetworkFactories* networkFactories; - SimpleEventLoop* eventLoop; - SluiftGlobals* globals; - Client* client; - ClientOptions options; - ClientXMLTracer* tracer; - bool rosterReceived; - std::deque<Event> pendingEvents; - boost::optional<ClientError> disconnectedError; - bool requestResponseReceived; - boost::shared_ptr<Payload> requestResponse; - boost::shared_ptr<ErrorPayload> requestError; - }; + struct SluiftGlobals; + class ClientXMLTracer; + class Client; + class Stanza; + class Payload; + class ErrorPayload; + class JID; + + class SluiftClient { + public: + struct Event { + enum Type { + MessageType, + PresenceType, + PubSubEventType, + BlockEventType, + UnblockEventType, + RosterAddType, + RosterRemoveType, + RosterUpdateType + }; + + Event(std::shared_ptr<Message> stanza) : type(MessageType), stanza(stanza) {} + Event(std::shared_ptr<Presence> stanza) : type(PresenceType), stanza(stanza) {} + Event(const JID& from, std::shared_ptr<PubSubEventPayload> payload) : type(PubSubEventType), from(from), pubsubEvent(payload) {} + Event(const JID& item, Type type) : type(type), item(item) {} + Type type; + + // Message & Presence + std::shared_ptr<Stanza> stanza; + + // PubSubEvent + JID from; + std::shared_ptr<PubSubEventPayload> pubsubEvent; + + // Blocklist & Roster Push + JID item; + }; + + SluiftClient( + const JID& jid, + const std::string& password, + NetworkFactories* networkFactories, + SimpleEventLoop* eventLoop); + ~SluiftClient(); + + Client* getClient() { + return client; + } + + ClientOptions& getOptions() { + return options; + } + + void connect(); + void waitConnected(int timeout); + bool isConnected() const; + void setTraceEnabled(bool b); + + template<typename T> + Sluift::Response sendPubSubRequest( + IQ::Type type, const JID& jid, std::shared_ptr<T> payload, int timeout) { + return sendRequest(client->getPubSubManager()->createRequest( + type, jid, payload), timeout); + } + + template<typename REQUEST_TYPE> + Sluift::Response sendRequest(REQUEST_TYPE request, int timeout) { + boost::signals2::scoped_connection c(request->onResponse.connect( + boost::bind(&SluiftClient::handleRequestResponse, this, _1, _2))); + return doSendRequest(request, timeout); + } + + template<typename REQUEST_TYPE> + Sluift::Response sendVoidRequest(REQUEST_TYPE request, int timeout) { + boost::signals2::scoped_connection c(request->onResponse.connect( + boost::bind(&SluiftClient::handleRequestResponse, this, std::shared_ptr<Payload>(), _1))); + return doSendRequest(request, timeout); + } + + void disconnect(); + void setSoftwareVersion(const std::string& name, const std::string& version, const std::string& os); + boost::optional<SluiftClient::Event> getNextEvent(int timeout, + boost::function<bool (const Event&)> condition = boost::function<bool (const Event&)>()); + std::vector<XMPPRosterItem> getRoster(int timeout); + std::vector<JID> getBlockList(int timeout); + + private: + Sluift::Response doSendRequest(std::shared_ptr<Request> request, int timeout); + + void handleIncomingMessage(std::shared_ptr<Message> stanza); + void handleIncomingPresence(std::shared_ptr<Presence> stanza); + void handleIncomingPubSubEvent(const JID& from, std::shared_ptr<PubSubEventPayload> event); + void handleIncomingBlockEvent(const JID& item); + void handleIncomingUnblockEvent(const JID& item); + void handleInitialRosterPopulated(); + void handleIncomingRosterAdd(const JID& item); + void handleIncomingRosterRemove(const JID& item); + void handleIncomingRosterUpdate(const JID& item); + void handleRequestResponse(std::shared_ptr<Payload> response, std::shared_ptr<ErrorPayload> error); + void handleDisconnected(const boost::optional<ClientError>& error); + + private: + NetworkFactories* networkFactories; + SimpleEventLoop* eventLoop; + Client* client; + ClientOptions options; + ClientXMLTracer* tracer; + bool rosterReceived = false; + bool blockListReceived = false; + std::deque<Event> pendingEvents; + boost::optional<ClientError> disconnectedError; + bool requestResponseReceived = false; + std::shared_ptr<Payload> requestResponse; + std::shared_ptr<ErrorPayload> requestError; + }; } diff --git a/Sluift/SluiftComponent.cpp b/Sluift/SluiftComponent.cpp new file mode 100644 index 0000000..74728ee --- /dev/null +++ b/Sluift/SluiftComponent.cpp @@ -0,0 +1,149 @@ +/* + * Copyright (c) 2014-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Sluift/SluiftComponent.h> + +#include <boost/numeric/conversion/cast.hpp> + +#include <Swiften/Component/Component.h> +#include <Swiften/Component/ComponentXMLTracer.h> +#include <Swiften/Elements/Message.h> +#include <Swiften/Elements/Presence.h> +#include <Swiften/Queries/RawRequest.h> +#include <Swiften/Roster/XMPPRoster.h> + +#include <Sluift/Helpers.h> +#include <Sluift/Lua/Exception.h> +#include <Sluift/SluiftGlobals.h> + +using namespace Swift; + +SluiftComponent::SluiftComponent( + const JID& jid, + const std::string& password, + NetworkFactories* networkFactories, + SimpleEventLoop* eventLoop): + networkFactories(networkFactories), + eventLoop(eventLoop), + tracer(nullptr) { + component = new Component(jid, password, networkFactories); + component->onError.connect(boost::bind(&SluiftComponent::handleError, this, _1)); + component->onMessageReceived.connect(boost::bind(&SluiftComponent::handleIncomingMessage, this, _1)); + component->onPresenceReceived.connect(boost::bind(&SluiftComponent::handleIncomingPresence, this, _1)); +} + +SluiftComponent::~SluiftComponent() { + delete tracer; + delete component; +} + +void SluiftComponent::connect(const std::string& host, unsigned short port) { + if (component->isActive()) { + throw Lua::Exception("Component is already connecting or connected"); + } + disconnectedError = boost::optional<ComponentError>(); + component->connect(host, port); +} + +void SluiftComponent::setTraceEnabled(bool b) { + if (b && !tracer) { + tracer = new ComponentXMLTracer(component); + } + else if (!b && tracer) { + delete tracer; + tracer = nullptr; + } +} + +void SluiftComponent::waitConnected(int timeout) { + Watchdog watchdog(timeout, networkFactories->getTimerFactory()); + while (!watchdog.getTimedOut() && !disconnectedError && !component->isAvailable()) { + eventLoop->runUntilEvents(); + } + if (watchdog.getTimedOut()) { + component->disconnect(); + throw Lua::Exception("Timeout while connecting"); + } + if (disconnectedError) { + throw Lua::Exception(getErrorString(*disconnectedError)); + } +} + +bool SluiftComponent::isConnected() const { + return component->isAvailable(); +} + +void SluiftComponent::disconnect() { + component->disconnect(); + while (component->isActive()) { + eventLoop->runUntilEvents(); + } +} + +void SluiftComponent::setSoftwareVersion(const std::string& name, const std::string& version, const std::string& /* os */) { + component->setSoftwareVersion(name, version); +} + +boost::optional<SluiftComponent::Event> SluiftComponent::getNextEvent( + int timeout, boost::function<bool (const Event&)> condition) { + Watchdog watchdog(timeout, networkFactories->getTimerFactory()); + size_t currentIndex = 0; + while (true) { + // Look for pending events in the queue + while (currentIndex < pendingEvents.size()) { + Event event = pendingEvents[currentIndex]; + if (!condition || condition(event)) { + pendingEvents.erase( + pendingEvents.begin() + + boost::numeric_cast<int>(currentIndex)); + return event; + } + ++currentIndex; + } + + // Wait for new events + while (!watchdog.getTimedOut() && currentIndex >= pendingEvents.size() && component->isActive()) { + eventLoop->runUntilEvents(); + } + + // Finish if we're disconnected or timed out + if (watchdog.getTimedOut() || !component->isActive()) { + return boost::optional<Event>(); + } + } +} + +void SluiftComponent::handleIncomingMessage(std::shared_ptr<Message> stanza) { + pendingEvents.push_back(Event(stanza)); +} + +void SluiftComponent::handleIncomingPresence(std::shared_ptr<Presence> stanza) { + pendingEvents.push_back(Event(stanza)); +} + +void SluiftComponent::handleRequestResponse(std::shared_ptr<Payload> response, std::shared_ptr<ErrorPayload> error) { + requestResponse = response; + requestError = error; + requestResponseReceived = true; +} + +void SluiftComponent::handleError(const boost::optional<ComponentError>& error) { + disconnectedError = error; +} + +Sluift::Response SluiftComponent::doSendRequest(std::shared_ptr<Request> request, int timeout) { + requestResponse.reset(); + requestError.reset(); + requestResponseReceived = false; + request->send(); + + Watchdog watchdog(timeout, networkFactories->getTimerFactory()); + while (!watchdog.getTimedOut() && !requestResponseReceived) { + eventLoop->runUntilEvents(); + } + return Sluift::Response(requestResponse, watchdog.getTimedOut() ? + std::make_shared<ErrorPayload>(ErrorPayload::RemoteServerTimeout) : requestError); +} diff --git a/Sluift/SluiftComponent.h b/Sluift/SluiftComponent.h new file mode 100644 index 0000000..586a94e --- /dev/null +++ b/Sluift/SluiftComponent.h @@ -0,0 +1,109 @@ +/* + * Copyright (c) 2014-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <deque> + +#include <boost/bind.hpp> +#include <boost/function.hpp> +#include <boost/optional.hpp> + +#include <Swiften/Client/ClientOptions.h> +#include <Swiften/Component/Component.h> +#include <Swiften/Component/ComponentError.h> +#include <Swiften/Elements/IQ.h> +#include <Swiften/Elements/Message.h> +#include <Swiften/Elements/Presence.h> +#include <Swiften/EventLoop/SimpleEventLoop.h> +#include <Swiften/Network/NetworkFactories.h> +#include <Swiften/Queries/GenericRequest.h> +#include <Swiften/Roster/XMPPRosterItem.h> + +#include <Sluift/Response.h> +#include <Sluift/Watchdog.h> + +namespace Swift { + struct SluiftGlobals; + class ComponentXMLTracer; + class Component; + class Stanza; + class Payload; + class ErrorPayload; + class JID; + + class SluiftComponent { + public: + struct Event { + enum Type { + MessageType, + PresenceType + }; + + Event(std::shared_ptr<Message> stanza) : type(MessageType), stanza(stanza) {} + Event(std::shared_ptr<Presence> stanza) : type(PresenceType), stanza(stanza) {} + + Type type; + + // Message & Presence + std::shared_ptr<Stanza> stanza; + }; + + SluiftComponent( + const JID& jid, + const std::string& password, + NetworkFactories* networkFactories, + SimpleEventLoop* eventLoop); + ~SluiftComponent(); + + Component* getComponent() { + return component; + } + + void connect(const std::string& host, unsigned short port); + void waitConnected(int timeout); + bool isConnected() const; + void setTraceEnabled(bool b); + + template<typename REQUEST_TYPE> + Sluift::Response sendRequest(REQUEST_TYPE request, int timeout) { + boost::signals2::scoped_connection c(request->onResponse.connect( + boost::bind(&SluiftComponent::handleRequestResponse, this, _1, _2))); + return doSendRequest(request, timeout); + } + + template<typename REQUEST_TYPE> + Sluift::Response sendVoidRequest(REQUEST_TYPE request, int timeout) { + boost::signals2::scoped_connection c(request->onResponse.connect( + boost::bind(&SluiftComponent::handleRequestResponse, this, std::shared_ptr<Payload>(), _1))); + return doSendRequest(request, timeout); + } + + void disconnect(); + void setSoftwareVersion(const std::string& name, const std::string& version, const std::string& os); + boost::optional<SluiftComponent::Event> getNextEvent(int timeout, + boost::function<bool (const Event&)> condition = boost::function<bool (const Event&)>()); + + private: + Sluift::Response doSendRequest(std::shared_ptr<Request> request, int timeout); + + void handleIncomingMessage(std::shared_ptr<Message> stanza); + void handleIncomingPresence(std::shared_ptr<Presence> stanza); + void handleRequestResponse(std::shared_ptr<Payload> response, std::shared_ptr<ErrorPayload> error); + void handleError(const boost::optional<ComponentError>& error); + + private: + NetworkFactories* networkFactories; + SimpleEventLoop* eventLoop; + Component* component; + ComponentXMLTracer* tracer; + std::deque<Event> pendingEvents; + boost::optional<ComponentError> disconnectedError; + bool requestResponseReceived = false; + std::shared_ptr<Payload> requestResponse; + std::shared_ptr<ErrorPayload> requestError; + }; +} diff --git a/Sluift/SluiftGlobals.h b/Sluift/SluiftGlobals.h index 03c1c1a..14ed6f3 100644 --- a/Sluift/SluiftGlobals.h +++ b/Sluift/SluiftGlobals.h @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2014 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ @@ -9,16 +9,29 @@ #include <Sluift/LuaElementConvertors.h> #include <Swiften/EventLoop/SimpleEventLoop.h> #include <Swiften/Network/BoostNetworkFactories.h> +#include <Swiften/TLS/PlatformTLSFactories.h> +#ifdef HAVE_ITUNES +#include <Sluift/ITunesInterface.h> +#endif +#include <signal.h> namespace Swift { - struct SluiftGlobals { - SluiftGlobals() : networkFactories(&eventLoop) {} + struct SluiftGlobals { + SluiftGlobals() : + networkFactories(&eventLoop), + coreLibIndex(-1), + moduleLibIndex(-1), + interruptRequested(0) {} - int timeout; - bool debug; - LuaElementConvertors elementConvertor; - SimpleEventLoop eventLoop; - BoostNetworkFactories networkFactories; - int bootIndex; - }; + LuaElementConvertors elementConvertor; + SimpleEventLoop eventLoop; + BoostNetworkFactories networkFactories; + PlatformTLSFactories tlsFactories; + int coreLibIndex; + int moduleLibIndex; + sig_atomic_t interruptRequested; +#ifdef HAVE_ITUNES + ITunesInterface iTunes; +#endif + }; } diff --git a/Sluift/StandardTerminal.cpp b/Sluift/StandardTerminal.cpp new file mode 100644 index 0000000..1378346 --- /dev/null +++ b/Sluift/StandardTerminal.cpp @@ -0,0 +1,39 @@ +/* + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Sluift/StandardTerminal.h> + +#include <iostream> +#include <stdexcept> + +#include <boost/optional.hpp> + +using namespace Swift; + +StandardTerminal::StandardTerminal() { +} + +StandardTerminal::~StandardTerminal() { +} + +void StandardTerminal::printError(const std::string& message) { + std::cout << message << std::endl; +} + +boost::optional<std::string> StandardTerminal::readLine(const std::string& prompt) { + std::cout << prompt << std::flush; + std::string input; + if (!std::getline(std::cin, input)) { + if (std::cin.eof()) { + return boost::optional<std::string>(); + } + throw std::runtime_error("Input error"); + } + return input; +} + +void StandardTerminal::addToHistory(const std::string&) { +} diff --git a/Sluift/StandardTerminal.h b/Sluift/StandardTerminal.h new file mode 100644 index 0000000..f32bd1c --- /dev/null +++ b/Sluift/StandardTerminal.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2013-2017 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <Sluift/Terminal.h> + +namespace Swift { + class StandardTerminal : public Terminal { + public: + StandardTerminal(); + virtual ~StandardTerminal() override; + + virtual boost::optional<std::string> readLine(const std::string& prompt) override; + virtual void printError(const std::string& message) override; + virtual void addToHistory(const std::string& command) override; + }; +} diff --git a/Sluift/Terminal.cpp b/Sluift/Terminal.cpp new file mode 100644 index 0000000..4b54a87 --- /dev/null +++ b/Sluift/Terminal.cpp @@ -0,0 +1,15 @@ +/* + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Sluift/Terminal.h> + +using namespace Swift; + +Terminal::Terminal() : completer(nullptr) { +} + +Terminal::~Terminal() { +} diff --git a/Sluift/Terminal.h b/Sluift/Terminal.h new file mode 100644 index 0000000..3443d16 --- /dev/null +++ b/Sluift/Terminal.h @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <string> + +#include <boost/optional/optional.hpp> + +namespace Swift { + class Completer; + + class Terminal { + public: + Terminal(); + virtual ~Terminal(); + + Completer* getCompleter() const { + return completer; + } + + void setCompleter(Completer* completer) { + this->completer = completer; + } + + virtual boost::optional<std::string> readLine(const std::string& prompt) = 0; + virtual void addToHistory(const std::string& command) = 0; + virtual void printError(const std::string& message) = 0; + + private: + Completer* completer; + }; +} diff --git a/Sluift/Tests/FormTest.lua b/Sluift/Tests/FormTest.lua index 7b6b4af..d584646 100644 --- a/Sluift/Tests/FormTest.lua +++ b/Sluift/Tests/FormTest.lua @@ -1,7 +1,7 @@ --[[ - Copyright (c) 2013 Remko Tronçon - Licensed under the GNU General Public License v3. - See Documentation/Licenses/GPLv3.txt for more information. + Copyright (c) 2013-2016 Isode Limited. + All rights reserved. + See the COPYING file for more information. --]] example_form = [[ @@ -13,7 +13,10 @@ example_form = [[ </field> <field type='fixed'><value>Section 1: Bot Info</value></field> <field type='text-single' label='The name of your bot' var='botname'/> - <field type='text-multi' label='Helpful description of your bot' var='description'/> + <field type='text-multi' label='Helpful description of your bot' var='description'> + <value>This is</value> + <value>my bot</value> + </field> <field type='boolean' label='Public bot?' var='public'> <required/> </field> @@ -59,10 +62,10 @@ assert(public_field['required'] == true) -- Test multi field features_field = form['fields'][8] assert(features_field['name'] == 'features') -assert(type(features_field['values']) == 'table') -assert(#features_field['values'] == 2) -assert(features_field['values'][1] == 'news') -assert(features_field['values'][2] == 'search') +assert(type(features_field['value']) == 'table') +assert(#features_field['value'] == 2) +assert(features_field['value'][1] == 'news') +assert(features_field['value'][2] == 'search') -- Test shortcut index assert(form['features']['name'] == 'features') @@ -71,9 +74,31 @@ assert(form['FORM_TYPE']['value'] == 'jabber:bot') -- Test response form submission = form:create_submission() assert(#(submission.fields) == 8) +description_submit_value = submission['description']['value'] +assert(type(description_submit_value) == 'table') +assert(description_submit_value[1] == 'This is') +assert(description_submit_value[2] == 'my bot') + submission['description'] = 'my description' assert(submission['description']['value'] == 'my description') submission['type'] = 'cancel' -assert(#(submission.fields) == 8) + +-- Test text-multi field +text_multi_field = form['fields'][4] +assert(text_multi_field['name'] == 'description') +assert(type(text_multi_field['value']) == 'table') + --print(sluift.to_xml({type = 'form', data = form})) + +-- test parsing an empty form -- this had issues as reported in SWIFT-174 +empty_form = [[<x xmlns='jabber:x:data' type='form'/>]] +form = sluift.from_xml(empty_form) +-- and check if we can access all fields without problems +assert(type(form._type)) +assert(type(form.title)) +assert(type(form.instructions)) +assert(type(form.type)) +assert(type(form.fields)) +assert(type(form.items)) +assert(type(form.reported_items)) diff --git a/Sluift/UnitTest/TokenizeTest.cpp b/Sluift/UnitTest/TokenizeTest.cpp new file mode 100644 index 0000000..cd617b5 --- /dev/null +++ b/Sluift/UnitTest/TokenizeTest.cpp @@ -0,0 +1,64 @@ +/* + * Copyright (c) 2013 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <cppunit/extensions/HelperMacros.h> +#include <cppunit/extensions/TestFactoryRegistry.h> + +#include <Sluift/tokenize.h> + +using namespace Swift; + +class TokenizeTest : public CppUnit::TestFixture { + CPPUNIT_TEST_SUITE(TokenizeTest); + CPPUNIT_TEST(testTokenize); + CPPUNIT_TEST(testTokenize); + CPPUNIT_TEST(testTokenize_String); + CPPUNIT_TEST(testTokenize_IncompleteString); + CPPUNIT_TEST(testTokenize_Identifier); + CPPUNIT_TEST_SUITE_END(); + + public: + void testTokenize() { + std::vector<std::string> tokens = Lua::tokenize("foo.bar + 1.23 - bam"); + + CPPUNIT_ASSERT_EQUAL(7, static_cast<int>(tokens.size())); + CPPUNIT_ASSERT_EQUAL(std::string("foo"), tokens[0]); + CPPUNIT_ASSERT_EQUAL(std::string("."), tokens[1]); + CPPUNIT_ASSERT_EQUAL(std::string("bar"), tokens[2]); + CPPUNIT_ASSERT_EQUAL(std::string("+"), tokens[3]); + CPPUNIT_ASSERT_EQUAL(std::string("1.23"), tokens[4]); + CPPUNIT_ASSERT_EQUAL(std::string("-"), tokens[5]); + CPPUNIT_ASSERT_EQUAL(std::string("bam"), tokens[6]); + } + + void testTokenize_String() { + std::vector<std::string> tokens = Lua::tokenize(" foo .. \"1234\\\"bla blo\""); + + CPPUNIT_ASSERT_EQUAL(3, static_cast<int>(tokens.size())); + CPPUNIT_ASSERT_EQUAL(std::string("foo"), tokens[0]); + CPPUNIT_ASSERT_EQUAL(std::string(".."), tokens[1]); + CPPUNIT_ASSERT_EQUAL(std::string("\"1234\\\"bla blo\""), tokens[2]); + } + + void testTokenize_IncompleteString() { + std::vector<std::string> tokens = Lua::tokenize("\"1234"); + + CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(tokens.size())); + CPPUNIT_ASSERT_EQUAL(std::string("\"1234"), tokens[0]); + } + + void testTokenize_Identifier() { + std::vector<std::string> tokens = Lua::tokenize("foo.bar_baz"); + + CPPUNIT_ASSERT_EQUAL(3, static_cast<int>(tokens.size())); + CPPUNIT_ASSERT_EQUAL(std::string("foo"), tokens[0]); + CPPUNIT_ASSERT_EQUAL(std::string("."), tokens[1]); + CPPUNIT_ASSERT_EQUAL(std::string("bar_baz"), tokens[2]); + } + +}; + +CPPUNIT_TEST_SUITE_REGISTRATION(TokenizeTest); diff --git a/Sluift/Watchdog.cpp b/Sluift/Watchdog.cpp new file mode 100644 index 0000000..a99d63a --- /dev/null +++ b/Sluift/Watchdog.cpp @@ -0,0 +1,50 @@ +/* + * Copyright (c) 2014 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Sluift/Watchdog.h> + +#include <Sluift/globals.h> + +static const int INTERVAL_MS = 500; + + +using namespace Swift; + +Watchdog::Watchdog(int timeout, TimerFactory* timerFactory) : + remainingTime(timeout), + timerFactory(timerFactory), + timedOut(false) { + Sluift::globals.interruptRequested = 0; + + int nextTimeout = remainingTime >= 0 ? std::min(remainingTime, INTERVAL_MS) : INTERVAL_MS; + + timer = timerFactory->createTimer(nextTimeout); + timer->onTick.connect(boost::bind(&Watchdog::handleTimerTick, this)); + remainingTime -= nextTimeout; + timer->start(); +} + +Watchdog::~Watchdog() { + if (timer) { + timer->stop(); + } +} + +void Watchdog::handleTimerTick() { + if (Sluift::globals.interruptRequested || remainingTime == 0) { + timedOut = true; + } + else { + int nextTimeout = remainingTime >= 0 ? std::min(remainingTime, INTERVAL_MS) : INTERVAL_MS; + if (nextTimeout != INTERVAL_MS) { + timer->onTick.disconnect(boost::bind(&Watchdog::handleTimerTick, this)); + timer = timerFactory->createTimer(nextTimeout); + timer->onTick.connect(boost::bind(&Watchdog::handleTimerTick, this)); + } + remainingTime -= nextTimeout; + timer->start(); + } +} diff --git a/Sluift/Watchdog.h b/Sluift/Watchdog.h index 95b6971..271c610 100644 --- a/Sluift/Watchdog.h +++ b/Sluift/Watchdog.h @@ -1,44 +1,32 @@ /* - * Copyright (c) 2011 Remko Tronçon - * Licensed under the GNU General Public License v3. - * See Documentation/Licenses/GPLv3.txt for more information. + * Copyright (c) 2011-2014 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once +#include <algorithm> + #include <Swiften/Network/TimerFactory.h> namespace Swift { - class Watchdog { - public: - Watchdog(int timeout, TimerFactory* timerFactory) : timedOut(false) { - if (timeout > 0) { - timer = timerFactory->createTimer(timeout); - timer->start(); - timer->onTick.connect(boost::bind(&Watchdog::handleTimerTick, this)); - } - else if (timeout == 0) { - timedOut = true; - } - } - - ~Watchdog() { - if (timer) { - timer->stop(); - } - } + class Watchdog { + public: + Watchdog(int timeout, TimerFactory* timerFactory); + ~Watchdog(); - bool getTimedOut() const { - return timedOut; - } + bool getTimedOut() const { + return timedOut; + } - private: - void handleTimerTick() { - timedOut = true; - } + private: + void handleTimerTick(); - private: - Timer::ref timer; - bool timedOut; - }; + private: + Timer::ref timer; + int remainingTime; + TimerFactory* timerFactory; + bool timedOut; + }; } diff --git a/Sluift/boot.lua b/Sluift/boot.lua deleted file mode 100644 index 2505736..0000000 --- a/Sluift/boot.lua +++ /dev/null @@ -1,436 +0,0 @@ ---[[ - Copyright (c) 2013 Remko Tronçon - Licensed under the GNU General Public License. - See the COPYING file for more information. ---]] - -local Client = {} -local PubSub = {} -local PubSubNode = {} - --------------------------------------------------------------------------------- --- Utility methods --------------------------------------------------------------------------------- - -local function merge_tables(...) - local result = {} - for _, table in ipairs({...}) do - for k, v in pairs(table) do - result[k] = v - end - end - return result -end - -local function clone_table(table) - return merge_tables(table) -end - -local function parse_options(unnamed_parameters, arg1, arg2) - local options = {} - if type(arg1) == 'table' then - options = arg1 - f = arg2 - elseif type(arg1) == 'function' then - f = arg1 - end - options.f = f or options.f - return clone_table(options) -end - - -local function table_value_tostring(value) - local result = tostring(value) - if type(value) == 'number' then return result - elseif type(value) == 'boolean' then return result - elseif type(value) == 'string' then return "'" .. result .. "'" - else return '<' .. result .. '>' - end -end - -local function table_tostring(table, indent, accumulator) - local INDENT = ' ' - local accumulator = accumulator or '' - local indent = indent or '' - accumulator = accumulator .. '{' - local is_first = true - for key, value in pairs(table) do - if type(value) ~= 'function' then - if not is_first then - accumulator = accumulator .. ',' - end - is_first = false - accumulator = accumulator .. '\n' .. indent .. INDENT .. '[' .. table_value_tostring(key) .. '] = ' - if type(value) == 'table' then - accumulator = table_tostring(value, indent .. INDENT, accumulator) - else - accumulator = accumulator .. table_value_tostring(value) - end - end - end - if not is_first then - accumulator = accumulator .. '\n' .. indent - end - accumulator = accumulator .. '}' - return accumulator -end - -local function tprint(table) - print(table_tostring(table)) -end - -local function register_table_tostring(table) - if type(table) == 'table' then - local metatable = getmetatable(table) - if not metatable then - metatable = {} - setmetatable(table, metatable) - end - metatable.__tostring = table_tostring - end - return table -end - -local function get_by_type(table, typ) - for _, v in ipairs(table) do - if v['_type'] == typ then - return v - end - end -end - -local function register_get_by_type_index(table) - if type(table) == 'table' then - local metatable = getmetatable(table) - if not metatable then - metatable = {} - setmetatable(table, metatable) - end - metatable.__index = get_by_type - end - return table -end - --------------------------------------------------------------------------------- --- Client --------------------------------------------------------------------------------- - -function Client.connect (client, ...) - local options = parse_options({}, ...) - local f = options.f - client:async_connect(options) - client:wait_connected() - if f then - local result = { xpcall(function() return f(client) end, debug.traceback) } - client:disconnect() - if result[1] then - table.remove(result, 1) - return unpack(result) - else - error(result[2]) - end - end - return true -end - -function Client.events (client, options) - local function client_events_iterator(s) - return s['client']:get_next_event(s['options']) - end - return client_events_iterator, {client = client, options = options} -end - -function Client.for_each_event (client, ...) - local options = parse_options({}, ...) - if not type(options.f) == 'function' then error('Expected function') end - for event in client:events(options) do - local result = options.f(event) - if result then - return result - end - end -end - -for method, event_type in pairs({message = 'message', presence = 'presence', pubsub_event = 'pubsub'}) do - Client['for_each_' .. method] = function (client, ...) - local options = parse_options({}, ...) - options['type'] = event_type - return client:for_each_event (options) - end - - Client['get_next_' .. method] = function (client, ...) - local options = parse_options({}, ...) - options['type'] = event_type - return client:get_next_event(options) - end -end - -for method, event_type in pairs({messages = 'message', pubsub_events = 'pubsub'}) do - Client[method] = function (client, ...) - local options = parse_options({}, ...) - options['type'] = event_type - return client:events (options) - end -end - --- --- Register get_* and set_* convenience methods for some type of queries --- --- Example usages: --- client:get_software_version{to = 'alice@wonderland.lit'} --- client:set_command{to = 'alice@wonderland.lit', command = { type = 'execute', node = 'uptime' }} --- -local get_set_shortcuts = { - get = {'software_version', 'disco_items', 'xml', 'dom', 'vcard'}, - set = {'command'} -} -for query_action, query_types in pairs(get_set_shortcuts) do - for _, query_type in ipairs(query_types) do - Client[query_action .. '_' .. query_type] = function (client, options) - options = options or {} - if type(options) ~= 'table' then error('Invalid options: ' .. options) end - options['query'] = merge_tables({_type = query_type}, options[query_type] or {}) - return client[query_action](client, options) - end - end -end - -function Client.pubsub (client, jid) - local result = { client = client, jid = jid } - setmetatable(result, PubSub) - return result -end - --------------------------------------------------------------------------------- --- PubSub --------------------------------------------------------------------------------- - -PubSub.__index = PubSub - -local function process_pubsub_event (event) - if event._type == 'pubsub_event_items' then - -- Add 'item' shortcut to payload of first item - event.item = event.items and event.items[1] and - event.items[1].data and event.items[1].data[1] - end -end - -function PubSub.list_nodes (service, options) - return service.client:get_disco_items(merge_tables({to = service.jid}, options)) -end - -function PubSub.node (service, node) - local result = { client = service.client, jid = service.jid, node = node } - setmetatable(result, PubSubNode) - return result -end - -local simple_pubsub_queries = { - get_default_configuration = 'pubsub_owner_default', - get_subscriptions = 'pubsub_subscriptions', - get_affiliations = 'pubsub_affiliations', - get_default_subscription_options = 'pubsub_default', -} -for method, query_type in pairs(simple_pubsub_queries) do - PubSub[method] = function (service, options) - options = options or {} - return service.client:query_pubsub(merge_tables( - { type = 'get', to = service.jid, query = { _type = query_type } }, - options)) - end -end - -for _, method in ipairs({'events', 'get_next_event', 'for_each_event'}) do - PubSub[method] = function (node, ...) - local options = parse_options({}, ...) - options['if'] = function (event) - return event.type == 'pubsub' and event.from == node.jid and event.node == node - end - return node.client[method](node.client, options) - end -end - --------------------------------------------------------------------------------- --- PubSubNode --------------------------------------------------------------------------------- - -PubSubNode.__index = PubSubNode - -local function pubsub_node_configuration_to_form(configuration) - if not configuration then - return - end - local fields = { {name = 'form_type', value = 'http://jabber.org/protocol/pubsub#node_config'} } - for var, value in pairs(configuration) do - fields[#fields+1] = { name = var, value = value } - end - return { type = "submit", fields = fields } -end - -function PubSubNode.list_items (node, options) - return node.client:get_disco_items(merge_tables({to = node.jid, query = { node = node.node }}, options)) -end - -local simple_pubsub_node_queries = { - get_configuration = 'pubsub_owner_configure', - get_subscriptions = 'pubsub_subscriptions', - get_affiliations = 'pubsub_affiliations', - get_default_subscription_options = 'pubsub_default', -} -for method, query_type in pairs(simple_pubsub_node_queries) do - PubSubNode[method] = function (node, options) - return node.client:query_pubsub(merge_tables({ - type = 'get', to = node.jid, query = { - _type = query_type, node = node.node - }}, options)) - end -end - -function PubSubNode.get_items (node, ...) - local options = parse_options({}, ...) - local items = options.items or {} - if options.maximum_items then - items = merge_tables({maximum_items = options.maximum_items}, items) - end - items = merge_tables({_type = 'pubsub_items', node = node.node}, items) - return node.client:query_pubsub(merge_tables({ - type = 'get', to = node.jid, query = items}, options)) -end - -function PubSubNode.get_item (node, ...) - local options = parse_options({}, ...) - if not type(options.id) == 'string' then error('Expected ID') end - return PubSubNode.get_items(node, {items = {{id = options.id}}}) -end - -function PubSubNode.create (node, options) - options = options or {} - local configure - if options['configuration'] then - configure = { data = pubsub_node_configuration_to_form(options['configuration']) } - end - return node.client:query_pubsub(merge_tables( - { type = 'set', to = node.jid, query = { - _type = 'pubsub_create', node = node.node, configure = configure } - }, options)) -end - -function PubSubNode.delete (node, options) - options = options or {} - local redirect - if options['redirect'] then - redirect = {uri = options['redirect']} - end - return node.client:query_pubsub(merge_tables({ type = 'set', to = node.jid, query = { - _type = 'pubsub_owner_delete', node = node.node, redirect = redirect - }}, options)) -end - -function PubSubNode.set_configuration(node, options) - options = options or {} - local configuration = pubsub_node_configuration_to_form(options['configuration']) - return node.client:query_pubsub(merge_tables( - { type = 'set', to = node.jid, query = { - _type = 'pubsub_owner_configure', node = node.node, data = configuration } - }, options)) -end - -function PubSubNode.subscribe(node, ...) - local options = parse_options(...) - local jid = options.jid or sluift.jid.to_bare(node.client:jid()) - return node.client:query_pubsub(merge_tables( - { type = 'set', to = node.jid, query = { - _type = 'pubsub_subscribe', node = node.node, jid = jid } - }, options)) -end - -function PubSubNode.unsubscribe(node, options) - options = options or {} - return node.client:query_pubsub(merge_tables( - { type = 'set', to = node.jid, query = { - _type = 'pubsub_unsubscribe', node = node.node, jid = options['jid'] } - }, options)) -end - -function PubSubNode.get_subscription_options (node, options) - return node.client:query_pubsub(merge_tables( - { type = 'get', to = node.jid, query = { - _type = 'pubsub_options', node = node.node, jid = options['jid'] } - }, options)) -end - -function PubSubNode.publish(node, ...) - local options = parse_options({}, ...) - local items = options.items or {} - if options.item then - if type(options.item) == 'string' or options.item._type then - items = {{id = options.id, data = { options.item } }} - options.id = nil - else - items = { options.item } - end - options.item = nil - end - return node.client:query_pubsub(merge_tables( - { type = 'set', to = node.jid, query = { - _type = 'pubsub_publish', node = node.node, items = items } - }, options)) -end - -function PubSubNode.retract(node, ...) - local options = parse_options({}, ...) - local items = options.items - if options.id then - items = {{id = options.id}} - end - return node.client:query_pubsub(merge_tables( - { type = 'set', to = node.jid, query = { - _type = 'pubsub_retract', node = node.node, items = items, notify = options['notify'] - }}, options)) -end - -function PubSubNode.purge(node, ...) - local options = parse_options({}, ...) - return node.client:query_pubsub(merge_tables( - { type = 'set', to = node.jid, query = { - _type = 'pubsub_owner_purge', node = node.node - }}, options)) -end - --- Iterators over events -for _, method in ipairs({'events', 'get_next_event', 'for_each_event'}) do - PubSubNode[method] = function (node, ...) - local options = parse_options({}, ...) - options['if'] = function (event) - return event.type == 'pubsub' and event.from == node.jid and event.node == node.node - end - return node.client[method](node.client, options) - end -end - --------------------------------------------------------------------------------- --- Service discovery --------------------------------------------------------------------------------- - -local disco = { - features = { - DISCO_INFO = 'http://jabber.org/protocol/disco#info', - COMMANDS = 'http://jabber.org/protocol/commands', - USER_LOCATION = 'http://jabber.org/protocol/geoloc', - USER_TUNE = 'http://jabber.org/protocol/tune', - USER_AVATAR_METADATA = 'urn:xmpp:avatar:metadata', - USER_ACTIVITY = 'http://jabber.org/protocol/activity', - USER_PROFILE = 'urn:xmpp:tmp:profile' - } -} - --------------------------------------------------------------------------------- - -return { - Client = Client, - register_table_tostring = register_table_tostring, - register_get_by_type_index = register_get_by_type_index, - process_pubsub_event = process_pubsub_event, - tprint = tprint, - disco = disco, -} diff --git a/Sluift/client.cpp b/Sluift/client.cpp index df43075..814ad45 100644 --- a/Sluift/client.cpp +++ b/Sluift/client.cpp @@ -1,564 +1,899 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013-2018 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ -#include <boost/lambda/lambda.hpp> -#include <boost/lambda/bind.hpp> #include <boost/assign/list_of.hpp> -#include <iostream> -#include <Sluift/SluiftClient.h> -#include <Swiften/JID/JID.h> -#include <Swiften/Elements/SoftwareVersion.h> +#include <Swiften/Base/IDGenerator.h> +#include <Swiften/Disco/ClientDiscoManager.h> +#include <Swiften/Elements/DiscoInfo.h> #include <Swiften/Elements/Message.h> #include <Swiften/Elements/Presence.h> #include <Swiften/Elements/RawXMLPayload.h> #include <Swiften/Elements/RosterItemPayload.h> #include <Swiften/Elements/RosterPayload.h> -#include <Swiften/Elements/DiscoInfo.h> -#include <Swiften/Disco/ClientDiscoManager.h> -#include <Swiften/Queries/GenericRequest.h> +#include <Swiften/Elements/SoftwareVersion.h> +#include <Swiften/JID/JID.h> #include <Swiften/Presence/PresenceSender.h> -#include <Swiften/Roster/XMPPRoster.h> -#include <Swiften/Roster/SetRosterRequest.h> #include <Swiften/Presence/SubscriptionManager.h> -#include <Swiften/Roster/XMPPRosterItem.h> -#include <Sluift/Watchdog.h> +#include <Swiften/Queries/GenericRequest.h> +#include <Swiften/Queries/IQRouter.h> #include <Swiften/Queries/Requests/GetSoftwareVersionRequest.h> -#include <Sluift/Lua/FunctionRegistration.h> -#include <Swiften/Base/foreach.h> +#include <Swiften/Roster/SetRosterRequest.h> +#include <Swiften/Roster/XMPPRoster.h> +#include <Swiften/Roster/XMPPRosterItem.h> +#include <Swiften/TLS/PKCS12Certificate.h> + +#include <Sluift/ElementConvertors/IQConvertor.h> +#include <Sluift/ElementConvertors/MessageConvertor.h> +#include <Sluift/ElementConvertors/PresenceConvertor.h> +#include <Sluift/ElementConvertors/StanzaConvertor.h> +#include <Sluift/ElementConvertors/StatusShowConvertor.h> #include <Sluift/Lua/Check.h> -#include <Sluift/Lua/Value.h> #include <Sluift/Lua/Exception.h> +#include <Sluift/Lua/FunctionRegistration.h> #include <Sluift/Lua/LuaUtils.h> +#include <Sluift/Lua/Value.h> +#include <Sluift/SluiftClient.h> #include <Sluift/globals.h> using namespace Swift; -namespace lambda = boost::lambda; - -static const std::string SLUIFT_CLIENT = Lua::FunctionRegistry::getMetaTableNameForType("Client"); static inline SluiftClient* getClient(lua_State* L) { - return *Lua::checkUserData<SluiftClient>(L, 1, SLUIFT_CLIENT.c_str()); + return *Lua::checkUserData<SluiftClient>(L, 1); +} + +static inline int getGlobalTimeout(lua_State* L) { + lua_rawgeti(L, LUA_REGISTRYINDEX, Sluift::globals.moduleLibIndex); + lua_getfield(L, -1, "timeout"); + int result = boost::numeric_cast<int>(lua_tointeger(L, -1)); + lua_pop(L, 2); + return result; +} + +static void addPayloadsToTable(lua_State* L, const std::vector<std::shared_ptr<Payload> >& payloads) { + if (!payloads.empty()) { + lua_createtable(L, boost::numeric_cast<int>(payloads.size()), 0); + for (size_t i = 0; i < payloads.size(); ++i) { + Sluift::globals.elementConvertor.convertToLua(L, payloads[i]); + lua_rawseti(L, -2, boost::numeric_cast<int>(i+1)); + } + Lua::registerGetByTypeIndex(L, -1); + lua_setfield(L, -2, "payloads"); + } +} + +static std::shared_ptr<Payload> getPayload(lua_State* L, int index) { + if (lua_type(L, index) == LUA_TTABLE) { + return std::dynamic_pointer_cast<Payload>(Sluift::globals.elementConvertor.convertFromLua(L, index)); + } + else if (lua_type(L, index) == LUA_TSTRING) { + return std::make_shared<RawXMLPayload>(Lua::checkString(L, index)); + } + else { + return std::shared_ptr<Payload>(); + } +} + +static std::vector< std::shared_ptr<Payload> > getPayloadsFromTable(lua_State* L, int index) { + index = Lua::absoluteOffset(L, index); + std::vector< std::shared_ptr<Payload> > result; + lua_getfield(L, index, "payloads"); + if (lua_istable(L, -1)) { + for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) { + std::shared_ptr<Payload> payload = getPayload(L, -1); + if (payload) { + result.push_back(payload); + } + } + } + lua_pop(L, 1); + return result; +} + +static void setOptions(lua_State* L, SluiftClient* client) { + Lua::checkType(L, 2, LUA_TTABLE); + lua_getfield(L, 2, "host"); + if (!lua_isnil(L, -1)) { + client->getOptions().manualHostname = lua_tostring(L, -1); + } + lua_getfield(L, 2, "port"); + if (!lua_isnil(L, -1)) { + client->getOptions().manualPort = boost::numeric_cast<int>(lua_tointeger(L, -1)); + } + lua_getfield(L, 2, "ack"); + if (!lua_isnil(L, -1)) { + client->getOptions().useAcks = lua_toboolean(L, -1); + } + lua_getfield(L, 2, "compress"); + if (!lua_isnil(L, -1)) { + client->getOptions().useStreamCompression = lua_toboolean(L, -1); + } + lua_getfield(L, 2, "tls"); + if (!lua_isnil(L, -1)) { + bool useTLS = lua_toboolean(L, -1); + client->getOptions().useTLS = (useTLS ? ClientOptions::UseTLSWhenAvailable : ClientOptions::NeverUseTLS); + } + lua_getfield(L, 2, "bosh_url"); + if (!lua_isnil(L, -1)) { + client->getOptions().boshURL = URL::fromString(lua_tostring(L, -1)); + } + lua_getfield(L, 2, "allow_plain_without_tls"); + if (!lua_isnil(L, -1)) { + client->getOptions().allowPLAINWithoutTLS = lua_toboolean(L, -1); + } + lua_pushvalue(L, 1); } + SLUIFT_LUA_FUNCTION(Client, async_connect) { - SluiftClient* client = getClient(L); - - std::string host; - if (lua_istable(L, 2)) { - if (boost::optional<std::string> hostString = Lua::getStringField(L, 2, "host")) { - host = *hostString; - } - } - if (host.empty()) { - client->connect(); - } - else { - client->connect(host); - } - return 0; -} - -SLUIFT_LUA_FUNCTION(Client, wait_connected) { - getClient(L)->waitConnected(); - return 0; -} - -SLUIFT_LUA_FUNCTION(Client, is_connected) { - lua_pushboolean(L, getClient(L)->isConnected()); - return 1; -} - -SLUIFT_LUA_FUNCTION(Client, disconnect) { - getClient(L)->disconnect(); - return 0; -} - -SLUIFT_LUA_FUNCTION(Client, set_version) { - Sluift::globals.eventLoop.runOnce(); - SluiftClient* client = getClient(L); - if (boost::shared_ptr<SoftwareVersion> version = boost::dynamic_pointer_cast<SoftwareVersion>(Sluift::globals.elementConvertor.convertFromLuaUntyped(L, 2, "software_version"))) { - client->setSoftwareVersion(version->getName(), version->getVersion(), version->getOS()); - } - return 0; -} - -SLUIFT_LUA_FUNCTION(Client, get_contacts) { - Sluift::globals.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::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); - Lua::registerTableToString(L, -1); - return 1; -} - -SLUIFT_LUA_FUNCTION(Client, send_message) { - Sluift::globals.eventLoop.runOnce(); - JID to; - std::string body; - int index = 2; - Message::Type type = Message::Chat; - if (lua_isstring(L, index)) { - to = std::string(lua_tostring(L, index)); - ++index; - if (!lua_isstring(L, index)) { - std::string body = lua_tostring(L, index); - ++index; - } - } - if (lua_istable(L, index)) { - if (boost::optional<std::string> value = Lua::getStringField(L, index, "to")) { - to = *value; - } - - if (boost::optional<std::string> value = Lua::getStringField(L, index, "body")) { - body = *value; - } - - if (boost::optional<std::string> value = Lua::getStringField(L, index, "type")) { - if (*value == "normal") { - type = Message::Normal; - } - else if (*value == "chat") { - type = Message::Chat; - } - else if (*value == "error") { - type = Message::Error; - } - else if (*value == "groupchat") { - type = Message::Groupchat; - } - else if (*value == "headline") { - type = Message::Headline; - } - } - } - - if (!to.isValid()) { - throw Lua::Exception("Missing 'to'"); - } - if (body.empty()) { - throw Lua::Exception("Missing 'body'"); - } - - Message::ref message = boost::make_shared<Message>(); - message->setTo(to); - message->setBody(body); - message->setType(type); - getClient(L)->getClient()->sendMessage(message); - return 0; -} - -SLUIFT_LUA_FUNCTION(Client, send_presence) { - Sluift::globals.eventLoop.runOnce(); - boost::shared_ptr<Presence> presence = boost::make_shared<Presence>(); - - int index = 2; - if (lua_isstring(L, index)) { - presence->setStatus(lua_tostring(L, index)); - ++index; - } - if (lua_istable(L, index)) { - if (boost::optional<std::string> value = Lua::getStringField(L, index, "to")) { - presence->setTo(*value); - } - if (boost::optional<std::string> value = Lua::getStringField(L, index, "status")) { - presence->setStatus(*value); - } - if (boost::optional<int> value = Lua::getIntField(L, index, "priority")) { - presence->setPriority(*value); - } - if (boost::optional<std::string> value = Lua::getStringField(L, index, "type")) { - if (*value == "available") { - presence->setType(Presence::Available); - } - else if (*value == "error") { - presence->setType(Presence::Error); - } - else if (*value == "probe") { - presence->setType(Presence::Probe); - } - else if (*value == "subscribe") { - presence->setType(Presence::Subscribe); - } - else if (*value == "subscribed") { - presence->setType(Presence::Subscribed); - } - else if (*value == "unavailable") { - presence->setType(Presence::Unavailable); - } - else if (*value == "unsubscribe") { - presence->setType(Presence::Unsubscribe); - } - else if (*value == "unsubscribed") { - presence->setType(Presence::Unsubscribed); - } - } - } - - getClient(L)->getClient()->getPresenceSender()->sendPresence(presence); - lua_pushvalue(L, 1); - return 0; + SluiftClient* client = getClient(L); + setOptions(L, client); + client->connect(); + return 0; +} + +SLUIFT_LUA_FUNCTION_WITH_HELP( + Client, set_trace_enabled, + "Enable/disable tracing of the data sent/received.\n\n.", + "self\n" + "enable a boolean specifying whether to enable/disable tracing", + "" +) { + getClient(L)->setTraceEnabled(lua_toboolean(L, 1)); + return 0; +} + +SLUIFT_LUA_FUNCTION_WITH_HELP( + Client, wait_connected, + "Block until the client is connected.\n\nThis is useful after an `async_connect`.", + "self", + "" +) { + getClient(L)->waitConnected(getGlobalTimeout(L)); + return 0; +} + +SLUIFT_LUA_FUNCTION_WITH_HELP( + Client, is_connected, + "Checks whether this client is still connected.\n\nReturns a boolean.", + "self\n", + "" +) { + lua_pushboolean(L, getClient(L)->isConnected()); + return 1; +} + +SLUIFT_LUA_FUNCTION_WITH_HELP( + Client, disconnect, + "Disconnect from the server", + "self\n", + "" +) { + Sluift::globals.eventLoop.runOnce(); + getClient(L)->disconnect(); + return 0; +} + +SLUIFT_LUA_FUNCTION_WITH_HELP( + Client, set_version, + + "Sets the published version of this client.", + + "self", + + "name the name of the client software\n" + "version the version identifier of this client\n" + "os the OS this client is running on\n" +) { + Sluift::globals.eventLoop.runOnce(); + SluiftClient* client = getClient(L); + if (std::shared_ptr<SoftwareVersion> version = std::dynamic_pointer_cast<SoftwareVersion>(Sluift::globals.elementConvertor.convertFromLuaUntyped(L, 2, "software_version"))) { + client->setSoftwareVersion(version->getName(), version->getVersion(), version->getOS()); + } + return 0; +} + +SLUIFT_LUA_FUNCTION_WITH_HELP( + Client, get_contacts, + "Returns a table of all the contacts in the contact list.", + "self\n", + "" +) { + Sluift::globals.eventLoop.runOnce(); + + SluiftClient* client = getClient(L); + Lua::Table contactsTable; + for (const auto& item : client->getRoster(getGlobalTimeout(L))) { + 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::Table itemTable = boost::assign::map_list_of + ("jid", std::make_shared<Lua::Value>(item.getJID().toString())) + ("name", std::make_shared<Lua::Value>(item.getName())) + ("subscription", std::make_shared<Lua::Value>(subscription)) + ("groups", std::make_shared<Lua::Value>(std::vector<Lua::Value>(item.getGroups().begin(), item.getGroups().end()))); + contactsTable[item.getJID().toString()] = std::make_shared<Lua::Value>(itemTable); + } + pushValue(L, contactsTable); + Lua::registerTableToString(L, -1); + return 1; +} + +SLUIFT_LUA_FUNCTION_WITH_HELP( + Client, get_block_list, + "Returns a table of all the items in the blocking list.", + "self\n", + "" +) { + Sluift::globals.eventLoop.runOnce(); + SluiftClient* client = getClient(L); + lua_newtable(L); + int i = 0; + for (const auto& item : client->getBlockList(getGlobalTimeout(L))) { + lua_pushstring(L, item.toString().c_str()); + lua_rawseti(L, -2, boost::numeric_cast<int>(++i)); + } + Lua::registerTableToString(L, -1); + return 1; +} + +SLUIFT_LUA_FUNCTION_WITH_HELP( + Client, add_block, + "Adds a user or domain to the blocking list.", + "self\n", + "jid the JID of the user or domain to add to the blocking list\n" + +) { + SluiftClient* client = getClient(L); + JID jid(Lua::checkString(L, 2)); + int timeout = getGlobalTimeout(L); + + std::shared_ptr<BlockPayload> payload = std::make_shared<BlockPayload>(std::vector<JID>(1, jid)); + return client->sendRequest( + std::make_shared< GenericRequest<BlockPayload> >(IQ::Set, JID(), payload, client->getClient()->getIQRouter()), timeout).convertToLuaResult(L); +} + +SLUIFT_LUA_FUNCTION_WITH_HELP( + Client, remove_block, + "Removes a user or domain from the blocking list.", + "self\n", + "jid the JID of the user or domain to remove from the blocking list\n" + +) { + SluiftClient* client = getClient(L); + JID jid(Lua::checkString(L, 2)); + int timeout = getGlobalTimeout(L); + + std::shared_ptr<UnblockPayload> payload = std::make_shared<UnblockPayload>(std::vector<JID>(1, jid)); + return client->sendRequest( + std::make_shared< GenericRequest<UnblockPayload> >(IQ::Set, JID(), payload, client->getClient()->getIQRouter()), timeout).convertToLuaResult(L); +} + +SLUIFT_LUA_FUNCTION_WITH_HELP( + Client, remove_all_block, + "Removes all users and domains from the blocking list.", + "self\n", + "" +) { + SluiftClient* client = getClient(L); + int timeout = getGlobalTimeout(L); + + std::shared_ptr<UnblockPayload> payload = std::make_shared<UnblockPayload>(std::vector<JID>()); + return client->sendRequest( + std::make_shared< GenericRequest<UnblockPayload> >(IQ::Set, JID(), payload, client->getClient()->getIQRouter()), timeout).convertToLuaResult(L); +} + +SLUIFT_LUA_FUNCTION_WITH_HELP( + Client, send_message, + "Send a message.", + "self\n" + "to the JID to send the message to\n" + "body the body of the message. Can alternatively be specified using the `body` option\n", + + "to the JID to send the message to\n" + "id the id to set on the stanza\n" + "body the body of the message\n" + "subject the subject of the MUC room to set\n" + "type the type of message to send (`normal`, `chat`, `error`, `groupchat`, `headline`)\n" + "payloads payloads to add to the message\n" +) { + Sluift::globals.eventLoop.runOnce(); + JID to; + boost::optional<std::string> body; + boost::optional<std::string> id; + boost::optional<std::string> subject; + std::vector<std::shared_ptr<Payload> > payloads; + int index = 2; + Message::Type type = Message::Chat; + if (lua_isstring(L, index)) { + to = std::string(lua_tostring(L, index)); + ++index; + if (lua_isstring(L, index)) { + body = lua_tostring(L, index); + ++index; + } + } + if (lua_istable(L, index)) { + if (boost::optional<std::string> value = Lua::getStringField(L, index, "to")) { + to = *value; + } + + if (boost::optional<std::string> value = Lua::getStringField(L, index, "id")) { + id = value; + } + + if (boost::optional<std::string> value = Lua::getStringField(L, index, "body")) { + body = value; + } + + if (boost::optional<std::string> value = Lua::getStringField(L, index, "type")) { + type = MessageConvertor::convertMessageTypeFromString(*value); + } + + if (boost::optional<std::string> value = Lua::getStringField(L, index, "subject")) { + subject = value; + } + + payloads = getPayloadsFromTable(L, index); + } + + if (!to.isValid()) { + throw Lua::Exception("Missing 'to'"); + } + if ((!body || body->empty()) && !subject && payloads.empty()) { + throw Lua::Exception("Missing any of 'body', 'subject' or 'payloads'"); + } + Message::ref message = std::make_shared<Message>(); + message->setTo(to); + if (body && !body->empty()) { + message->setBody(*body); + } + if (id) { + message->setID(*id); + } + if (subject) { + message->setSubject(*subject); + } + message->addPayloads(payloads.begin(), payloads.end()); + message->setType(type); + if (!getClient(L)->getClient()->isAvailable()) { + throw Lua::Exception("Trying to send message while client is offline."); + } + getClient(L)->getClient()->sendMessage(message); + return 0; +} + +SLUIFT_LUA_FUNCTION_WITH_HELP( + Client, send_presence, + "Send presence.", + + "self\n" + "body the text of the presence. Can alternatively be specified using the `status` option\n", + + "to the JID to send the presence to\n" + "id the id to set on the stanza\n" + "status the text of the presence\n" + "show the availability of the presence (`online`, `ffc`, `away`, `xa`, `dnd`)\n" + "priority the priority of the presence\n" + "type the type of message to send (`available`, `error`, `probe`, `subscribe`, `subscribed`, `unavailable`, `unsubscribe`, `unsubscribed`)\n" + "payloads payloads to add to the presence\n" +) { + Sluift::globals.eventLoop.runOnce(); + std::shared_ptr<Presence> presence = std::make_shared<Presence>(); + + int index = 2; + if (lua_isstring(L, index)) { + presence->setStatus(lua_tostring(L, index)); + ++index; + } + if (lua_istable(L, index)) { + if (boost::optional<std::string> value = Lua::getStringField(L, index, "to")) { + presence->setTo(*value); + } + if (boost::optional<std::string> id = Lua::getStringField(L, index, "id")) { + presence->setID(*id); + } + if (boost::optional<std::string> value = Lua::getStringField(L, index, "status")) { + presence->setStatus(*value); + } + if (boost::optional<int> value = Lua::getIntField(L, index, "priority")) { + presence->setPriority(*value); + } + if (boost::optional<std::string> value = Lua::getStringField(L, index, "type")) { + presence->setType(PresenceConvertor::convertPresenceTypeFromString(*value)); + } + if (boost::optional<std::string> value = Lua::getStringField(L, index, "show")) { + presence->setShow(StatusShowConvertor::convertStatusShowTypeFromString(*value)); + } + std::vector< std::shared_ptr<Payload> > payloads = getPayloadsFromTable(L, index); + presence->addPayloads(payloads.begin(), payloads.end()); + } + if (!getClient(L)->getClient()->getPresenceSender()->isAvailable()) { + throw Lua::Exception("Trying to send presence while client is offline."); + } + getClient(L)->getClient()->getPresenceSender()->sendPresence(presence); + lua_pushvalue(L, 1); + return 0; } static int sendQuery(lua_State* L, IQ::Type type) { - SluiftClient* client = getClient(L); + SluiftClient* client = getClient(L); - JID to; - if (boost::optional<std::string> toString = Lua::getStringField(L, 2, "to")) { - to = JID(*toString); - } + JID to; + if (boost::optional<std::string> toString = Lua::getStringField(L, 2, "to")) { + to = JID(*toString); + } - int timeout = Sluift::globals.timeout; - if (boost::optional<int> timeoutInt = Lua::getIntField(L, 2, "timeout")) { - timeout = *timeoutInt; - } + int timeout = getGlobalTimeout(L); + if (boost::optional<int> timeoutInt = Lua::getIntField(L, 2, "timeout")) { + timeout = *timeoutInt; + } - boost::shared_ptr<Payload> payload; - lua_getfield(L, 2, "query"); - if (lua_type(L, -1) == LUA_TTABLE) { - payload = Sluift::globals.elementConvertor.convertFromLua(L, -1); - } - else if (lua_type(L, -1) == LUA_TSTRING) { - payload = boost::make_shared<RawXMLPayload>(Lua::checkString(L, -1)); - } - lua_pop(L, 1); + std::shared_ptr<Payload> payload; + lua_getfield(L, 2, "query"); + payload = getPayload(L, -1); + lua_pop(L, 1); - return client->sendRequest( - boost::make_shared< GenericRequest<Payload> >(type, to, payload, client->getClient()->getIQRouter()), timeout).convertToLuaResult(L); + return client->sendRequest( + std::make_shared< GenericRequest<Payload> >(type, to, payload, client->getClient()->getIQRouter()), timeout).convertToLuaResult(L); } #define DISPATCH_PUBSUB_PAYLOAD(payloadType, container, response) \ - else if (boost::shared_ptr<payloadType> p = boost::dynamic_pointer_cast<payloadType>(payload)) { \ - return client->sendPubSubRequest(type, to, p, timeout).convertToLuaResult(L); \ - } + else if (std::shared_ptr<payloadType> p = std::dynamic_pointer_cast<payloadType>(payload)) { \ + return client->sendPubSubRequest(type, to, p, timeout).convertToLuaResult(L); \ + } SLUIFT_LUA_FUNCTION(Client, query_pubsub) { - SluiftClient* client = getClient(L); - - JID to; - if (boost::optional<std::string> toString = Lua::getStringField(L, 2, "to")) { - to = JID(*toString); - } - - int timeout = Sluift::globals.timeout; - if (boost::optional<int> timeoutInt = Lua::getIntField(L, 2, "timeout")) { - timeout = *timeoutInt; - } - - IQ::Type type; - if (boost::optional<std::string> queryType = Lua::getStringField(L, 2, "type")) { - if (*queryType == "get") { - type = IQ::Get; - } - else if (*queryType == "set") { - type = IQ::Set; - } - else { - throw Lua::Exception("Illegal query type: '" + *queryType + "'"); - } - } - else { - throw Lua::Exception("Missing query type"); - } - - lua_getfield(L, 2, "query"); - if (!lua_istable(L, -1)) { - throw Lua::Exception("Missing/incorrect query"); - } - boost::shared_ptr<Payload> payload = Sluift::globals.elementConvertor.convertFromLua(L, -1); - - if (false) { } - SWIFTEN_PUBSUB_FOREACH_PUBSUB_PAYLOAD_TYPE(DISPATCH_PUBSUB_PAYLOAD) - else { - throw Lua::Exception("Incorrect PubSub payload"); - } + SluiftClient* client = getClient(L); + + JID to; + if (boost::optional<std::string> toString = Lua::getStringField(L, 2, "to")) { + to = JID(*toString); + } + + int timeout = getGlobalTimeout(L); + if (boost::optional<int> timeoutInt = Lua::getIntField(L, 2, "timeout")) { + timeout = *timeoutInt; + } + + IQ::Type type; + if (boost::optional<std::string> queryType = Lua::getStringField(L, 2, "type")) { + type = IQConvertor::convertIQTypeFromString(*queryType); + } + else { + throw Lua::Exception("Missing query type"); + } + + lua_getfield(L, 2, "query"); + if (!lua_istable(L, -1)) { + throw Lua::Exception("Missing/incorrect query"); + } + std::shared_ptr<Payload> payload = getPayload(L, -1); + + if (false) { } + SWIFTEN_PUBSUB_FOREACH_PUBSUB_PAYLOAD_TYPE(DISPATCH_PUBSUB_PAYLOAD) + else { + throw Lua::Exception("Incorrect PubSub payload"); + } } SLUIFT_LUA_FUNCTION(Client, get) { - return sendQuery(L, IQ::Get); + return sendQuery(L, IQ::Get); } SLUIFT_LUA_FUNCTION(Client, set) { - return sendQuery(L, IQ::Set); + return sendQuery(L, IQ::Set); } -SLUIFT_LUA_FUNCTION(Client, send) { - Sluift::globals.eventLoop.runOnce(); +SLUIFT_LUA_FUNCTION_WITH_HELP( + Client, send, + "Sends a raw string", + + "self\n" + "data the string to send\n", + + "" +) { + Sluift::globals.eventLoop.runOnce(); + if (!getClient(L)->getClient()->isAvailable()) { + throw Lua::Exception("Trying to send data while client is offline."); + } + getClient(L)->getClient()->sendData(std::string(Lua::checkString(L, 2))); + lua_pushvalue(L, 1); + return 0; +} + +SLUIFT_LUA_FUNCTION_WITH_HELP( + Client, set_options, + + "Sets the connection options of this client.", - getClient(L)->getClient()->sendData(std::string(Lua::checkString(L, 2))); - lua_pushvalue(L, 1); - return 0; + "self", + + "host The host to connect to. When omitted, is determined from resolving the JID domain.\n" + "port The port to connect to. When omitted, is determined from resolving the JID domain.\n" + "ack Request acknowledgements\n" + "compress Use stream compression when available\n" + "tls Use TLS when available\n" + "bosh_url Connect using the specified BOSH URL\n" + "allow_plain_without_tls Allow PLAIN authentication without a TLS encrypted connection\n" +) { + SluiftClient* client = getClient(L); + setOptions(L, client); + return 0; } -SLUIFT_LUA_FUNCTION(Client, set_options) { - SluiftClient* client = getClient(L); - Lua::checkType(L, 2, LUA_TTABLE); - lua_getfield(L, 2, "ack"); - if (!lua_isnil(L, -1)) { - client->getOptions().useAcks = lua_toboolean(L, -1); - } - lua_getfield(L, 2, "compress"); - if (!lua_isnil(L, -1)) { - client->getOptions().useStreamCompression = lua_toboolean(L, -1); - } - lua_getfield(L, 2, "tls"); - if (!lua_isnil(L, -1)) { - bool useTLS = lua_toboolean(L, -1); - client->getOptions().useTLS = (useTLS ? ClientOptions::UseTLSWhenAvailable : ClientOptions::NeverUseTLS); - } - lua_pushvalue(L, 1); - return 0; +SLUIFT_LUA_FUNCTION_WITH_HELP( + Client, get_options, + "Returns a table with all the connection options of this client.", + "self\n", + "" +) { + Sluift::globals.eventLoop.runOnce(); + + SluiftClient* client = getClient(L); + Lua::Table optionsTable = boost::assign::map_list_of + ("host", std::make_shared<Lua::Value>(client->getOptions().manualHostname)) + ("port", std::make_shared<Lua::Value>(client->getOptions().manualPort)) + ("ack", std::make_shared<Lua::Value>(client->getOptions().useAcks)) + ("compress", std::make_shared<Lua::Value>(client->getOptions().useStreamCompression)) + ("tls", std::make_shared<Lua::Value>(client->getOptions().useTLS == ClientOptions::NeverUseTLS ? false : true)) + ("bosh_url", std::make_shared<Lua::Value>(client->getOptions().boshURL.toString())) + ("allow_plain_without_tls", std::make_shared<Lua::Value>(client->getOptions().allowPLAINWithoutTLS)); + pushValue(L, optionsTable); + Lua::registerTableToString(L, -1); + return 1; } static void pushEvent(lua_State* L, const SluiftClient::Event& event) { - switch (event.type) { - case SluiftClient::Event::MessageType: { - Message::ref message = boost::dynamic_pointer_cast<Message>(event.stanza); - Lua::Table result = boost::assign::map_list_of - ("type", boost::make_shared<Lua::Value>(std::string("message"))) - ("from", boost::make_shared<Lua::Value>(message->getFrom().toString())) - ("body", boost::make_shared<Lua::Value>(message->getBody())); - Lua::pushValue(L, result); - Lua::registerTableToString(L, -1); - break; - } - case SluiftClient::Event::PresenceType: { - Presence::ref presence = boost::dynamic_pointer_cast<Presence>(event.stanza); - Lua::Table result = boost::assign::map_list_of - ("type", boost::make_shared<Lua::Value>(std::string("presence"))) - ("from", boost::make_shared<Lua::Value>(presence->getFrom().toString())) - ("status", boost::make_shared<Lua::Value>(presence->getStatus())); - Lua::pushValue(L, result); - if (!presence->getPayloads().empty()) { - const std::vector<boost::shared_ptr<Payload> > payloads = presence->getPayloads(); - lua_createtable(L, boost::numeric_cast<int>(payloads.size()), 0); - for (size_t i = 0; i < payloads.size(); ++i) { - Sluift::globals.elementConvertor.convertToLua(L, payloads[i]); - lua_rawseti(L, -2, boost::numeric_cast<int>(i+1)); - } - Lua::registerGetByTypeIndex(L, -1); - lua_setfield(L, -2, "payloads"); - } - Lua::registerTableToString(L, -1); - break; - } - case SluiftClient::Event::PubSubEventType: { - Sluift::globals.elementConvertor.convertToLua(L, event.pubsubEvent); - lua_pushstring(L, "pubsub"); - lua_setfield(L, -2, "type"); - lua_pushstring(L, event.from.toString().c_str()); - lua_setfield(L, -2, "from"); - - lua_rawgeti(L, LUA_REGISTRYINDEX, Sluift::globals.bootIndex); - lua_getfield(L, -1, "process_pubsub_event"); - lua_pushvalue(L, -3); - lua_call(L, 1, 0); - lua_pop(L, 1); - } - } + switch (event.type) { + case SluiftClient::Event::MessageType: { + Message::ref message = std::dynamic_pointer_cast<Message>(event.stanza); + Lua::Table result = boost::assign::map_list_of + ("type", std::make_shared<Lua::Value>(std::string("message"))) + ("from", std::make_shared<Lua::Value>(message->getFrom().toString())) + ("to", std::make_shared<Lua::Value>(message->getTo().toString())) + ("body", std::make_shared<Lua::Value>(message->getBody().get_value_or(""))) + ("message_type", std::make_shared<Lua::Value>(MessageConvertor::convertMessageTypeToString(message->getType()))); + Lua::pushValue(L, result); + addPayloadsToTable(L, message->getPayloads()); + Lua::registerTableToString(L, -1); + break; + } + case SluiftClient::Event::PresenceType: { + Presence::ref presence = std::dynamic_pointer_cast<Presence>(event.stanza); + Lua::Table result = boost::assign::map_list_of + ("type", std::make_shared<Lua::Value>(std::string("presence"))) + ("from", std::make_shared<Lua::Value>(presence->getFrom().toString())) + ("to", std::make_shared<Lua::Value>(presence->getTo().toString())) + ("status", std::make_shared<Lua::Value>(presence->getStatus())) + ("presence_type", std::make_shared<Lua::Value>(PresenceConvertor::convertPresenceTypeToString(presence->getType()))); + Lua::pushValue(L, result); + addPayloadsToTable(L, presence->getPayloads()); + Lua::registerTableToString(L, -1); + break; + } + case SluiftClient::Event::PubSubEventType: { + Sluift::globals.elementConvertor.convertToLua(L, event.pubsubEvent); + lua_pushstring(L, "pubsub"); + lua_setfield(L, -2, "type"); + lua_pushstring(L, event.from.toString().c_str()); + lua_setfield(L, -2, "from"); + + lua_rawgeti(L, LUA_REGISTRYINDEX, Sluift::globals.coreLibIndex); + lua_getfield(L, -1, "process_pubsub_event"); + lua_pushvalue(L, -3); + lua_call(L, 1, 0); + lua_pop(L, 1); + break; + } + case SluiftClient::Event::BlockEventType: { + Lua::Table result = boost::assign::map_list_of + ("type", std::make_shared<Lua::Value>(std::string("block"))) + ("jid", std::make_shared<Lua::Value>(event.item.toString())); + Lua::pushValue(L, result); + Lua::registerTableToString(L, -1); + break; + } + case SluiftClient::Event::UnblockEventType: { + Lua::Table result = boost::assign::map_list_of + ("type", std::make_shared<Lua::Value>(std::string("unblock"))) + ("jid", std::make_shared<Lua::Value>(event.item.toString())); + Lua::pushValue(L, result); + Lua::registerTableToString(L, -1); + break; + } + case SluiftClient::Event::RosterAddType: { + Lua::Table result = boost::assign::map_list_of + ("type", std::make_shared<Lua::Value>(std::string("rosterpush"))) + ("jid", std::make_shared<Lua::Value>(event.item.toString())) + ("action", std::make_shared<Lua::Value>(std::string("added"))); + Lua::pushValue(L, result); + Lua::registerTableToString(L, -1); + break; + } + case SluiftClient::Event::RosterRemoveType: { + Lua::Table result = boost::assign::map_list_of + ("type", std::make_shared<Lua::Value>(std::string("rosterpush"))) + ("jid", std::make_shared<Lua::Value>(event.item.toString())) + ("action", std::make_shared<Lua::Value>(std::string("removed"))); + Lua::pushValue(L, result); + Lua::registerTableToString(L, -1); + break; + } + case SluiftClient::Event::RosterUpdateType: { + Lua::Table result = boost::assign::map_list_of + ("type", std::make_shared<Lua::Value>(std::string("rosterpush"))) + ("jid", std::make_shared<Lua::Value>(event.item.toString())) + ("action", std::make_shared<Lua::Value>(std::string("updated"))); + Lua::pushValue(L, result); + Lua::registerTableToString(L, -1); + break; + } + } } struct CallUnaryLuaPredicateOnEvent { - CallUnaryLuaPredicateOnEvent(lua_State* L, int index) : L(L), index(index) { - } - - bool operator()(const SluiftClient::Event& event) { - lua_pushvalue(L, index); - pushEvent(L, event); - if (lua_pcall(L, 1, 1, 0) != 0) { - throw Lua::Exception(lua_tostring(L, -1)); - } - bool result = lua_toboolean(L, -1); - lua_pop(L, 1); - return result; - } - - lua_State* L; - int index; + CallUnaryLuaPredicateOnEvent(lua_State* L, int index) : L(L), index(index) { + } + + bool operator()(const SluiftClient::Event& event) { + lua_pushvalue(L, index); + pushEvent(L, event); + if (lua_pcall(L, 1, 1, 0) != 0) { + throw Lua::Exception(lua_tostring(L, -1)); + } + bool result = lua_toboolean(L, -1); + lua_pop(L, 1); + return result; + } + + lua_State* L; + int index; }; SLUIFT_LUA_FUNCTION(Client, get_next_event) { - Sluift::globals.eventLoop.runOnce(); - SluiftClient* client = getClient(L); - - int timeout = Sluift::globals.timeout; - boost::optional<SluiftClient::Event::Type> type; - int condition = 0; - if (lua_istable(L, 2)) { - if (boost::optional<std::string> typeString = Lua::getStringField(L, 2, "type")) { - if (*typeString == "message") { - type = SluiftClient::Event::MessageType; - } - else if (*typeString == "presence") { - type = SluiftClient::Event::PresenceType; - } - else if (*typeString == "pubsub") { - type = SluiftClient::Event::PubSubEventType; - } - } - if (boost::optional<int> timeoutInt = Lua::getIntField(L, 2, "timeout")) { - timeout = *timeoutInt; - } - lua_getfield(L, 2, "if"); - if (lua_isfunction(L, -1)) { - condition = Lua::absoluteOffset(L, -1); - } - } - - boost::optional<SluiftClient::Event> event; - if (condition) { - event = client->getNextEvent(timeout, CallUnaryLuaPredicateOnEvent(L, condition)); - } - else if (type) { - event = client->getNextEvent( - timeout, lambda::bind(&SluiftClient::Event::type, lambda::_1) == *type); - } - else { - event = client->getNextEvent(timeout); - } - - if (event) { - pushEvent(L, *event); - } - else { - lua_pushnil(L); - } - return 1; -} - - -SLUIFT_LUA_FUNCTION(Client, add_contact) { - Sluift::globals.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); - } - } - else { - throw Lua::Exception("Groups should be a table"); - } - } - } - else { - item.setJID(Lua::checkString(L, 2)); - } - - client->getRoster(); - if (!client->getClient()->getRoster()->containsJID(item.getJID())) { - RosterPayload::ref roster = boost::make_shared<RosterPayload>(); - roster->addItem(item); - - Sluift::Response response = client->sendVoidRequest( - SetRosterRequest::create(roster, client->getClient()->getIQRouter()), -1); - if (response.error) { - return response.convertToLuaResult(L); - } - } - client->getClient()->getSubscriptionManager()->requestSubscription(item.getJID()); - lua_pushboolean(L, true); - return 1; -} - -SLUIFT_LUA_FUNCTION(Client, remove_contact) { - Sluift::globals.eventLoop.runOnce(); - SluiftClient* client = getClient(L); - JID jid(Lua::checkString(L, 2)); - - RosterPayload::ref roster = boost::make_shared<RosterPayload>(); - roster->addItem(RosterItemPayload(JID(Lua::checkString(L, 2)), "", RosterItemPayload::Remove)); - - return client->sendVoidRequest( - SetRosterRequest::create(roster, client->getClient()->getIQRouter()), -1).convertToLuaResult(L); -} - -SLUIFT_LUA_FUNCTION(Client, confirm_subscription) { - Sluift::globals.eventLoop.runOnce(); - SluiftClient* client = getClient(L); - JID jid(Lua::checkString(L, 2)); - client->getClient()->getSubscriptionManager()->confirmSubscription(jid); - return 0; -} - -SLUIFT_LUA_FUNCTION(Client, cancel_subscription) { - Sluift::globals.eventLoop.runOnce(); - SluiftClient* client = getClient(L); - JID jid(Lua::checkString(L, 2)); - client->getClient()->getSubscriptionManager()->cancelSubscription(jid); - return 0; -} - -SLUIFT_LUA_FUNCTION(Client, set_disco_info) { - SluiftClient* client = getClient(L); - if (!lua_istable(L, 2)) { - throw Lua::Exception("Missing disco info"); - } - if (boost::shared_ptr<DiscoInfo> discoInfo = boost::dynamic_pointer_cast<DiscoInfo>(Sluift::globals.elementConvertor.convertFromLuaUntyped(L, 2, "disco_info"))) { - client->getClient()->getDiscoManager()->setDiscoInfo(*discoInfo); - } - else { - throw Lua::Exception("Illegal disco info"); - } - return 0; -} - -SLUIFT_LUA_FUNCTION(Client, set_caps_node) { - SluiftClient* client = getClient(L); - std::string node(Lua::checkString(L, 2)); - client->getClient()->getDiscoManager()->setCapsNode(Lua::checkString(L, 2)); - return 0; -} - -SLUIFT_LUA_FUNCTION(Client, jid) { - SluiftClient* client = getClient(L); - lua_pushstring(L, client->getClient()->getJID().toString().c_str()); - return 1; + Sluift::globals.eventLoop.runOnce(); + SluiftClient* client = getClient(L); + + int timeout = getGlobalTimeout(L); + boost::optional<SluiftClient::Event::Type> type; + int condition = 0; + if (lua_istable(L, 2)) { + if (boost::optional<std::string> typeString = Lua::getStringField(L, 2, "type")) { + if (*typeString == "message") { + type = SluiftClient::Event::MessageType; + } + else if (*typeString == "presence") { + type = SluiftClient::Event::PresenceType; + } + else if (*typeString == "pubsub") { + type = SluiftClient::Event::PubSubEventType; + } + } + if (boost::optional<int> timeoutInt = Lua::getIntField(L, 2, "timeout")) { + timeout = *timeoutInt; + } + lua_getfield(L, 2, "if"); + if (lua_isfunction(L, -1)) { + condition = Lua::absoluteOffset(L, -1); + } + } + + boost::optional<SluiftClient::Event> event; + if (condition) { + event = client->getNextEvent(timeout, CallUnaryLuaPredicateOnEvent(L, condition)); + } + else if (type) { + event = client->getNextEvent( + timeout, [&](const SluiftClient::Event& event) { + return event.type == *type; + }); + } + else { + event = client->getNextEvent(timeout); + } + + if (event) { + pushEvent(L, *event); + } + else { + lua_pushnil(L); + } + return 1; +} + + +SLUIFT_LUA_FUNCTION_WITH_HELP( + Client, add_contact, + "Add a contact to the contact list.", + "self\n", + "jid The JID of the contact to add\n" + "name The name to use in the contact list\n" + "groups An array of group names to add the contact to\n") { + Sluift::globals.eventLoop.runOnce(); + SluiftClient* client = getClient(L); + RosterItemPayload item; + int timeout = getGlobalTimeout(L); + + 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_rawlen(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); + } + } + else { + throw Lua::Exception("Groups should be a table"); + } + } + } + else { + item.setJID(Lua::checkString(L, 2)); + } + + client->getRoster(timeout); + if (!client->getClient()->getRoster()->containsJID(item.getJID())) { + RosterPayload::ref roster = std::make_shared<RosterPayload>(); + roster->addItem(item); + + Sluift::Response response = client->sendVoidRequest( + SetRosterRequest::create(roster, client->getClient()->getIQRouter()), timeout); + if (response.error) { + return response.convertToLuaResult(L); + } + } + client->getClient()->getSubscriptionManager()->requestSubscription(item.getJID()); + lua_pushboolean(L, true); + return 1; +} + +SLUIFT_LUA_FUNCTION_WITH_HELP( + Client, remove_contact, + "Remove a contact from the contact list.", + "self\n" + "jid the JID of the contact to remove\n", + "" +) { + Sluift::globals.eventLoop.runOnce(); + SluiftClient* client = getClient(L); + JID jid(Lua::checkString(L, 2)); + int timeout = getGlobalTimeout(L); + + RosterPayload::ref roster = std::make_shared<RosterPayload>(); + roster->addItem(RosterItemPayload(JID(Lua::checkString(L, 2)), "", RosterItemPayload::Remove)); + + return client->sendVoidRequest( + SetRosterRequest::create(roster, client->getClient()->getIQRouter()), timeout).convertToLuaResult(L); +} + +SLUIFT_LUA_FUNCTION_WITH_HELP( + Client, confirm_subscription, + "Confirm subscription of a contact.", + "self\n" + "jid the JID of the contact to confirm the subscription of\n", + "" +) { + Sluift::globals.eventLoop.runOnce(); + SluiftClient* client = getClient(L); + JID jid(Lua::checkString(L, 2)); + client->getClient()->getSubscriptionManager()->confirmSubscription(jid); + return 0; +} + +SLUIFT_LUA_FUNCTION_WITH_HELP( + Client, cancel_subscription, + "Cancel the subscription of a contact.", + "self\n" + "jid the JID of the contact to cancel the subscription of\n", + "" +) { + Sluift::globals.eventLoop.runOnce(); + SluiftClient* client = getClient(L); + JID jid(Lua::checkString(L, 2)); + client->getClient()->getSubscriptionManager()->cancelSubscription(jid); + return 0; +} + +SLUIFT_LUA_FUNCTION_WITH_HELP( + Client, set_disco_info, + "Sets the service discovery information for this client", + "self\n" + "disco_info A structured representation of the service discovery information\n", + "" +) { + SluiftClient* client = getClient(L); + if (!lua_istable(L, 2)) { + throw Lua::Exception("Missing disco info"); + } + if (std::shared_ptr<DiscoInfo> discoInfo = std::dynamic_pointer_cast<DiscoInfo>(Sluift::globals.elementConvertor.convertFromLuaUntyped(L, 2, "disco_info"))) { + client->getClient()->getDiscoManager()->setDiscoInfo(*discoInfo); + } + else { + throw Lua::Exception("Illegal disco info"); + } + return 0; +} + +SLUIFT_LUA_FUNCTION_WITH_HELP( + Client, set_caps_node, + "Sets the caps node of this client", + "self\n" + "node The caps node (e.g. 'http://swift.im/sluift')\n", + "" +) { + SluiftClient* client = getClient(L); + std::string node(Lua::checkString(L, 2)); + client->getClient()->getDiscoManager()->setCapsNode(Lua::checkString(L, 2)); + return 0; +} + +SLUIFT_LUA_FUNCTION_WITH_HELP( + Client, set_certificate, + "Sets a client certificate to use for strong authentication with the server.", + "self\n" + "file PKCS #12 file\n" + "pwd passphrase for the certificate private key\n", + "" +) { + std::string file; + std::string pwd; + int index = 2; + if (!lua_isnoneornil(L, index)) { + file = Lua::checkString(L, index); + ++index; + if (!lua_isnoneornil(L, index)) { + pwd = Lua::checkString(L, index); + ++index; + } + } + if (file.empty()) { + getClient(L)->getClient()->setCertificate(CertificateWithKey::ref()); + } else { + getClient(L)->getClient()->setCertificate(std::make_shared<PKCS12Certificate>(file, createSafeByteArray(pwd))); + } + return 0; +} + +SLUIFT_LUA_FUNCTION_WITH_HELP( + Client, jid, + "Returns the JID of this client", + "self\n", + "" +) { + SluiftClient* client = getClient(L); + lua_pushstring(L, client->getClient()->getJID().toString().c_str()); + return 1; } SLUIFT_LUA_FUNCTION(Client, __gc) { - SluiftClient* client = getClient(L); - delete client; - return 0; + SluiftClient* client = getClient(L); + delete client; + return 0; } diff --git a/Sluift/component.cpp b/Sluift/component.cpp new file mode 100644 index 0000000..c1b1da4 --- /dev/null +++ b/Sluift/component.cpp @@ -0,0 +1,465 @@ +/* + * Copyright (c) 2014-2018 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <boost/assign/list_of.hpp> + +#include <Swiften/Base/IDGenerator.h> +#include <Swiften/Elements/DiscoInfo.h> +#include <Swiften/Elements/MAMQuery.h> +#include <Swiften/Elements/Message.h> +#include <Swiften/Elements/Presence.h> +#include <Swiften/Elements/RawXMLPayload.h> +#include <Swiften/Elements/RosterItemPayload.h> +#include <Swiften/Elements/RosterPayload.h> +#include <Swiften/Elements/SoftwareVersion.h> +#include <Swiften/JID/JID.h> +#include <Swiften/Presence/PresenceSender.h> +#include <Swiften/Presence/SubscriptionManager.h> +#include <Swiften/Queries/GenericRequest.h> +#include <Swiften/Queries/IQRouter.h> +#include <Swiften/Queries/Requests/GetSoftwareVersionRequest.h> +#include <Swiften/Roster/SetRosterRequest.h> +#include <Swiften/Roster/XMPPRoster.h> +#include <Swiften/Roster/XMPPRosterItem.h> + +#include <Sluift/ElementConvertors/IQConvertor.h> +#include <Sluift/ElementConvertors/MessageConvertor.h> +#include <Sluift/ElementConvertors/PresenceConvertor.h> +#include <Sluift/ElementConvertors/StanzaConvertor.h> +#include <Sluift/ElementConvertors/StatusShowConvertor.h> +#include <Sluift/Lua/Check.h> +#include <Sluift/Lua/Exception.h> +#include <Sluift/Lua/FunctionRegistration.h> +#include <Sluift/Lua/LuaUtils.h> +#include <Sluift/Lua/Value.h> +#include <Sluift/SluiftComponent.h> +#include <Sluift/globals.h> + +using namespace Swift; + +static inline SluiftComponent* getComponent(lua_State* L) { + return *Lua::checkUserData<SluiftComponent>(L, 1); +} + +static inline int getGlobalTimeout(lua_State* L) { + lua_rawgeti(L, LUA_REGISTRYINDEX, Sluift::globals.moduleLibIndex); + lua_getfield(L, -1, "timeout"); + int result = boost::numeric_cast<int>(lua_tointeger(L, -1)); + lua_pop(L, 2); + return result; +} + +static void addPayloadsToTable(lua_State* L, const std::vector<std::shared_ptr<Payload> >& payloads) { + if (!payloads.empty()) { + lua_createtable(L, boost::numeric_cast<int>(payloads.size()), 0); + for (size_t i = 0; i < payloads.size(); ++i) { + Sluift::globals.elementConvertor.convertToLua(L, payloads[i]); + lua_rawseti(L, -2, boost::numeric_cast<int>(i+1)); + } + Lua::registerGetByTypeIndex(L, -1); + lua_setfield(L, -2, "payloads"); + } +} + +static std::shared_ptr<Payload> getPayload(lua_State* L, int index) { + if (lua_type(L, index) == LUA_TTABLE) { + return std::dynamic_pointer_cast<Payload>(Sluift::globals.elementConvertor.convertFromLua(L, index)); + } + else if (lua_type(L, index) == LUA_TSTRING) { + return std::make_shared<RawXMLPayload>(Lua::checkString(L, index)); + } + else { + return std::shared_ptr<Payload>(); + } +} + +static std::vector< std::shared_ptr<Payload> > getPayloadsFromTable(lua_State* L, int index) { + index = Lua::absoluteOffset(L, index); + std::vector< std::shared_ptr<Payload> > result; + lua_getfield(L, index, "payloads"); + if (lua_istable(L, -1)) { + for (lua_pushnil(L); lua_next(L, -2); lua_pop(L, 1)) { + std::shared_ptr<Payload> payload = getPayload(L, -1); + if (payload) { + result.push_back(payload); + } + } + } + lua_pop(L, 1); + return result; +} + +SLUIFT_LUA_FUNCTION(Component, async_connect) { + SluiftComponent* component = getComponent(L); + + std::string host; + unsigned short port = 0; + if (lua_istable(L, 2)) { + if (boost::optional<std::string> hostString = Lua::getStringField(L, 2, "host")) { + host = *hostString; + } + if (boost::optional<int> portInt = Lua::getIntField(L, 2, "port")) { + port = boost::numeric_cast<unsigned short>(*portInt); + } + } + component->connect(host, port); + return 0; +} + +SLUIFT_LUA_FUNCTION_WITH_HELP( + Component, set_trace_enabled, + "Enable/disable tracing of the data sent/received.\n\n.", + "self\n" + "enable a boolean specifying whether to enable/disable tracing", + "" +) { + getComponent(L)->setTraceEnabled(lua_toboolean(L, 1)); + return 0; +} + +SLUIFT_LUA_FUNCTION_WITH_HELP( + Component, wait_connected, + "Block until the component is connected.\n\nThis is useful after an `async_connect`.", + "self", + "" +) { + getComponent(L)->waitConnected(getGlobalTimeout(L)); + return 0; +} + +SLUIFT_LUA_FUNCTION_WITH_HELP( + Component, is_connected, + "Checks whether this component is still connected.\n\nReturns a boolean.", + "self\n", + "" +) { + lua_pushboolean(L, getComponent(L)->isConnected()); + return 1; +} + +SLUIFT_LUA_FUNCTION_WITH_HELP( + Component, disconnect, + "Disconnect from the server", + "self\n", + "" +) { + Sluift::globals.eventLoop.runOnce(); + getComponent(L)->disconnect(); + return 0; +} + +SLUIFT_LUA_FUNCTION_WITH_HELP( + Component, set_version, + + "Sets the published version of this component.", + + "self", + + "name the name of the component software\n" + "version the version identifier of this component\n" + "os the OS this component is running on\n" +) { + Sluift::globals.eventLoop.runOnce(); + SluiftComponent* component = getComponent(L); + if (std::shared_ptr<SoftwareVersion> version = std::dynamic_pointer_cast<SoftwareVersion>(Sluift::globals.elementConvertor.convertFromLuaUntyped(L, 2, "software_version"))) { + component->setSoftwareVersion(version->getName(), version->getVersion(), version->getOS()); + } + return 0; +} + +SLUIFT_LUA_FUNCTION_WITH_HELP( + Component, send_message, + "Send a message.", + "self\n" + "to the JID to send the message to\n" + "body the body of the message. Can alternatively be specified using the `body` option\n", + + "to the JID to send the message to\n" + "body the body of the message\n" + "subject the subject of the MUC room to set\n" + "type the type of message to send (`normal`, `chat`, `error`, `groupchat`, `headline`)\n" + "payloads payloads to add to the message\n" +) { + Sluift::globals.eventLoop.runOnce(); + JID to; + boost::optional<std::string> from; + boost::optional<std::string> body; + boost::optional<std::string> subject; + std::vector<std::shared_ptr<Payload> > payloads; + int index = 2; + Message::Type type = Message::Chat; + if (lua_isstring(L, index)) { + to = std::string(lua_tostring(L, index)); + ++index; + if (lua_isstring(L, index)) { + body = lua_tostring(L, index); + ++index; + } + } + if (lua_istable(L, index)) { + if (boost::optional<std::string> value = Lua::getStringField(L, index, "to")) { + to = *value; + } + + if (boost::optional<std::string> value = Lua::getStringField(L, index, "from")) { + from = value; + } + + if (boost::optional<std::string> value = Lua::getStringField(L, index, "body")) { + body = value; + } + + if (boost::optional<std::string> value = Lua::getStringField(L, index, "type")) { + type = MessageConvertor::convertMessageTypeFromString(*value); + } + + if (boost::optional<std::string> value = Lua::getStringField(L, index, "subject")) { + subject = value; + } + + payloads = getPayloadsFromTable(L, index); + } + + if (!to.isValid()) { + throw Lua::Exception("Missing 'to'"); + } + if ((!body || body->empty()) && !subject && payloads.empty()) { + throw Lua::Exception("Missing any of 'body', 'subject' or 'payloads'"); + } + Message::ref message = std::make_shared<Message>(); + message->setTo(to); + if (from && !from->empty()) { + message->setFrom(*from); + } + if (body && !body->empty()) { + message->setBody(*body); + } + if (subject) { + message->setSubject(*subject); + } + message->addPayloads(payloads.begin(), payloads.end()); + message->setType(type); + getComponent(L)->getComponent()->sendMessage(message); + return 0; +} + +SLUIFT_LUA_FUNCTION_WITH_HELP( + Component, send_presence, + "Send presence.", + + "self\n" + "body the text of the presence. Can alternatively be specified using the `status` option\n", + + "to the JID to send the message to\n" + "from the JID to send the message from\n" + "status the text of the presence\n" + "show the availability of the presence (`online`, `ffc`, `away`, `xa`, `dnd`)\n" + "priority the priority of the presence\n" + "type the type of message to send (`available`, `error`, `probe`, `subscribe`, `subscribed`, `unavailable`, `unsubscribe`, `unsubscribed`)\n" + "payloads payloads to add to the presence\n" +) { + Sluift::globals.eventLoop.runOnce(); + std::shared_ptr<Presence> presence = std::make_shared<Presence>(); + + int index = 2; + if (lua_isstring(L, index)) { + presence->setStatus(lua_tostring(L, index)); + ++index; + } + if (lua_istable(L, index)) { + if (boost::optional<std::string> value = Lua::getStringField(L, index, "to")) { + presence->setTo(*value); + } + if (boost::optional<std::string> value = Lua::getStringField(L, index, "from")) { + presence->setFrom(*value); + } + if (boost::optional<std::string> value = Lua::getStringField(L, index, "status")) { + presence->setStatus(*value); + } + if (boost::optional<int> value = Lua::getIntField(L, index, "priority")) { + presence->setPriority(*value); + } + if (boost::optional<std::string> value = Lua::getStringField(L, index, "type")) { + presence->setType(PresenceConvertor::convertPresenceTypeFromString(*value)); + } + if (boost::optional<std::string> value = Lua::getStringField(L, index, "show")) { + presence->setShow(StatusShowConvertor::convertStatusShowTypeFromString(*value)); + } + std::vector< std::shared_ptr<Payload> > payloads = getPayloadsFromTable(L, index); + presence->addPayloads(payloads.begin(), payloads.end()); + } + + getComponent(L)->getComponent()->sendPresence(presence); + lua_pushvalue(L, 1); + return 0; +} + +static int sendQuery(lua_State* L, IQ::Type type) { + SluiftComponent* component = getComponent(L); + + JID to; + if (boost::optional<std::string> toString = Lua::getStringField(L, 2, "to")) { + to = JID(*toString); + } + + JID from; + if (boost::optional<std::string> fromString = Lua::getStringField(L, 2, "from")) { + from = JID(*fromString); + } + + int timeout = getGlobalTimeout(L); + if (boost::optional<int> timeoutInt = Lua::getIntField(L, 2, "timeout")) { + timeout = *timeoutInt; + } + + std::shared_ptr<Payload> payload; + lua_getfield(L, 2, "query"); + payload = getPayload(L, -1); + lua_pop(L, 1); + + return component->sendRequest( + std::make_shared< GenericRequest<Payload> >(type, from, to, payload, component->getComponent()->getIQRouter()), timeout).convertToLuaResult(L); +} + +SLUIFT_LUA_FUNCTION(Component, get) { + return sendQuery(L, IQ::Get); +} + +SLUIFT_LUA_FUNCTION(Component, set) { + return sendQuery(L, IQ::Set); +} + +SLUIFT_LUA_FUNCTION_WITH_HELP( + Component, send, + "Sends a raw string", + + "self\n" + "data the string to send\n", + + "" +) { + Sluift::globals.eventLoop.runOnce(); + + getComponent(L)->getComponent()->sendData(std::string(Lua::checkString(L, 2))); + lua_pushvalue(L, 1); + return 0; +} + +static void pushEvent(lua_State* L, const SluiftComponent::Event& event) { + switch (event.type) { + case SluiftComponent::Event::MessageType: { + Message::ref message = std::dynamic_pointer_cast<Message>(event.stanza); + Lua::Table result = boost::assign::map_list_of + ("type", std::make_shared<Lua::Value>(std::string("message"))) + ("from", std::make_shared<Lua::Value>(message->getFrom().toString())) + ("to", std::make_shared<Lua::Value>(message->getTo().toString())) + ("body", std::make_shared<Lua::Value>(message->getBody().get_value_or(""))) + ("message_type", std::make_shared<Lua::Value>(MessageConvertor::convertMessageTypeToString(message->getType()))); + Lua::pushValue(L, result); + addPayloadsToTable(L, message->getPayloads()); + Lua::registerTableToString(L, -1); + break; + } + case SluiftComponent::Event::PresenceType: { + Presence::ref presence = std::dynamic_pointer_cast<Presence>(event.stanza); + Lua::Table result = boost::assign::map_list_of + ("type", std::make_shared<Lua::Value>(std::string("presence"))) + ("from", std::make_shared<Lua::Value>(presence->getFrom().toString())) + ("to", std::make_shared<Lua::Value>(presence->getTo().toString())) + ("status", std::make_shared<Lua::Value>(presence->getStatus())) + ("presence_type", std::make_shared<Lua::Value>(PresenceConvertor::convertPresenceTypeToString(presence->getType()))); + Lua::pushValue(L, result); + addPayloadsToTable(L, presence->getPayloads()); + Lua::registerTableToString(L, -1); + break; + } + } +} + +struct CallUnaryLuaPredicateOnEvent { + CallUnaryLuaPredicateOnEvent(lua_State* L, int index) : L(L), index(index) { + } + + bool operator()(const SluiftComponent::Event& event) { + lua_pushvalue(L, index); + pushEvent(L, event); + if (lua_pcall(L, 1, 1, 0) != 0) { + throw Lua::Exception(lua_tostring(L, -1)); + } + bool result = lua_toboolean(L, -1); + lua_pop(L, 1); + return result; + } + + lua_State* L; + int index; +}; + + +SLUIFT_LUA_FUNCTION(Component, get_next_event) { + Sluift::globals.eventLoop.runOnce(); + SluiftComponent* component = getComponent(L); + + int timeout = getGlobalTimeout(L); + boost::optional<SluiftComponent::Event::Type> type; + int condition = 0; + if (lua_istable(L, 2)) { + if (boost::optional<std::string> typeString = Lua::getStringField(L, 2, "type")) { + if (*typeString == "message") { + type = SluiftComponent::Event::MessageType; + } + else if (*typeString == "presence") { + type = SluiftComponent::Event::PresenceType; + } + } + if (boost::optional<int> timeoutInt = Lua::getIntField(L, 2, "timeout")) { + timeout = *timeoutInt; + } + lua_getfield(L, 2, "if"); + if (lua_isfunction(L, -1)) { + condition = Lua::absoluteOffset(L, -1); + } + } + + boost::optional<SluiftComponent::Event> event; + if (condition) { + event = component->getNextEvent(timeout, CallUnaryLuaPredicateOnEvent(L, condition)); + } + else if (type) { + event = component->getNextEvent( + timeout, [&](const SluiftComponent::Event& event) { + return event.type == *type; + }); + } + else { + event = component->getNextEvent(timeout); + } + + if (event) { + pushEvent(L, *event); + } + else { + lua_pushnil(L); + } + return 1; +} + +SLUIFT_LUA_FUNCTION_WITH_HELP( + Component, jid, + "Returns the JID of this component", + "self\n", + "" +) { + SluiftComponent* component = getComponent(L); + lua_pushstring(L, component->getComponent()->getJID().toString().c_str()); + return 1; +} + +SLUIFT_LUA_FUNCTION(Component, __gc) { + SluiftComponent* component = getComponent(L); + delete component; + return 0; +} diff --git a/Sluift/core.lua b/Sluift/core.lua new file mode 100644 index 0000000..f35a603 --- /dev/null +++ b/Sluift/core.lua @@ -0,0 +1,1244 @@ +--[[ + Copyright (c) 2013-2017 Isode Limited. + All rights reserved. + See the COPYING file for more information. +--]] + +local sluift = select(1, ...) +local _G = _G +local pairs, ipairs, print, tostring, type, error, assert, next, rawset, xpcall, io = pairs, ipairs, print, tostring, type, error, assert, next, rawset, xpcall, io +local unpack = table.unpack or unpack +local setmetatable, getmetatable = setmetatable, getmetatable +local string = require "string" +local table = require "table" +local debug = require "debug" +_ENV = nil + +-------------------------------------------------------------------------------- +-- Table utility methods +-------------------------------------------------------------------------------- + +local function table_value_tostring(value) + local result = tostring(value) + if type(value) == 'number' then return result + elseif type(value) == 'boolean' then return result + elseif type(value) == 'string' then return "'" .. result .. "'" + else return '<' .. result .. '>' + end +end + +local function table_tostring(table, print_functions, indent, accumulator, history) + local INDENT = ' ' + local accumulator = accumulator or '' + local history = history or {} + local indent = indent or '' + accumulator = accumulator .. '{' + history[table] = true + local is_first = true + for key, value in pairs(table) do + if print_functions or type(value) ~= 'function' then + if not is_first then + accumulator = accumulator .. ',' + end + is_first = false + accumulator = accumulator .. '\n' .. indent .. INDENT .. '[' .. table_value_tostring(key) .. '] = ' + if type(value) == 'table' then + if history[value] then + accumulator = accumulator .. "..." + else + accumulator = table_tostring(value, print_functions, indent .. INDENT, accumulator, history) + end + else + accumulator = accumulator .. table_value_tostring(value) + end + end + end + history[table] = false + if not is_first then + accumulator = accumulator .. '\n' .. indent + end + accumulator = accumulator .. '}' + return accumulator +end + +local function register_table_tostring(table, print_functions) + if type(table) == 'table' then + local metatable = getmetatable(table) + if not metatable then + metatable = {} + setmetatable(table, metatable) + end + if print_functions then + metatable.__tostring = function(table) return table_tostring(table, true) end + else + metatable.__tostring = table_tostring + end + end +end + +-- FIXME: Not really a good or efficiant equals, but does the trick for now +local function table_equals(t1, t2) + return tostring(t1) == tostring(t2) +end + +local function register_table_equals(table) + if type(table) == 'table' then + local metatable = getmetatable(table) + if not metatable then + metatable = {} + setmetatable(table, metatable) + end + metatable.__eq = table_equals + end +end + +local function merge_tables(...) + local result = {} + for _, table in ipairs({...}) do + for k, v in pairs(table) do + result[k] = v + end + end + return result +end + +local function copy(object) + if type(object) == 'table' then + local copy = {} + for key, value in pairs(object) do + copy[key] = value + end + return copy + else + return object + end +end + +local function clear(table) + setmetatable(table, nil) + for key, value in pairs(table) do + rawset(table, key, nil) + end +end + +local function trim(string) + return string:gsub("^%s*(.-)%s*$", "%1") +end + +local function keys(table) + local result = {} + for key in pairs(table) do + result[#result+1] = key + end + return result +end + +local function insert_all(table, values) + for _, value in pairs(values) do + table[#table+1] = value + end +end + +-------------------------------------------------------------------------------- +-- Help +-------------------------------------------------------------------------------- + +-- Contains help for native methods that we want access to from here +local extra_help = {} +local component_extra_help = {} +local help_data = {} +local help_classes = {} +local help_class_metatables = {} + +local _H + +local function get_synopsis(description) + return description:gsub("[\n\r].*", "") +end + +local function format_description(text) + local result = {} + local trim_whitespace + for line in (text .. "\n"):gmatch"(.-)\n" do + if not trim_whitespace and line:find('[^%s]') then + trim_whitespace = line:match("^(%s*)") + end + if trim_whitespace then + line = line:gsub("^" .. trim_whitespace, "") + end + table.insert(result, line) + end + return trim(table.concat(result, "\n")) +end + +local function strip_links(text) + return text:gsub("(@{(%w*)})", "`%2`") +end + +local function register_help(target, help) + assert(target) + if not help then + help = _H + end + assert(help) + + -- Transform description into canonical representation + local parameters = {} + for _, parameter in pairs(help.parameters or {}) do + local parameter_description = parameter[2] + if parameter_description and #parameter_description == 0 then + parameter_description = nil + end + if type(parameter) == "table" then + parameters[#parameters+1] = { name = parameter[1], description = parameter_description } + else + parameters[#parameters+1] = { name = parameter } + end + end + local options = {} + for option_name, option_description in pairs(help.options or {}) do + if type(option_description) == "table" then + options[#options+1] = { name = option_description.name, description = option_description.description } + else + options[#options+1] = { name = option_name, description = option_description } + end + end + local description = format_description(help[1] or help.description or "") + local synopsis = get_synopsis(description) + if #description == 0 then + synopsis = nil + description = nil + end + local data = { + description = description, + synopsis = synopsis, + parameters = parameters, + options = options, + classes = help.classes + } + register_table_tostring(data, true) + help_data[target] = data +end + +local function register_class_help(class, help) + help_classes[#help_classes+1] = class + register_help(class, help) +end + +local function register_class_table_help(target, class, help) + register_help(target, help) + help_class_metatables[class] = target + register_class_help(class, help) +end + +_H = { + [[ + Retrieves the help information from `target`. + + Returns a table with the following fields: + + - `description`: the description of `target` + - `parameters`: an array of parameters of `target` represented as tables with `name` and `description` fields. + - `options`: an array of options (named parameters) of `target` represented as tables with `name` and + `description` fields. + - `methods`: an array of methods + - `fields`: an array of fields + ]], + parameters = { {"target", "The target to retrieve help of"} } +} +local function get_help(target) + if not target then error("Nil argument or argument missing") end + local help = help_data[target] or help_data[getmetatable(target)] or {} + + -- Collect child methods and fields + local children = {} + if type(target) == "table" then children = target end + local mt + if type(target) == "string" then + mt = help_class_metatables[target] + else + mt = getmetatable(target) + end + if mt and type(mt.__index) == "table" then + children = merge_tables(children, mt.__index) + end + + local methods = {} + local fields = {} + for name, value in pairs(children) do + if name:sub(1, 1) ~= "_" then + if type(value) == "function" then + methods[#methods+1] = { name = name, ref = value } + else + fields[#fields+1] = { name = name, description = nil } + end + end + end + if next(methods) ~= nil then + help.methods = methods + end + if next(fields) ~= nil then + help.fields = fields + end + if next(help) then + return help + else + return nil + end +end +register_help(get_help) + +_H = { + [[ + Prints the help of `target`. + + `target` can be any object. When `target` is a string, prints the help of the class with + the given name. + ]], + parameters = { {"target", "The target to retrieve help of"} } +} +local function help(target) + print() + if not target then + print("Call `help(target)` to get the help of a specific `target`.") + print("`target` can be any object. When `target` is a string, prints") + print("the help of the class with the given name.") + print() + print("For general information about sluift, type:") + print(" help(sluift)") + print() + return + end + local data = get_help(target) + if not data then + print("No help available\n") + return + end + + -- Collect help of children + local methods = {} + for _, method in pairs(data.methods or {}) do + local description + local method_help = get_help(method.ref) + if method_help and method_help.description then + description = method_help.synopsis + end + methods[#methods+1] = { name = method.name, description = description } + end + local fields = copy(data.fields or {}) + + table.sort(methods, function (a, b) return (a.name or "") < (b.name or "") end) + table.sort(fields, function (a, b) return (a.name or "") < (b.name or "") end) + + local classes = {} + for _, class in pairs(data.classes or {}) do + classes[#classes+1] = { name = class, description = get_help(class).synopsis } + end + + print(strip_links(data.description) or "(No description available)") + for _, p in ipairs({ + {"Parameters", data.parameters}, {"Options", data.options}, {"Methods", methods}, {"Fields", fields}, {"Classes", classes}}) do + if p[2] and next(p[2]) ~= nil then + print() + print(p[1] .. ":") + for _, parameter in ipairs(p[2]) do + if parameter.description then + print(" " .. parameter.name .. ": " .. strip_links(parameter.description)) + else + print(" " .. parameter.name) + end + end + end + end + + print() +end +register_help(help) + +-------------------------------------------------------------------------------- +-- Utility methods +-------------------------------------------------------------------------------- + +_H = { + [[ Perform a shallow copy of `object`. ]], + parameters = {{"object", "the object to copy"}} +} +register_help(copy) + +_H = { + [[ Pretty-print a table ]], + parameters = {{"table", "the table to print"}} +} +local function tprint(table) + print(table_tostring(table, true)) +end +register_help(tprint) + +local function remove_help_parameters(elements, table) + if type(elements) ~= "table" then + elements = {elements} + end + local result = copy(table) + for k, v in ipairs(table) do + for _, element in ipairs(elements) do + if v.name == element then + result[k] = nil + end + end + end + return result +end + +local function parse_options(unnamed_parameters, arg1, arg2) + local options = {} + local f + if type(arg1) == 'table' then + options = arg1 + f = arg2 + elseif type(arg1) == 'function' then + f = arg1 + end + options.f = f or options.f + return copy(options) +end + + +local function get_by_type(table, typ) + for _, v in ipairs(table) do + if v['_type'] == typ then + return v + end + end +end + +local function register_get_by_type_index(table) + if type(table) == 'table' then + local metatable = getmetatable(table) + if not metatable then + metatable = {} + setmetatable(table, metatable) + end + metatable.__index = get_by_type + end + return table +end + +local function call(options) + local f = options[1] + local result = { xpcall(f, debug.traceback) } + if options.finally then + options.finally() + end + if result[1] then + table.remove(result, 1) + return unpack(result) + else + error(result[2]) + end +end + +local function read_file(file) + local f = io.open(file, 'rb') + local result = f:read('*all') + f:close() + return result +end + +_H = { + [[ Generate a form table, suitable for PubSubConfiguration and MAMQuery ]], + parameters = { {"fields", "The fields that will be converted into a form table"}, + {"form_type", "If specified, add a form_type field with this value"}, + {"type", "Form type, e.g. 'submit'"} } +} +local function create_form(...) + local options = parse_options({}, ...) + local result = { fields = {} } + -- FIXME: make nicer when parse_options binds positional arguments to names + if options.fields then + for var, value in pairs(options.fields) do + result.fields[#result.fields+1] = { name = var, value = value } + end + elseif options[1] then + for var, value in pairs(options[1]) do + result.fields[#result.fields+1] = { name = var, value = value } + end + end + if options.form_type then + result.fields[#result.fields+1] = { name = 'FORM_TYPE', value = options.form_type } + end + result['type'] = options.type + return result +end + +-------------------------------------------------------------------------------- +-- Metatables +-------------------------------------------------------------------------------- + +_H = { + [[ Client interface ]] +} +local Client = { + _with_prompt = function(client) return client:jid() end +} +Client.__index = Client +register_class_table_help(Client, "Client") + +_H = { + [[ Component interface ]] +} +local Component = { + _with_prompt = function(component) return component:jid() end +} +Component.__index = Component +register_class_table_help(Component, "Component") + + +_H = { + [[ Interface to communicate with a PubSub service ]] +} +local PubSub = {} +PubSub.__index = PubSub +register_class_table_help(PubSub, "PubSub") + +_H = { + [[ Interface to communicate with a PubSub node on a service ]] +} +local PubSubNode = {} +PubSubNode.__index = PubSubNode +register_class_table_help(PubSubNode, "PubSubNode") + + +-------------------------------------------------------------------------------- +-- with +-------------------------------------------------------------------------------- + +local original_G + +local function with (target, f) + -- Dynamic scope + if f then + with(target) + return call{f, finally = function() with() end} + end + + -- No scope + if target then + if not original_G then + original_G = copy(_G) + setmetatable(original_G, getmetatable(_G)) + clear(_G) + end + + setmetatable(_G, { + __index = function(_, key) + local value = target[key] + if value then + if type(value) == 'function' then + -- Add 'self' argument to all functions + return function(...) return value(target, ...) end + else + return value + end + else + return original_G[key] + end + end, + __newindex = original_G, + _completions = function () + local result = {} + if type(target) == "table" then + insert_all(result, keys(target)) + end + local mt = getmetatable(target) + if mt and type(mt.__index) == 'table' then + insert_all(result, keys(mt.__index)) + end + insert_all(result, keys(original_G)) + return result + end + }) + + -- Set prompt + local prompt = nil + + -- Try '_with_prompt' in metatable + local target_metatable = getmetatable(target) + if target_metatable then + if type(target_metatable._with_prompt) == "function" then + prompt = target_metatable._with_prompt(target) + else + prompt = target_metatable._with_prompt + end + end + + if not prompt then + -- Use tostring() + local target_string = tostring(target) + if string.len(target_string) > 25 then + prompt = string.sub(target_string, 0, 22) .. "..." + else + prompt = target_string + end + end + rawset(_G, "_PROMPT", prompt .. '> ') + else + -- Reset _G + clear(_G) + for key, value in pairs(original_G) do + _G[key] = value + end + setmetatable(_G, original_G) + end +end + +-------------------------------------------------------------------------------- +-- Client +-------------------------------------------------------------------------------- + +extra_help = { + ["Client.get_next_event"] = { + [[ Returns the next event. ]], + parameters = { "self" }, + options = { + type = "The type of event to return (`message`, `presence`, `pubsub`). When omitted, all event types are returned.", + timeout = "The amount of time to wait for events.", + ["if"] = "A function to filter events. When this function, called with the event as a parameter, returns true, the event will be returned" + } + }, + ["Client.get"] = { + [[ Sends a `get` query. ]], + parameters = { "self" }, + options = { + to = "The JID of the target to send the query to", + query = "The query to send", + timeout = "The amount of time to wait for the query to finish", + } + }, + ["Client.set"] = { + [[ Sends a `set` query. ]], + parameters = { "self" }, + options = { + to = "The JID of the target to send the query to", + query = "The query to send.", + timeout = "The amount of time to wait for the query to finish.", + } + }, + ["Client.async_connect"] = { + [[ + Connect to the server asynchronously. + + This method immediately returns. + ]], + parameters = { "self" }, + options = { + host = "The host to connect to. When omitted, is determined by resolving the client JID.", + port = "The port to connect to. When omitted, is determined by resolving the client JID." + } + } +} + +_H = { + [[ + Connect to the server. + + This method blocks until the connection has been established. + ]], + parameters = { "self" }, + options = extra_help["Client.async_connect"].options +} +function Client:connect (...) + local options = parse_options({}, ...) + local f = options.f + self:async_connect(options) + self:wait_connected() + if f then + return call {function() return f(self) end, finally = function() self:disconnect() end} + end + return true +end +register_help(Client.connect) + + +_H = { + [[ + Returns an iterator over all events. + + This function blocks until `timeout` is reached (or blocks forever if it is omitted). + ]], + parameters = { "self" }, + options = extra_help["Client.get_next_event"].options +} +function Client:events (options) + local function client_events_iterator(s) + return s['client']:get_next_event(s['options']) + end + return client_events_iterator, {client = self, options = options} +end +register_help(Client.events) + + +_H = { + [[ + Calls `f` for each event. + ]], + parameters = { "self" }, + options = merge_tables(get_help(Client.events).options, { + f = "The functor to call with each event. Required." + }) +} +function Client:for_each_event (...) + local options = parse_options({}, ...) + if not type(options.f) == 'function' then error('Expected function') end + for event in self:events(options) do + local result = options.f(event) + if result then + return result + end + end +end +register_help(Client.for_each_event) + +for method, event_type in pairs({message = 'message', presence = 'presence', pubsub_event = 'pubsub'}) do + _H = { + "Call `f` for all events of type `" .. event_type .. "`.", + parameters = { "self" }, + options = remove_help_parameters("type", get_help(Client.for_each_event).options) + } + Client['for_each_' .. method] = function (client, ...) + local options = parse_options({}, ...) + options['type'] = event_type + return client:for_each_event (options) + end + register_help(Client['for_each_' .. method]) + + _H = { + "Get the next event of type `" .. event_type .. "`.", + parameters = { "self" }, + options = remove_help_parameters("type", extra_help["Client.get_next_event"].options) + } + Client['get_next_' .. method] = function (client, ...) + local options = parse_options({}, ...) + options['type'] = event_type + return client:get_next_event(options) + end + register_help(Client['get_next_' .. method]) +end + +for method, event_type in pairs({messages = 'message', pubsub_events = 'pubsub'}) do + _H = { + "Returns an iterator over all events of type `" .. event_type .. "`.", + parameters = { "self" }, + options = remove_help_parameters("type", get_help(Client.for_each_event).options) + } + Client[method] = function (client, ...) + local options = parse_options({}, ...) + options['type'] = event_type + return client:events (options) + end + register_help(Client[method]) +end + +_H = { + [[ + Process all pending events + ]], + parameters = { "self" } +} +function Client:process_events () + for event in self:events{timeout=0} do end +end +register_help(Client.process_events) + + +-- +-- Register get_* and set_* convenience methods for some type of queries +-- +-- Example usages: +-- client:get_software_version{to = 'alice@wonderland.lit'} +-- client:set_command{to = 'alice@wonderland.lit', command = { type = 'execute', node = 'uptime' }} +-- +local get_set_shortcuts = { + get = {'software_version', 'disco_items', 'disco_info', 'xml', 'dom', 'vcard', 'mam'}, + set = {'command', 'vcard', 'mam'} +} +for query_action, query_types in pairs(get_set_shortcuts) do + for _, query_type in ipairs(query_types) do + _H = { + "Sends a `" .. query_action .. "` query of type `" .. query_type .. "`.\n" .. + "Apart from the options below, all top level elements of `" .. query_type .. "` can be passed.", + parameters = { "self" }, + options = remove_help_parameters({"query", "type"}, extra_help["Client.get"].options), + } + local method = query_action .. '_' .. query_type + Client[method] = function (client, options) + options = options or {} + if type(options) ~= 'table' then error('Invalid options: ' .. options) end + options['query'] = merge_tables({_type = query_type}, options[query_type] or {}) + return client[query_action](client, options) + end + register_help(Client[method]) + end +end + +_H = { + [[ Returns a @{PubSub} object for communicating with the PubSub service at `jid`. ]], + parameters = { + "self", + {"jid", "The JID of the PubSub service"} + } +} +function Client:pubsub (jid) + local result = { client = self, jid = jid } + setmetatable(result, PubSub) + return result +end +register_help(Client.pubsub) + + +-------------------------------------------------------------------------------- +-- Component +-------------------------------------------------------------------------------- + +component_extra_help = { + ["Component.get_next_event"] = { + [[ Returns the next event. ]], + parameters = { "self" }, + options = { + type = "The type of event to return (`message`, `presence`). When omitted, all event types are returned.", + timeout = "The amount of time to wait for events.", + ["if"] = "A function to filter events. When this function, called with the event as a parameter, returns true, the event will be returned" + } + }, + ["Component.get"] = { + [[ Sends a `get` query. ]], + parameters = { "self" }, + options = { + to = "The JID of the target to send the query to", + query = "The query to send", + timeout = "The amount of time to wait for the query to finish", + } + }, + ["Component.set"] = { + [[ Sends a `set` query. ]], + parameters = { "self" }, + options = { + to = "The JID of the target to send the query to", + query = "The query to send.", + timeout = "The amount of time to wait for the query to finish.", + } + }, + ["Component.async_connect"] = { + [[ + Connect to the server asynchronously. + + This method immediately returns. + ]], + parameters = { "self" }, + options = { + host = "The host to connect to.", + port = "The port to connect to." + } + } +} + +_H = { + [[ + Connect to the server. + + This method blocks until the connection has been established. + ]], + parameters = { "self" }, + options = component_extra_help["Component.async_connect"].options +} +function Component:connect (...) + local options = parse_options({}, ...) + local f = options.f + self:async_connect(options) + self:wait_connected() + if f then + return call {function() return f(self) end, finally = function() self:disconnect() end} + end + return true +end +register_help(Component.connect) + + +_H = { + [[ + Returns an iterator over all events. + + This function blocks until `timeout` is reached (or blocks forever if it is omitted). + ]], + parameters = { "self" }, + options = component_extra_help["Component.get_next_event"].options +} +function Component:events (options) + local function component_events_iterator(s) + return s['component']:get_next_event(s['options']) + end + return component_events_iterator, {component = self, options = options} +end +register_help(Component.events) + + +_H = { + [[ + Calls `f` for each event. + ]], + parameters = { "self" }, + options = merge_tables(get_help(Component.events).options, { + f = "The functor to call with each event. Required." + }) +} +function Component:for_each_event (...) + local options = parse_options({}, ...) + if not type(options.f) == 'function' then error('Expected function') end + for event in self:events(options) do + local result = options.f(event) + if result then + return result + end + end +end +register_help(Component.for_each_event) + +for method, event_type in pairs({message = 'message', presence = 'presence'}) do + _H = { + "Call `f` for all events of type `" .. event_type .. "`.", + parameters = { "self" }, + options = remove_help_parameters("type", get_help(Component.for_each_event).options) + } + Component['for_each_' .. method] = function (component, ...) + local options = parse_options({}, ...) + options['type'] = event_type + return component:for_each_event (options) + end + register_help(Component['for_each_' .. method]) + + _H = { + "Get the next event of type `" .. event_type .. "`.", + parameters = { "self" }, + options = remove_help_parameters("type", component_extra_help["Component.get_next_event"].options) + } + Component['get_next_' .. method] = function (component, ...) + local options = parse_options({}, ...) + options['type'] = event_type + return component:get_next_event(options) + end + register_help(Component['get_next_' .. method]) +end + +for method, event_type in pairs({messages = 'message'}) do + _H = { + "Returns an iterator over all events of type `" .. event_type .. "`.", + parameters = { "self" }, + options = remove_help_parameters("type", get_help(Component.for_each_event).options) + } + Component[method] = function (component, ...) + local options = parse_options({}, ...) + options['type'] = event_type + return component:events (options) + end + register_help(Component[method]) +end + +_H = { + [[ + Process all pending events + ]], + parameters = { "self" } +} +function Component:process_events () + for event in self:events{timeout=0} do end +end +register_help(Component.process_events) + + +-- +-- Register get_* and set_* convenience methods for some type of queries +-- +-- Example usages: +-- component:get_software_version{to = 'alice@wonderland.lit'} +-- component:set_command{to = 'alice@wonderland.lit', command = { type = 'execute', node = 'uptime' }} +-- +local get_set_shortcuts = { + get = {'software_version', 'disco_items', 'disco_info', 'xml', 'dom', 'vcard'}, + set = {'command', 'vcard'} +} +for query_action, query_types in pairs(get_set_shortcuts) do + for _, query_type in ipairs(query_types) do + _H = { + "Sends a `" .. query_action .. "` query of type `" .. query_type .. "`.\n" .. + "Apart from the options below, all top level elements of `" .. query_type .. "` can be passed.", + parameters = { "self" }, + options = remove_help_parameters({"query", "type"}, component_extra_help["Component.get"].options), + } + local method = query_action .. '_' .. query_type + Component[method] = function (component, options) + options = options or {} + if type(options) ~= 'table' then error('Invalid options: ' .. options) end + options['query'] = merge_tables({_type = query_type}, options[query_type] or {}) + return component[query_action](component, options) + end + register_help(Component[method]) + end +end + +-------------------------------------------------------------------------------- +-- PubSub +-------------------------------------------------------------------------------- + +local function process_pubsub_event (event) + if event._type == 'pubsub_event_items' then + -- Add 'item' shortcut to payload of first item + event.item = event.items and event.items[1] and + event.items[1].data and event.items[1].data[1] + end +end + +function PubSub:list_nodes (options) + return self.client:get_disco_items(merge_tables({to = self.jid}, options)) +end + +function PubSub:node (node) + local result = { client = self.client, jid = self.jid, node = node } + setmetatable(result, PubSubNode) + return result +end + +local simple_pubsub_queries = { + get_default_configuration = 'pubsub_owner_default', + get_subscriptions = 'pubsub_subscriptions', + get_affiliations = 'pubsub_affiliations', + get_default_subscription_options = 'pubsub_default', +} +for method, query_type in pairs(simple_pubsub_queries) do + PubSub[method] = function (service, options) + options = options or {} + return service.client:query_pubsub(merge_tables( + { type = 'get', to = service.jid, query = { _type = query_type } }, + options)) + end +end + +for _, method in ipairs({'events', 'get_next_event', 'for_each_event'}) do + PubSub[method] = function (node, ...) + local options = parse_options({}, ...) + options['if'] = function (event) + return event.type == 'pubsub' and event.from == node.jid and event.node == node + end + return node.client[method](node.client, options) + end +end + +-------------------------------------------------------------------------------- +-- PubSubNode +-------------------------------------------------------------------------------- + +local function pubsub_node_configuration_to_form(configuration) + return create_form{configuration, form_type="http://jabber.org/protocol/pubsub#node_config", type="submit"} +end + +function PubSubNode:list_items (options) + return self.client:get_disco_items(merge_tables({to = self.jid, disco_items = { node = self.node }}, options)) +end + +local simple_pubsub_node_queries = { + get_configuration = 'pubsub_owner_configure', + get_subscriptions = 'pubsub_subscriptions', + get_affiliations = 'pubsub_affiliations', + get_owner_subscriptions = 'pubsub_owner_subscriptions', + get_owner_affiliations = 'pubsub_owner_affiliations', + get_default_subscription_options = 'pubsub_default', +} +for method, query_type in pairs(simple_pubsub_node_queries) do + PubSubNode[method] = function (node, options) + return node.client:query_pubsub(merge_tables({ + type = 'get', to = node.jid, query = { + _type = query_type, node = node.node + }}, options)) + end +end + +function PubSubNode:get_items (...) + local options = parse_options({}, ...) + local items = options.items or {} + if options.maximum_items then + items = merge_tables({maximum_items = options.maximum_items}, items) + end + items = merge_tables({_type = 'pubsub_items', node = self.node}, items) + return self.client:query_pubsub(merge_tables({ + type = 'get', to = self.jid, query = items}, options)) +end + +function PubSubNode:get_item (...) + local options = parse_options({}, ...) + if not type(options.id) == 'string' then error('Expected ID') end + return self:get_items{items = {{id = options.id}}} +end + +function PubSubNode:create (options) + options = options or {} + local configure + if options['configuration'] then + configure = { data = pubsub_node_configuration_to_form(options['configuration']) } + end + return self.client:query_pubsub(merge_tables( + { type = 'set', to = self.jid, query = { + _type = 'pubsub_create', node = self.node, configure = configure } + }, options)) +end + +function PubSubNode:delete (options) + options = options or {} + local redirect + if options['redirect'] then + redirect = {uri = options['redirect']} + end + return self.client:query_pubsub(merge_tables({ type = 'set', to = self.jid, query = { + _type = 'pubsub_owner_delete', node = self.node, redirect = redirect + }}, options)) +end + +function PubSubNode:set_configuration(options) + options = options or {} + local configuration = pubsub_node_configuration_to_form(options['configuration']) + return self.client:query_pubsub(merge_tables( + { type = 'set', to = self.jid, query = { + _type = 'pubsub_owner_configure', node = self.node, data = configuration } + }, options)) +end + +function PubSubNode:set_owner_affiliations(...) + local options = parse_options({}, ...) + return self.client:query_pubsub(merge_tables({ + type = 'set', to = self.jid, query = merge_tables({ + _type = 'pubsub_owner_affiliations', node = self.node, + }, options.affiliations)}, options)) +end + + +function PubSubNode:subscribe(...) + local options = parse_options({}, ...) + local jid = options.jid or sluift.jid.to_bare(self.client:jid()) + return self.client:query_pubsub(merge_tables( + { type = 'set', to = self.jid, query = { + _type = 'pubsub_subscribe', node = self.node, jid = jid } + }, options)) +end + +function PubSubNode:unsubscribe(options) + options = options or {} + return self.client:query_pubsub(merge_tables( + { type = 'set', to = self.jid, query = { + _type = 'pubsub_unsubscribe', node = self.node, jid = options['jid'], + subscription_id = 'subscription_id'} + }, options)) +end + +function PubSubNode:get_subscription_options (options) + return self.client:query_pubsub(merge_tables( + { type = 'get', to = self.jid, query = { + _type = 'pubsub_options', node = self.node, jid = options['jid'] } + }, options)) +end + +function PubSubNode:publish(...) + local options = parse_options({}, ...) + local items = options.items or {} + if options.item then + if type(options.item) == 'string' or options.item._type then + items = {{id = options.id, data = { options.item } }} + options.id = nil + else + items = { options.item } + end + options.item = nil + end + return self.client:query_pubsub(merge_tables( + { type = 'set', to = self.jid, query = { + _type = 'pubsub_publish', node = self.node, items = items } + }, options)) +end + +function PubSubNode:retract(...) + local options = parse_options({}, ...) + local items = options.items + if options.id then + items = {{id = options.id}} + end + return self.client:query_pubsub(merge_tables( + { type = 'set', to = self.jid, query = { + _type = 'pubsub_retract', node = self.node, items = items, notify = options['notify'] + }}, options)) +end + +function PubSubNode:purge(...) + local options = parse_options({}, ...) + return self.client:query_pubsub(merge_tables( + { type = 'set', to = self.jid, query = { + _type = 'pubsub_owner_purge', node = self.node + }}, options)) +end + +-- Iterators over events +for _, method in ipairs({'events', 'get_next_event', 'for_each_event'}) do + PubSubNode[method] = function (node, ...) + local options = parse_options({}, ...) + options['if'] = function (event) + return event.type == 'pubsub' and event.from == node.jid and event.node == node.node + end + return node.client[method](node.client, options) + end +end + +-------------------------------------------------------------------------------- +-- Service discovery +-------------------------------------------------------------------------------- + +local disco = { + features = { + DISCO_INFO = 'http://jabber.org/protocol/disco#info', + COMMANDS = 'http://jabber.org/protocol/commands', + USER_LOCATION = 'http://jabber.org/protocol/geoloc', + USER_TUNE = 'http://jabber.org/protocol/tune', + USER_AVATAR_METADATA = 'urn:xmpp:avatar:metadata', + USER_ACTIVITY = 'http://jabber.org/protocol/activity', + USER_PROFILE = 'urn:xmpp:tmp:profile' + } +} + +-------------------------------------------------------------------------------- + +_H = nil + +extra_help['sluift'] = { + [[ + This module provides methods for XMPP communication. + + The main entry point of this module is the `new_client` method, which creates a + new client for communicating with an XMPP server. + ]], + classes = help_classes +} + +return { + Client = Client, + Component = Component, + register_help = register_help, + register_class_help = register_class_help, + register_table_tostring = register_table_tostring, + register_table_equals = register_table_equals, + register_get_by_type_index = register_get_by_type_index, + process_pubsub_event = process_pubsub_event, + tprint = tprint, + read_file = read_file, + disco = disco, + get_help = get_help, + help = help, + extra_help = extra_help, + component_extra_help = component_extra_help, + copy = copy, + with = with, + create_form = create_form +} diff --git a/Sluift/globals.h b/Sluift/globals.h index 3e7e1c9..f92beeb 100644 --- a/Sluift/globals.h +++ b/Sluift/globals.h @@ -1,6 +1,6 @@ /* - * Copyright (c) 2013 Remko Tronçon - * Licensed under the GNU General Public License. + * Copyright (c) 2013 Isode Limited. + * All rights reserved. * See the COPYING file for more information. */ @@ -9,7 +9,7 @@ #include <Sluift/SluiftGlobals.h> namespace Swift { - namespace Sluift { - extern SluiftGlobals globals; - } + namespace Sluift { + extern SluiftGlobals globals; + } } diff --git a/Sluift/linit.c b/Sluift/linit.c deleted file mode 100644 index 8507609..0000000 --- a/Sluift/linit.c +++ /dev/null @@ -1,27 +0,0 @@ -#include <lua.h> -#include <lualib.h> -#include <lauxlib.h> -#include "sluift.h" - -static const luaL_Reg lualibs[] = { - {"", luaopen_base}, - {LUA_LOADLIBNAME, luaopen_package}, - {LUA_TABLIBNAME, luaopen_table}, - {LUA_IOLIBNAME, luaopen_io}, - {LUA_OSLIBNAME, luaopen_os}, - {LUA_STRLIBNAME, luaopen_string}, - {LUA_MATHLIBNAME, luaopen_math}, - {LUA_DBLIBNAME, luaopen_debug}, - {"sluift", luaopen_sluift}, - {NULL, NULL} -}; - - -LUALIB_API void luaL_openlibs (lua_State *L) { - const luaL_Reg *lib = lualibs; - for (; lib->func; lib++) { - lua_pushcfunction(L, lib->func); - lua_pushstring(L, lib->name); - lua_call(L, 1, 0); - } -} diff --git a/Sluift/main.cpp b/Sluift/main.cpp new file mode 100644 index 0000000..65d6d60 --- /dev/null +++ b/Sluift/main.cpp @@ -0,0 +1,192 @@ +/* + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <iostream> +#include <string> +#include <vector> + +#include <boost/assign/list_of.hpp> +#include <boost/numeric/conversion/cast.hpp> +#include <boost/program_options.hpp> +#include <boost/program_options/options_description.hpp> +#include <boost/program_options/variables_map.hpp> +#include <boost/version.hpp> + +#include <lua.hpp> + +#include <Swiften/Base/Platform.h> + +#include <Sluift/globals.h> +#include <Sluift/Console.h> +#include <Sluift/StandardTerminal.h> +#include <Sluift/sluift.h> +#include <Sluift/Lua/LuaUtils.h> +#ifdef HAVE_EDITLINE +#include <Sluift/EditlineTerminal.h> +#endif +#include <Sluift/Version.h> + +using namespace Swift; + +#ifdef SWIFTEN_PLATFORM_WINDOWS +#define EXIT_KEY "Z" +#else +#define EXIT_KEY "D" +#endif + +static const std::string SLUIFT_WELCOME_STRING( + "== Sluift XMPP Console (" SLUIFT_VERSION_STRING ")\nPress Ctrl-" EXIT_KEY " to exit. Type help() for help."); + +static const luaL_Reg defaultLibraries[] = { + {"", luaopen_base}, + {LUA_LOADLIBNAME, luaopen_package}, + {LUA_TABLIBNAME, luaopen_table}, + {LUA_IOLIBNAME, luaopen_io}, + {LUA_OSLIBNAME, luaopen_os}, + {LUA_STRLIBNAME, luaopen_string}, + {LUA_MATHLIBNAME, luaopen_math}, + {LUA_DBLIBNAME, luaopen_debug}, + {"sluift", luaopen_sluift}, + {nullptr, nullptr} +}; + +static void handleInterruptSignal(int) { + Sluift::globals.interruptRequested = 1; +} + +static void checkResult(lua_State* L, int result) { + if (result && !lua_isnil(L, -1)) { + const char* errorMessage = lua_tostring(L, -1); + throw std::runtime_error(errorMessage ? errorMessage : "Unknown error"); + } +} + +static void initialize(lua_State* L) { + lua_gc(L, LUA_GCSTOP, 0); + for (const luaL_Reg* lib = defaultLibraries; lib->func; lib++) { +#if LUA_VERSION_NUM >= 502 + luaL_requiref(L, lib->name, lib->func, 1); + lua_pop(L, 1); +#else + lua_pushcfunction(L, lib->func); + lua_pushstring(L, lib->name); + lua_call(L, 1, 0); +#endif + } + lua_gc(L, LUA_GCRESTART, 0); +} + +static void runScript(lua_State* L, const std::string& script, const std::vector<std::string>& scriptArguments) { + // Create arguments table + lua_createtable(L, boost::numeric_cast<int>(scriptArguments.size()), 0); + for (size_t i = 0; i < scriptArguments.size(); ++i) { + lua_pushstring(L, scriptArguments[i].c_str()); + lua_rawseti(L, -2, boost::numeric_cast<int>(i+1)); + } + lua_setglobal(L, "arg"); + + // Load file + checkResult(L, luaL_loadfile(L, script.c_str())); + for (const auto& scriptArgument : scriptArguments) { + lua_pushstring(L, scriptArgument.c_str()); + } + checkResult(L, Console::call(L, boost::numeric_cast<int>(scriptArguments.size()), false)); +} + +int main(int argc, char* argv[]) { + // Parse program options + boost::program_options::options_description visibleOptions("Options"); + visibleOptions.add_options() + ("help,h", "Display this help message") + ("version,v", "Display version information") + ("interactive,i", "Enter interactive mode after executing script") + ; + boost::program_options::options_description hiddenOptions("Hidden Options"); + hiddenOptions.add_options() + ("script", boost::program_options::value< std::string >(), "Script to be executed") + ("script-arguments", boost::program_options::value< std::vector<std::string> >(), "Script arguments") + ; + boost::program_options::options_description options("All Options"); + options.add(visibleOptions).add(hiddenOptions); + + boost::program_options::positional_options_description positional_options; + positional_options.add("script", 1).add("script-arguments", -1); + + boost::program_options::variables_map arguments; + try { + boost::program_options::store( + boost::program_options::command_line_parser(argc, argv) + .options(options) + .positional(positional_options).run(), arguments); + } + catch (const boost::program_options::unknown_option& option) { +#if BOOST_VERSION >= 104200 + std::cout << "Ignoring unknown option " << option.get_option_name() << " but continuing." << std::endl; +#else + std::cout << "Error: " << option.what() << " (continuing)" << std::endl; +#endif + } + catch (const std::exception& e) { + std::cout << "Error: " << e.what() << std::endl; + return -1; + } + boost::program_options::notify(arguments); + + // Help & version + if (arguments.count("help")) { + std::cout << visibleOptions << "\n"; + return 0; + } + else if (arguments.count("version")) { + std::cout << SLUIFT_VERSION_STRING; + return 0; + } + + lua_State* L = luaL_newstate(); + initialize(L); + try { + // Run script + if (arguments.count("script")) { + std::vector<std::string> scriptArguments; + if (arguments.count("script-arguments")) { + scriptArguments = arguments["script-arguments"].as< std::vector<std::string> >(); + } + runScript(L, arguments["script"].as<std::string>(), scriptArguments); + } + + // Run console + if (arguments.count("interactive") || arguments.count("script") == 0) { + // Set up signal handler + signal(SIGINT, handleInterruptSignal); + + // Import some useful functions into the global namespace + lua_getglobal(L, "sluift"); + std::vector<std::string> globalImports = boost::assign::list_of + ("help")("with"); + for (const auto& globalImport : globalImports) { + lua_getfield(L, -1, globalImport.c_str()); + lua_setglobal(L, globalImport.c_str()); + } + lua_pop(L, 1); + + std::cout << SLUIFT_WELCOME_STRING << std::endl; +#ifdef HAVE_EDITLINE + EditlineTerminal& terminal = EditlineTerminal::getInstance(); +#else + StandardTerminal terminal; +#endif + Console console(L, &terminal); + console.run(); + } + } + catch (const std::exception& e) { + std::cerr << e.what() << std::endl; + lua_close(L); + return -1; + } + lua_close(L); + return 0; +} 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; } diff --git a/Sluift/sluift.h b/Sluift/sluift.h index b82e1c4..4ffe3bf 100644 --- a/Sluift/sluift.h +++ b/Sluift/sluift.h @@ -1,7 +1,7 @@ /* - * 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-2013 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. */ #pragma once diff --git a/Sluift/tokenize.cpp b/Sluift/tokenize.cpp new file mode 100644 index 0000000..ff162d6 --- /dev/null +++ b/Sluift/tokenize.cpp @@ -0,0 +1,87 @@ +/* + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#include <Sluift/tokenize.h> + +#include <cctype> + +#include <boost/tokenizer.hpp> + +using namespace Swift; + +namespace { + struct LuaTokenizeFunctor { + void reset() { + } + + template<typename InputIterator, typename Token> + bool operator()(InputIterator& next, InputIterator& end, Token& result) { + while (next != end && std::isspace(*next)) { + ++next; + } + if (next == end) { + return false; + } + + std::vector<char> token; + char c = *next++; + token.push_back(c); + + // String literal + if (c == '\'' || c == '"') { + char quote = c; + bool inEscape = false; + for (; next != end; ++next) { + c = *next; + token.push_back(c); + if (inEscape) { + inEscape = false; + } + else if (c == '\\') { + inEscape = true; + } + else if (c == quote) { + break; + } + } + if (next != end) { + ++next; + } + } + // Identifier + else if (std::isalpha(c) || c == '_') { + while (next != end && (std::isalpha(*next) || *next == '_' || std::isdigit(*next))) { + token.push_back(*next); + ++next; + } + } + // Digit + else if (std::isdigit(c)) { + while (next != end && !std::isspace(*next)) { + token.push_back(*next); + ++next; + } + } + // Dots + else if (c == '.') { + while (next != end && *next == '.') { + token.push_back(*next); + ++next; + } + } + + result = Token(&token[0], token.size()); + return true; + } + }; +} + + +std::vector<std::string> Lua::tokenize(const std::string& input) { + boost::tokenizer<LuaTokenizeFunctor> tokenizer(input); + return std::vector<std::string>(tokenizer.begin(), tokenizer.end()); +} + diff --git a/Sluift/tokenize.h b/Sluift/tokenize.h new file mode 100644 index 0000000..33ea435 --- /dev/null +++ b/Sluift/tokenize.h @@ -0,0 +1,16 @@ +/* + * Copyright (c) 2013-2016 Isode Limited. + * All rights reserved. + * See the COPYING file for more information. + */ + +#pragma once + +#include <string> +#include <vector> + +namespace Swift { + namespace Lua { + std::vector<std::string> tokenize(const std::string&); + } +} |