diff options
| -rw-r--r-- | .gitignore | 1 | ||||
| -rw-r--r-- | Sluift/ElementConvertors/BodyConvertor.cpp | 35 | ||||
| -rw-r--r-- | Sluift/ElementConvertors/BodyConvertor.h | 25 | ||||
| -rw-r--r-- | Sluift/ElementConvertors/DiscoItemsConvertor.cpp | 18 | ||||
| -rwxr-xr-x | Sluift/Examples/Wonderland.lua | 94 | ||||
| -rw-r--r-- | Sluift/LuaElementConvertors.cpp | 2 | ||||
| -rw-r--r-- | Sluift/SConscript | 1 | ||||
| -rw-r--r-- | Sluift/SluiftClient.cpp | 5 | ||||
| -rw-r--r-- | Sluift/SluiftClient.h | 4 | ||||
| -rw-r--r-- | Sluift/boot.lua | 68 | ||||
| -rw-r--r-- | Sluift/client.cpp | 53 | ||||
| -rw-r--r-- | Swiften/QA/ScriptedTests/PubSub.lua | 38 | ||||
| -rw-r--r-- | Swiften/Serializer/PayloadSerializers/UserLocationSerializer.cpp | 44 | 
13 files changed, 316 insertions, 72 deletions
| @@ -25,6 +25,7 @@  *.moc  *.patch  *.dSYM +*.ld_*  .gdb_history  .clang_complete  *~ 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/DiscoItemsConvertor.cpp b/Sluift/ElementConvertors/DiscoItemsConvertor.cpp index 6c39aea..a38e766 100644 --- a/Sluift/ElementConvertors/DiscoItemsConvertor.cpp +++ b/Sluift/ElementConvertors/DiscoItemsConvertor.cpp @@ -49,12 +49,18 @@ void DiscoItemsConvertor::doConvertToLua(lua_State* L, boost::shared_ptr<DiscoIt  		lua_createtable(L, boost::numeric_cast<int>(items.size()), 0);  		for (size_t i = 0; i < items.size(); ++i) {  			lua_createtable(L, 0, 0); -			lua_pushstring(L, items[i].getName().c_str()); -			lua_setfield(L, -2, "name"); -			lua_pushstring(L, items[i].getNode().c_str()); -			lua_setfield(L, -2, "node"); -			lua_pushstring(L, items[i].getJID().toString().c_str()); -			lua_setfield(L, -2, "jid"); +			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/Examples/Wonderland.lua b/Sluift/Examples/Wonderland.lua index 235d8d0..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 -		for message in client:messages {timeout = 1000} do -			client:send_message{to = e["from"], body = "Off with their heads!"} +	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/LuaElementConvertors.cpp b/Sluift/LuaElementConvertors.cpp index 5913858..cadfbc4 100644 --- a/Sluift/LuaElementConvertors.cpp +++ b/Sluift/LuaElementConvertors.cpp @@ -20,6 +20,7 @@  #include <Sluift/ElementConvertors/SoftwareVersionConvertor.h>  #include <Sluift/ElementConvertors/VCardUpdateConvertor.h>  #include <Sluift/ElementConvertors/VCardConvertor.h> +#include <Sluift/ElementConvertors/BodyConvertor.h>  #include <Sluift/Lua/LuaUtils.h>  #include <Sluift/Lua/Exception.h> @@ -28,6 +29,7 @@ using namespace Swift;  LuaElementConvertors::LuaElementConvertors() {  	registerConvertors();  	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>()); diff --git a/Sluift/SConscript b/Sluift/SConscript index fcc39fc..c4d3b28 100644 --- a/Sluift/SConscript +++ b/Sluift/SConscript @@ -18,6 +18,7 @@ elif env["SCONS_STAGE"] == "build" :  		"LuaElementConvertors.cpp",  		"LuaElementConvertor.cpp",  		"Response.cpp", +		"ElementConvertors/BodyConvertor.cpp",  		"ElementConvertors/VCardUpdateConvertor.cpp",  		"ElementConvertors/PubSubEventConvertor.cpp",  		"ElementConvertors/RawXMLElementConvertor.cpp", diff --git a/Sluift/SluiftClient.cpp b/Sluift/SluiftClient.cpp index 726a683..8a8d772 100644 --- a/Sluift/SluiftClient.cpp +++ b/Sluift/SluiftClient.cpp @@ -87,14 +87,15 @@ void SluiftClient::setSoftwareVersion(const std::string& name, const std::string  	client->setSoftwareVersion(name, version, os);  } -boost::optional<SluiftClient::Event> SluiftClient::getNextEvent(boost::optional<Event::Type> type, int timeout) { +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 (!type || *type == event.type) { +			if (!condition || condition(event)) {  				return event;  			}  		} diff --git a/Sluift/SluiftClient.h b/Sluift/SluiftClient.h index 6515b7d..bedd6ba 100644 --- a/Sluift/SluiftClient.h +++ b/Sluift/SluiftClient.h @@ -9,6 +9,7 @@  #include <deque>  #include <boost/optional.hpp>  #include <boost/bind.hpp> +#include <boost/function.hpp>  #include <Swiften/Client/ClientOptions.h>  #include <Sluift/globals.h> @@ -101,7 +102,8 @@ namespace Swift {  			void disconnect();  			void setSoftwareVersion(const std::string& name, const std::string& version, const std::string& os); -			boost::optional<SluiftClient::Event> getNextEvent(boost::optional<Event::Type> type, int timeout); +			boost::optional<SluiftClient::Event> getNextEvent(int timeout,  +					boost::function<bool (const Event&)> condition = 0);  			std::vector<XMPPRosterItem> getRoster();  		private: diff --git a/Sluift/boot.lua b/Sluift/boot.lua index ae8cc41..e81257a 100644 --- a/Sluift/boot.lua +++ b/Sluift/boot.lua @@ -157,6 +157,12 @@ for method, event_type in pairs({message = 'message', presence = 'presence', pub  		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 @@ -222,6 +228,16 @@ for method, query_type in pairs(simple_pubsub_queries) do  	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  -------------------------------------------------------------------------------- @@ -247,7 +263,6 @@ local simple_pubsub_node_queries = {  	get_configuration = 'pubsub_owner_configure',  	get_subscriptions = 'pubsub_subscriptions',  	get_affiliations = 'pubsub_affiliations', -	get_items = 'pubsub_items',  	get_default_subscription_options = 'pubsub_default',  }  for method, query_type in pairs(simple_pubsub_node_queries) do @@ -259,6 +274,23 @@ for method, query_type in pairs(simple_pubsub_node_queries) do  	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 @@ -291,11 +323,12 @@ function PubSubNode.set_configuration(node, options)  		}, options))  end -function PubSubNode.subscribe(node, options) -	options = options or {} +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 = options['jid'] } +				_type = 'pubsub_subscribe', node = node.node, jid = jid }  		}, options))  end @@ -332,13 +365,11 @@ function PubSubNode.publish(node, ...)  		}, options))  end -function PubSubNode.retract(node, options) -	options = options or {} -	local item_ids = options['items'] -	item_ids = item_ids or { options['item'] } -	local items = {} -	for _, item_id in ipairs(item_ids) do -		items[#items+1] = { id = item_id } +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 = {  @@ -346,14 +377,25 @@ function PubSubNode.retract(node, options)  		}}, options))  end -function PubSubNode.purge(node, options) -	options = options or {} +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  -------------------------------------------------------------------------------- diff --git a/Sluift/client.cpp b/Sluift/client.cpp index 6d8bee8..df43075 100644 --- a/Sluift/client.cpp +++ b/Sluift/client.cpp @@ -4,6 +4,11 @@   * 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> @@ -20,7 +25,6 @@  #include <Swiften/Roster/SetRosterRequest.h>  #include <Swiften/Presence/SubscriptionManager.h>  #include <Swiften/Roster/XMPPRosterItem.h> -#include <boost/assign/list_of.hpp>  #include <Sluift/Watchdog.h>  #include <Swiften/Queries/Requests/GetSoftwareVersionRequest.h>  #include <Sluift/Lua/FunctionRegistration.h> @@ -30,9 +34,9 @@  #include <Sluift/Lua/Exception.h>  #include <Sluift/Lua/LuaUtils.h>  #include <Sluift/globals.h> -#include <iostream>  using namespace Swift; +namespace lambda = boost::lambda;  static const std::string SLUIFT_CLIENT = Lua::FunctionRegistry::getMetaTableNameForType("Client"); @@ -376,12 +380,33 @@ static void pushEvent(lua_State* L, const SluiftClient::Event& event) {  	}  } +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") { @@ -397,9 +422,25 @@ SLUIFT_LUA_FUNCTION(Client, get_next_event) {  		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); +		}  	} -	if (boost::optional<SluiftClient::Event> event = client->getNextEvent(type, timeout)) { +	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 { @@ -510,6 +551,12 @@ SLUIFT_LUA_FUNCTION(Client, set_caps_node) {  	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; diff --git a/Swiften/QA/ScriptedTests/PubSub.lua b/Swiften/QA/ScriptedTests/PubSub.lua index a9c0fe8..cb4679a 100644 --- a/Swiften/QA/ScriptedTests/PubSub.lua +++ b/Swiften/QA/ScriptedTests/PubSub.lua @@ -22,6 +22,7 @@ local subscriber_node  local publish_item = {id = 'item_id', data = {{ _type = 'software_version', name = 'MyTest', os = 'Lua' }} }  local publish_item2 = {id = 'item_id2', data = {{ _type = 'software_version', name = 'MyTest2', os = 'Lua' }} } +local publish_item3 = {id = 'item_id3', data = {{ _type = 'software_version', name = 'MyTest3', os = 'Lua' }} }  --------------------------------------------------------------------------------  -- Helper methods @@ -109,11 +110,40 @@ function test_subscriber_use_cases()  	-- 6.5 Retrieve items of a node  	assert(node:create()) -	assert(node:publish {item = publish_item}) +	assert(node:set_configuration{configuration = {['pubsub#max_items'] = '10'}}) +	assert(node:publish{item = publish_item}) +	assert(node:publish{item = publish_item2})  	local items = assert(subscriber_node:get_items()) -	assert(#items == 1) +	assert(#items == 2)  	assert(items[1].id == 'item_id')  	assert(items[1].data[1].name == 'MyTest') +	assert(items[2].id == 'item_id2') +	assert(items[2].data[1].name == 'MyTest2') +	assert(node:delete()) + +	-- 6.5.7 Requesting most recent items +	assert(node:create()) +	assert(node:set_configuration{configuration = {['pubsub#max_items'] = '10'}}) +	assert(node:publish{item = publish_item}) +	assert(node:publish{item = publish_item2}) +	assert(node:publish{item = publish_item3}) +	local items = assert(subscriber_node:get_items{maximum_items = 2}) +	assert(#items == 2) +	assert(items[1].id == 'item_id2') +	assert(items[1].data[1].name == 'MyTest2') +	assert(items[2].id == 'item_id3') +	assert(items[2].data[1].name == 'MyTest3') +	assert(node:delete()) +	 +	-- 6.5.8 requesting specific item +	assert(node:create()) +	assert(node:set_configuration{configuration = {['pubsub#max_items'] = '10'}}) +	assert(node:publish{item = publish_item}) +	assert(node:publish{item = publish_item2}) +	local items = assert(subscriber_node:get_item{id = 'item_id2'}) +	assert(#items == 1) +	assert(items[1].id == 'item_id2') +	assert(items[1].data[1].name == 'MyTest2')  	assert(node:delete())  end @@ -141,7 +171,7 @@ function test_publisher_use_cases()  	assert(node:create())  	assert(subscriber_node:subscribe({ jid = subscriber_jid }))  	assert(node:publish {items = {publish_item}}) -	assert(node:retract { item = 'item_id', notify = true }) +	assert(node:retract { id = 'item_id', notify = true })  	assert(node:delete())  	-- 7.2.2.1 Delete and notify @@ -149,7 +179,7 @@ function test_publisher_use_cases()  	assert(subscriber_node:subscribe({ jid = subscriber_jid }))  	assert(node:publish {items = {publish_item}})  	purge_pubsub_events(subscriber) -	assert(node:retract { item = 'item_id', notify = true }) +	assert(node:retract { id = 'item_id', notify = true })  	local event = assert(subscriber:get_next_event { type = 'pubsub' })  	assert(event._type == 'pubsub_event_items')  	assert(event.retracts[1].id == 'item_id') diff --git a/Swiften/Serializer/PayloadSerializers/UserLocationSerializer.cpp b/Swiften/Serializer/PayloadSerializers/UserLocationSerializer.cpp index 373276b..e257654 100644 --- a/Swiften/Serializer/PayloadSerializers/UserLocationSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/UserLocationSerializer.cpp @@ -25,67 +25,67 @@ std::string UserLocationSerializer::serializePayload(  	if (boost::optional<std::string> value = payload->getArea()) {  		result.addNode(boost::make_shared<XMLElement>("area", "", *value));  	} -	else if (boost::optional<float> value = payload->getAltitude()) { +	if (boost::optional<float> value = payload->getAltitude()) {  		result.addNode(boost::make_shared<XMLElement>("alt", "", boost::lexical_cast<std::string>(*value)));  	} -	else if (boost::optional<std::string> value = payload->getLocality()) { +	if (boost::optional<std::string> value = payload->getLocality()) {  		result.addNode(boost::make_shared<XMLElement>("locality", "", *value));  	} -	else if (boost::optional<float> value = payload->getLatitude()) { +	if (boost::optional<float> value = payload->getLatitude()) {  		result.addNode(boost::make_shared<XMLElement>("lat", "", boost::lexical_cast<std::string>(*value)));  	} -	else if (boost::optional<float> value = payload->getAccuracy()) { -		result.addNode(boost::make_shared<XMLElement>("lon", "", boost::lexical_cast<std::string>(*value))); +	if (boost::optional<float> value = payload->getAccuracy()) { +		result.addNode(boost::make_shared<XMLElement>("accuracy", "", boost::lexical_cast<std::string>(*value)));  	} -	else if (boost::optional<std::string> value = payload->getDescription()) { +	if (boost::optional<std::string> value = payload->getDescription()) {  		result.addNode(boost::make_shared<XMLElement>("description", "", *value));  	} -	else if (boost::optional<std::string> value = payload->getCountryCode()) { +	if (boost::optional<std::string> value = payload->getCountryCode()) {  		result.addNode(boost::make_shared<XMLElement>("countrycode", "", *value));  	} -	else if (boost::optional<boost::posix_time::ptime> value = payload->getTimestamp()) { +	if (boost::optional<boost::posix_time::ptime> value = payload->getTimestamp()) {  		result.addNode(boost::make_shared<XMLElement>("timestamp", "", dateTimeToString(*value)));  	} -	else if (boost::optional<std::string> value = payload->getFloor()) { +	if (boost::optional<std::string> value = payload->getFloor()) {  		result.addNode(boost::make_shared<XMLElement>("floor", "", *value));  	} -	else if (boost::optional<std::string> value = payload->getBuilding()) { +	if (boost::optional<std::string> value = payload->getBuilding()) {  		result.addNode(boost::make_shared<XMLElement>("building", "", *value));  	} -	else if (boost::optional<std::string> value = payload->getRoom()) { +	if (boost::optional<std::string> value = payload->getRoom()) {  		result.addNode(boost::make_shared<XMLElement>("room", "", *value));  	} -	else if (boost::optional<std::string> value = payload->getCountry()) { +	if (boost::optional<std::string> value = payload->getCountry()) {  		result.addNode(boost::make_shared<XMLElement>("country", "", *value));  	} -	else if (boost::optional<std::string> value = payload->getRegion()) { +	if (boost::optional<std::string> value = payload->getRegion()) {  		result.addNode(boost::make_shared<XMLElement>("region", "", *value));  	} -	else if (boost::optional<std::string> value = payload->getURI()) { +	if (boost::optional<std::string> value = payload->getURI()) {  		result.addNode(boost::make_shared<XMLElement>("uri", "", *value));  	} -	else if (boost::optional<float> value = payload->getLongitude()) { +	if (boost::optional<float> value = payload->getLongitude()) {  		result.addNode(boost::make_shared<XMLElement>("lon", "", boost::lexical_cast<std::string>(*value)));  	} -	else if (boost::optional<float> value = payload->getError()) { +	if (boost::optional<float> value = payload->getError()) {  		result.addNode(boost::make_shared<XMLElement>("error", "", boost::lexical_cast<std::string>(*value)));  	} -	else if (boost::optional<std::string> value = payload->getPostalCode()) { +	if (boost::optional<std::string> value = payload->getPostalCode()) {  		result.addNode(boost::make_shared<XMLElement>("postalcode", "", *value));  	} -	else if (boost::optional<float> value = payload->getBearing()) { +	if (boost::optional<float> value = payload->getBearing()) {  		result.addNode(boost::make_shared<XMLElement>("bearing", "", boost::lexical_cast<std::string>(*value)));  	} -	else if (boost::optional<std::string> value = payload->getText()) { +	if (boost::optional<std::string> value = payload->getText()) {  		result.addNode(boost::make_shared<XMLElement>("text", "", *value));  	} -	else if (boost::optional<std::string> value = payload->getDatum()) { +	if (boost::optional<std::string> value = payload->getDatum()) {  		result.addNode(boost::make_shared<XMLElement>("datum", "", *value));  	} -	else if (boost::optional<std::string> value = payload->getStreet()) { +	if (boost::optional<std::string> value = payload->getStreet()) {  		result.addNode(boost::make_shared<XMLElement>("street", "", *value));  	} -	else if (boost::optional<float> value = payload->getSpeed()) { +	if (boost::optional<float> value = payload->getSpeed()) {  		result.addNode(boost::make_shared<XMLElement>("speed", "", boost::lexical_cast<std::string>(*value)));  	}  	return result.serialize(); | 
 Swift
 Swift