Changeset - 321215840b51
[Not reviewed]
0 6 0
Jan Kaluza - 10 years ago 2016-02-04 06:55:14
jkaluza@redhat.com
Fix #92 - Handle the XMPP user's VCard change and forward it to the backend.
6 files changed with 96 insertions and 1 deletions:
0 comments (0 inline, 0 general)
include/transport/User.h
Show inline comments
 
@@ -55,48 +55,49 @@ class User {
 
		/// Returns JID of XMPP user who is currently connected using this User class.
 
		/// \return full JID
 
		const Swift::JID &getJID();
 

	
 
		/// Returns full JID which supports particular feature or invalid JID.
 
		/// \param feature disco#info feature.
 
		/// \return full JID which supports particular feature or invalid JID.
 
		std::vector<Swift::JID> getJIDWithFeature(const std::string &feature);
 

	
 
// 		Swift::DiscoInfo::ref getCaps(const Swift::JID &jid) const;
 

	
 
		/// Returns UserInfo struct with informations needed to connect the legacy network.
 
		/// \return UserInfo struct
 
		UserInfo &getUserInfo() { return m_userInfo; }
 

	
 
		RosterManager *getRosterManager() { return m_rosterManager; }
 

	
 
		ConversationManager *getConversationManager() { return m_conversationManager; }
 

	
 
		Component *getComponent() { return m_component; }
 

	
 
		UserManager *getUserManager() { return m_userManager; }
 
		
 
		virtual void disconnectUser(const std::string &error, Swift::SpectrumErrorPayload::Error e) = 0;
 
		virtual void requestVCard() {}
 

	
 
		void setData(void *data) { m_data = data; }
 
		void *getData() { return m_data; }
 

	
 
		/// Handles presence from XMPP JID associated with this user.
 
		/// \param presence Swift::Presence.
 
		void handlePresence(Swift::Presence::ref presence, bool forceJoin = false);
 

	
 
		void handleSubscription(Swift::Presence::ref presence);
 

	
 
		void handleDiscoInfo(const Swift::JID& jid, boost::shared_ptr<Swift::DiscoInfo> info);
 

	
 
		time_t &getLastActivity() {
 
			return m_lastActivity;
 
		}
 

	
 
		void updateLastActivity() {
 
			m_lastActivity = time(NULL);
 
		}
 

	
 
		/// Returns language.
 
		/// \return language
 
		const char *getLang() { return "en"; }
 

	
 
@@ -117,61 +118,66 @@ class User {
 
		}
 

	
 
		int getResourceCount() {
 
			return m_resources;
 
		}
 

	
 
		void addUserSetting(const std::string &key, const std::string &value) {
 
			m_settings[key] = value;
 
		}
 

	
 
		const std::string &getUserSetting(const std::string &key) {
 
			return m_settings[key];
 
		}
 

	
 
		void setCacheMessages(bool cacheMessages);
 

	
 
		bool shouldCacheMessages() {
 
			return m_cacheMessages;
 
		}
 

	
 
		void setReconnectLimit(int limit) {
 
			m_reconnectLimit = limit;
 
		}
 

	
 
		void setStorageBackend(StorageBackend *storageBackend) {
 
			m_storageBackend = storageBackend;
 
		}
 

	
 
		void leaveRoom(const std::string &room);
 

	
 
		boost::signal<void ()> onReadyToConnect;
 
		boost::signal<void (Swift::Presence::ref presence)> onPresenceChanged;
 
		boost::signal<void (Swift::Presence::ref presence)> onRawPresenceReceived;
 
		boost::signal<void (const Swift::JID &who, const std::string &room, const std::string &nickname, const std::string &password)> onRoomJoined;
 
		boost::signal<void (const std::string &room)> onRoomLeft;
 
		boost::signal<void ()> onDisconnected;
 

	
 
	private:
 
		void onConnectingTimeout();
 

	
 
		Swift::JID m_jid;
 
		Component *m_component;
 
		RosterManager *m_rosterManager;
 
		UserManager *m_userManager;
 
		ConversationManager *m_conversationManager;
 
		PresenceOracle *m_presenceOracle;
 
		UserInfo m_userInfo;
 
		void *m_data;
 
		bool m_connected;
 
		bool m_readyForConnect;
 
		bool m_ignoreDisconnect;
 
		Swift::Timer::ref m_reconnectTimer;
 
		boost::shared_ptr<Swift::Connection> connection;
 
		time_t m_lastActivity;
 
		std::map<Swift::JID, Swift::DiscoInfo::ref> m_legacyCaps;
 
		std::vector<boost::shared_ptr<Swift::OutgoingFileTransfer> > m_filetransfers;
 
		int m_resources;
 
		int m_reconnectCounter;
 
		std::list<Swift::Presence::ref> m_joinedRooms;
 
		std::map<std::string, std::string> m_settings;
 
		bool m_cacheMessages;
 
		int m_reconnectLimit;
 
		StorageBackend *m_storageBackend;
 
};
 

	
 
}
libtransport/NetworkPluginServer.cpp
Show inline comments
 
@@ -1821,48 +1821,53 @@ void NetworkPluginServer::handleBlockToggled(Buddy *b) {
 
	pbnetwork::Buddy buddy;
 
	buddy.set_username(user->getJID().toBare());
 
	buddy.set_buddyname(b->getName());
 
	buddy.set_alias(b->getAlias());
 
	BOOST_FOREACH(const std::string &g, b->getGroups()) {
 
		buddy.add_group(g);
 
	}
 
	buddy.set_status(pbnetwork::STATUS_NONE);
 
	buddy.set_blocked(!b->isBlocked());
 

	
 
	std::string message;
 
	buddy.SerializeToString(&message);
 

	
 
	WRAP(message, pbnetwork::WrapperMessage_Type_TYPE_BUDDY_CHANGED);
 

	
 
	Backend *c = (Backend *) user->getData();
 
	if (!c) {
 
		return;
 
	}
 
	send(c->connection, message);
 
}
 

	
 

	
 
void NetworkPluginServer::handleVCardUpdated(User *user, boost::shared_ptr<Swift::VCard> v) {
 
	if (!v) {
 
		LOG4CXX_INFO(logger, user->getJID().toString() << ": Received empty VCard");
 
		return;
 
	}
 

	
 
	pbnetwork::VCard vcard;
 
	vcard.set_username(user->getJID().toBare());
 
	vcard.set_buddyname("");
 
	vcard.set_id(0);
 
	vcard.set_photo(&v->getPhoto()[0], v->getPhoto().size());
 
	vcard.set_nickname(v->getNickname());
 

	
 
	std::string message;
 
	vcard.SerializeToString(&message);
 

	
 
	WRAP(message, pbnetwork::WrapperMessage_Type_TYPE_VCARD);
 

	
 
	Backend *c = (Backend *) user->getData();
 
	if (!c) {
 
		return;
 
	}
 
	send(c->connection, message);
 
}
 

	
 
void NetworkPluginServer::handleVCardRequired(User *user, const std::string &name, unsigned int id) {
 
	pbnetwork::VCard vcard;
 
	vcard.set_username(user->getJID().toBare());
 
	vcard.set_buddyname(name);
 
	vcard.set_id(id);
libtransport/User.cpp
Show inline comments
 
@@ -13,81 +13,83 @@
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
 * GNU General Public License for more details.
 
 *
 
 * You should have received a copy of the GNU General Public License
 
 * along with this program; if not, write to the Free Software
 
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
 
 */
 

	
 
#include "transport/User.h"
 
#include "transport/Frontend.h"
 
#include "transport/Transport.h"
 
#include "transport/RosterManager.h"
 
#include "transport/UserManager.h"
 
#include "transport/Conversation.h"
 
#include "transport/Factory.h"
 
#include "transport/ConversationManager.h"
 
#include "transport/PresenceOracle.h"
 
#include "transport/Logging.h"
 
#include "transport/StorageBackend.h"
 
#include "transport/Buddy.h"
 
#include "Swiften/Server/ServerStanzaChannel.h"
 
#include "Swiften/Elements/MUCPayload.h"
 
#include "Swiften/Elements/SpectrumErrorPayload.h"
 
#include "Swiften/Elements/CapsInfo.h"
 
#include "Swiften/Elements/VCardUpdate.h"
 
#include <boost/foreach.hpp>
 
#include <stdio.h>
 
#include <stdlib.h>
 

	
 
using namespace boost;
 

	
 
#define foreach         BOOST_FOREACH
 

	
 
namespace Transport {
 

	
 
DEFINE_LOGGER(logger, "User");
 

	
 
User::User(const Swift::JID &jid, UserInfo &userInfo, Component *component, UserManager *userManager) {
 
	m_jid = jid.toBare();
 
	m_data = NULL;
 

	
 
	m_cacheMessages = false;
 
	m_component = component;
 
	m_presenceOracle = component->m_presenceOracle;
 
	m_userManager = userManager;
 
	m_userInfo = userInfo;
 
	m_connected = false;
 
	m_readyForConnect = false;
 
	m_ignoreDisconnect = false;
 
	m_resources = 0;
 
	m_reconnectCounter = 0;
 
	m_reconnectLimit = 3;
 

	
 
	m_reconnectTimer = m_component->getNetworkFactories()->getTimerFactory()->createTimer(5000);
 
	m_reconnectTimer->onTick.connect(boost::bind(&User::onConnectingTimeout, this)); 
 

	
 
	m_rosterManager = component->getFrontend()->createRosterManager(this, m_component);
 
	m_conversationManager = new ConversationManager(this, m_component);
 

	
 
	LOG4CXX_INFO(logger, m_jid.toString() << ": Created");
 
	updateLastActivity();
 
}
 

	
 
User::~User(){
 
	LOG4CXX_INFO(logger, m_jid.toString() << ": Destroying");
 
// 	if (m_component->inServerMode()) {
 
// #if HAVE_SWIFTEN_3
 
// 		dynamic_cast<Swift::ServerStanzaChannel *>(m_component->getFrontend())->finishSession(m_jid, boost::shared_ptr<Swift::ToplevelElement>());
 
// #else
 
// 		dynamic_cast<Swift::ServerStanzaChannel *>(m_component->getFrontend())->finishSession(m_jid, boost::shared_ptr<Swift::Element>());
 
// #endif
 
// 	}
 

	
 

	
 
	m_reconnectTimer->stop();
 
	delete m_rosterManager;
 
	delete m_conversationManager;
 
}
 

	
 
const Swift::JID &User::getJID() {
 
	return m_jid;
 
}
 

	
 
@@ -149,48 +151,63 @@ void User::setCacheMessages(bool cacheMessages) {
 
		m_conversationManager->sendCachedChatMessages();
 
	}
 
	m_cacheMessages = cacheMessages;
 
}
 

	
 
void User::leaveRoom(const std::string &room) {
 
	onRoomLeft(room);
 

	
 
	BOOST_FOREACH(Swift::Presence::ref &p, m_joinedRooms) {
 
		if (Buddy::JIDToLegacyName(p->getTo()) == room) {
 
			m_joinedRooms.remove(p);
 
			break;
 
		}
 
	}
 

	
 
	Conversation *conv = m_conversationManager->getConversation(room);
 
	if (conv) {
 
		m_conversationManager->removeConversation(conv);
 
		delete conv;
 
	}
 
}
 

	
 
void User::handlePresence(Swift::Presence::ref presence, bool forceJoin) {
 
	LOG4CXX_INFO(logger, "PRESENCE " << presence->getFrom().toString() << " " << presence->getTo().toString());
 

	
 
	if (m_storageBackend) {
 
		boost::shared_ptr<Swift::VCardUpdate> vcardUpdate = presence->getPayload<Swift::VCardUpdate>();
 
		if (vcardUpdate) {
 
			std::string value = "";
 
			int type = (int) TYPE_STRING;
 
			m_storageBackend->getUserSetting(m_userInfo.id, "photohash", type, value);
 
			if (value != vcardUpdate->getPhotoHash()) {
 
				LOG4CXX_INFO(logger, m_jid.toString() << ": Requesting VCard")
 
				m_storageBackend->updateUserSetting(m_userInfo.id, "photohash", vcardUpdate->getPhotoHash());
 
				requestVCard();
 
			}
 
		}
 
	}
 

	
 
	if (!m_connected) {
 
		// we are not connected to legacy network, so we should do it when disco#info arrive :)
 
		if (m_readyForConnect == false) {
 
			boost::shared_ptr<Swift::CapsInfo> capsInfo = presence->getPayload<Swift::CapsInfo>();
 
			if (capsInfo && capsInfo->getHash() == "sha-1") {
 
				if (m_component->getFrontend()->sendCapabilitiesRequest(presence->getFrom()) != Swift::DiscoInfo::ref()) {
 
					LOG4CXX_INFO(logger, m_jid.toString() << ": Ready to be connected to legacy network");
 
					m_readyForConnect = true;
 
					onReadyToConnect();
 
				}
 
				else {
 
					m_reconnectTimer->start();
 
				}
 
			}
 
			else if (m_component->inServerMode()) {
 
				LOG4CXX_INFO(logger, m_jid.toString() << ": Ready to be connected to legacy network");
 
				m_readyForConnect = true;
 
				onReadyToConnect();
 
			}
 
			else {
 
				m_reconnectTimer->start();
 
			}
 
		}
 
	}
spectrum/src/frontends/xmpp/XMPPUser.cpp
Show inline comments
 
@@ -5,73 +5,98 @@
 
 *
 
 * This program is free software; you can redistribute it and/or modify
 
 * it under the terms of the GNU General Public License as published by
 
 * the Free Software Foundation; either version 2 of the License, or
 
 * (at your option) any later version.
 
 *
 
 * This program is distributed in the hope that it will be useful,
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
 * GNU General Public License for more details.
 
 *
 
 * You should have received a copy of the GNU General Public License
 
 * along with this program; if not, write to the Free Software
 
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
 
 */
 

	
 
#include "XMPPUser.h"
 
#include "XMPPFrontend.h"
 
#include "transport/Transport.h"
 
#include "transport/UserManager.h"
 
#include "transport/Logging.h"
 
#include "Swiften/Server/ServerStanzaChannel.h"
 
#include "Swiften/Elements/StreamError.h"
 
#include "Swiften/Elements/SpectrumErrorPayload.h"
 
#include "Swiften/Queries/IQRouter.h"
 
#include <boost/foreach.hpp>
 
#include <stdio.h>
 
#include <stdlib.h>
 

	
 
using namespace boost;
 

	
 
#define foreach         BOOST_FOREACH
 

	
 
namespace Transport {
 

	
 
DEFINE_LOGGER(logger, "XMPPUser");
 

	
 
XMPPUser::XMPPUser(const Swift::JID &jid, UserInfo &userInfo, Component *component, UserManager *userManager) : User(jid, userInfo, component, userManager) {
 
	m_jid = jid.toBare();
 

	
 
	m_component = component;
 
	m_userManager = userManager;
 
	m_userInfo = userInfo;
 
}
 

	
 
XMPPUser::~XMPPUser(){
 
	if (m_component->inServerMode()) {
 
#if HAVE_SWIFTEN_3
 
		dynamic_cast<Swift::ServerStanzaChannel *>(static_cast<XMPPFrontend*>(m_component->getFrontend())->getStanzaChannel())->finishSession(m_jid, boost::shared_ptr<Swift::ToplevelElement>());
 
#else
 
		dynamic_cast<Swift::ServerStanzaChannel *>(static_cast<XMPPFrontend*>(m_component->getFrontend())->getStanzaChannel())->finishSession(m_jid, boost::shared_ptr<Swift::Element>());
 
#endif
 
	}
 

	
 
	if (m_vcardRequests.size() != 0) {
 
		LOG4CXX_INFO(logger, m_jid.toString() <<  ": Removing " << m_vcardRequests.size() << " unresponded IQs");
 
		BOOST_FOREACH(Swift::GetVCardRequest::ref request, m_vcardRequests) {
 
			request->onResponse.disconnect_all_slots();
 
			static_cast<XMPPFrontend *>(m_component->getFrontend())->getIQRouter()->removeHandler(request);
 
		}
 
		m_vcardRequests.clear();
 
	}
 
}
 

	
 
void XMPPUser::disconnectUser(const std::string &error, Swift::SpectrumErrorPayload::Error e) {
 
	// In server mode, server finishes the session and pass unavailable session to userManager if we're connected to legacy network,
 
	// so we can't removeUser() in server mode, because it would be removed twice.
 
	// Once in finishSession and once in m_userManager->removeUser.
 
	if (m_component->inServerMode()) {
 
		// Remove user later just to be sure there won't be double-free.
 
		// We can't be sure finishSession sends unavailable presence everytime, so check if user gets removed
 
		// in finishSession(...) call and if not, remove it here.
 
		std::string jid = m_jid.toBare().toString();
 
#if HAVE_SWIFTEN_3
 
		dynamic_cast<Swift::ServerStanzaChannel *>(static_cast<XMPPFrontend*>(m_component->getFrontend())->getStanzaChannel())->finishSession(m_jid, boost::shared_ptr<Swift::ToplevelElement>(new Swift::StreamError(Swift::StreamError::UndefinedCondition, error)));
 
#else
 
		dynamic_cast<Swift::ServerStanzaChannel *>(static_cast<XMPPFrontend*>(m_component->getFrontend())->getStanzaChannel())->finishSession(m_jid, boost::shared_ptr<Swift::Element>(new Swift::StreamError(Swift::StreamError::UndefinedCondition, error)));
 
#endif
 
	}
 
}
 

	
 
void XMPPUser::handleVCardReceived(boost::shared_ptr<Swift::VCard> vcard, Swift::ErrorPayload::ref error, Swift::GetVCardRequest::ref request) {
 
	m_vcardRequests.remove(request);
 
	request->onResponse.disconnect_all_slots();
 
	m_component->getFrontend()->onVCardUpdated(this, vcard);
 
}
 

	
 
void XMPPUser::requestVCard() {
 
	LOG4CXX_INFO(logger, m_jid.toString() << ": Requesting VCard");
 

	
 
	Swift::GetVCardRequest::ref request = Swift::GetVCardRequest::create(m_jid, static_cast<XMPPFrontend *>(m_component->getFrontend())->getIQRouter());
 
	request->onResponse.connect(boost::bind(&XMPPUser::handleVCardReceived, this, _1, _2, request));
 
	request->send();
 
	m_vcardRequests.push_back(request);
 
}
 

	
 

	
 
}
spectrum/src/frontends/xmpp/XMPPUser.h
Show inline comments
 
@@ -8,61 +8,64 @@
 
 * the Free Software Foundation; either version 2 of the License, or
 
 * (at your option) any later version.
 
 *
 
 * This program is distributed in the hope that it will be useful,
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
 * GNU General Public License for more details.
 
 *
 
 * You should have received a copy of the GNU General Public License
 
 * along with this program; if not, write to the Free Software
 
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
 
 */
 

	
 
#pragma once
 

	
 
#include "transport/User.h"
 

	
 
#include <time.h>
 
#include "Swiften/Disco/EntityCapsManager.h"
 
#include "Swiften/Disco/EntityCapsProvider.h"
 
#include <Swiften/FileTransfer/OutgoingFileTransfer.h>
 
#include "Swiften/Elements/SpectrumErrorPayload.h"
 
#include "Swiften/Network/Timer.h"
 
#include "Swiften/Network/Connection.h"
 
#include "Swiften/VCards/GetVCardRequest.h"
 

	
 
namespace Transport {
 

	
 
class Component;
 
class RosterManager;
 
class ConversationManager;
 
class UserManager;
 
class PresenceOracle;
 
struct UserInfo;
 

	
 
/// Represents online XMPP user.
 
class XMPPUser : public User {
 
	public:
 
		/// Creates new User class.
 
		/// \param jid XMPP JID associated with this user
 
		/// \param userInfo UserInfo struct with informations needed to connect
 
		/// this user to legacy network
 
		/// \param component Component associated with this user
 
		XMPPUser(const Swift::JID &jid, UserInfo &userInfo, Component * component, UserManager *userManager);
 

	
 
		/// Destroyes User.
 
		virtual ~XMPPUser();
 

	
 
		void disconnectUser(const std::string &error, Swift::SpectrumErrorPayload::Error e);
 

	
 

	
 
		void requestVCard();
 

	
 
	private:
 
		void onConnectingTimeout();
 
		void handleVCardReceived(boost::shared_ptr<Swift::VCard> vcard, Swift::ErrorPayload::ref error, Swift::GetVCardRequest::ref request);
 

	
 
		Swift::JID m_jid;
 
		Component *m_component;
 
		UserManager *m_userManager;
 
		UserInfo m_userInfo;
 
		std::list <Swift::GetVCardRequest::ref> m_vcardRequests;
 
};
 

	
 
}
tests/libtransport/user.cpp
Show inline comments
 
@@ -9,81 +9,90 @@
 
#include "Swiften/Server/ServerFromClientSession.h"
 
#include "Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.h"
 
#include "basictest.h"
 

	
 
using namespace Transport;
 

	
 
class UserTest : public CPPUNIT_NS :: TestFixture, public BasicTest {
 
	CPPUNIT_TEST_SUITE(UserTest);
 
	CPPUNIT_TEST(sendCurrentPresence);
 
    CPPUNIT_TEST(handlePresence);
 
	CPPUNIT_TEST(handlePresenceJoinRoom);
 
	CPPUNIT_TEST(handlePresenceJoinRoomTwoResources);
 
	CPPUNIT_TEST(handlePresenceLeaveRoom);
 
	CPPUNIT_TEST(handlePresenceLeaveRoomTwoResources);
 
	CPPUNIT_TEST(handlePresenceLeaveRoomTwoResourcesOneDisconnects);
 
	CPPUNIT_TEST(handlePresenceLeaveRoomBouncer);
 
	CPPUNIT_TEST(handlePresenceLeaveRoomTwoResourcesBouncer);
 
	CPPUNIT_TEST(handlePresenceLeaveRoomTwoResourcesOneDisconnectsBouncer);
 
	CPPUNIT_TEST(leaveJoinedRoom);
 
	CPPUNIT_TEST(joinRoomBeforeConnected);
 
	CPPUNIT_TEST(handleDisconnected);
 
	CPPUNIT_TEST(handleDisconnectedReconnect);
 
	CPPUNIT_TEST(joinRoomHandleDisconnectedRejoin);
 
	CPPUNIT_TEST(joinRoomAfterFlagNotAuthorized);
 
	CPPUNIT_TEST(requestVCard);
 
	CPPUNIT_TEST_SUITE_END();
 

	
 
	public:
 
		std::string room;
 
		std::string roomNickname;
 
		std::string roomPassword;
 
		std::string photo;
 
		bool readyToConnect;
 
		bool disconnected;
 
		Swift::Presence::ref changedPresence;
 

	
 
		void setUp (void) {
 
			disconnected = false;
 
			readyToConnect = false;
 
			changedPresence = Swift::Presence::ref();
 
			room = "";
 
			roomNickname = "";
 
			roomPassword = "";
 
			photo = "";
 

	
 
			setMeUp();
 
			userManager->onUserCreated.connect(boost::bind(&UserTest::handleUserCreated, this, _1));
 
			connectUser();
 
			received.clear();
 

	
 
			frontend->onVCardUpdated.connect(boost::bind(&UserTest::handleVCardUpdated, this, _1, _2));
 
		}
 

	
 
		void tearDown (void) {
 
			received.clear();
 
			if (!disconnected) {
 
				disconnectUser();
 
			}
 
			userManager->removeAllUsers();
 
			tearMeDown();
 
		}
 

	
 
	void handleVCardUpdated(User *user, boost::shared_ptr<Swift::VCard> v) {
 
		photo = Swift::byteArrayToString(v->getPhoto());
 
	}
 

	
 
	void handleUserCreated(User *user) {
 
		user->onReadyToConnect.connect(boost::bind(&UserTest::handleUserReadyToConnect, this, user));
 
		user->onPresenceChanged.connect(boost::bind(&UserTest::handleUserPresenceChanged, this, user, _1));
 
		user->onRoomJoined.connect(boost::bind(&UserTest::handleRoomJoined, this, user, _1, _2, _3, _4));
 
		user->onRoomLeft.connect(boost::bind(&UserTest::handleRoomLeft, this, user, _1));
 
	}
 

	
 
	void handleUserReadyToConnect(User *user) {
 
		readyToConnect = true;
 
	}
 

	
 
	void handleUserPresenceChanged(User *user, Swift::Presence::ref presence) {
 
		changedPresence = presence;
 
	}
 

	
 
	void handleRoomJoined(User *user, const std::string &jid, const std::string &r, const std::string &nickname, const std::string &password) {
 
		room = r;
 
		roomNickname = nickname;
 
		roomPassword = password;
 
	}
 

	
 
	void handleRoomLeft(User *user, const std::string &r) {
 
		room = r;
 
	}
 
@@ -451,27 +460,57 @@ class UserTest : public CPPUNIT_NS :: TestFixture, public BasicTest {
 
		CPPUNIT_ASSERT_EQUAL(std::string("room"), room);
 
		CPPUNIT_ASSERT_EQUAL(std::string("hanzz"), roomNickname);
 
		CPPUNIT_ASSERT_EQUAL(std::string("password"), roomPassword);
 
		CPPUNIT_ASSERT_EQUAL(0, (int) received.size());
 
	}
 

	
 
	void joinRoomAfterFlagNotAuthorized() {
 
		User *user = userManager->getUser("user@localhost");
 
		handlePresenceJoinRoom();
 

	
 
		Conversation *conv = user->getConversationManager()->getConversation("room");
 
		conv->handleParticipantChanged("hanzz", Conversation::PARTICIPANT_FLAG_NOT_AUTHORIZED, Swift::StatusShow::Away, "my status message");
 
		loop->processEvents();
 

	
 
		CPPUNIT_ASSERT_EQUAL(1, (int) received.size());
 
		CPPUNIT_ASSERT(dynamic_cast<Swift::Presence *>(getStanza(received[0])));
 
		CPPUNIT_ASSERT_EQUAL(Swift::Presence::Error, dynamic_cast<Swift::Presence *>(getStanza(received[0]))->getType());
 
		CPPUNIT_ASSERT(getStanza(received[0])->getPayload<Swift::ErrorPayload>());
 
		CPPUNIT_ASSERT_EQUAL(Swift::ErrorPayload::NotAuthorized, getStanza(received[0])->getPayload<Swift::ErrorPayload>()->getCondition());
 

	
 
		received.clear();
 
		handlePresenceJoinRoom();
 
	}
 

	
 
	void requestVCard() {
 
		User *user = userManager->getUser("user@localhost");
 
		user->setStorageBackend(storage);
 

	
 
		Swift::Presence::ref response = Swift::Presence::create();
 
		response->setTo("localhost");
 
		response->setFrom("user@localhost/resource");
 
		response->addPayload(boost::shared_ptr<Swift::Payload>(new Swift::VCardUpdate("hash")));
 

	
 
		injectPresence(response);
 
		loop->processEvents();
 

	
 
		CPPUNIT_ASSERT_EQUAL(2, (int) received.size());
 
		Swift::VCard::ref payload1 = getStanza(received[1])->getPayload<Swift::VCard>();
 
		CPPUNIT_ASSERT(payload1);
 

	
 
		boost::shared_ptr<Swift::VCard> vcard(new Swift::VCard());
 
		vcard->setPhoto(Swift::createByteArray("photo"));
 
		injectIQ(Swift::IQ::createResult(getStanza(received[1])->getFrom(), getStanza(received[1])->getTo(), getStanza(received[1])->getID(), vcard));
 
		loop->processEvents();
 

	
 
		CPPUNIT_ASSERT_EQUAL(2, (int) received.size());
 
		CPPUNIT_ASSERT_EQUAL(std::string("photo"), photo);
 

	
 
		received.clear();
 
		injectPresence(response);
 
		loop->processEvents();
 
		CPPUNIT_ASSERT_EQUAL(1, (int) received.size());
 
	}
 

	
 
};
 

	
 
CPPUNIT_TEST_SUITE_REGISTRATION (UserTest);
0 comments (0 inline, 0 general)