summaryrefslogtreecommitdiffstats
path: root/Sluift
diff options
context:
space:
mode:
Diffstat (limited to 'Sluift')
-rw-r--r--Sluift/.gitignore3
-rw-r--r--Sluift/ClientHelpers.cpp50
-rw-r--r--Sluift/ClientHelpers.h18
-rw-r--r--Sluift/ElementConvertors/BodyConvertor.cpp35
-rw-r--r--Sluift/ElementConvertors/BodyConvertor.h25
-rw-r--r--Sluift/ElementConvertors/CommandConvertor.cpp195
-rw-r--r--Sluift/ElementConvertors/CommandConvertor.h28
-rw-r--r--Sluift/ElementConvertors/DOMElementConvertor.cpp194
-rw-r--r--Sluift/ElementConvertors/DOMElementConvertor.h28
-rw-r--r--Sluift/ElementConvertors/DefaultElementConvertor.cpp30
-rw-r--r--Sluift/ElementConvertors/DefaultElementConvertor.h22
-rw-r--r--Sluift/ElementConvertors/DiscoInfoConvertor.cpp101
-rw-r--r--Sluift/ElementConvertors/DiscoInfoConvertor.h23
-rw-r--r--Sluift/ElementConvertors/DiscoItemsConvertor.cpp68
-rw-r--r--Sluift/ElementConvertors/DiscoItemsConvertor.h23
-rw-r--r--Sluift/ElementConvertors/ElementConvertors.ipp81
-rw-r--r--Sluift/ElementConvertors/FormConvertor.cpp361
-rw-r--r--Sluift/ElementConvertors/FormConvertor.h23
-rw-r--r--Sluift/ElementConvertors/PubSubAffiliationConvertor.cpp84
-rw-r--r--Sluift/ElementConvertors/PubSubAffiliationConvertor.h28
-rw-r--r--Sluift/ElementConvertors/PubSubAffiliationsConvertor.cpp70
-rw-r--r--Sluift/ElementConvertors/PubSubAffiliationsConvertor.h28
-rw-r--r--Sluift/ElementConvertors/PubSubConfigureConvertor.cpp44
-rw-r--r--Sluift/ElementConvertors/PubSubConfigureConvertor.h28
-rw-r--r--Sluift/ElementConvertors/PubSubCreateConvertor.cpp51
-rw-r--r--Sluift/ElementConvertors/PubSubCreateConvertor.h28
-rw-r--r--Sluift/ElementConvertors/PubSubDefaultConvertor.cpp68
-rw-r--r--Sluift/ElementConvertors/PubSubDefaultConvertor.h28
-rw-r--r--Sluift/ElementConvertors/PubSubEventAssociateConvertor.cpp41
-rw-r--r--Sluift/ElementConvertors/PubSubEventAssociateConvertor.h28
-rw-r--r--Sluift/ElementConvertors/PubSubEventCollectionConvertor.cpp63
-rw-r--r--Sluift/ElementConvertors/PubSubEventCollectionConvertor.h28
-rw-r--r--Sluift/ElementConvertors/PubSubEventConfigurationConvertor.cpp51
-rw-r--r--Sluift/ElementConvertors/PubSubEventConfigurationConvertor.h28
-rw-r--r--Sluift/ElementConvertors/PubSubEventConvertor.cpp37
-rw-r--r--Sluift/ElementConvertors/PubSubEventConvertor.h28
-rw-r--r--Sluift/ElementConvertors/PubSubEventDeleteConvertor.cpp51
-rw-r--r--Sluift/ElementConvertors/PubSubEventDeleteConvertor.h28
-rw-r--r--Sluift/ElementConvertors/PubSubEventDisassociateConvertor.cpp41
-rw-r--r--Sluift/ElementConvertors/PubSubEventDisassociateConvertor.h28
-rw-r--r--Sluift/ElementConvertors/PubSubEventItemConvertor.cpp92
-rw-r--r--Sluift/ElementConvertors/PubSubEventItemConvertor.h28
-rw-r--r--Sluift/ElementConvertors/PubSubEventItemsConvertor.cpp102
-rw-r--r--Sluift/ElementConvertors/PubSubEventItemsConvertor.h28
-rw-r--r--Sluift/ElementConvertors/PubSubEventPurgeConvertor.cpp41
-rw-r--r--Sluift/ElementConvertors/PubSubEventPurgeConvertor.h28
-rw-r--r--Sluift/ElementConvertors/PubSubEventRedirectConvertor.cpp41
-rw-r--r--Sluift/ElementConvertors/PubSubEventRedirectConvertor.h28
-rw-r--r--Sluift/ElementConvertors/PubSubEventRetractConvertor.cpp41
-rw-r--r--Sluift/ElementConvertors/PubSubEventRetractConvertor.h28
-rw-r--r--Sluift/ElementConvertors/PubSubEventSubscriptionConvertor.cpp95
-rw-r--r--Sluift/ElementConvertors/PubSubEventSubscriptionConvertor.h28
-rw-r--r--Sluift/ElementConvertors/PubSubItemConvertor.cpp72
-rw-r--r--Sluift/ElementConvertors/PubSubItemConvertor.h28
-rw-r--r--Sluift/ElementConvertors/PubSubItemsConvertor.cpp86
-rw-r--r--Sluift/ElementConvertors/PubSubItemsConvertor.h28
-rw-r--r--Sluift/ElementConvertors/PubSubOptionsConvertor.cpp67
-rw-r--r--Sluift/ElementConvertors/PubSubOptionsConvertor.h28
-rw-r--r--Sluift/ElementConvertors/PubSubOwnerAffiliationConvertor.cpp84
-rw-r--r--Sluift/ElementConvertors/PubSubOwnerAffiliationConvertor.h28
-rw-r--r--Sluift/ElementConvertors/PubSubOwnerAffiliationsConvertor.cpp68
-rw-r--r--Sluift/ElementConvertors/PubSubOwnerAffiliationsConvertor.h28
-rw-r--r--Sluift/ElementConvertors/PubSubOwnerConfigureConvertor.cpp53
-rw-r--r--Sluift/ElementConvertors/PubSubOwnerConfigureConvertor.h28
-rw-r--r--Sluift/ElementConvertors/PubSubOwnerDefaultConvertor.cpp44
-rw-r--r--Sluift/ElementConvertors/PubSubOwnerDefaultConvertor.h28
-rw-r--r--Sluift/ElementConvertors/PubSubOwnerDeleteConvertor.cpp51
-rw-r--r--Sluift/ElementConvertors/PubSubOwnerDeleteConvertor.h28
-rw-r--r--Sluift/ElementConvertors/PubSubOwnerPurgeConvertor.cpp41
-rw-r--r--Sluift/ElementConvertors/PubSubOwnerPurgeConvertor.h28
-rw-r--r--Sluift/ElementConvertors/PubSubOwnerRedirectConvertor.cpp41
-rw-r--r--Sluift/ElementConvertors/PubSubOwnerRedirectConvertor.h28
-rw-r--r--Sluift/ElementConvertors/PubSubOwnerSubscriptionConvertor.cpp72
-rw-r--r--Sluift/ElementConvertors/PubSubOwnerSubscriptionConvertor.h28
-rw-r--r--Sluift/ElementConvertors/PubSubOwnerSubscriptionsConvertor.cpp68
-rw-r--r--Sluift/ElementConvertors/PubSubOwnerSubscriptionsConvertor.h28
-rw-r--r--Sluift/ElementConvertors/PubSubPublishConvertor.cpp72
-rw-r--r--Sluift/ElementConvertors/PubSubPublishConvertor.h28
-rw-r--r--Sluift/ElementConvertors/PubSubRetractConvertor.cpp79
-rw-r--r--Sluift/ElementConvertors/PubSubRetractConvertor.h28
-rw-r--r--Sluift/ElementConvertors/PubSubSubscribeConvertor.cpp60
-rw-r--r--Sluift/ElementConvertors/PubSubSubscribeConvertor.h28
-rw-r--r--Sluift/ElementConvertors/PubSubSubscribeOptionsConvertor.cpp41
-rw-r--r--Sluift/ElementConvertors/PubSubSubscribeOptionsConvertor.h28
-rw-r--r--Sluift/ElementConvertors/PubSubSubscriptionConvertor.cpp100
-rw-r--r--Sluift/ElementConvertors/PubSubSubscriptionConvertor.h28
-rw-r--r--Sluift/ElementConvertors/PubSubSubscriptionsConvertor.cpp70
-rw-r--r--Sluift/ElementConvertors/PubSubSubscriptionsConvertor.h28
-rw-r--r--Sluift/ElementConvertors/PubSubUnsubscribeConvertor.cpp59
-rw-r--r--Sluift/ElementConvertors/PubSubUnsubscribeConvertor.h28
-rw-r--r--Sluift/ElementConvertors/RawXMLElementConvertor.cpp37
-rw-r--r--Sluift/ElementConvertors/RawXMLElementConvertor.h26
-rw-r--r--Sluift/ElementConvertors/SConscript42
-rw-r--r--Sluift/ElementConvertors/SoftwareVersionConvertor.cpp50
-rw-r--r--Sluift/ElementConvertors/SoftwareVersionConvertor.h23
-rw-r--r--Sluift/ElementConvertors/UserLocationConvertor.cpp232
-rw-r--r--Sluift/ElementConvertors/UserLocationConvertor.h28
-rw-r--r--Sluift/ElementConvertors/VCardConvertor.cpp46
-rw-r--r--Sluift/ElementConvertors/VCardConvertor.h23
-rw-r--r--Sluift/ElementConvertors/VCardUpdateConvertor.cpp36
-rw-r--r--Sluift/ElementConvertors/VCardUpdateConvertor.h23
-rw-r--r--Sluift/Examples/AdHocCommands.lua48
-rw-r--r--Sluift/Examples/CollectVersions.lua36
-rw-r--r--Sluift/Examples/ContactsMap.lua120
-rw-r--r--Sluift/Examples/EchoBot.lua44
-rw-r--r--Sluift/Examples/Login.lua32
-rw-r--r--Sluift/Examples/PEPListener.lua46
-rw-r--r--Sluift/Examples/RemoveUnreachableContacts.lua63
-rwxr-xr-xSluift/Examples/Wonderland.lua96
-rw-r--r--Sluift/GenericLuaElementConvertor.h54
-rw-r--r--Sluift/Lua/Check.cpp60
-rw-r--r--Sluift/Lua/Check.h26
-rw-r--r--Sluift/Lua/Debug.h28
-rw-r--r--Sluift/Lua/Exception.cpp15
-rw-r--r--Sluift/Lua/Exception.h20
-rw-r--r--Sluift/Lua/FunctionRegistration.cpp16
-rw-r--r--Sluift/Lua/FunctionRegistration.h36
-rw-r--r--Sluift/Lua/FunctionRegistry.cpp55
-rw-r--r--Sluift/Lua/FunctionRegistry.h46
-rw-r--r--Sluift/Lua/LuaUtils.cpp79
-rw-r--r--Sluift/Lua/LuaUtils.h32
-rw-r--r--Sluift/Lua/Value.cpp11
-rw-r--r--Sluift/Lua/Value.h28
-rw-r--r--Sluift/LuaElementConvertor.cpp14
-rw-r--r--Sluift/LuaElementConvertor.h28
-rw-r--r--Sluift/LuaElementConvertors.cpp112
-rw-r--r--Sluift/LuaElementConvertors.h47
-rw-r--r--Sluift/README2
-rw-r--r--Sluift/README.md52
-rw-r--r--Sluift/Response.cpp78
-rw-r--r--Sluift/Response.h34
-rw-r--r--Sluift/ResponseSink.h48
-rw-r--r--Sluift/SConscript105
-rw-r--r--Sluift/SConscript.variant25
-rw-r--r--Sluift/SluiftClient.cpp169
-rw-r--r--Sluift/SluiftClient.h133
-rw-r--r--Sluift/SluiftException.h70
-rw-r--r--Sluift/SluiftGlobals.h24
-rw-r--r--Sluift/Tests/ConnectTest.lua6
-rw-r--r--Sluift/Tests/DOMTest.lua14
-rw-r--r--Sluift/Tests/FormTest.lua79
-rw-r--r--Sluift/boot.lua447
-rw-r--r--Sluift/client.cpp576
-rw-r--r--Sluift/globals.h15
-rw-r--r--Sluift/linit.c33
-rw-r--r--Sluift/sluift.cpp914
-rw-r--r--Sluift/sluift.h13
147 files changed, 8113 insertions, 1039 deletions
diff --git a/Sluift/.gitignore b/Sluift/.gitignore
index 35a18c0..e5fd1e5 100644
--- a/Sluift/.gitignore
+++ b/Sluift/.gitignore
@@ -2,3 +2,6 @@ lua.c
sluift_dll.cpp
sluift
dll.c
+boot.c
+dll/
+exe/
diff --git a/Sluift/ClientHelpers.cpp b/Sluift/ClientHelpers.cpp
new file mode 100644
index 0000000..8e07112
--- /dev/null
+++ b/Sluift/ClientHelpers.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#include <Sluift/ClientHelpers.h>
+
+#include <Swiften/Client/ClientError.h>
+
+using namespace Swift;
+
+std::string Swift::getClientErrorString(const ClientError& error) {
+ std::string reason = "Disconnected: ";
+ switch(error.getType()) {
+ case ClientError::UnknownError: reason += "Unknown Error"; break;
+ case ClientError::DomainNameResolveError: reason += "Unable to find server"; break;
+ case ClientError::ConnectionError: reason += "Error connecting to server"; break;
+ case ClientError::ConnectionReadError: reason += "Error while receiving server data"; break;
+ case ClientError::ConnectionWriteError: reason += "Error while sending data to the server"; break;
+ case ClientError::XMLError: reason += "Error parsing server data"; break;
+ case ClientError::AuthenticationFailedError: reason += "Login/password invalid"; break;
+ case ClientError::CompressionFailedError: reason += "Error while compressing stream"; break;
+ case ClientError::ServerVerificationFailedError: reason += "Server verification failed"; break;
+ case ClientError::NoSupportedAuthMechanismsError: reason += "Authentication mechanisms not supported"; break;
+ case ClientError::UnexpectedElementError: reason += "Unexpected response"; break;
+ case ClientError::ResourceBindError: reason += "Error binding resource"; break;
+ case ClientError::RevokedError: reason += "Certificate got revoked"; break;
+ case ClientError::RevocationCheckFailedError: reason += "Failed to do revokation check"; break;
+ case ClientError::SessionStartError: reason += "Error starting session"; break;
+ case ClientError::StreamError: reason += "Stream error"; break;
+ case ClientError::TLSError: reason += "Encryption error"; break;
+ case ClientError::ClientCertificateLoadError: reason += "Error loading certificate (Invalid password?)"; break;
+ case ClientError::ClientCertificateError: reason += "Certificate not authorized"; break;
+ case ClientError::UnknownCertificateError: reason += "Unknown certificate"; break;
+ case ClientError::CertificateCardRemoved: reason += "Certificate card removed"; break;
+ case ClientError::CertificateExpiredError: reason += "Certificate has expired"; break;
+ case ClientError::CertificateNotYetValidError: reason += "Certificate is not yet valid"; break;
+ case ClientError::CertificateSelfSignedError: reason += "Certificate is self-signed"; break;
+ case ClientError::CertificateRejectedError: reason += "Certificate has been rejected"; break;
+ case ClientError::CertificateUntrustedError: reason += "Certificate is not trusted"; break;
+ case ClientError::InvalidCertificatePurposeError: reason += "Certificate cannot be used for encrypting your connection"; break;
+ case ClientError::CertificatePathLengthExceededError: reason += "Certificate path length constraint exceeded"; break;
+ case ClientError::InvalidCertificateSignatureError: reason += "Invalid certificate signature"; break;
+ case ClientError::InvalidCAError: reason += "Invalid Certificate Authority"; break;
+ case ClientError::InvalidServerIdentityError: reason += "Certificate does not match the host identity"; break;
+ }
+ return reason;
+}
+
diff --git a/Sluift/ClientHelpers.h b/Sluift/ClientHelpers.h
new file mode 100644
index 0000000..eb78ba6
--- /dev/null
+++ b/Sluift/ClientHelpers.h
@@ -0,0 +1,18 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#pragma once
+
+#include <Swiften/Base/Override.h>
+#include <Swiften/Base/API.h>
+
+#include <string>
+
+namespace Swift {
+ class ClientError;
+
+ std::string getClientErrorString(const ClientError& error);
+}
diff --git a/Sluift/ElementConvertors/BodyConvertor.cpp b/Sluift/ElementConvertors/BodyConvertor.cpp
new file mode 100644
index 0000000..a7abc1e
--- /dev/null
+++ b/Sluift/ElementConvertors/BodyConvertor.cpp
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#include <Sluift/ElementConvertors/BodyConvertor.h>
+
+#include <lua.hpp>
+#include <boost/smart_ptr/make_shared.hpp>
+#include <Sluift/Lua/LuaUtils.h>
+
+using namespace Swift;
+
+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;
+}
+
+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");
+ }
+}
diff --git a/Sluift/ElementConvertors/BodyConvertor.h b/Sluift/ElementConvertors/BodyConvertor.h
new file mode 100644
index 0000000..b1cd494
--- /dev/null
+++ b/Sluift/ElementConvertors/BodyConvertor.h
@@ -0,0 +1,25 @@
+/*
+ * 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 <Sluift/GenericLuaElementConvertor.h>
+#include <Swiften/Elements/Body.h>
+
+namespace Swift {
+ class LuaElementConvertors;
+
+ class BodyConvertor : public GenericLuaElementConvertor<Body> {
+ public:
+ BodyConvertor();
+ virtual ~BodyConvertor();
+
+ virtual boost::shared_ptr<Body> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE;
+ virtual void doConvertToLua(lua_State*, boost::shared_ptr<Body>) SWIFTEN_OVERRIDE;
+ };
+}
diff --git a/Sluift/ElementConvertors/CommandConvertor.cpp b/Sluift/ElementConvertors/CommandConvertor.cpp
new file mode 100644
index 0000000..7fb7b22
--- /dev/null
+++ b/Sluift/ElementConvertors/CommandConvertor.cpp
@@ -0,0 +1,195 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#include <Sluift/ElementConvertors/CommandConvertor.h>
+
+#include <lua.hpp>
+#include <boost/smart_ptr/make_shared.hpp>
+#include <boost/numeric/conversion/cast.hpp>
+
+#include <Swiften/Base/foreach.h>
+#include <Sluift/Lua/Check.h>
+#include <Sluift/Lua/Value.h>
+#include <Sluift/LuaElementConvertors.h>
+
+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;
+}
+
+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 "";
+}
+
+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;
+}
+
+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");
+ }
+}
diff --git a/Sluift/ElementConvertors/CommandConvertor.h b/Sluift/ElementConvertors/CommandConvertor.h
new file mode 100644
index 0000000..7008b50
--- /dev/null
+++ b/Sluift/ElementConvertors/CommandConvertor.h
@@ -0,0 +1,28 @@
+/*
+ * 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 <Sluift/GenericLuaElementConvertor.h>
+#include <Swiften/Elements/Command.h>
+
+namespace Swift {
+ class LuaElementConvertors;
+
+ class CommandConvertor : public GenericLuaElementConvertor<Command> {
+ public:
+ CommandConvertor(LuaElementConvertors* convertors);
+ virtual ~CommandConvertor();
+
+ virtual boost::shared_ptr<Command> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE;
+ virtual void doConvertToLua(lua_State*, boost::shared_ptr<Command>) SWIFTEN_OVERRIDE;
+
+ private:
+ LuaElementConvertors* convertors;
+ };
+}
diff --git a/Sluift/ElementConvertors/DOMElementConvertor.cpp b/Sluift/ElementConvertors/DOMElementConvertor.cpp
new file mode 100644
index 0000000..bb4256d
--- /dev/null
+++ b/Sluift/ElementConvertors/DOMElementConvertor.cpp
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#include <Sluift/ElementConvertors/DOMElementConvertor.h>
+
+#include <iostream>
+#include <boost/smart_ptr/make_shared.hpp>
+#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/Serializer/XML/XMLElement.h>
+#include <Swiften/Serializer/XML/XMLTextNode.h>
+#include <Swiften/Serializer/XML/XMLRawTextNode.h>
+#include <Sluift/Lua/Debug.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();
+ }
+}
+
+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());
+}
+
+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");
+}
diff --git a/Sluift/ElementConvertors/DOMElementConvertor.h b/Sluift/ElementConvertors/DOMElementConvertor.h
new file mode 100644
index 0000000..94d0669
--- /dev/null
+++ b/Sluift/ElementConvertors/DOMElementConvertor.h
@@ -0,0 +1,28 @@
+/*
+ * 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 <Sluift/LuaElementConvertor.h>
+#include <Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.h>
+#include <Swiften/Parser/PlatformXMLParserFactory.h>
+
+namespace Swift {
+ class DOMElementConvertor : public LuaElementConvertor {
+ public:
+ DOMElementConvertor();
+ virtual ~DOMElementConvertor();
+
+ 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;
+
+ private:
+ PlatformXMLParserFactory parsers;
+ FullPayloadSerializerCollection serializers;
+ };
+}
diff --git a/Sluift/ElementConvertors/DefaultElementConvertor.cpp b/Sluift/ElementConvertors/DefaultElementConvertor.cpp
new file mode 100644
index 0000000..62c799b
--- /dev/null
+++ b/Sluift/ElementConvertors/DefaultElementConvertor.cpp
@@ -0,0 +1,30 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#include <Sluift/ElementConvertors/DefaultElementConvertor.h>
+
+#include <iostream>
+#include <typeinfo>
+#include <string>
+
+using namespace Swift;
+
+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>();
+}
+
+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;
+}
diff --git a/Sluift/ElementConvertors/DefaultElementConvertor.h b/Sluift/ElementConvertors/DefaultElementConvertor.h
new file mode 100644
index 0000000..ad8fe75
--- /dev/null
+++ b/Sluift/ElementConvertors/DefaultElementConvertor.h
@@ -0,0 +1,22 @@
+/*
+ * 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 <Sluift/LuaElementConvertor.h>
+
+namespace Swift {
+ class DefaultElementConvertor : public LuaElementConvertor {
+ public:
+ DefaultElementConvertor();
+ virtual ~DefaultElementConvertor();
+
+ 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;
+ };
+}
diff --git a/Sluift/ElementConvertors/DiscoInfoConvertor.cpp b/Sluift/ElementConvertors/DiscoInfoConvertor.cpp
new file mode 100644
index 0000000..ac0cf2e
--- /dev/null
+++ b/Sluift/ElementConvertors/DiscoInfoConvertor.cpp
@@ -0,0 +1,101 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#include <Sluift/ElementConvertors/DiscoInfoConvertor.h>
+
+#include <lua.hpp>
+#include <boost/smart_ptr/make_shared.hpp>
+#include <boost/numeric/conversion/cast.hpp>
+#include <Sluift/Lua/LuaUtils.h>
+
+using namespace Swift;
+
+DiscoInfoConvertor::DiscoInfoConvertor() : GenericLuaElementConvertor<DiscoInfo>("disco_info") {
+}
+
+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;
+}
+
+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
+}
diff --git a/Sluift/ElementConvertors/DiscoInfoConvertor.h b/Sluift/ElementConvertors/DiscoInfoConvertor.h
new file mode 100644
index 0000000..7a2270e
--- /dev/null
+++ b/Sluift/ElementConvertors/DiscoInfoConvertor.h
@@ -0,0 +1,23 @@
+/*
+ * 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 <Sluift/GenericLuaElementConvertor.h>
+#include <Swiften/Elements/DiscoInfo.h>
+
+namespace Swift {
+ class DiscoInfoConvertor : public GenericLuaElementConvertor<DiscoInfo> {
+ public:
+ DiscoInfoConvertor();
+ virtual ~DiscoInfoConvertor();
+
+ virtual boost::shared_ptr<DiscoInfo> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE;
+ virtual void doConvertToLua(lua_State*, boost::shared_ptr<DiscoInfo>) SWIFTEN_OVERRIDE;
+ };
+}
diff --git a/Sluift/ElementConvertors/DiscoItemsConvertor.cpp b/Sluift/ElementConvertors/DiscoItemsConvertor.cpp
new file mode 100644
index 0000000..9049912
--- /dev/null
+++ b/Sluift/ElementConvertors/DiscoItemsConvertor.cpp
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#include <Sluift/ElementConvertors/DiscoItemsConvertor.h>
+
+#include <lua.hpp>
+#include <boost/smart_ptr/make_shared.hpp>
+#include <boost/numeric/conversion/cast.hpp>
+#include <Sluift/Lua/LuaUtils.h>
+
+using namespace Swift;
+
+DiscoItemsConvertor::DiscoItemsConvertor() : GenericLuaElementConvertor<DiscoItems>("disco_items") {
+}
+
+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;
+}
+
+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");
+ }
+}
diff --git a/Sluift/ElementConvertors/DiscoItemsConvertor.h b/Sluift/ElementConvertors/DiscoItemsConvertor.h
new file mode 100644
index 0000000..8972a84
--- /dev/null
+++ b/Sluift/ElementConvertors/DiscoItemsConvertor.h
@@ -0,0 +1,23 @@
+/*
+ * 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 <Sluift/GenericLuaElementConvertor.h>
+#include <Swiften/Elements/DiscoItems.h>
+
+namespace Swift {
+ class DiscoItemsConvertor : public GenericLuaElementConvertor<DiscoItems> {
+ public:
+ DiscoItemsConvertor();
+ virtual ~DiscoItemsConvertor();
+
+ virtual boost::shared_ptr<DiscoItems> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE;
+ virtual void doConvertToLua(lua_State*, boost::shared_ptr<DiscoItems>) SWIFTEN_OVERRIDE;
+ };
+}
diff --git a/Sluift/ElementConvertors/ElementConvertors.ipp b/Sluift/ElementConvertors/ElementConvertors.ipp
new file mode 100644
index 0000000..b7b9166
--- /dev/null
+++ b/Sluift/ElementConvertors/ElementConvertors.ipp
@@ -0,0 +1,81 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#include <Sluift/ElementConvertors/PubSubRetractConvertor.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/PubSubDefaultConvertor.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/PubSubEventDeleteConvertor.h>
+#include <Sluift/ElementConvertors/PubSubCreateConvertor.h>
+#include <Sluift/ElementConvertors/PubSubOwnerPurgeConvertor.h>
+#include <Sluift/ElementConvertors/PubSubEventItemsConvertor.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/PubSubOwnerDefaultConvertor.h>
+#include <Sluift/ElementConvertors/PubSubSubscriptionsConvertor.h>
+#include <Sluift/ElementConvertors/PubSubEventAssociateConvertor.h>
+#include <Sluift/ElementConvertors/PubSubSubscriptionConvertor.h>
+#include <Sluift/ElementConvertors/PubSubEventConfigurationConvertor.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));
+}
diff --git a/Sluift/ElementConvertors/FormConvertor.cpp b/Sluift/ElementConvertors/FormConvertor.cpp
new file mode 100644
index 0000000..e44ca3e
--- /dev/null
+++ b/Sluift/ElementConvertors/FormConvertor.cpp
@@ -0,0 +1,361 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#include <Sluift/ElementConvertors/FormConvertor.h>
+
+#include <lua.hpp>
+#include <boost/smart_ptr/make_shared.hpp>
+#include <boost/numeric/conversion/cast.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;
+ }
+}
+
+FormConvertor::FormConvertor() : GenericLuaElementConvertor<Form>("form") {
+}
+
+FormConvertor::~FormConvertor() {
+}
+
+boost::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);
+
+ 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
new file mode 100644
index 0000000..eaccf74
--- /dev/null
+++ b/Sluift/ElementConvertors/FormConvertor.h
@@ -0,0 +1,23 @@
+/*
+ * 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 <Sluift/GenericLuaElementConvertor.h>
+#include <Swiften/Elements/Form.h>
+
+namespace Swift {
+ class FormConvertor : public GenericLuaElementConvertor<Form> {
+ public:
+ FormConvertor();
+ virtual ~FormConvertor();
+
+ virtual boost::shared_ptr<Form> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE;
+ virtual void doConvertToLua(lua_State*, boost::shared_ptr<Form>) SWIFTEN_OVERRIDE;
+ };
+}
diff --git a/Sluift/ElementConvertors/PubSubAffiliationConvertor.cpp b/Sluift/ElementConvertors/PubSubAffiliationConvertor.cpp
new file mode 100644
index 0000000..73d7d6a
--- /dev/null
+++ b/Sluift/ElementConvertors/PubSubAffiliationConvertor.cpp
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#include <Sluift/ElementConvertors/PubSubAffiliationConvertor.h>
+
+#include <lua.hpp>
+#include <boost/smart_ptr/make_shared.hpp>
+
+
+
+
+#pragma clang diagnostic ignored "-Wunused-private-field"
+
+using namespace Swift;
+
+PubSubAffiliationConvertor::PubSubAffiliationConvertor(LuaElementConvertors* convertors) :
+ GenericLuaElementConvertor<PubSubAffiliation>("pubsub_affiliation"),
+ convertors(convertors) {
+}
+
+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");
+ 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, 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");
+}
diff --git a/Sluift/ElementConvertors/PubSubAffiliationConvertor.h b/Sluift/ElementConvertors/PubSubAffiliationConvertor.h
new file mode 100644
index 0000000..632a8d7
--- /dev/null
+++ b/Sluift/ElementConvertors/PubSubAffiliationConvertor.h
@@ -0,0 +1,28 @@
+/*
+ * 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 <Sluift/GenericLuaElementConvertor.h>
+#include <Swiften/Elements/PubSubAffiliation.h>
+
+namespace Swift {
+ class LuaElementConvertors;
+
+ class PubSubAffiliationConvertor : public GenericLuaElementConvertor<PubSubAffiliation> {
+ public:
+ PubSubAffiliationConvertor(LuaElementConvertors* convertors);
+ virtual ~PubSubAffiliationConvertor();
+
+ virtual boost::shared_ptr<PubSubAffiliation> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE;
+ virtual void doConvertToLua(lua_State*, boost::shared_ptr<PubSubAffiliation>) SWIFTEN_OVERRIDE;
+
+ private:
+ LuaElementConvertors* convertors;
+ };
+}
diff --git a/Sluift/ElementConvertors/PubSubAffiliationsConvertor.cpp b/Sluift/ElementConvertors/PubSubAffiliationsConvertor.cpp
new file mode 100644
index 0000000..9f34235
--- /dev/null
+++ b/Sluift/ElementConvertors/PubSubAffiliationsConvertor.cpp
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#include <Sluift/ElementConvertors/PubSubAffiliationsConvertor.h>
+
+#include <lua.hpp>
+#include <boost/smart_ptr/make_shared.hpp>
+#include <boost/numeric/conversion/cast.hpp>
+
+#include <Sluift/LuaElementConvertors.h>
+#include <Swiften/Base/foreach.h>
+
+#pragma clang diagnostic ignored "-Wunused-private-field"
+
+using namespace Swift;
+
+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);
+ }
+
+ result->setAffiliations(items);
+ }
+ return result;
+}
+
+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;
+ }
+ }
+ }
+ }
+}
diff --git a/Sluift/ElementConvertors/PubSubAffiliationsConvertor.h b/Sluift/ElementConvertors/PubSubAffiliationsConvertor.h
new file mode 100644
index 0000000..fb0279a
--- /dev/null
+++ b/Sluift/ElementConvertors/PubSubAffiliationsConvertor.h
@@ -0,0 +1,28 @@
+/*
+ * 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 <Sluift/GenericLuaElementConvertor.h>
+#include <Swiften/Elements/PubSubAffiliations.h>
+
+namespace Swift {
+ class LuaElementConvertors;
+
+ class PubSubAffiliationsConvertor : public GenericLuaElementConvertor<PubSubAffiliations> {
+ public:
+ PubSubAffiliationsConvertor(LuaElementConvertors* convertors);
+ virtual ~PubSubAffiliationsConvertor();
+
+ virtual boost::shared_ptr<PubSubAffiliations> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE;
+ virtual void doConvertToLua(lua_State*, boost::shared_ptr<PubSubAffiliations>) SWIFTEN_OVERRIDE;
+
+ private:
+ LuaElementConvertors* convertors;
+ };
+}
diff --git a/Sluift/ElementConvertors/PubSubConfigureConvertor.cpp b/Sluift/ElementConvertors/PubSubConfigureConvertor.cpp
new file mode 100644
index 0000000..893bc27
--- /dev/null
+++ b/Sluift/ElementConvertors/PubSubConfigureConvertor.cpp
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#include <Sluift/ElementConvertors/PubSubConfigureConvertor.h>
+
+#include <lua.hpp>
+#include <boost/smart_ptr/make_shared.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() {
+}
+
+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;
+}
+
+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");
+ }
+}
diff --git a/Sluift/ElementConvertors/PubSubConfigureConvertor.h b/Sluift/ElementConvertors/PubSubConfigureConvertor.h
new file mode 100644
index 0000000..0dd9094
--- /dev/null
+++ b/Sluift/ElementConvertors/PubSubConfigureConvertor.h
@@ -0,0 +1,28 @@
+/*
+ * 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 <Sluift/GenericLuaElementConvertor.h>
+#include <Swiften/Elements/PubSubConfigure.h>
+
+namespace Swift {
+ class LuaElementConvertors;
+
+ class PubSubConfigureConvertor : public GenericLuaElementConvertor<PubSubConfigure> {
+ public:
+ PubSubConfigureConvertor(LuaElementConvertors* convertors);
+ virtual ~PubSubConfigureConvertor();
+
+ virtual boost::shared_ptr<PubSubConfigure> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE;
+ virtual void doConvertToLua(lua_State*, boost::shared_ptr<PubSubConfigure>) SWIFTEN_OVERRIDE;
+
+ private:
+ LuaElementConvertors* convertors;
+ };
+}
diff --git a/Sluift/ElementConvertors/PubSubCreateConvertor.cpp b/Sluift/ElementConvertors/PubSubCreateConvertor.cpp
new file mode 100644
index 0000000..64e2ee3
--- /dev/null
+++ b/Sluift/ElementConvertors/PubSubCreateConvertor.cpp
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#include <Sluift/ElementConvertors/PubSubCreateConvertor.h>
+
+#include <lua.hpp>
+#include <boost/smart_ptr/make_shared.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() {
+}
+
+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;
+}
+
+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");
+ }
+}
diff --git a/Sluift/ElementConvertors/PubSubCreateConvertor.h b/Sluift/ElementConvertors/PubSubCreateConvertor.h
new file mode 100644
index 0000000..2cb1ea6
--- /dev/null
+++ b/Sluift/ElementConvertors/PubSubCreateConvertor.h
@@ -0,0 +1,28 @@
+/*
+ * 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 <Sluift/GenericLuaElementConvertor.h>
+#include <Swiften/Elements/PubSubCreate.h>
+
+namespace Swift {
+ class LuaElementConvertors;
+
+ class PubSubCreateConvertor : public GenericLuaElementConvertor<PubSubCreate> {
+ public:
+ PubSubCreateConvertor(LuaElementConvertors* convertors);
+ virtual ~PubSubCreateConvertor();
+
+ virtual boost::shared_ptr<PubSubCreate> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE;
+ virtual void doConvertToLua(lua_State*, boost::shared_ptr<PubSubCreate>) SWIFTEN_OVERRIDE;
+
+ private:
+ LuaElementConvertors* convertors;
+ };
+}
diff --git a/Sluift/ElementConvertors/PubSubDefaultConvertor.cpp b/Sluift/ElementConvertors/PubSubDefaultConvertor.cpp
new file mode 100644
index 0000000..d9b68ac
--- /dev/null
+++ b/Sluift/ElementConvertors/PubSubDefaultConvertor.cpp
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#include <Sluift/ElementConvertors/PubSubDefaultConvertor.h>
+
+#include <lua.hpp>
+#include <boost/smart_ptr/make_shared.hpp>
+
+
+
+
+#pragma clang diagnostic ignored "-Wunused-private-field"
+
+using namespace Swift;
+
+PubSubDefaultConvertor::PubSubDefaultConvertor(LuaElementConvertors* convertors) :
+ GenericLuaElementConvertor<PubSubDefault>("pubsub_default"),
+ convertors(convertors) {
+}
+
+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");
+ 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, 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");
+}
diff --git a/Sluift/ElementConvertors/PubSubDefaultConvertor.h b/Sluift/ElementConvertors/PubSubDefaultConvertor.h
new file mode 100644
index 0000000..89dd9be
--- /dev/null
+++ b/Sluift/ElementConvertors/PubSubDefaultConvertor.h
@@ -0,0 +1,28 @@
+/*
+ * 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 <Sluift/GenericLuaElementConvertor.h>
+#include <Swiften/Elements/PubSubDefault.h>
+
+namespace Swift {
+ class LuaElementConvertors;
+
+ class PubSubDefaultConvertor : public GenericLuaElementConvertor<PubSubDefault> {
+ public:
+ PubSubDefaultConvertor(LuaElementConvertors* convertors);
+ virtual ~PubSubDefaultConvertor();
+
+ virtual boost::shared_ptr<PubSubDefault> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE;
+ virtual void doConvertToLua(lua_State*, boost::shared_ptr<PubSubDefault>) SWIFTEN_OVERRIDE;
+
+ private:
+ LuaElementConvertors* convertors;
+ };
+}
diff --git a/Sluift/ElementConvertors/PubSubEventAssociateConvertor.cpp b/Sluift/ElementConvertors/PubSubEventAssociateConvertor.cpp
new file mode 100644
index 0000000..2b004c8
--- /dev/null
+++ b/Sluift/ElementConvertors/PubSubEventAssociateConvertor.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#include <Sluift/ElementConvertors/PubSubEventAssociateConvertor.h>
+
+#include <lua.hpp>
+#include <boost/smart_ptr/make_shared.hpp>
+
+
+
+
+#pragma clang diagnostic ignored "-Wunused-private-field"
+
+using namespace Swift;
+
+PubSubEventAssociateConvertor::PubSubEventAssociateConvertor(LuaElementConvertors* convertors) :
+ GenericLuaElementConvertor<PubSubEventAssociate>("pubsub_event_associate"),
+ convertors(convertors) {
+}
+
+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;
+}
+
+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");
+}
diff --git a/Sluift/ElementConvertors/PubSubEventAssociateConvertor.h b/Sluift/ElementConvertors/PubSubEventAssociateConvertor.h
new file mode 100644
index 0000000..60c9d28
--- /dev/null
+++ b/Sluift/ElementConvertors/PubSubEventAssociateConvertor.h
@@ -0,0 +1,28 @@
+/*
+ * 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 <Sluift/GenericLuaElementConvertor.h>
+#include <Swiften/Elements/PubSubEventAssociate.h>
+
+namespace Swift {
+ class LuaElementConvertors;
+
+ class PubSubEventAssociateConvertor : public GenericLuaElementConvertor<PubSubEventAssociate> {
+ public:
+ PubSubEventAssociateConvertor(LuaElementConvertors* convertors);
+ virtual ~PubSubEventAssociateConvertor();
+
+ virtual boost::shared_ptr<PubSubEventAssociate> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE;
+ virtual void doConvertToLua(lua_State*, boost::shared_ptr<PubSubEventAssociate>) SWIFTEN_OVERRIDE;
+
+ private:
+ LuaElementConvertors* convertors;
+ };
+}
diff --git a/Sluift/ElementConvertors/PubSubEventCollectionConvertor.cpp b/Sluift/ElementConvertors/PubSubEventCollectionConvertor.cpp
new file mode 100644
index 0000000..d05b479
--- /dev/null
+++ b/Sluift/ElementConvertors/PubSubEventCollectionConvertor.cpp
@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#include <Sluift/ElementConvertors/PubSubEventCollectionConvertor.h>
+
+#include <lua.hpp>
+#include <boost/smart_ptr/make_shared.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() {
+}
+
+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;
+}
+
+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");
+ }
+}
diff --git a/Sluift/ElementConvertors/PubSubEventCollectionConvertor.h b/Sluift/ElementConvertors/PubSubEventCollectionConvertor.h
new file mode 100644
index 0000000..eed2541
--- /dev/null
+++ b/Sluift/ElementConvertors/PubSubEventCollectionConvertor.h
@@ -0,0 +1,28 @@
+/*
+ * 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 <Sluift/GenericLuaElementConvertor.h>
+#include <Swiften/Elements/PubSubEventCollection.h>
+
+namespace Swift {
+ class LuaElementConvertors;
+
+ class PubSubEventCollectionConvertor : public GenericLuaElementConvertor<PubSubEventCollection> {
+ public:
+ PubSubEventCollectionConvertor(LuaElementConvertors* convertors);
+ virtual ~PubSubEventCollectionConvertor();
+
+ virtual boost::shared_ptr<PubSubEventCollection> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE;
+ virtual void doConvertToLua(lua_State*, boost::shared_ptr<PubSubEventCollection>) SWIFTEN_OVERRIDE;
+
+ private:
+ LuaElementConvertors* convertors;
+ };
+}
diff --git a/Sluift/ElementConvertors/PubSubEventConfigurationConvertor.cpp b/Sluift/ElementConvertors/PubSubEventConfigurationConvertor.cpp
new file mode 100644
index 0000000..ecdf145
--- /dev/null
+++ b/Sluift/ElementConvertors/PubSubEventConfigurationConvertor.cpp
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#include <Sluift/ElementConvertors/PubSubEventConfigurationConvertor.h>
+
+#include <lua.hpp>
+#include <boost/smart_ptr/make_shared.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() {
+}
+
+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;
+}
+
+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");
+ }
+}
diff --git a/Sluift/ElementConvertors/PubSubEventConfigurationConvertor.h b/Sluift/ElementConvertors/PubSubEventConfigurationConvertor.h
new file mode 100644
index 0000000..4347ebc
--- /dev/null
+++ b/Sluift/ElementConvertors/PubSubEventConfigurationConvertor.h
@@ -0,0 +1,28 @@
+/*
+ * 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 <Sluift/GenericLuaElementConvertor.h>
+#include <Swiften/Elements/PubSubEventConfiguration.h>
+
+namespace Swift {
+ class LuaElementConvertors;
+
+ class PubSubEventConfigurationConvertor : public GenericLuaElementConvertor<PubSubEventConfiguration> {
+ public:
+ PubSubEventConfigurationConvertor(LuaElementConvertors* convertors);
+ virtual ~PubSubEventConfigurationConvertor();
+
+ virtual boost::shared_ptr<PubSubEventConfiguration> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE;
+ virtual void doConvertToLua(lua_State*, boost::shared_ptr<PubSubEventConfiguration>) SWIFTEN_OVERRIDE;
+
+ private:
+ LuaElementConvertors* convertors;
+ };
+}
diff --git a/Sluift/ElementConvertors/PubSubEventConvertor.cpp b/Sluift/ElementConvertors/PubSubEventConvertor.cpp
new file mode 100644
index 0000000..46d870a
--- /dev/null
+++ b/Sluift/ElementConvertors/PubSubEventConvertor.cpp
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#include <Sluift/ElementConvertors/PubSubEventConvertor.h>
+
+#include <lua.hpp>
+#include <boost/smart_ptr/make_shared.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() {
+}
+
+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;
+}
+
+void PubSubEventConvertor::doConvertToLua(lua_State* L, boost::shared_ptr<PubSubEvent> event) {
+ convertors->convertToLua(L, event->getPayload());
+}
diff --git a/Sluift/ElementConvertors/PubSubEventConvertor.h b/Sluift/ElementConvertors/PubSubEventConvertor.h
new file mode 100644
index 0000000..8250fc4
--- /dev/null
+++ b/Sluift/ElementConvertors/PubSubEventConvertor.h
@@ -0,0 +1,28 @@
+/*
+ * 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 <Sluift/GenericLuaElementConvertor.h>
+#include <Swiften/Elements/PubSubEvent.h>
+
+namespace Swift {
+ class LuaElementConvertors;
+
+ class PubSubEventConvertor : public GenericLuaElementConvertor<PubSubEvent> {
+ public:
+ PubSubEventConvertor(LuaElementConvertors* convertors);
+ virtual ~PubSubEventConvertor();
+
+ virtual boost::shared_ptr<PubSubEvent> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE;
+ virtual void doConvertToLua(lua_State*, boost::shared_ptr<PubSubEvent>) SWIFTEN_OVERRIDE;
+
+ private:
+ LuaElementConvertors* convertors;
+ };
+}
diff --git a/Sluift/ElementConvertors/PubSubEventDeleteConvertor.cpp b/Sluift/ElementConvertors/PubSubEventDeleteConvertor.cpp
new file mode 100644
index 0000000..b03f22a
--- /dev/null
+++ b/Sluift/ElementConvertors/PubSubEventDeleteConvertor.cpp
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#include <Sluift/ElementConvertors/PubSubEventDeleteConvertor.h>
+
+#include <lua.hpp>
+#include <boost/smart_ptr/make_shared.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() {
+}
+
+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;
+}
+
+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");
+ }
+}
diff --git a/Sluift/ElementConvertors/PubSubEventDeleteConvertor.h b/Sluift/ElementConvertors/PubSubEventDeleteConvertor.h
new file mode 100644
index 0000000..a0cfd3d
--- /dev/null
+++ b/Sluift/ElementConvertors/PubSubEventDeleteConvertor.h
@@ -0,0 +1,28 @@
+/*
+ * 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 <Sluift/GenericLuaElementConvertor.h>
+#include <Swiften/Elements/PubSubEventDelete.h>
+
+namespace Swift {
+ class LuaElementConvertors;
+
+ class PubSubEventDeleteConvertor : public GenericLuaElementConvertor<PubSubEventDelete> {
+ public:
+ PubSubEventDeleteConvertor(LuaElementConvertors* convertors);
+ virtual ~PubSubEventDeleteConvertor();
+
+ virtual boost::shared_ptr<PubSubEventDelete> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE;
+ virtual void doConvertToLua(lua_State*, boost::shared_ptr<PubSubEventDelete>) SWIFTEN_OVERRIDE;
+
+ private:
+ LuaElementConvertors* convertors;
+ };
+}
diff --git a/Sluift/ElementConvertors/PubSubEventDisassociateConvertor.cpp b/Sluift/ElementConvertors/PubSubEventDisassociateConvertor.cpp
new file mode 100644
index 0000000..ccd8c6e
--- /dev/null
+++ b/Sluift/ElementConvertors/PubSubEventDisassociateConvertor.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#include <Sluift/ElementConvertors/PubSubEventDisassociateConvertor.h>
+
+#include <lua.hpp>
+#include <boost/smart_ptr/make_shared.hpp>
+
+
+
+
+#pragma clang diagnostic ignored "-Wunused-private-field"
+
+using namespace Swift;
+
+PubSubEventDisassociateConvertor::PubSubEventDisassociateConvertor(LuaElementConvertors* convertors) :
+ GenericLuaElementConvertor<PubSubEventDisassociate>("pubsub_event_disassociate"),
+ convertors(convertors) {
+}
+
+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;
+}
+
+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");
+}
diff --git a/Sluift/ElementConvertors/PubSubEventDisassociateConvertor.h b/Sluift/ElementConvertors/PubSubEventDisassociateConvertor.h
new file mode 100644
index 0000000..90c8232
--- /dev/null
+++ b/Sluift/ElementConvertors/PubSubEventDisassociateConvertor.h
@@ -0,0 +1,28 @@
+/*
+ * 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 <Sluift/GenericLuaElementConvertor.h>
+#include <Swiften/Elements/PubSubEventDisassociate.h>
+
+namespace Swift {
+ class LuaElementConvertors;
+
+ class PubSubEventDisassociateConvertor : public GenericLuaElementConvertor<PubSubEventDisassociate> {
+ public:
+ PubSubEventDisassociateConvertor(LuaElementConvertors* convertors);
+ virtual ~PubSubEventDisassociateConvertor();
+
+ virtual boost::shared_ptr<PubSubEventDisassociate> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE;
+ virtual void doConvertToLua(lua_State*, boost::shared_ptr<PubSubEventDisassociate>) SWIFTEN_OVERRIDE;
+
+ private:
+ LuaElementConvertors* convertors;
+ };
+}
diff --git a/Sluift/ElementConvertors/PubSubEventItemConvertor.cpp b/Sluift/ElementConvertors/PubSubEventItemConvertor.cpp
new file mode 100644
index 0000000..fab4bff
--- /dev/null
+++ b/Sluift/ElementConvertors/PubSubEventItemConvertor.cpp
@@ -0,0 +1,92 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#include <Sluift/ElementConvertors/PubSubEventItemConvertor.h>
+
+#include <lua.hpp>
+#include <boost/smart_ptr/make_shared.hpp>
+#include <boost/numeric/conversion/cast.hpp>
+
+#include <Sluift/LuaElementConvertors.h>
+#include <Swiften/Base/foreach.h>
+
+#pragma clang diagnostic ignored "-Wunused-private-field"
+
+using namespace Swift;
+
+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);
+ }
+
+ 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, 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");
+ }
+}
diff --git a/Sluift/ElementConvertors/PubSubEventItemConvertor.h b/Sluift/ElementConvertors/PubSubEventItemConvertor.h
new file mode 100644
index 0000000..340602a
--- /dev/null
+++ b/Sluift/ElementConvertors/PubSubEventItemConvertor.h
@@ -0,0 +1,28 @@
+/*
+ * 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 <Sluift/GenericLuaElementConvertor.h>
+#include <Swiften/Elements/PubSubEventItem.h>
+
+namespace Swift {
+ class LuaElementConvertors;
+
+ class PubSubEventItemConvertor : public GenericLuaElementConvertor<PubSubEventItem> {
+ public:
+ PubSubEventItemConvertor(LuaElementConvertors* convertors);
+ virtual ~PubSubEventItemConvertor();
+
+ virtual boost::shared_ptr<PubSubEventItem> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE;
+ virtual void doConvertToLua(lua_State*, boost::shared_ptr<PubSubEventItem>) SWIFTEN_OVERRIDE;
+
+ private:
+ LuaElementConvertors* convertors;
+ };
+}
diff --git a/Sluift/ElementConvertors/PubSubEventItemsConvertor.cpp b/Sluift/ElementConvertors/PubSubEventItemsConvertor.cpp
new file mode 100644
index 0000000..9996cc6
--- /dev/null
+++ b/Sluift/ElementConvertors/PubSubEventItemsConvertor.cpp
@@ -0,0 +1,102 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#include <Sluift/ElementConvertors/PubSubEventItemsConvertor.h>
+
+#include <lua.hpp>
+#include <boost/smart_ptr/make_shared.hpp>
+#include <boost/numeric/conversion/cast.hpp>
+
+#include <Sluift/LuaElementConvertors.h>
+#include <Swiften/Base/foreach.h>
+
+#pragma clang diagnostic ignored "-Wunused-private-field"
+
+using namespace Swift;
+
+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);
+ }
+
+ 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;
+}
+
+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");
+ }
+}
diff --git a/Sluift/ElementConvertors/PubSubEventItemsConvertor.h b/Sluift/ElementConvertors/PubSubEventItemsConvertor.h
new file mode 100644
index 0000000..9adbf15
--- /dev/null
+++ b/Sluift/ElementConvertors/PubSubEventItemsConvertor.h
@@ -0,0 +1,28 @@
+/*
+ * 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 <Sluift/GenericLuaElementConvertor.h>
+#include <Swiften/Elements/PubSubEventItems.h>
+
+namespace Swift {
+ class LuaElementConvertors;
+
+ class PubSubEventItemsConvertor : public GenericLuaElementConvertor<PubSubEventItems> {
+ public:
+ PubSubEventItemsConvertor(LuaElementConvertors* convertors);
+ virtual ~PubSubEventItemsConvertor();
+
+ virtual boost::shared_ptr<PubSubEventItems> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE;
+ virtual void doConvertToLua(lua_State*, boost::shared_ptr<PubSubEventItems>) SWIFTEN_OVERRIDE;
+
+ private:
+ LuaElementConvertors* convertors;
+ };
+}
diff --git a/Sluift/ElementConvertors/PubSubEventPurgeConvertor.cpp b/Sluift/ElementConvertors/PubSubEventPurgeConvertor.cpp
new file mode 100644
index 0000000..e389fcf
--- /dev/null
+++ b/Sluift/ElementConvertors/PubSubEventPurgeConvertor.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#include <Sluift/ElementConvertors/PubSubEventPurgeConvertor.h>
+
+#include <lua.hpp>
+#include <boost/smart_ptr/make_shared.hpp>
+
+
+
+
+#pragma clang diagnostic ignored "-Wunused-private-field"
+
+using namespace Swift;
+
+PubSubEventPurgeConvertor::PubSubEventPurgeConvertor(LuaElementConvertors* convertors) :
+ GenericLuaElementConvertor<PubSubEventPurge>("pubsub_event_purge"),
+ convertors(convertors) {
+}
+
+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;
+}
+
+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");
+}
diff --git a/Sluift/ElementConvertors/PubSubEventPurgeConvertor.h b/Sluift/ElementConvertors/PubSubEventPurgeConvertor.h
new file mode 100644
index 0000000..d94aa36
--- /dev/null
+++ b/Sluift/ElementConvertors/PubSubEventPurgeConvertor.h
@@ -0,0 +1,28 @@
+/*
+ * 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 <Sluift/GenericLuaElementConvertor.h>
+#include <Swiften/Elements/PubSubEventPurge.h>
+
+namespace Swift {
+ class LuaElementConvertors;
+
+ class PubSubEventPurgeConvertor : public GenericLuaElementConvertor<PubSubEventPurge> {
+ public:
+ PubSubEventPurgeConvertor(LuaElementConvertors* convertors);
+ virtual ~PubSubEventPurgeConvertor();
+
+ virtual boost::shared_ptr<PubSubEventPurge> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE;
+ virtual void doConvertToLua(lua_State*, boost::shared_ptr<PubSubEventPurge>) SWIFTEN_OVERRIDE;
+
+ private:
+ LuaElementConvertors* convertors;
+ };
+}
diff --git a/Sluift/ElementConvertors/PubSubEventRedirectConvertor.cpp b/Sluift/ElementConvertors/PubSubEventRedirectConvertor.cpp
new file mode 100644
index 0000000..6e128da
--- /dev/null
+++ b/Sluift/ElementConvertors/PubSubEventRedirectConvertor.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#include <Sluift/ElementConvertors/PubSubEventRedirectConvertor.h>
+
+#include <lua.hpp>
+#include <boost/smart_ptr/make_shared.hpp>
+
+
+
+
+#pragma clang diagnostic ignored "-Wunused-private-field"
+
+using namespace Swift;
+
+PubSubEventRedirectConvertor::PubSubEventRedirectConvertor(LuaElementConvertors* convertors) :
+ GenericLuaElementConvertor<PubSubEventRedirect>("pubsub_event_redirect"),
+ convertors(convertors) {
+}
+
+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;
+}
+
+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");
+}
diff --git a/Sluift/ElementConvertors/PubSubEventRedirectConvertor.h b/Sluift/ElementConvertors/PubSubEventRedirectConvertor.h
new file mode 100644
index 0000000..4904102
--- /dev/null
+++ b/Sluift/ElementConvertors/PubSubEventRedirectConvertor.h
@@ -0,0 +1,28 @@
+/*
+ * 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 <Sluift/GenericLuaElementConvertor.h>
+#include <Swiften/Elements/PubSubEventRedirect.h>
+
+namespace Swift {
+ class LuaElementConvertors;
+
+ class PubSubEventRedirectConvertor : public GenericLuaElementConvertor<PubSubEventRedirect> {
+ public:
+ PubSubEventRedirectConvertor(LuaElementConvertors* convertors);
+ virtual ~PubSubEventRedirectConvertor();
+
+ virtual boost::shared_ptr<PubSubEventRedirect> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE;
+ virtual void doConvertToLua(lua_State*, boost::shared_ptr<PubSubEventRedirect>) SWIFTEN_OVERRIDE;
+
+ private:
+ LuaElementConvertors* convertors;
+ };
+}
diff --git a/Sluift/ElementConvertors/PubSubEventRetractConvertor.cpp b/Sluift/ElementConvertors/PubSubEventRetractConvertor.cpp
new file mode 100644
index 0000000..aed29a0
--- /dev/null
+++ b/Sluift/ElementConvertors/PubSubEventRetractConvertor.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#include <Sluift/ElementConvertors/PubSubEventRetractConvertor.h>
+
+#include <lua.hpp>
+#include <boost/smart_ptr/make_shared.hpp>
+
+
+
+
+#pragma clang diagnostic ignored "-Wunused-private-field"
+
+using namespace Swift;
+
+PubSubEventRetractConvertor::PubSubEventRetractConvertor(LuaElementConvertors* convertors) :
+ GenericLuaElementConvertor<PubSubEventRetract>("pubsub_event_retract"),
+ convertors(convertors) {
+}
+
+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;
+}
+
+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");
+}
diff --git a/Sluift/ElementConvertors/PubSubEventRetractConvertor.h b/Sluift/ElementConvertors/PubSubEventRetractConvertor.h
new file mode 100644
index 0000000..7a7c0f9
--- /dev/null
+++ b/Sluift/ElementConvertors/PubSubEventRetractConvertor.h
@@ -0,0 +1,28 @@
+/*
+ * 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 <Sluift/GenericLuaElementConvertor.h>
+#include <Swiften/Elements/PubSubEventRetract.h>
+
+namespace Swift {
+ class LuaElementConvertors;
+
+ class PubSubEventRetractConvertor : public GenericLuaElementConvertor<PubSubEventRetract> {
+ public:
+ PubSubEventRetractConvertor(LuaElementConvertors* convertors);
+ virtual ~PubSubEventRetractConvertor();
+
+ virtual boost::shared_ptr<PubSubEventRetract> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE;
+ virtual void doConvertToLua(lua_State*, boost::shared_ptr<PubSubEventRetract>) SWIFTEN_OVERRIDE;
+
+ private:
+ LuaElementConvertors* convertors;
+ };
+}
diff --git a/Sluift/ElementConvertors/PubSubEventSubscriptionConvertor.cpp b/Sluift/ElementConvertors/PubSubEventSubscriptionConvertor.cpp
new file mode 100644
index 0000000..a4c160f
--- /dev/null
+++ b/Sluift/ElementConvertors/PubSubEventSubscriptionConvertor.cpp
@@ -0,0 +1,95 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#include <Sluift/ElementConvertors/PubSubEventSubscriptionConvertor.h>
+
+#include <lua.hpp>
+#include <boost/smart_ptr/make_shared.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() {
+}
+
+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");
+ 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, "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;
+}
+
+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");
+}
diff --git a/Sluift/ElementConvertors/PubSubEventSubscriptionConvertor.h b/Sluift/ElementConvertors/PubSubEventSubscriptionConvertor.h
new file mode 100644
index 0000000..fa04fb7
--- /dev/null
+++ b/Sluift/ElementConvertors/PubSubEventSubscriptionConvertor.h
@@ -0,0 +1,28 @@
+/*
+ * 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 <Sluift/GenericLuaElementConvertor.h>
+#include <Swiften/Elements/PubSubEventSubscription.h>
+
+namespace Swift {
+ class LuaElementConvertors;
+
+ class PubSubEventSubscriptionConvertor : public GenericLuaElementConvertor<PubSubEventSubscription> {
+ public:
+ PubSubEventSubscriptionConvertor(LuaElementConvertors* convertors);
+ virtual ~PubSubEventSubscriptionConvertor();
+
+ virtual boost::shared_ptr<PubSubEventSubscription> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE;
+ virtual void doConvertToLua(lua_State*, boost::shared_ptr<PubSubEventSubscription>) SWIFTEN_OVERRIDE;
+
+ private:
+ LuaElementConvertors* convertors;
+ };
+}
diff --git a/Sluift/ElementConvertors/PubSubItemConvertor.cpp b/Sluift/ElementConvertors/PubSubItemConvertor.cpp
new file mode 100644
index 0000000..e06065b
--- /dev/null
+++ b/Sluift/ElementConvertors/PubSubItemConvertor.cpp
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#include <Sluift/ElementConvertors/PubSubItemConvertor.h>
+
+#include <lua.hpp>
+#include <boost/smart_ptr/make_shared.hpp>
+#include <boost/numeric/conversion/cast.hpp>
+
+#include <Sluift/LuaElementConvertors.h>
+#include <Swiften/Base/foreach.h>
+
+#pragma clang diagnostic ignored "-Wunused-private-field"
+
+using namespace Swift;
+
+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);
+ }
+
+ 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, 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");
+}
diff --git a/Sluift/ElementConvertors/PubSubItemConvertor.h b/Sluift/ElementConvertors/PubSubItemConvertor.h
new file mode 100644
index 0000000..176e1c4
--- /dev/null
+++ b/Sluift/ElementConvertors/PubSubItemConvertor.h
@@ -0,0 +1,28 @@
+/*
+ * 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 <Sluift/GenericLuaElementConvertor.h>
+#include <Swiften/Elements/PubSubItem.h>
+
+namespace Swift {
+ class LuaElementConvertors;
+
+ class PubSubItemConvertor : public GenericLuaElementConvertor<PubSubItem> {
+ public:
+ PubSubItemConvertor(LuaElementConvertors* convertors);
+ virtual ~PubSubItemConvertor();
+
+ virtual boost::shared_ptr<PubSubItem> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE;
+ virtual void doConvertToLua(lua_State*, boost::shared_ptr<PubSubItem>) SWIFTEN_OVERRIDE;
+
+ private:
+ LuaElementConvertors* convertors;
+ };
+}
diff --git a/Sluift/ElementConvertors/PubSubItemsConvertor.cpp b/Sluift/ElementConvertors/PubSubItemsConvertor.cpp
new file mode 100644
index 0000000..5ecb72e
--- /dev/null
+++ b/Sluift/ElementConvertors/PubSubItemsConvertor.cpp
@@ -0,0 +1,86 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#include <Sluift/ElementConvertors/PubSubItemsConvertor.h>
+
+#include <lua.hpp>
+#include <boost/smart_ptr/make_shared.hpp>
+#include <boost/numeric/conversion/cast.hpp>
+
+#include <Sluift/LuaElementConvertors.h>
+#include <Swiften/Base/foreach.h>
+
+#pragma clang diagnostic ignored "-Wunused-private-field"
+
+using namespace Swift;
+
+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);
+ }
+
+ 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, 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");
+ }
+}
diff --git a/Sluift/ElementConvertors/PubSubItemsConvertor.h b/Sluift/ElementConvertors/PubSubItemsConvertor.h
new file mode 100644
index 0000000..9978806
--- /dev/null
+++ b/Sluift/ElementConvertors/PubSubItemsConvertor.h
@@ -0,0 +1,28 @@
+/*
+ * 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 <Sluift/GenericLuaElementConvertor.h>
+#include <Swiften/Elements/PubSubItems.h>
+
+namespace Swift {
+ class LuaElementConvertors;
+
+ class PubSubItemsConvertor : public GenericLuaElementConvertor<PubSubItems> {
+ public:
+ PubSubItemsConvertor(LuaElementConvertors* convertors);
+ virtual ~PubSubItemsConvertor();
+
+ virtual boost::shared_ptr<PubSubItems> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE;
+ virtual void doConvertToLua(lua_State*, boost::shared_ptr<PubSubItems>) SWIFTEN_OVERRIDE;
+
+ private:
+ LuaElementConvertors* convertors;
+ };
+}
diff --git a/Sluift/ElementConvertors/PubSubOptionsConvertor.cpp b/Sluift/ElementConvertors/PubSubOptionsConvertor.cpp
new file mode 100644
index 0000000..cc27973
--- /dev/null
+++ b/Sluift/ElementConvertors/PubSubOptionsConvertor.cpp
@@ -0,0 +1,67 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#include <Sluift/ElementConvertors/PubSubOptionsConvertor.h>
+
+#include <lua.hpp>
+#include <boost/smart_ptr/make_shared.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() {
+}
+
+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;
+}
+
+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");
+ }
+}
diff --git a/Sluift/ElementConvertors/PubSubOptionsConvertor.h b/Sluift/ElementConvertors/PubSubOptionsConvertor.h
new file mode 100644
index 0000000..95a1dc8
--- /dev/null
+++ b/Sluift/ElementConvertors/PubSubOptionsConvertor.h
@@ -0,0 +1,28 @@
+/*
+ * 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 <Sluift/GenericLuaElementConvertor.h>
+#include <Swiften/Elements/PubSubOptions.h>
+
+namespace Swift {
+ class LuaElementConvertors;
+
+ class PubSubOptionsConvertor : public GenericLuaElementConvertor<PubSubOptions> {
+ public:
+ PubSubOptionsConvertor(LuaElementConvertors* convertors);
+ virtual ~PubSubOptionsConvertor();
+
+ virtual boost::shared_ptr<PubSubOptions> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE;
+ virtual void doConvertToLua(lua_State*, boost::shared_ptr<PubSubOptions>) SWIFTEN_OVERRIDE;
+
+ private:
+ LuaElementConvertors* convertors;
+ };
+}
diff --git a/Sluift/ElementConvertors/PubSubOwnerAffiliationConvertor.cpp b/Sluift/ElementConvertors/PubSubOwnerAffiliationConvertor.cpp
new file mode 100644
index 0000000..f1a7b50
--- /dev/null
+++ b/Sluift/ElementConvertors/PubSubOwnerAffiliationConvertor.cpp
@@ -0,0 +1,84 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#include <Sluift/ElementConvertors/PubSubOwnerAffiliationConvertor.h>
+
+#include <lua.hpp>
+#include <boost/smart_ptr/make_shared.hpp>
+
+
+
+
+#pragma clang diagnostic ignored "-Wunused-private-field"
+
+using namespace Swift;
+
+PubSubOwnerAffiliationConvertor::PubSubOwnerAffiliationConvertor(LuaElementConvertors* convertors) :
+ GenericLuaElementConvertor<PubSubOwnerAffiliation>("pubsub_owner_affiliation"),
+ convertors(convertors) {
+}
+
+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");
+ 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, 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");
+}
diff --git a/Sluift/ElementConvertors/PubSubOwnerAffiliationConvertor.h b/Sluift/ElementConvertors/PubSubOwnerAffiliationConvertor.h
new file mode 100644
index 0000000..72bfaa1
--- /dev/null
+++ b/Sluift/ElementConvertors/PubSubOwnerAffiliationConvertor.h
@@ -0,0 +1,28 @@
+/*
+ * 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 <Sluift/GenericLuaElementConvertor.h>
+#include <Swiften/Elements/PubSubOwnerAffiliation.h>
+
+namespace Swift {
+ class LuaElementConvertors;
+
+ class PubSubOwnerAffiliationConvertor : public GenericLuaElementConvertor<PubSubOwnerAffiliation> {
+ public:
+ PubSubOwnerAffiliationConvertor(LuaElementConvertors* convertors);
+ virtual ~PubSubOwnerAffiliationConvertor();
+
+ virtual boost::shared_ptr<PubSubOwnerAffiliation> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE;
+ virtual void doConvertToLua(lua_State*, boost::shared_ptr<PubSubOwnerAffiliation>) SWIFTEN_OVERRIDE;
+
+ private:
+ LuaElementConvertors* convertors;
+ };
+}
diff --git a/Sluift/ElementConvertors/PubSubOwnerAffiliationsConvertor.cpp b/Sluift/ElementConvertors/PubSubOwnerAffiliationsConvertor.cpp
new file mode 100644
index 0000000..bee8539
--- /dev/null
+++ b/Sluift/ElementConvertors/PubSubOwnerAffiliationsConvertor.cpp
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#include <Sluift/ElementConvertors/PubSubOwnerAffiliationsConvertor.h>
+
+#include <lua.hpp>
+#include <boost/smart_ptr/make_shared.hpp>
+#include <boost/numeric/conversion/cast.hpp>
+
+#include <Sluift/LuaElementConvertors.h>
+#include <Swiften/Base/foreach.h>
+
+#pragma clang diagnostic ignored "-Wunused-private-field"
+
+using namespace Swift;
+
+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);
+ }
+
+ result->setAffiliations(items);
+ }
+ return result;
+}
+
+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;
+ }
+ }
+ }
+ }
+}
diff --git a/Sluift/ElementConvertors/PubSubOwnerAffiliationsConvertor.h b/Sluift/ElementConvertors/PubSubOwnerAffiliationsConvertor.h
new file mode 100644
index 0000000..377e108
--- /dev/null
+++ b/Sluift/ElementConvertors/PubSubOwnerAffiliationsConvertor.h
@@ -0,0 +1,28 @@
+/*
+ * 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 <Sluift/GenericLuaElementConvertor.h>
+#include <Swiften/Elements/PubSubOwnerAffiliations.h>
+
+namespace Swift {
+ class LuaElementConvertors;
+
+ class PubSubOwnerAffiliationsConvertor : public GenericLuaElementConvertor<PubSubOwnerAffiliations> {
+ public:
+ PubSubOwnerAffiliationsConvertor(LuaElementConvertors* convertors);
+ virtual ~PubSubOwnerAffiliationsConvertor();
+
+ virtual boost::shared_ptr<PubSubOwnerAffiliations> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE;
+ virtual void doConvertToLua(lua_State*, boost::shared_ptr<PubSubOwnerAffiliations>) SWIFTEN_OVERRIDE;
+
+ private:
+ LuaElementConvertors* convertors;
+ };
+}
diff --git a/Sluift/ElementConvertors/PubSubOwnerConfigureConvertor.cpp b/Sluift/ElementConvertors/PubSubOwnerConfigureConvertor.cpp
new file mode 100644
index 0000000..87505e1
--- /dev/null
+++ b/Sluift/ElementConvertors/PubSubOwnerConfigureConvertor.cpp
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#include <Sluift/ElementConvertors/PubSubOwnerConfigureConvertor.h>
+
+#include <lua.hpp>
+#include <boost/smart_ptr/make_shared.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() {
+}
+
+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;
+}
+
+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");
+ }
+}
diff --git a/Sluift/ElementConvertors/PubSubOwnerConfigureConvertor.h b/Sluift/ElementConvertors/PubSubOwnerConfigureConvertor.h
new file mode 100644
index 0000000..83b1153
--- /dev/null
+++ b/Sluift/ElementConvertors/PubSubOwnerConfigureConvertor.h
@@ -0,0 +1,28 @@
+/*
+ * 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 <Sluift/GenericLuaElementConvertor.h>
+#include <Swiften/Elements/PubSubOwnerConfigure.h>
+
+namespace Swift {
+ class LuaElementConvertors;
+
+ class PubSubOwnerConfigureConvertor : public GenericLuaElementConvertor<PubSubOwnerConfigure> {
+ public:
+ PubSubOwnerConfigureConvertor(LuaElementConvertors* convertors);
+ virtual ~PubSubOwnerConfigureConvertor();
+
+ virtual boost::shared_ptr<PubSubOwnerConfigure> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE;
+ virtual void doConvertToLua(lua_State*, boost::shared_ptr<PubSubOwnerConfigure>) SWIFTEN_OVERRIDE;
+
+ private:
+ LuaElementConvertors* convertors;
+ };
+}
diff --git a/Sluift/ElementConvertors/PubSubOwnerDefaultConvertor.cpp b/Sluift/ElementConvertors/PubSubOwnerDefaultConvertor.cpp
new file mode 100644
index 0000000..17612cc
--- /dev/null
+++ b/Sluift/ElementConvertors/PubSubOwnerDefaultConvertor.cpp
@@ -0,0 +1,44 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#include <Sluift/ElementConvertors/PubSubOwnerDefaultConvertor.h>
+
+#include <lua.hpp>
+#include <boost/smart_ptr/make_shared.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() {
+}
+
+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;
+}
+
+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");
+ }
+}
diff --git a/Sluift/ElementConvertors/PubSubOwnerDefaultConvertor.h b/Sluift/ElementConvertors/PubSubOwnerDefaultConvertor.h
new file mode 100644
index 0000000..3a0f8ee
--- /dev/null
+++ b/Sluift/ElementConvertors/PubSubOwnerDefaultConvertor.h
@@ -0,0 +1,28 @@
+/*
+ * 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 <Sluift/GenericLuaElementConvertor.h>
+#include <Swiften/Elements/PubSubOwnerDefault.h>
+
+namespace Swift {
+ class LuaElementConvertors;
+
+ class PubSubOwnerDefaultConvertor : public GenericLuaElementConvertor<PubSubOwnerDefault> {
+ public:
+ PubSubOwnerDefaultConvertor(LuaElementConvertors* convertors);
+ virtual ~PubSubOwnerDefaultConvertor();
+
+ virtual boost::shared_ptr<PubSubOwnerDefault> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE;
+ virtual void doConvertToLua(lua_State*, boost::shared_ptr<PubSubOwnerDefault>) SWIFTEN_OVERRIDE;
+
+ private:
+ LuaElementConvertors* convertors;
+ };
+}
diff --git a/Sluift/ElementConvertors/PubSubOwnerDeleteConvertor.cpp b/Sluift/ElementConvertors/PubSubOwnerDeleteConvertor.cpp
new file mode 100644
index 0000000..f67ed1e
--- /dev/null
+++ b/Sluift/ElementConvertors/PubSubOwnerDeleteConvertor.cpp
@@ -0,0 +1,51 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#include <Sluift/ElementConvertors/PubSubOwnerDeleteConvertor.h>
+
+#include <lua.hpp>
+#include <boost/smart_ptr/make_shared.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() {
+}
+
+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;
+}
+
+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");
+ }
+}
diff --git a/Sluift/ElementConvertors/PubSubOwnerDeleteConvertor.h b/Sluift/ElementConvertors/PubSubOwnerDeleteConvertor.h
new file mode 100644
index 0000000..7475e9c
--- /dev/null
+++ b/Sluift/ElementConvertors/PubSubOwnerDeleteConvertor.h
@@ -0,0 +1,28 @@
+/*
+ * 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 <Sluift/GenericLuaElementConvertor.h>
+#include <Swiften/Elements/PubSubOwnerDelete.h>
+
+namespace Swift {
+ class LuaElementConvertors;
+
+ class PubSubOwnerDeleteConvertor : public GenericLuaElementConvertor<PubSubOwnerDelete> {
+ public:
+ PubSubOwnerDeleteConvertor(LuaElementConvertors* convertors);
+ virtual ~PubSubOwnerDeleteConvertor();
+
+ virtual boost::shared_ptr<PubSubOwnerDelete> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE;
+ virtual void doConvertToLua(lua_State*, boost::shared_ptr<PubSubOwnerDelete>) SWIFTEN_OVERRIDE;
+
+ private:
+ LuaElementConvertors* convertors;
+ };
+}
diff --git a/Sluift/ElementConvertors/PubSubOwnerPurgeConvertor.cpp b/Sluift/ElementConvertors/PubSubOwnerPurgeConvertor.cpp
new file mode 100644
index 0000000..a060db9
--- /dev/null
+++ b/Sluift/ElementConvertors/PubSubOwnerPurgeConvertor.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#include <Sluift/ElementConvertors/PubSubOwnerPurgeConvertor.h>
+
+#include <lua.hpp>
+#include <boost/smart_ptr/make_shared.hpp>
+
+
+
+
+#pragma clang diagnostic ignored "-Wunused-private-field"
+
+using namespace Swift;
+
+PubSubOwnerPurgeConvertor::PubSubOwnerPurgeConvertor(LuaElementConvertors* convertors) :
+ GenericLuaElementConvertor<PubSubOwnerPurge>("pubsub_owner_purge"),
+ convertors(convertors) {
+}
+
+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;
+}
+
+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");
+}
diff --git a/Sluift/ElementConvertors/PubSubOwnerPurgeConvertor.h b/Sluift/ElementConvertors/PubSubOwnerPurgeConvertor.h
new file mode 100644
index 0000000..34c979b
--- /dev/null
+++ b/Sluift/ElementConvertors/PubSubOwnerPurgeConvertor.h
@@ -0,0 +1,28 @@
+/*
+ * 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 <Sluift/GenericLuaElementConvertor.h>
+#include <Swiften/Elements/PubSubOwnerPurge.h>
+
+namespace Swift {
+ class LuaElementConvertors;
+
+ class PubSubOwnerPurgeConvertor : public GenericLuaElementConvertor<PubSubOwnerPurge> {
+ public:
+ PubSubOwnerPurgeConvertor(LuaElementConvertors* convertors);
+ virtual ~PubSubOwnerPurgeConvertor();
+
+ virtual boost::shared_ptr<PubSubOwnerPurge> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE;
+ virtual void doConvertToLua(lua_State*, boost::shared_ptr<PubSubOwnerPurge>) SWIFTEN_OVERRIDE;
+
+ private:
+ LuaElementConvertors* convertors;
+ };
+}
diff --git a/Sluift/ElementConvertors/PubSubOwnerRedirectConvertor.cpp b/Sluift/ElementConvertors/PubSubOwnerRedirectConvertor.cpp
new file mode 100644
index 0000000..d11df72
--- /dev/null
+++ b/Sluift/ElementConvertors/PubSubOwnerRedirectConvertor.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#include <Sluift/ElementConvertors/PubSubOwnerRedirectConvertor.h>
+
+#include <lua.hpp>
+#include <boost/smart_ptr/make_shared.hpp>
+
+
+
+
+#pragma clang diagnostic ignored "-Wunused-private-field"
+
+using namespace Swift;
+
+PubSubOwnerRedirectConvertor::PubSubOwnerRedirectConvertor(LuaElementConvertors* convertors) :
+ GenericLuaElementConvertor<PubSubOwnerRedirect>("pubsub_owner_redirect"),
+ convertors(convertors) {
+}
+
+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;
+}
+
+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");
+}
diff --git a/Sluift/ElementConvertors/PubSubOwnerRedirectConvertor.h b/Sluift/ElementConvertors/PubSubOwnerRedirectConvertor.h
new file mode 100644
index 0000000..fc1ddce
--- /dev/null
+++ b/Sluift/ElementConvertors/PubSubOwnerRedirectConvertor.h
@@ -0,0 +1,28 @@
+/*
+ * 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 <Sluift/GenericLuaElementConvertor.h>
+#include <Swiften/Elements/PubSubOwnerRedirect.h>
+
+namespace Swift {
+ class LuaElementConvertors;
+
+ class PubSubOwnerRedirectConvertor : public GenericLuaElementConvertor<PubSubOwnerRedirect> {
+ public:
+ PubSubOwnerRedirectConvertor(LuaElementConvertors* convertors);
+ virtual ~PubSubOwnerRedirectConvertor();
+
+ virtual boost::shared_ptr<PubSubOwnerRedirect> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE;
+ virtual void doConvertToLua(lua_State*, boost::shared_ptr<PubSubOwnerRedirect>) SWIFTEN_OVERRIDE;
+
+ private:
+ LuaElementConvertors* convertors;
+ };
+}
diff --git a/Sluift/ElementConvertors/PubSubOwnerSubscriptionConvertor.cpp b/Sluift/ElementConvertors/PubSubOwnerSubscriptionConvertor.cpp
new file mode 100644
index 0000000..dbba238
--- /dev/null
+++ b/Sluift/ElementConvertors/PubSubOwnerSubscriptionConvertor.cpp
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#include <Sluift/ElementConvertors/PubSubOwnerSubscriptionConvertor.h>
+
+#include <lua.hpp>
+#include <boost/smart_ptr/make_shared.hpp>
+
+
+
+
+#pragma clang diagnostic ignored "-Wunused-private-field"
+
+using namespace Swift;
+
+PubSubOwnerSubscriptionConvertor::PubSubOwnerSubscriptionConvertor(LuaElementConvertors* convertors) :
+ GenericLuaElementConvertor<PubSubOwnerSubscription>("pubsub_owner_subscription"),
+ convertors(convertors) {
+}
+
+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");
+ 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, 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");
+}
diff --git a/Sluift/ElementConvertors/PubSubOwnerSubscriptionConvertor.h b/Sluift/ElementConvertors/PubSubOwnerSubscriptionConvertor.h
new file mode 100644
index 0000000..ca80c82
--- /dev/null
+++ b/Sluift/ElementConvertors/PubSubOwnerSubscriptionConvertor.h
@@ -0,0 +1,28 @@
+/*
+ * 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 <Sluift/GenericLuaElementConvertor.h>
+#include <Swiften/Elements/PubSubOwnerSubscription.h>
+
+namespace Swift {
+ class LuaElementConvertors;
+
+ class PubSubOwnerSubscriptionConvertor : public GenericLuaElementConvertor<PubSubOwnerSubscription> {
+ public:
+ PubSubOwnerSubscriptionConvertor(LuaElementConvertors* convertors);
+ virtual ~PubSubOwnerSubscriptionConvertor();
+
+ virtual boost::shared_ptr<PubSubOwnerSubscription> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE;
+ virtual void doConvertToLua(lua_State*, boost::shared_ptr<PubSubOwnerSubscription>) SWIFTEN_OVERRIDE;
+
+ private:
+ LuaElementConvertors* convertors;
+ };
+}
diff --git a/Sluift/ElementConvertors/PubSubOwnerSubscriptionsConvertor.cpp b/Sluift/ElementConvertors/PubSubOwnerSubscriptionsConvertor.cpp
new file mode 100644
index 0000000..045cf12
--- /dev/null
+++ b/Sluift/ElementConvertors/PubSubOwnerSubscriptionsConvertor.cpp
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#include <Sluift/ElementConvertors/PubSubOwnerSubscriptionsConvertor.h>
+
+#include <lua.hpp>
+#include <boost/smart_ptr/make_shared.hpp>
+#include <boost/numeric/conversion/cast.hpp>
+
+#include <Sluift/LuaElementConvertors.h>
+#include <Swiften/Base/foreach.h>
+
+#pragma clang diagnostic ignored "-Wunused-private-field"
+
+using namespace Swift;
+
+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);
+ }
+
+ result->setSubscriptions(items);
+ }
+ return result;
+}
+
+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;
+ }
+ }
+ }
+ }
+}
diff --git a/Sluift/ElementConvertors/PubSubOwnerSubscriptionsConvertor.h b/Sluift/ElementConvertors/PubSubOwnerSubscriptionsConvertor.h
new file mode 100644
index 0000000..2e12c93
--- /dev/null
+++ b/Sluift/ElementConvertors/PubSubOwnerSubscriptionsConvertor.h
@@ -0,0 +1,28 @@
+/*
+ * 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 <Sluift/GenericLuaElementConvertor.h>
+#include <Swiften/Elements/PubSubOwnerSubscriptions.h>
+
+namespace Swift {
+ class LuaElementConvertors;
+
+ class PubSubOwnerSubscriptionsConvertor : public GenericLuaElementConvertor<PubSubOwnerSubscriptions> {
+ public:
+ PubSubOwnerSubscriptionsConvertor(LuaElementConvertors* convertors);
+ virtual ~PubSubOwnerSubscriptionsConvertor();
+
+ virtual boost::shared_ptr<PubSubOwnerSubscriptions> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE;
+ virtual void doConvertToLua(lua_State*, boost::shared_ptr<PubSubOwnerSubscriptions>) SWIFTEN_OVERRIDE;
+
+ private:
+ LuaElementConvertors* convertors;
+ };
+}
diff --git a/Sluift/ElementConvertors/PubSubPublishConvertor.cpp b/Sluift/ElementConvertors/PubSubPublishConvertor.cpp
new file mode 100644
index 0000000..880d9fc
--- /dev/null
+++ b/Sluift/ElementConvertors/PubSubPublishConvertor.cpp
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#include <Sluift/ElementConvertors/PubSubPublishConvertor.h>
+
+#include <lua.hpp>
+#include <boost/smart_ptr/make_shared.hpp>
+#include <boost/numeric/conversion/cast.hpp>
+
+#include <Sluift/LuaElementConvertors.h>
+#include <Swiften/Base/foreach.h>
+
+#pragma clang diagnostic ignored "-Wunused-private-field"
+
+using namespace Swift;
+
+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);
+ }
+
+ result->setItems(items);
+ }
+ lua_pop(L, 1);
+ return result;
+}
+
+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");
+ }
+}
diff --git a/Sluift/ElementConvertors/PubSubPublishConvertor.h b/Sluift/ElementConvertors/PubSubPublishConvertor.h
new file mode 100644
index 0000000..4415566
--- /dev/null
+++ b/Sluift/ElementConvertors/PubSubPublishConvertor.h
@@ -0,0 +1,28 @@
+/*
+ * 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 <Sluift/GenericLuaElementConvertor.h>
+#include <Swiften/Elements/PubSubPublish.h>
+
+namespace Swift {
+ class LuaElementConvertors;
+
+ class PubSubPublishConvertor : public GenericLuaElementConvertor<PubSubPublish> {
+ public:
+ PubSubPublishConvertor(LuaElementConvertors* convertors);
+ virtual ~PubSubPublishConvertor();
+
+ virtual boost::shared_ptr<PubSubPublish> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE;
+ virtual void doConvertToLua(lua_State*, boost::shared_ptr<PubSubPublish>) SWIFTEN_OVERRIDE;
+
+ private:
+ LuaElementConvertors* convertors;
+ };
+}
diff --git a/Sluift/ElementConvertors/PubSubRetractConvertor.cpp b/Sluift/ElementConvertors/PubSubRetractConvertor.cpp
new file mode 100644
index 0000000..61ca3df
--- /dev/null
+++ b/Sluift/ElementConvertors/PubSubRetractConvertor.cpp
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#include <Sluift/ElementConvertors/PubSubRetractConvertor.h>
+
+#include <lua.hpp>
+#include <boost/smart_ptr/make_shared.hpp>
+#include <boost/numeric/conversion/cast.hpp>
+
+#include <Sluift/LuaElementConvertors.h>
+#include <Swiften/Base/foreach.h>
+
+#pragma clang diagnostic ignored "-Wunused-private-field"
+
+using namespace Swift;
+
+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);
+ }
+
+ 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, 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");
+}
diff --git a/Sluift/ElementConvertors/PubSubRetractConvertor.h b/Sluift/ElementConvertors/PubSubRetractConvertor.h
new file mode 100644
index 0000000..80d888b
--- /dev/null
+++ b/Sluift/ElementConvertors/PubSubRetractConvertor.h
@@ -0,0 +1,28 @@
+/*
+ * 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 <Sluift/GenericLuaElementConvertor.h>
+#include <Swiften/Elements/PubSubRetract.h>
+
+namespace Swift {
+ class LuaElementConvertors;
+
+ class PubSubRetractConvertor : public GenericLuaElementConvertor<PubSubRetract> {
+ public:
+ PubSubRetractConvertor(LuaElementConvertors* convertors);
+ virtual ~PubSubRetractConvertor();
+
+ virtual boost::shared_ptr<PubSubRetract> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE;
+ virtual void doConvertToLua(lua_State*, boost::shared_ptr<PubSubRetract>) SWIFTEN_OVERRIDE;
+
+ private:
+ LuaElementConvertors* convertors;
+ };
+}
diff --git a/Sluift/ElementConvertors/PubSubSubscribeConvertor.cpp b/Sluift/ElementConvertors/PubSubSubscribeConvertor.cpp
new file mode 100644
index 0000000..06d6447
--- /dev/null
+++ b/Sluift/ElementConvertors/PubSubSubscribeConvertor.cpp
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#include <Sluift/ElementConvertors/PubSubSubscribeConvertor.h>
+
+#include <lua.hpp>
+#include <boost/smart_ptr/make_shared.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() {
+}
+
+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;
+}
+
+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");
+ }
+}
diff --git a/Sluift/ElementConvertors/PubSubSubscribeConvertor.h b/Sluift/ElementConvertors/PubSubSubscribeConvertor.h
new file mode 100644
index 0000000..2073c09
--- /dev/null
+++ b/Sluift/ElementConvertors/PubSubSubscribeConvertor.h
@@ -0,0 +1,28 @@
+/*
+ * 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 <Sluift/GenericLuaElementConvertor.h>
+#include <Swiften/Elements/PubSubSubscribe.h>
+
+namespace Swift {
+ class LuaElementConvertors;
+
+ class PubSubSubscribeConvertor : public GenericLuaElementConvertor<PubSubSubscribe> {
+ public:
+ PubSubSubscribeConvertor(LuaElementConvertors* convertors);
+ virtual ~PubSubSubscribeConvertor();
+
+ virtual boost::shared_ptr<PubSubSubscribe> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE;
+ virtual void doConvertToLua(lua_State*, boost::shared_ptr<PubSubSubscribe>) SWIFTEN_OVERRIDE;
+
+ private:
+ LuaElementConvertors* convertors;
+ };
+}
diff --git a/Sluift/ElementConvertors/PubSubSubscribeOptionsConvertor.cpp b/Sluift/ElementConvertors/PubSubSubscribeOptionsConvertor.cpp
new file mode 100644
index 0000000..e8053fb
--- /dev/null
+++ b/Sluift/ElementConvertors/PubSubSubscribeOptionsConvertor.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#include <Sluift/ElementConvertors/PubSubSubscribeOptionsConvertor.h>
+
+#include <lua.hpp>
+#include <boost/smart_ptr/make_shared.hpp>
+
+
+
+
+#pragma clang diagnostic ignored "-Wunused-private-field"
+
+using namespace Swift;
+
+PubSubSubscribeOptionsConvertor::PubSubSubscribeOptionsConvertor(LuaElementConvertors* convertors) :
+ GenericLuaElementConvertor<PubSubSubscribeOptions>("pubsub_subscribe_options"),
+ convertors(convertors) {
+}
+
+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;
+}
+
+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");
+}
diff --git a/Sluift/ElementConvertors/PubSubSubscribeOptionsConvertor.h b/Sluift/ElementConvertors/PubSubSubscribeOptionsConvertor.h
new file mode 100644
index 0000000..71e1baf
--- /dev/null
+++ b/Sluift/ElementConvertors/PubSubSubscribeOptionsConvertor.h
@@ -0,0 +1,28 @@
+/*
+ * 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 <Sluift/GenericLuaElementConvertor.h>
+#include <Swiften/Elements/PubSubSubscribeOptions.h>
+
+namespace Swift {
+ class LuaElementConvertors;
+
+ class PubSubSubscribeOptionsConvertor : public GenericLuaElementConvertor<PubSubSubscribeOptions> {
+ public:
+ PubSubSubscribeOptionsConvertor(LuaElementConvertors* convertors);
+ virtual ~PubSubSubscribeOptionsConvertor();
+
+ virtual boost::shared_ptr<PubSubSubscribeOptions> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE;
+ virtual void doConvertToLua(lua_State*, boost::shared_ptr<PubSubSubscribeOptions>) SWIFTEN_OVERRIDE;
+
+ private:
+ LuaElementConvertors* convertors;
+ };
+}
diff --git a/Sluift/ElementConvertors/PubSubSubscriptionConvertor.cpp b/Sluift/ElementConvertors/PubSubSubscriptionConvertor.cpp
new file mode 100644
index 0000000..69cd85a
--- /dev/null
+++ b/Sluift/ElementConvertors/PubSubSubscriptionConvertor.cpp
@@ -0,0 +1,100 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#include <Sluift/ElementConvertors/PubSubSubscriptionConvertor.h>
+
+#include <lua.hpp>
+#include <boost/smart_ptr/make_shared.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() {
+}
+
+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");
+ 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, 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");
+}
diff --git a/Sluift/ElementConvertors/PubSubSubscriptionConvertor.h b/Sluift/ElementConvertors/PubSubSubscriptionConvertor.h
new file mode 100644
index 0000000..2da4930
--- /dev/null
+++ b/Sluift/ElementConvertors/PubSubSubscriptionConvertor.h
@@ -0,0 +1,28 @@
+/*
+ * 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 <Sluift/GenericLuaElementConvertor.h>
+#include <Swiften/Elements/PubSubSubscription.h>
+
+namespace Swift {
+ class LuaElementConvertors;
+
+ class PubSubSubscriptionConvertor : public GenericLuaElementConvertor<PubSubSubscription> {
+ public:
+ PubSubSubscriptionConvertor(LuaElementConvertors* convertors);
+ virtual ~PubSubSubscriptionConvertor();
+
+ virtual boost::shared_ptr<PubSubSubscription> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE;
+ virtual void doConvertToLua(lua_State*, boost::shared_ptr<PubSubSubscription>) SWIFTEN_OVERRIDE;
+
+ private:
+ LuaElementConvertors* convertors;
+ };
+}
diff --git a/Sluift/ElementConvertors/PubSubSubscriptionsConvertor.cpp b/Sluift/ElementConvertors/PubSubSubscriptionsConvertor.cpp
new file mode 100644
index 0000000..04f8da8
--- /dev/null
+++ b/Sluift/ElementConvertors/PubSubSubscriptionsConvertor.cpp
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#include <Sluift/ElementConvertors/PubSubSubscriptionsConvertor.h>
+
+#include <lua.hpp>
+#include <boost/smart_ptr/make_shared.hpp>
+#include <boost/numeric/conversion/cast.hpp>
+
+#include <Sluift/LuaElementConvertors.h>
+#include <Swiften/Base/foreach.h>
+
+#pragma clang diagnostic ignored "-Wunused-private-field"
+
+using namespace Swift;
+
+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);
+ }
+
+ result->setSubscriptions(items);
+ }
+ return result;
+}
+
+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;
+ }
+ }
+ }
+ }
+}
diff --git a/Sluift/ElementConvertors/PubSubSubscriptionsConvertor.h b/Sluift/ElementConvertors/PubSubSubscriptionsConvertor.h
new file mode 100644
index 0000000..7f18f64
--- /dev/null
+++ b/Sluift/ElementConvertors/PubSubSubscriptionsConvertor.h
@@ -0,0 +1,28 @@
+/*
+ * 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 <Sluift/GenericLuaElementConvertor.h>
+#include <Swiften/Elements/PubSubSubscriptions.h>
+
+namespace Swift {
+ class LuaElementConvertors;
+
+ class PubSubSubscriptionsConvertor : public GenericLuaElementConvertor<PubSubSubscriptions> {
+ public:
+ PubSubSubscriptionsConvertor(LuaElementConvertors* convertors);
+ virtual ~PubSubSubscriptionsConvertor();
+
+ virtual boost::shared_ptr<PubSubSubscriptions> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE;
+ virtual void doConvertToLua(lua_State*, boost::shared_ptr<PubSubSubscriptions>) SWIFTEN_OVERRIDE;
+
+ private:
+ LuaElementConvertors* convertors;
+ };
+}
diff --git a/Sluift/ElementConvertors/PubSubUnsubscribeConvertor.cpp b/Sluift/ElementConvertors/PubSubUnsubscribeConvertor.cpp
new file mode 100644
index 0000000..323cb29
--- /dev/null
+++ b/Sluift/ElementConvertors/PubSubUnsubscribeConvertor.cpp
@@ -0,0 +1,59 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#include <Sluift/ElementConvertors/PubSubUnsubscribeConvertor.h>
+
+#include <lua.hpp>
+#include <boost/smart_ptr/make_shared.hpp>
+
+
+
+
+#pragma clang diagnostic ignored "-Wunused-private-field"
+
+using namespace Swift;
+
+PubSubUnsubscribeConvertor::PubSubUnsubscribeConvertor(LuaElementConvertors* convertors) :
+ GenericLuaElementConvertor<PubSubUnsubscribe>("pubsub_unsubscribe"),
+ convertors(convertors) {
+}
+
+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;
+}
+
+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");
+ }
+}
diff --git a/Sluift/ElementConvertors/PubSubUnsubscribeConvertor.h b/Sluift/ElementConvertors/PubSubUnsubscribeConvertor.h
new file mode 100644
index 0000000..16d279f
--- /dev/null
+++ b/Sluift/ElementConvertors/PubSubUnsubscribeConvertor.h
@@ -0,0 +1,28 @@
+/*
+ * 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 <Sluift/GenericLuaElementConvertor.h>
+#include <Swiften/Elements/PubSubUnsubscribe.h>
+
+namespace Swift {
+ class LuaElementConvertors;
+
+ class PubSubUnsubscribeConvertor : public GenericLuaElementConvertor<PubSubUnsubscribe> {
+ public:
+ PubSubUnsubscribeConvertor(LuaElementConvertors* convertors);
+ virtual ~PubSubUnsubscribeConvertor();
+
+ virtual boost::shared_ptr<PubSubUnsubscribe> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE;
+ virtual void doConvertToLua(lua_State*, boost::shared_ptr<PubSubUnsubscribe>) SWIFTEN_OVERRIDE;
+
+ private:
+ LuaElementConvertors* convertors;
+ };
+}
diff --git a/Sluift/ElementConvertors/RawXMLElementConvertor.cpp b/Sluift/ElementConvertors/RawXMLElementConvertor.cpp
new file mode 100644
index 0000000..35a53ca
--- /dev/null
+++ b/Sluift/ElementConvertors/RawXMLElementConvertor.cpp
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#include <Sluift/ElementConvertors/RawXMLElementConvertor.h>
+
+#include <iostream>
+#include <boost/smart_ptr/make_shared.hpp>
+#include <lua.hpp>
+
+#include <Swiften/Elements/RawXMLPayload.h>
+#include <Swiften/Serializer/PayloadSerializer.h>
+#include <Sluift/Lua/Check.h>
+
+using namespace Swift;
+
+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>();
+}
+
+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");
+}
diff --git a/Sluift/ElementConvertors/RawXMLElementConvertor.h b/Sluift/ElementConvertors/RawXMLElementConvertor.h
new file mode 100644
index 0000000..6087ba0
--- /dev/null
+++ b/Sluift/ElementConvertors/RawXMLElementConvertor.h
@@ -0,0 +1,26 @@
+/*
+ * 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 <Sluift/LuaElementConvertor.h>
+#include <Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.h>
+
+namespace Swift {
+ class RawXMLElementConvertor : public LuaElementConvertor {
+ public:
+ RawXMLElementConvertor();
+ virtual ~RawXMLElementConvertor();
+
+ 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;
+
+ private:
+ FullPayloadSerializerCollection serializers;
+ };
+}
diff --git a/Sluift/ElementConvertors/SConscript b/Sluift/ElementConvertors/SConscript
new file mode 100644
index 0000000..e98f7c4
--- /dev/null
+++ b/Sluift/ElementConvertors/SConscript
@@ -0,0 +1,42 @@
+
+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")
+]
+Return('convertors')
diff --git a/Sluift/ElementConvertors/SoftwareVersionConvertor.cpp b/Sluift/ElementConvertors/SoftwareVersionConvertor.cpp
new file mode 100644
index 0000000..5799614
--- /dev/null
+++ b/Sluift/ElementConvertors/SoftwareVersionConvertor.cpp
@@ -0,0 +1,50 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#include <Sluift/ElementConvertors/SoftwareVersionConvertor.h>
+
+#include <lua.hpp>
+#include <boost/smart_ptr/make_shared.hpp>
+#include <boost/numeric/conversion/cast.hpp>
+#include <Sluift/Lua/Check.h>
+
+using namespace Swift;
+
+SoftwareVersionConvertor::SoftwareVersionConvertor() : GenericLuaElementConvertor<SoftwareVersion>("software_version") {
+}
+
+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;
+}
+
+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");
+}
diff --git a/Sluift/ElementConvertors/SoftwareVersionConvertor.h b/Sluift/ElementConvertors/SoftwareVersionConvertor.h
new file mode 100644
index 0000000..5fa3cc3
--- /dev/null
+++ b/Sluift/ElementConvertors/SoftwareVersionConvertor.h
@@ -0,0 +1,23 @@
+/*
+ * 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 <Sluift/GenericLuaElementConvertor.h>
+#include <Swiften/Elements/SoftwareVersion.h>
+
+namespace Swift {
+ class SoftwareVersionConvertor : public GenericLuaElementConvertor<SoftwareVersion> {
+ public:
+ SoftwareVersionConvertor();
+ virtual ~SoftwareVersionConvertor();
+
+ virtual boost::shared_ptr<SoftwareVersion> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE;
+ virtual void doConvertToLua(lua_State*, boost::shared_ptr<SoftwareVersion>) SWIFTEN_OVERRIDE;
+ };
+}
diff --git a/Sluift/ElementConvertors/UserLocationConvertor.cpp b/Sluift/ElementConvertors/UserLocationConvertor.cpp
new file mode 100644
index 0000000..97cb288
--- /dev/null
+++ b/Sluift/ElementConvertors/UserLocationConvertor.cpp
@@ -0,0 +1,232 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#include <Sluift/ElementConvertors/UserLocationConvertor.h>
+
+#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() {
+}
+
+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;
+}
+
+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");
+ }
+}
diff --git a/Sluift/ElementConvertors/UserLocationConvertor.h b/Sluift/ElementConvertors/UserLocationConvertor.h
new file mode 100644
index 0000000..a5eb153
--- /dev/null
+++ b/Sluift/ElementConvertors/UserLocationConvertor.h
@@ -0,0 +1,28 @@
+/*
+ * 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 <Sluift/GenericLuaElementConvertor.h>
+#include <Swiften/Elements/UserLocation.h>
+
+namespace Swift {
+ class LuaElementConvertors;
+
+ class UserLocationConvertor : public GenericLuaElementConvertor<UserLocation> {
+ public:
+ UserLocationConvertor(LuaElementConvertors* convertors);
+ virtual ~UserLocationConvertor();
+
+ virtual boost::shared_ptr<UserLocation> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE;
+ virtual void doConvertToLua(lua_State*, boost::shared_ptr<UserLocation>) SWIFTEN_OVERRIDE;
+
+ private:
+ LuaElementConvertors* convertors;
+ };
+}
diff --git a/Sluift/ElementConvertors/VCardConvertor.cpp b/Sluift/ElementConvertors/VCardConvertor.cpp
new file mode 100644
index 0000000..a1c57be
--- /dev/null
+++ b/Sluift/ElementConvertors/VCardConvertor.cpp
@@ -0,0 +1,46 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#include <Sluift/ElementConvertors/VCardConvertor.h>
+
+#include <lua.hpp>
+#include <boost/smart_ptr/make_shared.hpp>
+#include <boost/numeric/conversion/cast.hpp>
+#include <Sluift/Lua/LuaUtils.h>
+#include <Swiften/Base/ByteArray.h>
+
+using namespace Swift;
+
+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;
+}
+
+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");
+ }
+}
diff --git a/Sluift/ElementConvertors/VCardConvertor.h b/Sluift/ElementConvertors/VCardConvertor.h
new file mode 100644
index 0000000..1cf4e9f
--- /dev/null
+++ b/Sluift/ElementConvertors/VCardConvertor.h
@@ -0,0 +1,23 @@
+/*
+ * 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 <Sluift/GenericLuaElementConvertor.h>
+#include <Swiften/Elements/VCard.h>
+
+namespace Swift {
+ class VCardConvertor : public GenericLuaElementConvertor<VCard> {
+ public:
+ VCardConvertor();
+ virtual ~VCardConvertor();
+
+ virtual boost::shared_ptr<VCard> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE;
+ virtual void doConvertToLua(lua_State*, boost::shared_ptr<VCard>) SWIFTEN_OVERRIDE;
+ };
+}
diff --git a/Sluift/ElementConvertors/VCardUpdateConvertor.cpp b/Sluift/ElementConvertors/VCardUpdateConvertor.cpp
new file mode 100644
index 0000000..0010ca5
--- /dev/null
+++ b/Sluift/ElementConvertors/VCardUpdateConvertor.cpp
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#include <Sluift/ElementConvertors/VCardUpdateConvertor.h>
+
+#include <lua.hpp>
+#include <boost/smart_ptr/make_shared.hpp>
+#include <boost/numeric/conversion/cast.hpp>
+#include <Sluift/Lua/LuaUtils.h>
+
+using namespace Swift;
+
+VCardUpdateConvertor::VCardUpdateConvertor() : GenericLuaElementConvertor<VCardUpdate>("vcard_update") {
+}
+
+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;
+}
+
+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");
+ }
+}
diff --git a/Sluift/ElementConvertors/VCardUpdateConvertor.h b/Sluift/ElementConvertors/VCardUpdateConvertor.h
new file mode 100644
index 0000000..e9bcd0f
--- /dev/null
+++ b/Sluift/ElementConvertors/VCardUpdateConvertor.h
@@ -0,0 +1,23 @@
+/*
+ * 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 <Sluift/GenericLuaElementConvertor.h>
+#include <Swiften/Elements/VCardUpdate.h>
+
+namespace Swift {
+ class VCardUpdateConvertor : public GenericLuaElementConvertor<VCardUpdate> {
+ public:
+ VCardUpdateConvertor();
+ virtual ~VCardUpdateConvertor();
+
+ virtual boost::shared_ptr<VCardUpdate> doConvertFromLua(lua_State*) SWIFTEN_OVERRIDE;
+ virtual void doConvertToLua(lua_State*, boost::shared_ptr<VCardUpdate>) SWIFTEN_OVERRIDE;
+ };
+}
diff --git a/Sluift/Examples/AdHocCommands.lua b/Sluift/Examples/AdHocCommands.lua
new file mode 100644
index 0000000..9e83f0c
--- /dev/null
+++ b/Sluift/Examples/AdHocCommands.lua
@@ -0,0 +1,48 @@
+--[[
+ Copyright (c) 2013 Remko Tronçon
+ Licensed under the GNU General Public License v3.
+ See Documentation/Licenses/GPLv3.txt for more information.
+--]]
+
+--[[
+
+ Ad-hoc command example.
+
+ This script logs into an XMPP server, and executes a
+ multi-step ad-hoc command.
+
+ 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
+
+c = sluift.new_client(os.getenv("SLUIFT_JID"), os.getenv("SLUIFT_PASS"))
+c:connect(function ()
+ to = sluift.jid.domain(os.getenv("SLUIFT_JID"))
+
+ -- Get the list of commands
+ commands = assert(c:get_disco_items{ to = to, disco_items = {
+ node = sluift.disco.features.COMMANDS }})
+ print(commands)
+
+ -- Get the initial form
+ result = assert(c:set_command{ to = to, command = {
+ action = 'execute', node = 'http://jabber.org/protocol/admin#get-user-roster'}})
+
+ -- Fill in the form
+ submission = result.form:create_submission()
+ submission.accountjid = os.getenv("SLUIFT_JID")
+
+ -- Submit the form
+ result = assert(c:set_command{ to = to, command = {
+ action = 'complete', node = 'http://jabber.org/protocol/admin#get-user-roster',
+ session_id = result.session_id, form = submission}})
+ for _, v in ipairs(result.form.roster.values) do
+ print(v)
+ end
+end)
diff --git a/Sluift/Examples/CollectVersions.lua b/Sluift/Examples/CollectVersions.lua
index c93c8c8..38bf6ac 100644
--- a/Sluift/Examples/CollectVersions.lua
+++ b/Sluift/Examples/CollectVersions.lua
@@ -1,22 +1,22 @@
---
--- Copyright (c) 2010 Remko Tronçon
--- Licensed under the GNU General Public License v3.
--- See Documentation/Licenses/GPLv3.txt for more information.
---
+--[[
+
+ Copyright (c) 2010-2013 Remko Tronçon
+ Licensed under the GNU General Public License v3.
+ See Documentation/Licenses/GPLv3.txt for more information.
--- This script logs into an XMPP server, and collects statistics about
--- the server software of all contacts in your roster
+ This script logs into an XMPP server, and collects statistics about
+ the server software of all contacts in your roster
-require "sluift"
+--]]
-c = sluift.new_client(os.getenv("SLUIFT_JID"), os.getenv("SLUIFT_PASS"))
-c:connect()
+require 'sluift'
-versions = {}
-for jid, _ in pairs(c:get_contacts()) do
- v = c:get_version(sluift.jid_domain(jid))
- if v then versions[v["name"]] = (versions[v["name"]] or 0) + 1 end
-end
-for name, count in pairs(versions) do print(name .. ": " .. count) end
-
-c:disconnect()
+c = sluift.new_client(os.getenv('SLUIFT_JID'), os.getenv('SLUIFT_PASS'))
+c:connect(function ()
+ versions = {}
+ for jid in pairs(c:get_contacts()) do
+ local v = c:get_software_version {to = sluift.jid.domain(jid), timeout = 3000} or {name = 'Unknown'}
+ versions[v['name']] = (versions[v['name']] or 0) + 1
+ end
+ for name, count in pairs(versions) do print(name .. ': ' .. count) end
+end)
diff --git a/Sluift/Examples/ContactsMap.lua b/Sluift/Examples/ContactsMap.lua
new file mode 100644
index 0000000..d248dc7
--- /dev/null
+++ b/Sluift/Examples/ContactsMap.lua
@@ -0,0 +1,120 @@
+--[[
+ Copyright (c) 2013 Remko Tronçon
+ Licensed under the GNU General Public License v3.
+ See Documentation/Licenses/GPLv3.txt for more information.
+--]]
+
+--[[
+
+ Contacts map
+
+ Creates an HTML file of a map with all your contacts on it.
+
+ The following environment variables are used:
+ - SLUIFT_JID, SWIFT_PASS: JID and password to log in with
+
+--]]
+
+require "sluift"
+
+output_dir = arg[1]
+if not output_dir then
+ error("Please specify the directory to write the map to")
+end
+
+-- Collect all data
+geolocs = {}
+avatars = {}
+c = sluift.new_client(os.getenv("SLUIFT_JID"), os.getenv("SLUIFT_PASS"))
+c:connect(function ()
+ -- Indicate we're interested in getting user location information, and send initial presence
+ c:set_caps_node("http://swift.im/ContactsMap")
+ c:set_disco_info({identities = {{name = 'ContactsMap'}}, features = {
+ sluift.disco.features.DISCO_INFO,
+ sluift.disco.features.USER_LOCATION .. '+notify',
+ }})
+ c:send_presence()
+
+ -- Collect geoloc info
+ for event in c:pubsub_events {timeout = 10000} do
+ local from = sluift.jid.to_bare(event.from)
+ if event._type == 'pubsub_event_items' and event.item then
+ if event.node == sluift.disco.features.USER_LOCATION then
+ local lat, lon = event.item.latitude, event.item.longitude
+ if lat and lon then geolocs[from] = {lat = lat, lon = lon} end
+ end
+ end
+ end
+
+ -- Download the necessary avatars
+ for contact in pairs(geolocs) do
+ local vcard = c:get_vcard {to = contact}
+ if vcard and vcard.photo then
+ local avatar_hash = sluift.hexify(sluift.sha1(vcard.photo))
+ local file = io.open(output_dir.."/" .. avatar_hash .. ".png", "wb")
+ file:write(vcard.photo)
+ file:close()
+ avatars[contact] = avatar_hash
+ end
+ end
+end)
+
+-- Generate html
+min_lat, max_lat = 90, -90
+min_lon, max_lon = 180, -180
+contacts_html = {}
+for contact, geoloc in pairs(geolocs) do
+ if geoloc.lat < min_lat then min_lat = geoloc.lat end
+ if geoloc.lon < min_lon then min_lon = geoloc.lon end
+ if geoloc.lat > max_lat then max_lat = geoloc.lat end
+ if geoloc.lon > max_lon then max_lon = geoloc.lon end
+ local image = 'null'
+ if avatars[contact] then
+ image = "'" .. avatars[contact] .. ".png'"
+ end
+ contacts_html[#contacts_html+1] = "['" .. contact .. "'," .. geoloc.lat .. "," .. geoloc.lon .. "," .. image .. "]"
+end
+center_html = ((min_lat + max_lat) / 2) .. ',' .. ((min_lon + max_lon) / 2)
+
+map_html = [[
+<html>
+ <head>
+ <title>Contacts Map</title>
+ <script src="http://maps.google.com/maps/api/js?sensor=false" type="text/javascript"></script>
+ </head>
+ <body>
+ <div id="map" style="height: 100%; width: 100%;"/>
+ <script>
+ var map = new google.maps.Map(document.getElementById('map'), {
+ zoom: 2,
+ center: new google.maps.LatLng(%(CENTER)),
+ mapTypeId: google.maps.MapTypeId.ROADMAP
+ });
+ var infowindow = new google.maps.InfoWindow();
+ var contacts = [%(CONTACTS)];
+ for (var i = 0; i < contacts.length; i++) {
+ var icon = null;
+ if (contacts[i][3]) {
+ icon = { url: contacts[i][3], scaledSize: { width: 30, height: 30} };
+ }
+ var marker = new google.maps.Marker({
+ position: new google.maps.LatLng(contacts[i][1], contacts[i][2]),
+ map: map,
+ icon: icon,
+ });
+ google.maps.event.addListener(marker, 'click', (function(marker, i) {
+ return function() {
+ infowindow.setContent(contacts[i][0]);
+ infowindow.open(map, marker);
+ }
+ })(marker, i));
+ }
+ </script>
+ </body>
+</html>
+]]
+local file = io.open(output_dir .. "/index.html", "w")
+file:write(map_html:
+ gsub('%%%(CONTACTS%)', table.concat(contacts_html, ",")):
+ gsub('%%%(CENTER%)', center_html))
+file:close()
diff --git a/Sluift/Examples/EchoBot.lua b/Sluift/Examples/EchoBot.lua
index 09da63b..fc495c4 100644
--- a/Sluift/Examples/EchoBot.lua
+++ b/Sluift/Examples/EchoBot.lua
@@ -1,27 +1,31 @@
---
--- Copyright (c) 2010 Remko Tronçon
--- Licensed under the GNU General Public License v3.
--- See Documentation/Licenses/GPLv3.txt for more information.
---
+--[[
+ Copyright (c) 2010-2013 Remko Tronçon
+ Licensed under the GNU General Public License v3.
+ See Documentation/Licenses/GPLv3.txt for more information.
+--]]
---
--- An XMPP Echoing Bot
---
--- 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
---
+--[[
+
+ An XMPP Echoing Bot
+
+ 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
c = sluift.new_client(os.getenv("SLUIFT_JID"), os.getenv("SLUIFT_PASS"))
-c:connect()
-c:send_presence("Send me a message")
-c:for_event(function(e)
- if e["type"] == "message" then c:send_message(e["from"], e["body"]) end
- end)
+c:connect(function ()
+ c:set_version{name = "EchoBot", version = "0.1"}
+ c:send_presence("Send me a message")
+ for message in c:messages() do
+ c:send_message{to = message["from"], body = message["body"]}
+ end
+end)
diff --git a/Sluift/Examples/Login.lua b/Sluift/Examples/Login.lua
index 1733bb9..c43b72a 100644
--- a/Sluift/Examples/Login.lua
+++ b/Sluift/Examples/Login.lua
@@ -1,16 +1,20 @@
---
--- Copyright (c) 2010 Remko Tronçon
--- Licensed under the GNU General Public License v3.
--- See Documentation/Licenses/GPLv3.txt for more information.
---
+--[[
+ Copyright (c) 2010-2013 Remko Tronçon
+ Licensed under the GNU General Public License v3.
+ See Documentation/Licenses/GPLv3.txt for more information.
+--]]
--- This script logs into an XMPP server, and sends initial presence
--- Useful as initialization script for an interactive session ('-i'),
--- or as a starting point for scripts.
---
--- 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
+--[[
+
+ This script logs into an XMPP server, and sends initial presence
+ Useful as initialization script for an interactive session ('-i'),
+ or as a starting point for scripts.
+
+ 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
@@ -18,6 +22,8 @@ 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:connect():send_presence("")
+c:connect()
+c:send_presence("")
print("Connected ...")
+print("Use the 'c' variable to communicate.")
diff --git a/Sluift/Examples/PEPListener.lua b/Sluift/Examples/PEPListener.lua
new file mode 100644
index 0000000..f196f84
--- /dev/null
+++ b/Sluift/Examples/PEPListener.lua
@@ -0,0 +1,46 @@
+--[[
+ Copyright (c) 2010-2013 Remko Tronçon
+ Licensed under the GNU General Public License v3.
+ See Documentation/Licenses/GPLv3.txt for more information.
+--]]
+
+--[[
+
+ PEP Listener
+
+ Listens to a series of PEP events of all 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
+
+pep_protocols = {
+ [sluift.disco.features.USER_LOCATION] = true,
+ [sluift.disco.features.USER_TUNE] = true,
+ [sluift.disco.features.USER_ACTIVITY] = true,
+ [sluift.disco.features.USER_AVATAR_METADATA] = true,
+ [sluift.disco.features.USER_PROFILE] = true,
+}
+
+client = sluift.new_client(os.getenv("SLUIFT_JID"), os.getenv("SLUIFT_PASS"))
+client:connect(function (c)
+ features = {sluift.disco.features.DISCO_INFO}
+ for protocol in pairs(pep_protocols) do
+ features[#features+1] = protocol .. '+notify'
+ end
+
+ c:set_caps_node("http://swift.im/PEPListener")
+ c:set_disco_info({identities = {{name = 'PEPListener'}}, features = features})
+ c:send_presence()
+ for event in c:pubsub_events() do
+ if event._type == 'pubsub_event_items' and pep_protocols[event.node] then
+ print("<" .. event.from .. "> " .. tostring(event.item))
+ end
+ end
+end)
diff --git a/Sluift/Examples/RemoveUnreachableContacts.lua b/Sluift/Examples/RemoveUnreachableContacts.lua
index 90122df..a202e62 100644
--- a/Sluift/Examples/RemoveUnreachableContacts.lua
+++ b/Sluift/Examples/RemoveUnreachableContacts.lua
@@ -1,37 +1,38 @@
---
--- Copyright (c) 2010 Remko Tronçon
--- Licensed under the GNU General Public License v3.
--- See Documentation/Licenses/GPLv3.txt for more information.
---
+--[[
+ Copyright (c) 2010-2013 Remko Tronçon
+ Licensed under the GNU General Public License v3.
+ See Documentation/Licenses/GPLv3.txt for more information.
+--]]
--- This script logs into an XMPP server, iterates over all roster items,
--- and checks if their server is still alive. If not, the script asks you
--- whether it should remove the contact from your contact list.
---
--- 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
+--[[
+ This script logs into an XMPP server, iterates over all roster items,
+ and checks if their server is still alive. If not, the script asks you
+ whether it should remove the contact from your contact list.
-require "sluift"
-sluift.debug = os.getenv("SLUIFT_DEBUG")
+ 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
+--]]
-print "Connecting ..."
-c = sluift.new_client(os.getenv("SLUIFT_JID"), os.getenv("SLUIFT_PASS"))
-c:connect()
+require 'sluift'
+sluift.debug = os.getenv('SLUIFT_DEBUG')
-print "Checking for unreachable contacts ..."
-for jid, _ in pairs(c:get_contacts()) do
- _, err = c:get_version(sluift.jid_domain(jid), 10000)
- if err == "Remote server not found" or err == "Timeout" then
- print("Delete " .. jid .. " (" .. err .. ") ? [y/n/q]")
- answer = io.read()
- if answer == "y" then
- c:remove_contact(jid)
- elseif answer == "q" then
- break
+print 'Connecting ...'
+c = sluift.new_client(os.getenv('SLUIFT_JID'), os.getenv('SLUIFT_PASS'))
+c:connect(function (c)
+ print 'Checking for unreachable contacts ...'
+ for jid in pairs(c:get_contacts()) do
+ _, err = c:get_software_version {to = sluift.jid.domain(jid), timeout = 10000}
+ print(err)
+ if err == 'Remote server not found' or err == 'Remote server timeout' then
+ print('Delete ' .. jid .. ' (' .. err .. ') ? [y/n/q]')
+ answer = io.read()
+ if answer == 'y' then
+ c:remove_contact(jid)
+ elseif answer == 'q' then
+ break
+ end
end
end
-end
-
-print "Done. Exiting ..."
-c:disconnect()
+ print 'Done. Exiting ...'
+end)
diff --git a/Sluift/Examples/Wonderland.lua b/Sluift/Examples/Wonderland.lua
index 58c00ca..426ec07 100755
--- a/Sluift/Examples/Wonderland.lua
+++ b/Sluift/Examples/Wonderland.lua
@@ -8,45 +8,97 @@
--
require "sluift"
---sluift.debug = true
+sluift.debug = true
characters = {
- {jid = "alice@wonderland.lit", name = "Alice", groups = {}, presence = "<presence/>"},
- {jid = "hatter@wonderland.lit", name = "Mad Hatter", groups = {}, presence = "<presence><show>away</show><status>At the Tea Party</status></presence>"},
- {jid ="queen@wonderland.lit", name = "Queen of Hearts", groups = {}, presence = "<presence><show>dnd</show><status>Executing</status></presence>"},
- {jid = "rabbit@wonderland.lit", name = "White Rabbit", groups = {"Animals"}, presence = "<presence><status>Oh dear!</status></presence>"},
- {jid = "turtle@wonderland.lit", name = "Mock Turtle", groups = {"Animals"}, presence = "<presence/>"},
+ ["Alice"] = {
+ jid = "alice@wonderland.lit", groups = {}, presence = "<presence/>"
+ },
+ ["Mad Hatter"] = {
+ jid = "hatter@wonderland.lit", groups = {},
+ presence = "<presence><show>away</show><status>At the Tea Party</status></presence>"
+ },
+ ["Queen of Hearts"] = {
+ jid ="queen@wonderland.lit", groups = {},
+ presence = "<presence><show>dnd</show><status>Executing</status></presence>"
+ },
+ ["White Rabbit"] = {
+ jid = "rabbit@wonderland.lit", groups = {"Animals"},
+ presence = "<presence><status>Oh dear!</status></presence>"},
+ ["Mock Turtle"] = {
+ jid = "turtle@wonderland.lit", groups = {"Animals"},
+ presence = "<presence/>"
+ },
}
-clients = {}
-for _, character in ipairs(characters) do
- print("Connecting " .. character["name"] .. "...")
- client = sluift.new_client(character["jid"], os.getenv("SLUIFT_PASS"))
+for name, character in pairs(characters) do
+ print("Connecting " .. name .. "...")
+ local client = sluift.new_client(character.jid, os.getenv("SLUIFT_PASS"))
client:set_options({compress = false, tls = false})
client:connect()
client:get_contacts()
- client:send(character["presence"])
- table.insert(clients, client)
- for _, contact in ipairs(characters) do
- if contact["jid"] ~= character["jid"] then
+ client:send(character.presence)
+ for contact_name, contact in pairs(characters) do
+ if contact.jid ~= character.jid then
client:add_contact(contact)
end
end
+ character.client = client
end
print("Confirming subscriptions")
-for _, client in ipairs(clients) do
- for _, contact in ipairs(characters) do
- client:confirm_subscription(contact["jid"])
+for _, character in pairs(characters) do
+ for _, contact in pairs(characters) do
+ character.client:confirm_subscription(contact.jid)
end
end
+print("Setting up PubSub nodes")
+local hatters_riddles = characters["Mad Hatter"].client:pubsub("pubsub.wonderland.lit"):node("hatters_riddles")
+hatters_riddles:delete()
+assert(hatters_riddles:create())
+
+local queen_quotes = characters["Queen of Hearts"].client:pubsub("pubsub.wonderland.lit"):node("queen_quotes")
+queen_quotes:delete()
+assert(queen_quotes:create())
+queen_quotes:publish{id = 'quote1', item = {_type = 'body', text = 'Off with his head!'}}
+queen_quotes:publish{id = 'quote2', item = {_type = 'body', text = 'Off with her head!'}}
+queen_quotes:publish{id = 'quote3', item = {_type = 'body', text = 'Off with their heads!'}}
+
+characters['Mad Hatter'].client:pubsub():node('http://jabber.org/protocol/geoloc'):publish{
+ item = {_type = 'user_location', latitude = 50.376739, longitude = -4.200709}}
+characters['Queen of Hearts'].client:pubsub():node('http://jabber.org/protocol/geoloc'):publish{
+ item = {_type = 'user_location', latitude = 50.551123, longitude = -4.141654}}
+characters['Mock Turtle'].client:pubsub():node('http://jabber.org/protocol/geoloc'):publish{
+ item = {_type = 'user_location', latitude = 50.366630, longitude = -4.134518}}
+characters['White Rabbit'].client:pubsub():node('http://jabber.org/protocol/geoloc'):publish{
+ item = {_type = 'user_location', latitude = 50.332907, longitude = -4.759194}}
+
+
+
+print("Disconnecting alice")
+characters['Alice'].client:disconnect()
+
print("Done. Waiting ...")
while true do
- for _, client in ipairs(clients) do
- client:for_event(function(e)
- if e["type"] == "message" then client:send_message(e["from"], "Off with their heads!") end
- end, 1000)
+ for name, character in pairs(characters) do
+ if name == 'Queen of Hearts' then
+ for message in character.client:messages{timeout = 1000} do
+ if message.body == 'publish' then
+ queen_quotes:publish{item = {_type = 'body', text = 'Off with her head!'}}
+ queen_quotes:publish{item = {_type = 'body', text = 'Off with his head!'}}
+ else
+ character.client:send_message{to = e["from"], body = "Off with their heads!"}
+ end
+ end
+ elseif name == "Mad Hatter" then
+ for message in character.client:messages{timeout = 1000} do
+ if message.body == 'publish' then
+ hatters_riddles:publish{item = {_type = 'body', text = 'Why is a raven like a writing desk?'}}
+ end
+ end
+ else
+ for message in character.client:messages{timeout = 100} do end
+ end
end
- sluift.sleep(1000)
end
diff --git a/Sluift/GenericLuaElementConvertor.h b/Sluift/GenericLuaElementConvertor.h
new file mode 100644
index 0000000..afad481
--- /dev/null
+++ b/Sluift/GenericLuaElementConvertor.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#pragma once
+
+#include <lua.hpp>
+#include <string>
+
+#include <Swiften/Base/Override.h>
+#include <Sluift/LuaElementConvertor.h>
+#include <Sluift/Lua/Check.h>
+#include <Sluift/Lua/LuaUtils.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;
+ };
+}
diff --git a/Sluift/Lua/Check.cpp b/Sluift/Lua/Check.cpp
new file mode 100644
index 0000000..cfb726a
--- /dev/null
+++ b/Sluift/Lua/Check.cpp
@@ -0,0 +1,60 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#include <Sluift/Lua/Check.h>
+
+#include <boost/numeric/conversion/cast.hpp>
+#include <iostream>
+#include <sstream>
+#include <lua.hpp>
+
+#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();
+}
+
+void Lua::checkType(lua_State* L, int arg, int 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));
+}
+
+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);
+}
+
+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;
+}
diff --git a/Sluift/Lua/Check.h b/Sluift/Lua/Check.h
new file mode 100644
index 0000000..a569826
--- /dev/null
+++ b/Sluift/Lua/Check.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#pragma once
+
+#include <string>
+
+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);
+
+ void* checkUserDataRaw(lua_State* L, int arg, const char* tableName);
+
+ template<typename T>
+ T** checkUserData(lua_State* L, int arg, const char* tableName) {
+ return reinterpret_cast<T**>(checkUserDataRaw(L, arg, tableName));
+ }
+ }
+}
diff --git a/Sluift/Lua/Debug.h b/Sluift/Lua/Debug.h
new file mode 100644
index 0000000..8e86b89
--- /dev/null
+++ b/Sluift/Lua/Debug.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#pragma once
+
+#include <lua.hpp>
+#include <iostream>
+
+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;
+ }
+ }
+ }
+}
diff --git a/Sluift/Lua/Exception.cpp b/Sluift/Lua/Exception.cpp
new file mode 100644
index 0000000..d80b9fb
--- /dev/null
+++ b/Sluift/Lua/Exception.cpp
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#include <Sluift/Lua/Exception.h>
+
+using namespace Swift::Lua;
+
+Exception::Exception(const std::string& what) : std::runtime_error(what) {
+}
+
+Exception::~Exception() throw() {
+}
diff --git a/Sluift/Lua/Exception.h b/Sluift/Lua/Exception.h
new file mode 100644
index 0000000..6d00d01
--- /dev/null
+++ b/Sluift/Lua/Exception.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#pragma once
+
+#include <stdexcept>
+
+namespace Swift {
+ namespace Lua {
+ class Exception : public std::runtime_error {
+ public:
+ Exception(const std::string& what);
+ virtual ~Exception() throw();
+ };
+ }
+}
+
diff --git a/Sluift/Lua/FunctionRegistration.cpp b/Sluift/Lua/FunctionRegistration.cpp
new file mode 100644
index 0000000..b773952
--- /dev/null
+++ b/Sluift/Lua/FunctionRegistration.cpp
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#include <Sluift/Lua/FunctionRegistration.h>
+
+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() {
+}
diff --git a/Sluift/Lua/FunctionRegistration.h b/Sluift/Lua/FunctionRegistration.h
new file mode 100644
index 0000000..0df1da1
--- /dev/null
+++ b/Sluift/Lua/FunctionRegistration.h
@@ -0,0 +1,36 @@
+/*
+ * 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 <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();
+ };
+ }
+}
+#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)
diff --git a/Sluift/Lua/FunctionRegistry.cpp b/Sluift/Lua/FunctionRegistry.cpp
new file mode 100644
index 0000000..99ea096
--- /dev/null
+++ b/Sluift/Lua/FunctionRegistry.cpp
@@ -0,0 +1,55 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#include <Sluift/Lua/FunctionRegistry.h>
+
+#include <Swiften/Base/foreach.h>
+
+using namespace Swift::Lua;
+
+FunctionRegistry::FunctionRegistry() {
+}
+
+FunctionRegistry::~FunctionRegistry() {
+}
+
+FunctionRegistry& FunctionRegistry::getInstance() {
+ 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::createFunctionTable(lua_State* L, const std::string& 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());
+ }
+ }
+}
diff --git a/Sluift/Lua/FunctionRegistry.h b/Sluift/Lua/FunctionRegistry.h
new file mode 100644
index 0000000..e3ad620
--- /dev/null
+++ b/Sluift/Lua/FunctionRegistry.h
@@ -0,0 +1,46 @@
+/*
+ * 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 <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();
+
+
+ private:
+ struct Registration {
+ std::string name;
+ lua_CFunction function;
+ std::string type;
+ };
+ std::vector<Registration> registrations;
+ };
+ }
+}
diff --git a/Sluift/Lua/LuaUtils.cpp b/Sluift/Lua/LuaUtils.cpp
new file mode 100644
index 0000000..7052abe
--- /dev/null
+++ b/Sluift/Lua/LuaUtils.cpp
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * 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/numeric/conversion/cast.hpp>
+#include <Sluift/globals.h>
+
+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);
+}
+
+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);
+}
+
+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;
+}
+
+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;
+}
+
+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;
+}
diff --git a/Sluift/Lua/LuaUtils.h b/Sluift/Lua/LuaUtils.h
new file mode 100644
index 0000000..bad307c
--- /dev/null
+++ b/Sluift/Lua/LuaUtils.h
@@ -0,0 +1,32 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#pragma once
+
+#include <lua.hpp>
+#include <boost/optional.hpp>
+
+struct lua_State;
+
+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&);
+ }
+}
diff --git a/Sluift/Lua/Value.cpp b/Sluift/Lua/Value.cpp
index 3164ec6..4f8078e 100644
--- a/Sluift/Lua/Value.cpp
+++ b/Sluift/Lua/Value.cpp
@@ -6,8 +6,11 @@
#include "Value.h"
-#include <lualib.h>
+extern "C" {
+ #include <lualib.h>
+}
#include <boost/variant/apply_visitor.hpp>
+#include <boost/numeric/conversion/cast.hpp>
#include <Swiften/Base/foreach.h>
using namespace Swift;
@@ -35,15 +38,15 @@ namespace {
}
void operator()(const std::vector<Value>& values) const {
- lua_createtable(state, values.size(), 0);
+ 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, i + 1);
+ 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, table.size());
+ 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());
diff --git a/Sluift/Lua/Value.h b/Sluift/Lua/Value.h
index 7b10cd2..55aa347 100644
--- a/Sluift/Lua/Value.h
+++ b/Sluift/Lua/Value.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011 Remko Tronçon
+ * Copyright (c) 2010-2013 Remko Tronçon
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
@@ -11,6 +11,7 @@
#include <vector>
#include <boost/variant.hpp>
#include <boost/shared_ptr.hpp>
+#include <boost/smart_ptr/make_shared.hpp>
struct lua_State;
@@ -28,7 +29,32 @@ namespace Swift {
>::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);
}
}
diff --git a/Sluift/LuaElementConvertor.cpp b/Sluift/LuaElementConvertor.cpp
new file mode 100644
index 0000000..c1d0720
--- /dev/null
+++ b/Sluift/LuaElementConvertor.cpp
@@ -0,0 +1,14 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#include <Sluift/LuaElementConvertor.h>
+
+using namespace Swift;
+
+LuaElementConvertor::~LuaElementConvertor() {
+}
+
+boost::optional<std::string> LuaElementConvertor::NO_RESULT;
diff --git a/Sluift/LuaElementConvertor.h b/Sluift/LuaElementConvertor.h
new file mode 100644
index 0000000..187ccf1
--- /dev/null
+++ b/Sluift/LuaElementConvertor.h
@@ -0,0 +1,28 @@
+/*
+ * 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 <boost/shared_ptr.hpp>
+#include <boost/optional.hpp>
+
+struct lua_State;
+
+namespace Swift {
+ class Payload;
+
+ class LuaElementConvertor {
+ public:
+ static boost::optional<std::string> NO_RESULT;
+
+ virtual ~LuaElementConvertor();
+
+ 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;
+ };
+}
diff --git a/Sluift/LuaElementConvertors.cpp b/Sluift/LuaElementConvertors.cpp
new file mode 100644
index 0000000..71957c1
--- /dev/null
+++ b/Sluift/LuaElementConvertors.cpp
@@ -0,0 +1,112 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#include <Sluift/LuaElementConvertors.h>
+
+#include <boost/smart_ptr/make_shared.hpp>
+
+#include <Swiften/Base/foreach.h>
+#include <Sluift/LuaElementConvertor.h>
+#include <Sluift/ElementConvertors/RawXMLElementConvertor.h>
+#include <Sluift/ElementConvertors/PubSubEventConvertor.h>
+#include <Sluift/ElementConvertors/DOMElementConvertor.h>
+#include <Sluift/ElementConvertors/DefaultElementConvertor.h>
+#include <Sluift/ElementConvertors/DiscoItemsConvertor.h>
+#include <Sluift/ElementConvertors/DiscoInfoConvertor.h>
+#include <Sluift/ElementConvertors/FormConvertor.h>
+#include <Sluift/ElementConvertors/SoftwareVersionConvertor.h>
+#include <Sluift/ElementConvertors/VCardUpdateConvertor.h>
+#include <Sluift/ElementConvertors/VCardConvertor.h>
+#include <Sluift/ElementConvertors/BodyConvertor.h>
+#include <Sluift/ElementConvertors/CommandConvertor.h>
+#include <Sluift/Lua/LuaUtils.h>
+#include <Sluift/Lua/Exception.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>());
+}
+
+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");
+}
+
+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>();
+}
+
+
+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::convertToLuaUntyped(lua_State* L, boost::shared_ptr<Payload> 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;
+}
+
diff --git a/Sluift/LuaElementConvertors.h b/Sluift/LuaElementConvertors.h
new file mode 100644
index 0000000..36da15a
--- /dev/null
+++ b/Sluift/LuaElementConvertors.h
@@ -0,0 +1,47 @@
+/*
+ * 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 <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;
+ };
+}
diff --git a/Sluift/README b/Sluift/README
deleted file mode 100644
index 65fb648..0000000
--- a/Sluift/README
+++ /dev/null
@@ -1,2 +0,0 @@
-For example scripts, see the 'login.lua' script and the scripts in
-Swiften/QA/ScriptedTests.
diff --git a/Sluift/README.md b/Sluift/README.md
new file mode 100644
index 0000000..ae43846
--- /dev/null
+++ b/Sluift/README.md
@@ -0,0 +1,52 @@
+# Sluift
+
+## Building/Installing
+
+If you have a Lua installed on your system, edit `config.py` to point the build
+to it using the `lua_libdir`, `lua_includedir`, and `lua_libname` (usually
+only needed on Windows) variables.
+
+In case no Lua installation is found, a bundled Lua version will be used.
+Note that there are several limitations when using the bundled Lua:
+
+- The standalone Sluift binary will not support dynamic loading of modules.
+- The Sluift module will not be built
+
+The standalone executable will be placed into `Sluift/exe`, and the loadable
+Lua module in `Sluift/dll`.
+
+In order to use the Sluift Lua module, make sure it is copied to a location in the
+Lua search path (`LUA_PATH`, or the built-in path). On Linux and Mac OS X, this is
+typically `<LUA_INSTALLPREFIX>/lib/lua/<LUA_VERSION>/`. If `require 'sluift'` fails,
+the error message will give an indication what this path is.
+
+
+## Examples
+
+Example scripts can be found in `Examples/`, and in the Swift tree under
+`Swiften/QA/ScriptedTests`.
+
+## Extending
+
+### Adding support for payloads
+
+To add support for a specific Swiften payload, create a new `LuaElementConvertor`
+in `ElementConvertors/` by inheriting from `GenericLuaElementConvertor`, and register
+it it `LuaElementConvertors.cpp`. The name of the convertor passed in the constructor
+of `GenericLuaElementConvertor` should correspond to the snake case version of the
+Swiften element it converts. For examples, see the existing convertors in
+`ElementConvertors/`.
+
+When the convertor is registered, you can use it in message bodies, or in get/set
+queries. For example, for the `command` convertor:
+
+ client:set{to = 'alice@wonderland.lit', query = {_type = 'command',
+ type = 'execute', node = 'uptime'}}
+
+Optionally, you can add a convenience `set_<type>` shortcut on the client object by
+adding it to the list of `get_set_shortcuts` in `boot.lua`. With such a shortcut, the
+command above can be rewritten as:
+
+ client:set_command{to = 'alice@wonderland.lit', command = {
+ type = 'execute', node = 'uptime'}}
+
diff --git a/Sluift/Response.cpp b/Sluift/Response.cpp
new file mode 100644
index 0000000..519379c
--- /dev/null
+++ b/Sluift/Response.cpp
@@ -0,0 +1,78 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#include <Sluift/Response.h>
+
+#include <lua.hpp>
+
+#include <Sluift/globals.h>
+#include <Swiften/Elements/ErrorPayload.h>
+#include <Sluift/Lua/LuaUtils.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;
+}
+
+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;
+ }
+
+}
+
diff --git a/Sluift/Response.h b/Sluift/Response.h
new file mode 100644
index 0000000..1cd059a
--- /dev/null
+++ b/Sluift/Response.h
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#pragma once
+
+#include <Swiften/Elements/Payload.h>
+#include <Swiften/Elements/ErrorPayload.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;
+ };
+ }
+}
diff --git a/Sluift/ResponseSink.h b/Sluift/ResponseSink.h
deleted file mode 100644
index 700363a..0000000
--- a/Sluift/ResponseSink.h
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 2011 Remko Tronçon
- * Licensed under the GNU General Public License v3.
- * See Documentation/Licenses/GPLv3.txt for more information.
- */
-
-#pragma once
-
-#include <boost/shared_ptr.hpp>
-
-#include <Swiften/Elements/ErrorPayload.h>
-
-namespace Swift {
- template<typename T>
- class ResponseSink {
- public:
- ResponseSink() : responseReceived(false) {
- }
-
- bool hasResponse() const {
- return responseReceived;
- }
-
- boost::shared_ptr<T> getResponsePayload() const {
- return payload;
- }
-
- ErrorPayload::ref getResponseError() const {
- return error;
- }
-
- void operator()(boost::shared_ptr<T> payload, ErrorPayload::ref error) {
- this->payload = payload;
- this->error = error;
- this->responseReceived = true;
- }
-
- void operator()(ErrorPayload::ref error) {
- this->error = error;
- this->responseReceived = true;
- }
-
- private:
- bool responseReceived;
- boost::shared_ptr<T> payload;
- ErrorPayload::ref error;
- };
-}
diff --git a/Sluift/SConscript b/Sluift/SConscript
index f6388a0..1a29e43 100644
--- a/Sluift/SConscript
+++ b/Sluift/SConscript
@@ -2,32 +2,51 @@ import Version, os.path
Import(["env", "conf_env"])
-if env["SCONS_STAGE"] == "build" :
- lib_env = env.Clone()
- lib_env.UseFlags(env["LUA_FLAGS"])
- lib_env.UseFlags(env["SWIFTEN_FLAGS"])
- lib_env.UseFlags(env["SWIFTEN_DEP_FLAGS"])
- sluift_lib = lib_env.StaticLibrary("SluiftCore", [
- "Lua/Value.cpp",
- "sluift.cpp"
- ]);
+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")
+
+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")
- myenv = env.Clone()
- myenv.Append(LIBS = sluift_lib)
- myenv.UseFlags(env.get("LUA_FLAGS", {}))
- myenv.UseFlags(env["SWIFTEN_FLAGS"])
- myenv.UseFlags(env["SWIFTEN_DEP_FLAGS"])
- myenv["SHLIBPREFIX"] = ""
- if myenv["PLATFORM"] == "win32" :
- myenv.Append(CPPDEFINES = ["SLUIFT_BUILD_DLL"])
- elif myenv["PLATFORM"] == "darwin" :
- myenv["SHLIBSUFFIX"] = ".so"
- if env["PLATFORM"] == "win32" :
- myenv.Append(CFLAGS = ["/TP"])
- else :
- myenv.Append(CFLAGS = ["-x", "c++"])
+ 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"])
- myenv["SLUIFT_VERSION"] = Version.getBuildVersion(env.Dir("#").abspath, "sluift")
+ # 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()
@@ -41,24 +60,26 @@ if env["SCONS_STAGE"] == "build" :
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"))
- myenv.Command("lua.c", ["#/3rdParty/Lua/src/lua.c", myenv.Value(myenv["SLUIFT_VERSION"])], env.Action(patchLua, cmdstr = "$GENCOMSTR"))
- if myenv.get("HAVE_READLINE", False) :
- myenv.Append(CPPDEFINES = ["LUA_USE_READLINE"])
- myenv.MergeFlags(myenv["READLINE_FLAGS"])
- env["SLUIFT"] = myenv.Program("sluift", [
- "lua.c",
- "linit.c",
- ])
+ # 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"))
+
+ if sluift_env.get("HAVE_READLINE", False) :
+ sluift_env.Append(CPPDEFINES = ["LUA_USE_READLINE"])
+ sluift_env.MergeFlags(sluift_env["READLINE_FLAGS"])
- myenv.WriteVal("dll.c", myenv.Value(""))
- myenv.SharedLibrary("sluift", ["dll.c"])
+ sluift_env.WriteVal("dll.c", sluift_env.Value(""))
- if env["PLATFORM"] == "win32" :
- ssl_libs = []
- if myenv.get("OPENSSL_DIR", False) :
- ssl_libs = [
- os.path.join(env["OPENSSL_DIR"], "bin", "ssleay32.dll"),
- os.path.join(env["OPENSSL_DIR"], "bin", "libeay32.dll")
- ]
- myenv.WindowsBundle("Sluift", resources = {"": ssl_libs})
+ 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
new file mode 100644
index 0000000..92ee493
--- /dev/null
+++ b/Sluift/SConscript.variant
@@ -0,0 +1,25 @@
+import os
+
+Import('env')
+Import('sluift_env')
+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"])
+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)
+
diff --git a/Sluift/SluiftClient.cpp b/Sluift/SluiftClient.cpp
new file mode 100644
index 0000000..bfae621
--- /dev/null
+++ b/Sluift/SluiftClient.cpp
@@ -0,0 +1,169 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#include <Sluift/SluiftClient.h>
+
+#include <Swiften/Client/ClientXMLTracer.h>
+#include <Swiften/Client/Client.h>
+#include <Swiften/Roster/XMPPRoster.h>
+#include <Sluift/SluiftGlobals.h>
+#include <Sluift/Lua/Exception.h>
+#include <Swiften/Elements/Message.h>
+#include <Swiften/Elements/PubSubEvent.h>
+#include <Swiften/Queries/RawRequest.h>
+#include <Sluift/ClientHelpers.h>
+#include <Swiften/Elements/Presence.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);
+ }
+}
+
+SluiftClient::~SluiftClient() {
+ delete tracer;
+ delete client;
+}
+
+void SluiftClient::connect() {
+ rosterReceived = false;
+ disconnectedError = boost::optional<ClientError>();
+ client->connect(options);
+}
+
+void SluiftClient::connect(const std::string& host, int port) {
+ rosterReceived = false;
+ options.manualHostname = host;
+ options.manualPort = port;
+ 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));
+ }
+}
+
+bool SluiftClient::isConnected() const {
+ return client->isAvailable();
+}
+
+void SluiftClient::disconnect() {
+ 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);
+}
+
+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;
+ }
+ }
+
+ // Wait for new events
+ while (!watchdog.getTimedOut() && pendingEvents.empty() && client->isActive()) {
+ eventLoop->runUntilEvents();
+ }
+
+ // 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();
+}
+
+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(boost::shared_ptr<Presence> stanza) {
+ pendingEvents.push_back(Event(stanza));
+}
+
+void SluiftClient::handleIncomingPubSubEvent(const JID& from, boost::shared_ptr<PubSubEventPayload> event) {
+ pendingEvents.push_back(Event(from, event));
+}
+
+void SluiftClient::handleInitialRosterPopulated() {
+ rosterReceived = true;
+}
+
+void SluiftClient::handleRequestResponse(boost::shared_ptr<Payload> response, boost::shared_ptr<ErrorPayload> error) {
+ requestResponse = response;
+ requestError = error;
+ requestResponseReceived = true;
+}
+
+void SluiftClient::handleDisconnected(const boost::optional<ClientError>& error) {
+ disconnectedError = error;
+}
+
+Sluift::Response SluiftClient::doSendRequest(boost::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);
+}
diff --git a/Sluift/SluiftClient.h b/Sluift/SluiftClient.h
new file mode 100644
index 0000000..60eae16
--- /dev/null
+++ b/Sluift/SluiftClient.h
@@ -0,0 +1,133 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#pragma once
+
+#include <deque>
+#include <boost/optional.hpp>
+#include <boost/bind.hpp>
+#include <boost/function.hpp>
+
+#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/PubSub/PubSubManager.h>
+#include <Sluift/Response.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, int port);
+ 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;
+ };
+}
diff --git a/Sluift/SluiftException.h b/Sluift/SluiftException.h
deleted file mode 100644
index 6964523..0000000
--- a/Sluift/SluiftException.h
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (c) 2011 Remko Tronçon
- * Licensed under the GNU General Public License v3.
- * See Documentation/Licenses/GPLv3.txt for more information.
- */
-
-#pragma once
-
-#include <string>
-
-#include <Swiften/Client/ClientError.h>
-
-namespace Swift {
- class SluiftException : public std::exception {
- public:
- virtual ~SluiftException() throw() {}
-
- SluiftException(const std::string& reason) : reason(reason) {
- }
-
- SluiftException(const ClientError& error) {
- reason = "Disconnected: ";
- switch(error.getType()) {
- case ClientError::UnknownError: reason += "Unknown Error"; break;
- case ClientError::DomainNameResolveError: reason += "Unable to find server"; break;
- case ClientError::ConnectionError: reason += "Error connecting to server"; break;
- case ClientError::ConnectionReadError: reason += "Error while receiving server data"; break;
- case ClientError::ConnectionWriteError: reason += "Error while sending data to the server"; break;
- case ClientError::XMLError: reason += "Error parsing server data"; break;
- case ClientError::AuthenticationFailedError: reason += "Login/password invalid"; break;
- case ClientError::CompressionFailedError: reason += "Error while compressing stream"; break;
- case ClientError::ServerVerificationFailedError: reason += "Server verification failed"; break;
- case ClientError::NoSupportedAuthMechanismsError: reason += "Authentication mechanisms not supported"; break;
- case ClientError::UnexpectedElementError: reason += "Unexpected response"; break;
- case ClientError::ResourceBindError: reason += "Error binding resource"; break;
- case ClientError::RevokedError: reason += "Certificate got revoked"; break;
- case ClientError::RevocationCheckFailedError: reason += "Failed to do revokation check"; break;
- case ClientError::SessionStartError: reason += "Error starting session"; break;
- case ClientError::StreamError: reason += "Stream error"; break;
- case ClientError::TLSError: reason += "Encryption error"; break;
- case ClientError::ClientCertificateLoadError: reason += "Error loading certificate (Invalid password?)"; break;
- case ClientError::ClientCertificateError: reason += "Certificate not authorized"; break;
- case ClientError::UnknownCertificateError: reason += "Unknown certificate"; break;
- case ClientError::CertificateCardRemoved: reason += "Certificate card removed"; break;
- case ClientError::CertificateExpiredError: reason += "Certificate has expired"; break;
- case ClientError::CertificateNotYetValidError: reason += "Certificate is not yet valid"; break;
- case ClientError::CertificateSelfSignedError: reason += "Certificate is self-signed"; break;
- case ClientError::CertificateRejectedError: reason += "Certificate has been rejected"; break;
- case ClientError::CertificateUntrustedError: reason += "Certificate is not trusted"; break;
- case ClientError::InvalidCertificatePurposeError: reason += "Certificate cannot be used for encrypting your connection"; break;
- case ClientError::CertificatePathLengthExceededError: reason += "Certificate path length constraint exceeded"; break;
- case ClientError::InvalidCertificateSignatureError: reason += "Invalid certificate signature"; break;
- case ClientError::InvalidCAError: reason += "Invalid Certificate Authority"; break;
- case ClientError::InvalidServerIdentityError: reason += "Certificate does not match the host identity"; break;
- }
- }
-
- const std::string& getReason() const {
- return reason;
- }
-
- virtual const char* what() const throw() {
- return getReason().c_str();
- }
-
-
- private:
- std::string reason;
- };
-}
diff --git a/Sluift/SluiftGlobals.h b/Sluift/SluiftGlobals.h
new file mode 100644
index 0000000..03c1c1a
--- /dev/null
+++ b/Sluift/SluiftGlobals.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#pragma once
+
+#include <Sluift/LuaElementConvertors.h>
+#include <Swiften/EventLoop/SimpleEventLoop.h>
+#include <Swiften/Network/BoostNetworkFactories.h>
+
+namespace Swift {
+ struct SluiftGlobals {
+ SluiftGlobals() : networkFactories(&eventLoop) {}
+
+ int timeout;
+ bool debug;
+ LuaElementConvertors elementConvertor;
+ SimpleEventLoop eventLoop;
+ BoostNetworkFactories networkFactories;
+ int bootIndex;
+ };
+}
diff --git a/Sluift/Tests/ConnectTest.lua b/Sluift/Tests/ConnectTest.lua
new file mode 100644
index 0000000..0afa3fa
--- /dev/null
+++ b/Sluift/Tests/ConnectTest.lua
@@ -0,0 +1,6 @@
+-- Test connect with function parameter
+client = sluift.new_client(os.getenv("SLUIFT_JID"), os.getenv("SLUIFT_PASS"))
+x, y, z = client:connect(function (c) return 1, '2', true end)
+assert(x == 1)
+assert(y == '2')
+assert(z == true)
diff --git a/Sluift/Tests/DOMTest.lua b/Sluift/Tests/DOMTest.lua
new file mode 100644
index 0000000..0c31183
--- /dev/null
+++ b/Sluift/Tests/DOMTest.lua
@@ -0,0 +1,14 @@
+t = sluift.from_xml([[
+ <foo xmlns='http://swift.im/test' myattr1='myval1' myattr2='myval2'>
+ <bar myattr3='myval3'>
+ <baz/>
+ </bar>
+ Some Text
+ <bam myattr4='myval4'>
+ Some other text
+ </bam>
+ </foo>
+]])
+
+print(t)
+print(sluift.to_xml(t))
diff --git a/Sluift/Tests/FormTest.lua b/Sluift/Tests/FormTest.lua
new file mode 100644
index 0000000..7b6b4af
--- /dev/null
+++ b/Sluift/Tests/FormTest.lua
@@ -0,0 +1,79 @@
+--[[
+ Copyright (c) 2013 Remko Tronçon
+ Licensed under the GNU General Public License v3.
+ See Documentation/Licenses/GPLv3.txt for more information.
+--]]
+
+example_form = [[
+<x xmlns='jabber:x:data' type='form'>
+ <title>Bot Configuration</title>
+ <instructions>Fill out this form to configure your new bot!</instructions>
+ <field type='hidden' var='FORM_TYPE'>
+ <value>jabber:bot</value>
+ </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='boolean' label='Public bot?' var='public'>
+ <required/>
+ </field>
+ <field type='text-private' label='Password for special access' var='password'/>
+ <field type='fixed'><value>Section 2: Features</value></field>
+ <field type='list-multi' label='What features will the bot support?' var='features'>
+ <option label='Contests'><value>contests</value></option>
+ <option label='News'><value>news</value></option>
+ <option label='Polls'><value>polls</value></option>
+ <option label='Reminders'><value>reminders</value></option>
+ <option label='Search'><value>search</value></option>
+ <value>news</value>
+ <value>search</value>
+ </field>
+ <field type='fixed'><value>Section 3: Subscriber List</value></field>
+ <field type='list-single' label='Maximum number of subscribers' var='maxsubs'>
+ <value>20</value>
+ <option label='10'><value>10</value></option>
+ <option label='20'><value>20</value></option>
+ <option label='30'><value>30</value></option>
+ <option label='50'><value>50</value></option>
+ <option label='100'><value>100</value></option>
+ <option label='None'><value>none</value></option>
+ </field>
+ <field type='fixed'><value>Section 4: Invitations</value></field>
+ <field type='jid-multi' label='People to invite' var='invitelist'>
+ <desc>Tell all your friends about your new bot!</desc>
+ </field>
+</x>]]
+
+form = sluift.from_xml(example_form)
+--print(form)
+
+-- Test form properties
+assert(form['title'] == 'Bot Configuration')
+
+-- Test boolean field
+public_field = form['fields'][5]
+assert(public_field['name'] == 'public')
+assert(type(public_field['value']) == 'boolean')
+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')
+
+-- Test shortcut index
+assert(form['features']['name'] == 'features')
+assert(form['FORM_TYPE']['value'] == 'jabber:bot')
+
+-- Test response form
+submission = form:create_submission()
+assert(#(submission.fields) == 8)
+submission['description'] = 'my description'
+assert(submission['description']['value'] == 'my description')
+submission['type'] = 'cancel'
+assert(#(submission.fields) == 8)
+
+--print(sluift.to_xml({type = 'form', data = form}))
diff --git a/Sluift/boot.lua b/Sluift/boot.lua
new file mode 100644
index 0000000..e019fe6
--- /dev/null
+++ b/Sluift/boot.lua
@@ -0,0 +1,447 @@
+--[[
+ 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, disco_items = { node = node.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 (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.set_owner_affiliations(node, ...)
+ local options = parse_options({}, ...)
+ return node.client:query_pubsub(merge_tables({
+ type = 'set', to = node.jid, query = merge_tables({
+ _type = 'pubsub_owner_affiliations', node = node.node,
+ }, options.affiliations)}, 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
new file mode 100644
index 0000000..04ce8f4
--- /dev/null
+++ b/Sluift/client.cpp
@@ -0,0 +1,576 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * 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/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/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/Requests/GetSoftwareVersionRequest.h>
+#include <Sluift/Lua/FunctionRegistration.h>
+#include <Swiften/Base/foreach.h>
+#include <Sluift/Lua/Check.h>
+#include <Sluift/Lua/Value.h>
+#include <Sluift/Lua/Exception.h>
+#include <Sluift/Lua/LuaUtils.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());
+}
+
+SLUIFT_LUA_FUNCTION(Client, async_connect) {
+ SluiftClient* client = getClient(L);
+
+ std::string host;
+ int port = -1;
+ 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 = *portInt;
+ }
+ }
+ if (host.empty() && port == -1) {
+ client->connect();
+ }
+ else {
+ client->connect(host, port);
+ }
+ 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;
+}
+
+static int sendQuery(lua_State* L, IQ::Type type) {
+ 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;
+ }
+
+ 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);
+
+ return client->sendRequest(
+ boost::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); \
+ }
+
+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");
+ }
+}
+
+
+SLUIFT_LUA_FUNCTION(Client, get) {
+ return sendQuery(L, IQ::Get);
+}
+
+SLUIFT_LUA_FUNCTION(Client, set) {
+ return sendQuery(L, IQ::Set);
+}
+
+SLUIFT_LUA_FUNCTION(Client, send) {
+ Sluift::globals.eventLoop.runOnce();
+
+ getClient(L)->getClient()->sendData(std::string(Lua::checkString(L, 2)));
+ lua_pushvalue(L, 1);
+ return 0;
+}
+
+SLUIFT_LUA_FUNCTION(Client, set_options) {
+ SluiftClient* client = getClient(L);
+ 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 = 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_pushvalue(L, 1);
+ return 0;
+}
+
+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);
+ }
+ }
+}
+
+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;
+};
+
+
+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_LUA_FUNCTION(Client, __gc) {
+ SluiftClient* client = getClient(L);
+ delete client;
+ return 0;
+}
diff --git a/Sluift/globals.h b/Sluift/globals.h
new file mode 100644
index 0000000..3e7e1c9
--- /dev/null
+++ b/Sluift/globals.h
@@ -0,0 +1,15 @@
+/*
+ * Copyright (c) 2013 Remko Tronçon
+ * Licensed under the GNU General Public License.
+ * See the COPYING file for more information.
+ */
+
+#pragma once
+
+#include <Sluift/SluiftGlobals.h>
+
+namespace Swift {
+ namespace Sluift {
+ extern SluiftGlobals globals;
+ }
+}
diff --git a/Sluift/linit.c b/Sluift/linit.c
index 73f0522..8507609 100644
--- a/Sluift/linit.c
+++ b/Sluift/linit.c
@@ -3,35 +3,6 @@
#include <lauxlib.h>
#include "sluift.h"
-// A built-in table print function
-// From: http://lua-users.org/wiki/TableSerialization
-static const char tprint[] =
- "function tprint (tt, indent, done)\n"
- " done = done or {}\n"
- " indent = indent or 0\n"
- " if type(tt) == \"table\" then\n"
- " for key, value in pairs (tt) do\n"
- " io.write(string.rep (\" \", indent)) -- indent it\n"
- " if type (value) == \"table\" and not done [value] then\n"
- " done [value] = true\n"
- " io.write(string.format(\"[%s] => table\\n\", tostring (key)));\n"
- " io.write(string.rep (\" \", indent+4)) -- indent it\n"
- " io.write(\"(\\n\");\n"
- " tprint (value, indent + 7, done)\n"
- " io.write(string.rep (\" \", indent+4)) -- indent it\n"
- " io.write(\")\\n\");\n"
- " else\n"
- " io.write(string.format(\"[%s] => %s\\n\",\n"
- " tostring (key), tostring(value)))\n"
- " end\n"
- " end\n"
- " elseif type(tt) == \"nil\" then\n"
- " io.write(\"nil\\n\")\n"
- " else\n"
- " io.write(tt .. \"\\n\")\n"
- " end\n"
- "end\n";
-
static const luaL_Reg lualibs[] = {
{"", luaopen_base},
{LUA_LOADLIBNAME, luaopen_package},
@@ -53,8 +24,4 @@ LUALIB_API void luaL_openlibs (lua_State *L) {
lua_pushstring(L, lib->name);
lua_call(L, 1, 0);
}
- if (luaL_dostring(L, tprint) != 0) {
- fprintf(stderr, "%s\n", lua_tostring(L, -1));
- lua_pop(L, 1);
- }
}
diff --git a/Sluift/sluift.cpp b/Sluift/sluift.cpp
index 8076f5a..e6096a0 100644
--- a/Sluift/sluift.cpp
+++ b/Sluift/sluift.cpp
@@ -1,832 +1,280 @@
/*
- * Copyright (c) 2011 Remko Tronçon
+ * Copyright (c) 2011-2013 Remko Tronçon
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
-#include "sluift.h"
-#include <lauxlib.h>
+#include <Sluift/sluift.h>
+
+#include <lua.hpp>
-#include <iostream>
#include <string>
-#include <deque>
+#include <boost/bind.hpp>
+#include <boost/numeric/conversion/cast.hpp>
#include <boost/assign/list_of.hpp>
-#include <Swiften/Base/foreach.h>
-#include <Swiften/Swiften.h>
-
#include "Watchdog.h"
-#include "SluiftException.h"
-#include "ResponseSink.h"
-#include "Lua/Value.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 <Swiften/Base/sleep.h>
+#include <Swiften/Base/foreach.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/StringCodecs/Base64.h>
+#include <Swiften/StringCodecs/Hexify.h>
+#include <Swiften/Crypto/CryptoProvider.h>
+#include <Swiften/Crypto/PlatformCryptoProvider.h>
using namespace Swift;
-#define SLUIFT_CLIENT "SluiftClient*"
-
-/*******************************************************************************
- * Forward declarations
- ******************************************************************************/
-
-static bool debug = false;
-static int globalTimeout = 30000;
-
-/*******************************************************************************
- * Helper classes
- ******************************************************************************/
-
-SimpleEventLoop eventLoop;
-BoostNetworkFactories networkFactories(&eventLoop);
-
-
-class SluiftClient {
- public:
- SluiftClient(const JID& jid, const std::string& password) : 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::handleIncomingEvent, this, _1));
- client->onPresenceReceived.connect(boost::bind(&SluiftClient::handleIncomingEvent, this, _1));
- client->getRoster()->onInitialRosterPopulated.connect(boost::bind(&SluiftClient::handleInitialRosterPopulated, this));
- if (debug) {
- tracer = new ClientXMLTracer(client);
- }
- }
-
- ~SluiftClient() {
- delete tracer;
- delete client;
- }
-
- Client* getClient() {
- return client;
- }
-
- ClientOptions& getOptions() {
- return options;
- }
-
- void connect() {
- rosterReceived = false;
- client->connect(options);
- }
-
- void connect(const std::string& host) {
- rosterReceived = false;
- options.manualHostname = host;
- client->connect(options);
- }
-
- void waitConnected() {
- Watchdog watchdog(globalTimeout, networkFactories.getTimerFactory());
- while (!watchdog.getTimedOut() && client->isActive() && !client->isAvailable()) {
- eventLoop.runUntilEvents();
- }
- if (watchdog.getTimedOut()) {
- client->disconnect();
- throw SluiftException("Timeout while connecting");
- }
- }
-
- bool isConnected() const {
- return client->isAvailable();
- }
-
- void sendMessage(const JID& to, const std::string& body) {
- Message::ref message = boost::make_shared<Message>();
- message->setTo(to);
- message->setBody(body);
- client->sendMessage(message);
- }
-
- void sendPresence(const std::string& status) {
- client->sendPresence(boost::make_shared<Presence>(status));
- }
-
- boost::optional<std::string> sendQuery(const JID& jid, IQ::Type type, const std::string& data, int timeout) {
- rawRequestResponse.reset();
- RawRequest::ref request = RawRequest::create(type, jid, data, client->getIQRouter());
- boost::signals::scoped_connection c = request->onResponse.connect(boost::bind(&SluiftClient::handleRawRequestResponse, this, _1));
- request->send();
-
- Watchdog watchdog(timeout, networkFactories.getTimerFactory());
- while (!watchdog.getTimedOut() && !rawRequestResponse) {
- eventLoop.runUntilEvents();
- }
-
- if (watchdog.getTimedOut()) {
- return boost::optional<std::string>();
- }
- else {
- return *rawRequestResponse;
- }
- }
-
- void disconnect() {
- client->disconnect();
- while (client->isActive()) {
- eventLoop.runUntilEvents();
- }
- }
-
- void setSoftwareVersion(const std::string& name, const std::string& version, const std::string& os) {
- client->setSoftwareVersion(name, version, os);
- }
-
- Stanza::ref getNextEvent(int timeout) {
- if (!pendingEvents.empty()) {
- Stanza::ref event = pendingEvents.front();
- pendingEvents.pop_front();
- return event;
- }
- Watchdog watchdog(timeout, networkFactories.getTimerFactory());
- while (!watchdog.getTimedOut() && pendingEvents.empty() && !client->isActive()) {
- eventLoop.runUntilEvents();
- }
- if (watchdog.getTimedOut() || !client->isActive()) {
- return Stanza::ref();
- }
- else if (!pendingEvents.empty()) {
- Stanza::ref event = pendingEvents.front();
- pendingEvents.pop_front();
- return event;
- }
- else {
- return Stanza::ref();
- }
- }
-
- std::vector<XMPPRosterItem> 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();
- }
-
- private:
- void handleIncomingEvent(Stanza::ref stanza) {
- pendingEvents.push_back(stanza);
- }
-
- void handleInitialRosterPopulated() {
- rosterReceived = true;
- }
-
- void handleRawRequestResponse(const std::string& response) {
- rawRequestResponse = response;
- }
+namespace Swift {
+ namespace Sluift {
+ SluiftGlobals globals;
+ }
+}
- void handleDisconnected(const boost::optional<ClientError>& error) {
- if (error) {
- throw SluiftException(*error);
- }
- }
-
- private:
- Client* client;
- ClientOptions options;
- ClientXMLTracer* tracer;
- bool rosterReceived;
- std::deque<Stanza::ref> pendingEvents;
- boost::optional<std::string> rawRequestResponse;
-};
+extern "C" const char boot_lua[];
/*******************************************************************************
- * Client functions.
+ * Module functions
******************************************************************************/
-static inline SluiftClient* getClient(lua_State* L) {
- return *reinterpret_cast<SluiftClient**>(luaL_checkudata(L, 1, SLUIFT_CLIENT));
-}
-
-static int sluift_client_connect(lua_State *L) {
- try {
- SluiftClient* client = getClient(L);
- std::string host;
- if (lua_type(L, 2) != LUA_TNONE) {
- host = luaL_checkstring(L, 2);
- }
- if (host.empty()) {
- client->connect();
- }
- else {
- client->connect(host);
- }
- client->waitConnected();
- return 1;
- }
- catch (const SluiftException& e) {
- return luaL_error(L, e.getReason().c_str());
- }
-}
-
-static int sluift_client_async_connect(lua_State *L) {
- try {
- getClient(L)->connect();
- return 1;
- }
- catch (const SluiftException& e) {
- return luaL_error(L, e.getReason().c_str());
- }
-}
+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));
-static int sluift_client_wait_connected(lua_State *L) {
- try {
- getClient(L)->waitConnected();
- return 1;
- }
- catch (const SluiftException& e) {
- return luaL_error(L, e.getReason().c_str());
- }
-}
+ SluiftClient** client = reinterpret_cast<SluiftClient**>(lua_newuserdata(L, sizeof(SluiftClient*)));
+ luaL_getmetatable(L, Lua::FunctionRegistry::getMetaTableNameForType("Client").c_str());
+ lua_setmetatable(L, -2);
-static int sluift_client_is_connected(lua_State *L) {
- lua_pushboolean(L, getClient(L)->isConnected());
+ *client = new SluiftClient(jid, password, &Sluift::globals.networkFactories, &Sluift::globals.eventLoop, &Sluift::globals);
return 1;
}
-static int sluift_client_disconnect(lua_State *L) {
- try {
- getClient(L)->disconnect();
- return 1;
- }
- catch (const SluiftException& e) {
- return luaL_error(L, e.getReason().c_str());
- }
-}
-
-static int sluift_client_set_version(lua_State *L) {
- try {
- eventLoop.runOnce();
-
- SluiftClient* client = getClient(L);
- luaL_checktype(L, 2, LUA_TTABLE);
- lua_getfield(L, 2, "name");
- const char* rawName = lua_tostring(L, -1);
- lua_getfield(L, 2, "version");
- const char* rawVersion = lua_tostring(L, -1);
- lua_getfield(L, 2, "os");
- const char* rawOS = lua_tostring(L, -1);
- client->setSoftwareVersion(rawName ? rawName : "", rawVersion ? rawVersion : "", rawOS ? rawOS : "");
- lua_pop(L, 3);
- lua_pushvalue(L, 1);
- return 1;
- }
- catch (const SluiftException& e) {
- return luaL_error(L, e.getReason().c_str());
+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;
}
-static int sluift_client_get_contacts(lua_State *L) {
- try {
- eventLoop.runOnce();
-
- SluiftClient* client = getClient(L);
- Lua::Table contactsTable;
- foreach(const XMPPRosterItem& item, client->getRoster()) {
- std::string subscription;
- switch(item.getSubscription()) {
- case RosterItemPayload::None: subscription = "none"; break;
- case RosterItemPayload::To: subscription = "to"; break;
- case RosterItemPayload::From: subscription = "from"; break;
- case RosterItemPayload::Both: subscription = "both"; break;
- case RosterItemPayload::Remove: subscription = "remove"; break;
- }
- Lua::Value groups(std::vector<Lua::Value>(item.getGroups().begin(), item.getGroups().end()));
- Lua::Table itemTable = boost::assign::map_list_of
- ("jid", boost::make_shared<Lua::Value>(item.getJID().toString()))
- ("name", boost::make_shared<Lua::Value>(item.getName()))
- ("subscription", boost::make_shared<Lua::Value>(subscription))
- ("groups", boost::make_shared<Lua::Value>(std::vector<Lua::Value>(item.getGroups().begin(), item.getGroups().end())));
- contactsTable[item.getJID().toString()] = boost::make_shared<Lua::Value>(itemTable);
- }
- pushValue(L, contactsTable);
- return 1;
- }
- catch (const SluiftException& e) {
- return luaL_error(L, e.getReason().c_str());
+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;
}
-static int sluift_client_get_version(lua_State *L) {
+static int sluift_index(lua_State* L) {
try {
- SluiftClient* client = getClient(L);
- int timeout = -1;
- if (lua_type(L, 3) != LUA_TNONE) {
- timeout = luaL_checknumber(L, 3);
- }
-
- ResponseSink<SoftwareVersion> sink;
- GetSoftwareVersionRequest::ref request = GetSoftwareVersionRequest::create(std::string(luaL_checkstring(L, 2)), client->getClient()->getIQRouter());
- boost::signals::scoped_connection c = request->onResponse.connect(boost::ref(sink));
- request->send();
-
- Watchdog watchdog(timeout, networkFactories.getTimerFactory());
- while (!watchdog.getTimedOut() && !sink.hasResponse()) {
- eventLoop.runUntilEvents();
- }
-
- ErrorPayload::ref error = sink.getResponseError();
- if (error || watchdog.getTimedOut()) {
- lua_pushnil(L);
- if (watchdog.getTimedOut()) {
- lua_pushstring(L, "Timeout");
- }
- else if (error->getCondition() == ErrorPayload::RemoteServerNotFound) {
- lua_pushstring(L, "Remote server not found");
- }
- // TODO
- else {
- lua_pushstring(L, "Error");
- }
- return 2;
+ std::string key(Lua::checkString(L, 2));
+ if (key == "debug") {
+ lua_pushboolean(L, Sluift::globals.debug);
+ return 1;
}
- else if (SoftwareVersion::ref version = sink.getResponsePayload()) {
- Lua::Table result = boost::assign::map_list_of
- ("name", boost::make_shared<Lua::Value>(version->getName()))
- ("version", boost::make_shared<Lua::Value>(version->getVersion()))
- ("os", boost::make_shared<Lua::Value>(version->getOS()));
- Lua::pushValue(L, result);
+ else if (key == "timeout") {
+ lua_pushnumber(L, Sluift::globals.timeout);
+ return 1;
}
- else {
- lua_pushnil(L);
- }
- return 1;
- }
- catch (const SluiftException& e) {
- return luaL_error(L, e.getReason().c_str());
- }
-}
-
-static int sluift_client_send_message(lua_State *L) {
- try {
- eventLoop.runOnce();
-
- getClient(L)->sendMessage(std::string(luaL_checkstring(L, 2)), luaL_checkstring(L, 3));
- lua_pushvalue(L, 1);
- return 1;
- }
- catch (const SluiftException& e) {
- return luaL_error(L, e.getReason().c_str());
- }
-}
-
-static int sluift_client_send_presence(lua_State *L) {
- try {
- eventLoop.runOnce();
-
- getClient(L)->sendPresence(std::string(luaL_checkstring(L, 2)));
- lua_pushvalue(L, 1);
- return 0;
+ throw Lua::Exception("Unknown property");
}
- catch (const SluiftException& e) {
- return luaL_error(L, e.getReason().c_str());
+ catch (const std::exception& e) {
+ return luaL_error(L, e.what());
}
}
-static int sluift_client_get(lua_State *L) {
- try {
- SluiftClient* client = getClient(L);
- JID jid;
- std::string data;
- int timeout = -1;
- if (lua_type(L, 3) == LUA_TSTRING) {
- jid = JID(std::string(luaL_checkstring(L, 2)));
- data = std::string(luaL_checkstring(L, 3));
- if (lua_type(L, 4) != LUA_TNONE) {
- timeout = luaL_checknumber(L, 4);
- }
- }
- else {
- data = std::string(luaL_checkstring(L, 2));
- if (lua_type(L, 3) != LUA_TNONE) {
- timeout = luaL_checknumber(L, 3);
- }
- }
- boost::optional<std::string> result = client->sendQuery(jid, IQ::Get, data, timeout);
- if (result) {
- lua_pushstring(L, result->c_str());
- }
- else {
- lua_pushnil(L);
- }
- return 1;
- }
- catch (const SluiftException& e) {
- return luaL_error(L, e.getReason().c_str());
- }
-}
-static int sluift_client_set(lua_State *L) {
+static int sluift_newindex(lua_State* L) {
try {
- SluiftClient* client = getClient(L);
- JID jid;
- std::string data;
- int timeout = -1;
- if (lua_type(L, 3) == LUA_TSTRING) {
- jid = JID(std::string(luaL_checkstring(L, 2)));
- data = std::string(luaL_checkstring(L, 3));
- if (lua_type(L, 4) != LUA_TNONE) {
- timeout = luaL_checknumber(L, 4);
- }
- }
- else {
- data = std::string(luaL_checkstring(L, 2));
- if (lua_type(L, 3) != LUA_TNONE) {
- timeout = luaL_checknumber(L, 3);
- }
- }
- boost::optional<std::string> result = client->sendQuery(jid, IQ::Set, data, timeout);
- if (result) {
- lua_pushstring(L, result->c_str());
+ std::string key(Lua::checkString(L, 2));
+ if (key == "debug") {
+ Sluift::globals.debug = lua_toboolean(L, 3);
}
- else {
- lua_pushnil(L);
+ else if (key == "timeout") {
+ Sluift::globals.timeout = Lua::checkIntNumber(L, 3);
}
- return 1;
- }
- catch (const SluiftException& e) {
- return luaL_error(L, e.getReason().c_str());
- }
-}
-
-static int sluift_client_send(lua_State *L) {
- try {
- eventLoop.runOnce();
-
- getClient(L)->getClient()->sendData(std::string(luaL_checkstring(L, 2)));
- lua_pushvalue(L, 1);
return 0;
}
- catch (const SluiftException& e) {
- return luaL_error(L, e.getReason().c_str());
- }
-}
-
-static int sluift_client_set_options(lua_State* L) {
- SluiftClient* client = getClient(L);
- luaL_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;
-}
-
-static void pushEvent(lua_State* L, Stanza::ref event) {
- if (Message::ref message = boost::dynamic_pointer_cast<Message>(event)) {
- 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);
- }
- else if (Presence::ref presence = boost::dynamic_pointer_cast<Presence>(event)) {
- 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);
- }
- else {
- lua_pushnil(L);
- }
-}
-
-static int sluift_client_for_event(lua_State *L) {
- try {
- eventLoop.runOnce();
-
- SluiftClient* client = getClient(L);
- luaL_checktype(L, 2, LUA_TFUNCTION);
- int timeout = -1;
- if (lua_type(L, 3) != LUA_TNONE) {
- timeout = lua_tonumber(L, 3);
- }
-
- while (true) {
- Stanza::ref event = client->getNextEvent(timeout);
- if (!event) {
- // We got a timeout
- lua_pushnil(L);
- return 1;
- }
- else {
- // Push the function and event on the stack
- lua_pushvalue(L, 2);
- pushEvent(L, event);
- int oldTop = lua_gettop(L) - 2;
- lua_call(L, 1, LUA_MULTRET);
- int returnValues = lua_gettop(L) - oldTop;
- if (returnValues > 0) {
- lua_remove(L, -1 - returnValues);
- return returnValues;
- }
- }
- }
- }
- catch (const SluiftException& e) {
- return luaL_error(L, e.getReason().c_str());
+ catch (const std::exception& e) {
+ return luaL_error(L, e.what());
}
}
-static int sluift_client_get_next_event(lua_State *L) {
- try {
- eventLoop.runOnce();
-
- SluiftClient* client = getClient(L);
- int timeout = -1;
- if (lua_type(L, 2) != LUA_TNONE) {
- timeout = lua_tonumber(L, 2);
- }
- pushEvent(L, client->getNextEvent(timeout));
- return 1;
- }
- catch (const SluiftException& e) {
- return luaL_error(L, e.getReason().c_str());
- }
-}
-
-
-static int sluift_client_add_contact(lua_State* L) {
- try {
- eventLoop.runOnce();
- SluiftClient* client = getClient(L);
- RosterItemPayload item;
- if (lua_type(L, 2) == LUA_TTABLE) {
- lua_getfield(L, 2, "jid");
- const char* rawJID = lua_tostring(L, -1);
- if (rawJID) {
- item.setJID(std::string(rawJID));
- }
- lua_getfield(L, 2, "name");
- const char* rawName = lua_tostring(L, -1);
- if (rawName) {
- item.setName(rawName);
- }
- lua_getfield(L, 2, "groups");
- if (!lua_isnil(L, -1)) {
- if (lua_type(L, -1) == LUA_TTABLE) {
- for (size_t i = 1; i <= lua_objlen(L, -1); ++i) {
- lua_rawgeti(L, -1, i);
- const char* rawGroup = lua_tostring(L, -1);
- if (rawGroup) {
- item.addGroup(rawGroup);
- }
- lua_pop(L, 1);
- }
- }
- else {
- return luaL_error(L, "Groups should be a table");
- }
- }
- }
- else {
- item.setJID(luaL_checkstring(L, 2));
- }
-
- client->getRoster();
- if (!client->getClient()->getRoster()->containsJID(item.getJID())) {
- RosterPayload::ref roster = boost::make_shared<RosterPayload>();
- roster->addItem(item);
-
- ResponseSink<RosterPayload> sink;
- SetRosterRequest::ref request = SetRosterRequest::create(roster, client->getClient()->getIQRouter());
- boost::signals::scoped_connection c = request->onResponse.connect(boost::ref(sink));
- request->send();
- while (!sink.hasResponse()) {
- eventLoop.runUntilEvents();
- }
- if (sink.getResponseError()) {
- lua_pushboolean(L, false);
- return 1;
- }
- }
- client->getClient()->getSubscriptionManager()->requestSubscription(item.getJID());
- lua_pushboolean(L, true);
- return 1;
- }
- catch (const SluiftException& e) {
- return luaL_error(L, e.getReason().c_str());
+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());
}
-static int sluift_client_remove_contact(lua_State* L) {
- try {
- eventLoop.runOnce();
- SluiftClient* client = getClient(L);
- JID jid(luaL_checkstring(L, 2));
-
- RosterPayload::ref roster = boost::make_shared<RosterPayload>();
- roster->addItem(RosterItemPayload(JID(luaL_checkstring(L, 2)), "", RosterItemPayload::Remove));
- ResponseSink<RosterPayload> sink;
- SetRosterRequest::ref request = SetRosterRequest::create(roster, client->getClient()->getIQRouter());
- boost::signals::scoped_connection c = request->onResponse.connect(boost::ref(sink));
- request->send();
- while (!sink.hasResponse()) {
- eventLoop.runUntilEvents();
- }
- lua_pushboolean(L, !sink.getResponseError());
- return 1;
+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");
}
- catch (const SluiftException& e) {
- return luaL_error(L, e.getReason().c_str());
+ 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_client_confirm_subscription(lua_State* L) {
- try {
- eventLoop.runOnce();
- SluiftClient* client = getClient(L);
- JID jid(luaL_checkstring(L, 2));
- client->getClient()->getSubscriptionManager()->confirmSubscription(jid);
- return 0;
- }
- catch (const SluiftException& e) {
- return luaL_error(L, e.getReason().c_str());
+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;
}
-static int sluift_client_cancel_subscription(lua_State* L) {
- try {
- eventLoop.runOnce();
- SluiftClient* client = getClient(L);
- JID jid(luaL_checkstring(L, 2));
- client->getClient()->getSubscriptionManager()->cancelSubscription(jid);
- return 0;
- }
- catch (const SluiftException& e) {
- return luaL_error(L, e.getReason().c_str());
+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;
}
-static int sluift_client_gc (lua_State *L) {
- SluiftClient* client = getClient(L);
- delete client;
- return 0;
-}
-
-static const luaL_reg sluift_client_functions[] = {
- {"connect", sluift_client_connect},
- {"async_connect", sluift_client_async_connect},
- {"wait_connected", sluift_client_wait_connected},
- {"is_connected", sluift_client_is_connected},
- {"disconnect", sluift_client_disconnect},
- {"send_message", sluift_client_send_message},
- {"send_presence", sluift_client_send_presence},
- {"get", sluift_client_get},
- {"set", sluift_client_set},
- {"send", sluift_client_send},
- {"set_version", sluift_client_set_version},
- {"get_contacts", sluift_client_get_contacts},
- {"get_version", sluift_client_get_version},
- {"set_options", sluift_client_set_options},
- {"for_event", sluift_client_for_event},
- {"get_next_event", sluift_client_get_next_event},
- {"add_contact", sluift_client_add_contact},
- {"remove_contact", sluift_client_remove_contact},
- {"confirm_subscription", sluift_client_confirm_subscription},
- {"cancel_subscription", sluift_client_cancel_subscription},
- {"__gc", sluift_client_gc},
- {NULL, NULL}
-};
/*******************************************************************************
- * Module functions
+ * JID Functions
******************************************************************************/
-static int sluift_new_client(lua_State *L) {
- try {
- JID jid(std::string(luaL_checkstring(L, 1)));
- std::string password(luaL_checkstring(L, 2));
-
- SluiftClient** client = reinterpret_cast<SluiftClient**>(lua_newuserdata(L, sizeof(SluiftClient*)));
- luaL_getmetatable(L, SLUIFT_CLIENT);
- lua_setmetatable(L, -2);
-
- *client = new SluiftClient(jid, password);
- return 1;
- }
- catch (const SluiftException& e) {
- return luaL_error(L, e.getReason().c_str());
- }
-}
-
-static int sluift_jid_to_bare(lua_State *L) {
- JID jid(std::string(luaL_checkstring(L, 1)));
+SLUIFT_LUA_FUNCTION(JID, to_bare) {
+ JID jid(std::string(Lua::checkString(L, 1)));
lua_pushstring(L, jid.toBare().toString().c_str());
return 1;
}
-static int sluift_jid_node(lua_State *L) {
- JID jid(std::string(luaL_checkstring(L, 1)));
+SLUIFT_LUA_FUNCTION(JID, node) {
+ JID jid(std::string(Lua::checkString(L, 1)));
lua_pushstring(L, jid.getNode().c_str());
return 1;
}
-static int sluift_jid_domain(lua_State *L) {
- JID jid(std::string(luaL_checkstring(L, 1)));
+SLUIFT_LUA_FUNCTION(JID, domain) {
+ JID jid(std::string(Lua::checkString(L, 1)));
lua_pushstring(L, jid.getDomain().c_str());
return 1;
}
-static int sluift_jid_resource(lua_State *L) {
- JID jid(std::string(luaL_checkstring(L, 1)));
+SLUIFT_LUA_FUNCTION(JID, resource) {
+ JID jid(std::string(Lua::checkString(L, 1)));
lua_pushstring(L, jid.getResource().c_str());
return 1;
}
-static int sluift_sleep(lua_State *L) {
- try {
- eventLoop.runOnce();
-
- int timeout = luaL_checknumber(L, 1);
- Watchdog watchdog(timeout, networkFactories.getTimerFactory());
- while (!watchdog.getTimedOut()) {
- Swift::sleep(std::min(100, timeout));
- eventLoop.runOnce();
- }
- return 0;
- }
- catch (const SluiftException& e) {
- return luaL_error(L, e.getReason().c_str());
- }
+SLUIFT_LUA_FUNCTION(JID, escape_node) {
+ lua_pushstring(L, JID::getEscapedNode(Lua::checkString(L, 1)).c_str());
+ return 1;
}
-static int sluift_index(lua_State *L) {
- std::string key(luaL_checkstring(L, 2));
- if (key == "debug") {
- lua_pushboolean(L, debug);
- return 1;
- }
- else if (key == "timeout") {
- lua_pushnumber(L, globalTimeout);
- return 1;
- }
- else {
- return luaL_error(L, "Invalid index");
+/*******************************************************************************
+ * Base64 Functions
+ ******************************************************************************/
+
+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;
}
-static int sluift_newindex(lua_State *L) {
- std::string key(luaL_checkstring(L, 2));
- if (key == "debug") {
- debug = lua_toboolean(L, 3);
- return 0;
- }
- else if (key == "timeout") {
- globalTimeout = luaL_checknumber(L, 3);
- return 0;
- }
- else {
- return luaL_error(L, "Invalid index");
+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;
}
-static const luaL_reg sluift_functions[] = {
- {"new_client", sluift_new_client},
- {"jid_to_bare", sluift_jid_to_bare},
- {"jid_node", sluift_jid_node},
- {"jid_domain", sluift_jid_domain},
- {"jid_resource", sluift_jid_resource},
- {"sleep", sluift_sleep},
- {NULL, NULL}
-};
-
-
/*******************************************************************************
* Module registration
******************************************************************************/
-SLUIFT_API int luaopen_sluift(lua_State *L) {
- // Register functions
+static const luaL_reg sluift_functions[] = { {NULL, NULL} };
+
+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);
-
- // Register the client metatable
- luaL_newmetatable(L, SLUIFT_CLIENT);
- lua_pushvalue(L, -1);
- lua_setfield(L, -2, "__index");
- luaL_register(L, NULL, sluift_client_functions);
-
+
+ // 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;
}
diff --git a/Sluift/sluift.h b/Sluift/sluift.h
index 27b4eab..b82e1c4 100644
--- a/Sluift/sluift.h
+++ b/Sluift/sluift.h
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011 Remko Tronçon
+ * Copyright (c) 2011-2013 Remko Tronçon
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
@@ -8,10 +8,19 @@
#if defined(SLUIFT_BUILD_DLL)
#define SLUIFT_API __declspec(dllexport)
+#elif __GNUC__ >= 4
+#define SLUIFT_API __attribute__((visibility("default")))
#else
-#define SLUIFT_API extern
+#define SLUIFT_API
#endif
+#if defined(__cplusplus)
+#include <lua.hpp>
+#else
#include <lua.h>
+#endif
+#if defined(__cplusplus)
+extern "C"
+#endif
SLUIFT_API int (luaopen_sluift)(lua_State *L);