Changeset - fe47e0979be9
[Not reviewed]
! ! !
Jan Kaluza - 10 years ago 2015-11-16 10:49:10
jkaluza@redhat.com
Split libtransport in two - libtransport and XMPPFrontend (lives in ./spectrum/src/frontends/xmpp). It's first step to allow generic Spectrum 2 frontends.
75 files changed:
Changeset was too big and was cut off... Show full diff anyway
0 comments (0 inline, 0 general)
.gitignore
Show inline comments
 
*.pb.cc
 
*.pb.h
 
plugin/python/protocol_pb2.py
 
\ No newline at end of file
 
plugin/python/protocol_pb2.py
 
Makefile
 
*.cmake
 
*.so
 
*.so.*
 
*.log
 
libtransport_test
 
CMakeFiles
 
spectrum2
 
transport_config.h
 
Doxyfile
 
moc_*
 
CMakeCache.txt
 
*.patch
 
*.orig
 
spectrum2_manager
 
dfrotz
 
spectrum2_frotz_backend
 
spectrum2_libcommuni_backend
 
spectrum2_libpurple_backend
 
spectrum2_skype_backend
 
spectrum2_smstools3_backend
 
spectrum2_swiften_backend
 
spectrum2_template_backend
 
spectrum2_twitter_backend
 
install_manifest.txt
include/transport/buddy.h
Show inline comments
 
@@ -15,25 +15,25 @@
 
 *
 
 * 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 <string>
 
#include <algorithm>
 
#include "transport/transport.h"
 
#include "Swiften/Elements/VCard.h"
 

	
 
#include "Swiften/Elements/Presence.h"
 

	
 
namespace Transport {
 

	
 
class RosterManager;
 

	
 
typedef enum { 	BUDDY_NO_FLAG = 0,
 
				BUDDY_JID_ESCAPING = 2,
 
				BUDDY_IGNORE = 4,
 
				BUDDY_BLOCKED = 8,
 
			} BuddyFlag;
 

	
 
/// Represents one legacy network Buddy.
include/transport/conversation.h
Show inline comments
 
@@ -16,24 +16,25 @@
 
 * 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 <string>
 
#include <algorithm>
 
#include "transport/transport.h"
 

	
 
#include "Swiften/Elements/Message.h"
 
#include "Swiften/Elements/Presence.h"
 

	
 
namespace Transport {
 

	
 
class ConversationManager;
 

	
 
/// Represents one XMPP-Legacy network conversation.
 
class Conversation {
 
	public:
 
		typedef enum {
 
			PARTICIPANT_FLAG_NONE = 0,
 
			PARTICIPANT_FLAG_MODERATOR = 1,
 
			PARTICIPANT_FLAG_CONFLICT = 2,
include/transport/frontend.h
Show inline comments
 
new file 100644
 
/**
 
 * XMPP - libpurple transport
 
 *
 
 * Copyright (C) 2009, Jan Kaluza <hanzz@soc.pidgin.im>
 
 *
 
 * 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
 
 */
 

	
 
#pragma once
 

	
 
#include <string>
 
#include <algorithm>
 
#include <Swiften/EventLoop/EventLoop.h>
 
#include <Swiften/Network/NetworkFactories.h>
 
#include "Swiften/Elements/RosterPayload.h"
 
#include "Swiften/Elements/VCard.h"
 
#include "Swiften/Elements/Message.h"
 
#include "Swiften/Elements/IQ.h"
 
#include "Swiften/Elements/DiscoInfo.h"
 
#include "Swiften/Elements/Presence.h"
 

	
 
#include <boost/signal.hpp>
 

	
 
namespace Transport {
 

	
 
class Config;
 
class UserRegistry;
 
class Component;
 
class User;
 
class Buddy;
 
class RosterManager;
 
class UserManager;
 
class StorageBackend;
 

	
 
struct UserInfo;
 

	
 
class Frontend {
 
	public:
 
		Frontend() {}
 

	
 
		virtual ~Frontend() {}
 

	
 
		virtual void init(Component *component, Swift::EventLoop *loop, Swift::NetworkFactories *factories, Config *config, UserRegistry *userRegistry) = 0;
 

	
 
		virtual void connectToServer() = 0;
 

	
 
		virtual void disconnectFromServer() = 0;
 

	
 
		virtual void sendPresence(Swift::Presence::ref presence) = 0;
 

	
 
		virtual void sendVCard(Swift::VCard::ref vcard, Swift::JID to) = 0;
 

	
 
		virtual void sendRosterRequest(Swift::RosterPayload::ref, Swift::JID to) = 0;
 

	
 
		virtual void sendMessage(boost::shared_ptr<Swift::Message> message) = 0;
 

	
 
		virtual void sendIQ(boost::shared_ptr<Swift::IQ>) = 0;
 

	
 
		virtual boost::shared_ptr<Swift::DiscoInfo> sendCapabilitiesRequest(Swift::JID to) = 0;
 

	
 
		virtual void reconnectUser(const std::string &user) = 0;
 

	
 
		virtual RosterManager *createRosterManager(User *user, Component *component) = 0;
 

	
 
		virtual User *createUser(const Swift::JID &jid, UserInfo &userInfo, Component *component, UserManager *userManager) = 0;
 

	
 
		virtual UserManager *createUserManager(Component *component, UserRegistry *userRegistry, StorageBackend *storageBackend = NULL) = 0;
 

	
 
		virtual void clearRoomList() = 0;
 
		virtual void addRoomToRoomList(const std::string &handle, const std::string &name) = 0;
 

	
 
		boost::signal<void (User *, const std::string &name, unsigned int id)> onVCardRequired;
 
		boost::signal<void (User *, boost::shared_ptr<Swift::VCard> vcard)> onVCardUpdated;
 
		boost::signal<void (Buddy *, const Swift::RosterItemPayload &item)> onBuddyUpdated;
 
		boost::signal<void (Buddy *)> onBuddyRemoved;
 
		boost::signal<void (Buddy *, const Swift::RosterItemPayload &item)> onBuddyAdded;
 
		boost::signal<void (Swift::Message::ref message)> onMessageReceived;
 
		boost::signal<void (bool /* isAvailable */)> onAvailableChanged;
 
		boost::signal<void (boost::shared_ptr<Swift::Presence>) > onPresenceReceived;
 
		boost::signal<void (const Swift::JID& jid, boost::shared_ptr<Swift::DiscoInfo> info)> onCapabilitiesReceived;
 
};
 

	
 
}
include/transport/networkpluginserver.h
Show inline comments
 
@@ -43,43 +43,42 @@ namespace Transport {
 
class UserManager;
 
class User;
 
class Component;
 
class Buddy;
 
class LocalBuddy;
 
class Config;
 
class NetworkConversation;
 
class VCardResponder;
 
class RosterResponder;
 
class BlockResponder;
 
class DummyReadBytestream;
 
class AdminInterface;
 
class DiscoItemsResponder;
 

	
 
class NetworkPluginServer : Swift::XMPPParserClient {
 
	public:
 
		struct Backend {
 
			int pongReceived;
 
			std::list<User *> users;
 
			Swift::SafeByteArray data;
 
			boost::shared_ptr<Swift::Connection> connection;
 
			unsigned long res;
 
			unsigned long init_res;
 
			unsigned long shared;
 
			bool acceptUsers;
 
			bool longRun;
 
			bool willDie;
 
			std::string id;
 
		};
 

	
 
		NetworkPluginServer(Component *component, Config *config, UserManager *userManager, FileTransferManager *ftManager, DiscoItemsResponder *discoItemsResponder);
 
		NetworkPluginServer(Component *component, Config *config, UserManager *userManager, FileTransferManager *ftManager);
 

	
 
		virtual ~NetworkPluginServer();
 

	
 
		void start();
 

	
 
		void setAdminInterface(AdminInterface *adminInterface) {
 
			m_adminInterface = adminInterface;
 
		}
 

	
 
		int getBackendCount() {
 
			return m_clients.size();
 
		}
 
@@ -178,22 +177,21 @@ class NetworkPluginServer : Swift::XMPPParserClient {
 
		std::vector<unsigned long> m_pids;
 
		Swift::Timer::ref m_pingTimer;
 
		Swift::Timer::ref m_collectTimer;
 
		Swift::Timer::ref m_loginTimer;
 
		Component *m_component;
 
		std::list<User *> m_waitingUsers;
 
		bool m_isNextLongRun;
 
		std::map<unsigned long, FileTransferManager::Transfer> m_filetransfers;
 
		FileTransferManager *m_ftManager;
 
		std::vector<std::string> m_crashedBackends;
 
		AdminInterface *m_adminInterface;
 
		bool m_startingBackend;
 
		DiscoItemsResponder *m_discoItemsResponder;
 
		time_t m_lastLogin;
 
		Swift::XMPPParser *m_xmppParser;
 
		Swift::FullPayloadParserFactoryCollection m_collection;
 
		Swift::XMPPSerializer *m_serializer;
 
		Swift::FullPayloadSerializerCollection m_collection2;
 
		std::map <std::string, std::string> m_id2resource;
 
};
 

	
 
}
include/transport/presenceoracle.h
Show inline comments
 
@@ -21,39 +21,41 @@
 
#pragma once
 

	
 
#include <map>
 

	
 
#include <string>
 
#include <Swiften/Elements/Presence.h>
 
#include <Swiften/Client/StanzaChannel.h>
 

	
 
#include <Swiften/Base/boost_bsignals.h>
 

	
 
namespace Transport {
 

	
 
class Frontend;
 

	
 
class PresenceOracle {
 
	public:
 
		PresenceOracle(Swift::StanzaChannel* stanzaChannel);
 
		PresenceOracle(Frontend* frontend);
 
		~PresenceOracle();
 

	
 
		Swift::Presence::ref getLastPresence(const Swift::JID&) const;
 
		Swift::Presence::ref getHighestPriorityPresence(const Swift::JID& bareJID) const;
 
		std::vector<Swift::Presence::ref> getAllPresence(const Swift::JID& bareJID) const;
 

	
 
		void clearPresences(const Swift::JID& bareJID);
 

	
 
	public:
 
		boost::signal<void (Swift::Presence::ref)> onPresenceChange;
 

	
 
	private:
 
		void handleIncomingPresence(Swift::Presence::ref presence);
 
		void handleStanzaChannelAvailableChanged(bool);
 

	
 
	private:
 
		typedef std::map<Swift::JID, Swift::Presence::ref> PresenceMap;
 
		typedef std::map<Swift::JID, PresenceMap> PresencesMap;
 
		PresencesMap entries_;
 
		Swift::StanzaChannel* stanzaChannel_;
 
		Frontend* frontend_;
 
};
 

	
 
}
 

	
include/transport/rostermanager.h
Show inline comments
 
@@ -31,46 +31,40 @@
 
#include "Swiften/Roster/SetRosterRequest.h"
 
#include "Swiften/Elements/Presence.h"
 
#include "Swiften/Network/Timer.h"
 

	
 
namespace Transport {
 

	
 
class Buddy;
 
class User;
 
class Component;
 
class StorageBackend;
 
class RosterStorage;
 

	
 
// TODO: Once Swiften GetRosterRequest will support setting to="", this can be removed
 
class AddressedRosterRequest : public Swift::GenericRequest<Swift::RosterPayload> {
 
	public:
 
		typedef boost::shared_ptr<AddressedRosterRequest> ref;
 

	
 
		AddressedRosterRequest(Swift::IQRouter* router, Swift::JID to) :
 
				Swift::GenericRequest<Swift::RosterPayload>(Swift::IQ::Get, to, boost::shared_ptr<Swift::Payload>(new Swift::RosterPayload()), router) {
 
		}
 
};
 

	
 
/// Manages roster of one XMPP user.
 
class RosterManager {
 
	public:
 
		typedef std::map<std::string, Buddy *, std::less<std::string>, boost::pool_allocator< std::pair<std::string, Buddy *> > > BuddiesMap;
 
		/// Creates new RosterManager.
 
		/// \param user User associated with this RosterManager.
 
		/// \param component Transport instance associated with this roster.
 
		RosterManager(User *user, Component *component);
 

	
 
		/// Destructor.
 
		virtual ~RosterManager();
 

	
 
		virtual void doRemoveBuddy(Buddy *buddy) = 0;
 
		virtual void doAddBuddy(Buddy *buddy) = 0;
 
		virtual void doUpdateBuddy(Buddy *buddy) = 0;
 

	
 
		/// Associates the buddy with this roster,
 
		/// and if the buddy is not already in XMPP user's server-side roster, the proper requests
 
		/// are sent to XMPP user (subscribe presences, Roster Item Exchange stanza or
 
		/// the buddy is added to server-side roster using remote-roster protoXEP).
 
		/// \param buddy Buddy
 
		void setBuddy(Buddy *buddy);
 

	
 
		/// Deassociates the buddy with this roster.
 
		/// \param buddy Buddy.
 
		void unsetBuddy(Buddy *buddy);
 

	
 
		/// Removes buddy from this roster, sends proper XML to XMPP side and deletes it.
 
@@ -104,45 +98,38 @@ class RosterManager {
 
		/// Called when Buddy has been removed from this roster.
 
		/// \param buddy removed Buddy
 
		boost::signal<void (Buddy *buddy)> onBuddyUnset;
 

	
 
		boost::signal<void (Buddy *buddy)> onBuddyAdded;
 
		
 
		boost::signal<void (Buddy *buddy)> onBuddyRemoved;
 

	
 
		void handleBuddyChanged(Buddy *buddy);
 

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

	
 
		void sendBuddyRosterPush(Buddy *buddy);
 

	
 
		void sendBuddyRosterRemove(Buddy *buddy);
 

	
 
		void sendBuddySubscribePresence(Buddy *buddy);
 
		
 
		void sendBuddyUnsubscribePresence(Buddy *buddy);
 

	
 
		void sendCurrentPresences(const Swift::JID &to);
 

	
 
		void sendCurrentPresence(const Swift::JID &from, const Swift::JID &to);
 

	
 
		void sendUnavailablePresences(const Swift::JID &to);
 

	
 
	private:
 
		void setBuddyCallback(Buddy *buddy);
 

	
 
		void sendRIE();
 
		void handleBuddyRosterPushResponse(Swift::ErrorPayload::ref error, Swift::SetRosterRequest::ref request, const std::string &key);
 
		void handleRemoteRosterResponse(boost::shared_ptr<Swift::RosterPayload> roster, Swift::ErrorPayload::ref error);
 

	
 
	protected:
 
		std::map<std::string, Buddy *, std::less<std::string>, boost::pool_allocator< std::pair<std::string, Buddy *> > > m_buddies;
 

	
 
	private:
 
		Component *m_component;
 
		RosterStorage *m_rosterStorage;
 
		User *m_user;
 
		Swift::Timer::ref m_setBuddyTimer;
 
		Swift::Timer::ref m_RIETimer;
 
		std::list <Swift::SetRosterRequest::ref> m_requests;
 
		bool m_supportRemoteRoster;
 
		AddressedRosterRequest::ref m_remoteRosterRequest;
 
};
 

	
 
}
include/transport/rosterresponder.h
Show inline comments
 
@@ -37,15 +37,16 @@ class RosterResponder : public Swift::Responder<Swift::RosterPayload> {
 
		~RosterResponder();
 

	
 
		boost::signal<void (Buddy *, const Swift::RosterItemPayload &item)> onBuddyUpdated;
 

	
 
		boost::signal<void (Buddy *)> onBuddyRemoved;
 

	
 
		boost::signal<void (Buddy *, const Swift::RosterItemPayload &item)> onBuddyAdded;
 

	
 
	private:
 
		virtual bool handleGetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr<Swift::RosterPayload> payload);
 
		virtual bool handleSetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr<Swift::RosterPayload> payload);
 
		UserManager *m_userManager;
 
		Swift::IQRouter *m_router;
 
};
 

	
 
}
include/transport/transport.h
Show inline comments
 
@@ -12,97 +12,67 @@
 
 * 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 <vector>
 
#include "Swiften/Server/Server.h"
 
#include "Swiften/Disco/GetDiscoInfoRequest.h"
 
#include "Swiften/Disco/EntityCapsManager.h"
 
#include "Swiften/Disco/CapsManager.h"
 
#include "Swiften/Disco/CapsMemoryStorage.h"
 
#include <boost/bind.hpp>
 
#include "Swiften/Network/BoostTimerFactory.h"
 
#include "Swiften/Network/BoostIOServiceThread.h"
 
#include "Swiften/Server/UserRegistry.h"
 
#include "Swiften/Base/SafeByteArray.h"
 
#include "Swiften/Queries/IQHandler.h"
 
#include "Swiften/Jingle/JingleSessionManager.h"
 
#include "Swiften/Component/ComponentError.h"
 
#include "Swiften/Component/Component.h"
 
#include "Swiften/Queries/IQHandler.h"
 

	
 
#include <boost/bind.hpp>
 
#include "transport/config.h"
 
#include "transport/factory.h"
 
#include "transport/presenceoracle.h"
 
#include <Swiften/Network/BoostConnectionServer.h>
 
#include "Swiften/Network/NetworkFactories.h"
 
#include "Swiften/Elements/DiscoInfo.h"
 
#include "Swiften/Elements/Presence.h"
 
#include "Swiften/Elements/IQ.h"
 

	
 
namespace Transport {
 
	class StorageBackend;
 
	class Factory;
 
	class UserRegistry;
 
	class Frontend;
 
	class PresenceOracle;
 
	class Factory;
 
	class Config;
 
	class UserManager;
 

	
 
	/// Represents one transport instance.
 

	
 
	/// It's used to connect the Jabber server and provides transaction layer
 
	/// between Jabber server and other classes.
 
	///
 
	/// In server mode it represents Jabber server to which users can connect and use
 
	/// it as transport.
 
	class Component : Swift::IQHandler {
 
	class Component {
 
		public:
 
			/// Creates new Component instance.
 

	
 
			/// \param loop Main event loop.
 
			/// \param config Cofiguration; this class uses following Config values:
 
			/// 	- service.jid
 
			/// 	- service.password
 
			/// 	- service.server
 
			/// 	- service.port
 
			/// 	- service.server_mode
 
			/// \param factories Swift::NetworkFactories.
 
			/// \param factory Transport Abstract factory used to create basic transport structures.
 
			/// \param userRegistery UserRegistry class instance. It's needed only when running transport in server-mode.
 
			Component(Swift::EventLoop *loop, Swift::NetworkFactories *factories, Config *config, Factory *factory, Transport::UserRegistry *userRegistry = NULL);
 
			Component(Frontend *frontend, Swift::EventLoop *loop, Swift::NetworkFactories *factories, Config *config, Factory *factory, Transport::UserRegistry *userRegistry = NULL);
 

	
 
			/// Component destructor.
 
			~Component();
 

	
 
			/// Returns Swift::StanzaChannel associated with this Transport::Component.
 

	
 
			/// It can be used to send presences and other stanzas.
 
			/// \return Swift::StanzaChannel associated with this Transport::Component.
 
			Swift::StanzaChannel *getStanzaChannel();
 

	
 
			/// Returns Swift::IQRouter associated with this Component.
 

	
 
			/// \return Swift::IQRouter associated with this Component.
 
			Swift::IQRouter *getIQRouter() { return m_iqRouter; }
 

	
 
			/// Returns Swift::PresenceOracle associated with this Transport::Component.
 

	
 
			/// You can use it to check current resource connected for particular user.
 
			/// \return Swift::PresenceOracle associated with this Transport::Component.
 
			PresenceOracle *getPresenceOracle();
 

	
 
			/// Returns True if the component is in server mode.
 

	
 
			/// \return True if the component is in server mode.
 
			bool inServerMode() { return m_server != NULL; }
 
			bool inServerMode();
 

	
 
			/// Starts the Component.
 
			
 
			/// In server-mode, it starts listening on particular port for new client connections.
 
			/// In gateway-mode, it connects the XMPP server.
 
			void start();
 

	
 
			/// Stops the component.
 
			void stop();
 

	
 
			/// Returns Jabber ID of this transport.
 

	
 
@@ -113,89 +83,70 @@ namespace Transport {
 

	
 
			/// \return Swift::NetworkFactories which can be used to create new connections.
 
			Swift::NetworkFactories *getNetworkFactories() { return m_factories; }
 

	
 
			/// Returns Transport Factory used to create basic Transport components.
 

	
 
			/// \return Transport Factory used to create basic Transport components.
 
			Factory *getFactory() { return m_factory; }
 

	
 
			/// This signal is emitted when server disconnects the transport because of some error.
 

	
 
			/// \param error disconnection error
 
			boost::signal<void (const Swift::ComponentError &error)> onConnectionError;
 
			boost::signal<void (const std::string &error)> onConnectionError;
 

	
 
			/// This signal is emitted when transport successfully connects the server.
 
			boost::signal<void ()> onConnected;
 

	
 
			/// This signal is emitted when XML stanza is sent to server.
 

	
 
			/// \param xml xml stanza
 
			boost::signal<void (const std::string &xml)> onXMLOut;
 

	
 
			/// This signal is emitted when XML stanza is received from server.
 

	
 
			/// \param xml xml stanza
 
			boost::signal<void (const std::string &xml)> onXMLIn;
 

	
 
			Config *getConfig() { return m_config; }
 

	
 
			/// This signal is emitted when presence from XMPP user is received.
 
			bool isRawXMLEnabled() {
 
				return m_rawXML;
 
			}
 

	
 
			/// It's emitted only for presences addressed to transport itself
 
			/// (for example to="j2j.domain.tld") and for presences comming to
 
			/// MUC (for example to="#chat%irc.freenode.org@irc.domain.tld")
 
			/// \param presence Presence.
 
			boost::signal<void (Swift::Presence::ref presence)> onUserPresenceReceived;
 

	
 
			/// Component class asks the XMPP clients automatically for their capabilities.
 
			/// This signal is emitted when capabilities have been received or changed.
 
			/// \param jid JID of the client for which we received capabilities
 
			/// \param info disco#info with response.
 
			boost::signal<void (const Swift::JID& jid, boost::shared_ptr<Swift::DiscoInfo> info)> onUserDiscoInfoReceived;
 

	
 
			boost::signal<void (boost::shared_ptr<Swift::IQ>)> onRawIQReceived;
 
			
 
			void handlePresence(Swift::Presence::ref presence);
 
			void handleConnected();
 
			void handleConnectionError(const std::string &error);
 
			void handleDataRead(const std::string &data);
 
			void handleDataWritten(const std::string &data);
 

	
 
			bool isRawXMLEnabled() {
 
				return m_rawXML;
 
			Frontend *getFrontend() {
 
				return m_frontend;
 
			}
 

	
 
		private:
 
			void handleConnected();
 
			void handleConnectionError(const Swift::ComponentError &error);
 
			void handleServerStopped(boost::optional<Swift::BoostConnectionServer::Error> e);
 
			void handlePresence(Swift::Presence::ref presence);
 
			void handleDataRead(const Swift::SafeByteArray &data);
 
			void handleDataWritten(const Swift::SafeByteArray &data);
 
			PresenceOracle *getPresenceOracle();
 

	
 
		private:
 
			void handleDiscoInfoResponse(boost::shared_ptr<Swift::DiscoInfo> info, Swift::ErrorPayload::ref error, const Swift::JID& jid);
 
			void handleCapsChanged(const Swift::JID& jid);
 

	
 
			void handleBackendConfigChanged();
 
			bool handleIQ(boost::shared_ptr<Swift::IQ>);
 

	
 
			Swift::NetworkFactories *m_factories;
 
			Swift::Component *m_component;
 
			Swift::Server *m_server;
 
			Swift::Timer::ref m_reconnectTimer;
 
			Swift::EntityCapsManager *m_entityCapsManager;
 
			Swift::CapsManager *m_capsManager;
 
			Swift::CapsMemoryStorage *m_capsMemoryStorage;
 
			PresenceOracle *m_presenceOracle;
 
			Swift::StanzaChannel *m_stanzaChannel;
 
			Swift::IQRouter *m_iqRouter;
 
			
 
			Transport::UserRegistry *m_userRegistry;
 
			StorageBackend *m_storageBackend;
 
			int m_reconnectCount;
 
			Config* m_config;
 
			std::string m_protocol;
 
			Swift::JID m_jid;
 
			Factory *m_factory;
 
			Swift::EventLoop *m_loop;
 
			bool m_rawXML;
 
			Frontend *m_frontend;
 

	
 
		friend class User;
 
		friend class UserRegistration;
 
		friend class NetworkPluginServer;
 
	};
 
}
include/transport/user.h
Show inline comments
 
@@ -30,58 +30,60 @@
 
#include "Swiften/Network/Connection.h"
 

	
 
namespace Transport {
 

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

	
 
/// Represents online XMPP user.
 
class User : public Swift::EntityCapsProvider {
 
class 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
 
		User(const Swift::JID &jid, UserInfo &userInfo, Component * component, UserManager *userManager);
 

	
 
		/// Destroyes User.
 
		virtual ~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;
 
// 		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;
 

	
 
		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);
 

	
 
@@ -137,25 +139,24 @@ class User : public Swift::EntityCapsProvider {
 
		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;
 
		Swift::EntityCapsManager *m_entityCapsManager;
 
		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;
include/transport/usermanager.h
Show inline comments
 
@@ -18,87 +18,90 @@
 
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
 
 */
 

	
 
#pragma once
 

	
 
#include <string>
 
#include <map>
 
#include "transport/userregistry.h"
 
#include "Swiften/Elements/Message.h"
 
#include "Swiften/Elements/Presence.h"
 
#include "Swiften/Disco/EntityCapsProvider.h"
 
#include "Swiften/Elements/DiscoInfo.h"
 
#include "Swiften/Elements/VCard.h"
 
#include "Swiften/Network/Timer.h"
 

	
 
namespace Transport {
 

	
 
class User;
 
class Component;
 
class StorageBackend;
 
class StorageResponder;
 
class RosterResponder;
 
class DiscoItemsResponder;
 
class UserRegistration;
 

	
 
/// Manages online XMPP Users.
 

	
 
/// This class handles presences and creates User classes when new user connects.
 
/// It also removes the User class once the last user's resource disconnected.
 

	
 
/// Basic user creation process:
 
/**
 
	\msc
 
	Component,UserManager,User,StorageBackend,Slot;
 
	---  [ label = "Available presence received"];
 
	Component->UserManager [label="handlePresence(...)", URL="\ref UserManager::handlePresence()"];
 
	UserManager->StorageBackend [label="getUser(...)", URL="\ref StorageBackend::getUser()"];
 
	UserManager->User [label="User::User(...)", URL="\ref User"];
 
	UserManager->Slot [label="onUserCreated(...)", URL="\ref UserManager::onUserCreated()"];
 
	UserManager->User [label="handlePresence(...)", URL="\ref User::handlePresence()"];
 
	\endmsc
 
*/
 
class UserManager : public Swift::EntityCapsProvider {
 
class UserManager /*: public Swift::EntityCapsProvider*/ {
 
	public:
 
		/// Creates new UserManager.
 
		/// \param component Component which's presence will be handled
 
		/// \param storageBackend Storage backend used to fetch UserInfos
 
		UserManager(Component *component, UserRegistry *userRegistry, DiscoItemsResponder *discoItemsResponder, StorageBackend *storageBackend = NULL);
 
		UserManager(Component *component, UserRegistry *userRegistry, StorageBackend *storageBackend = NULL);
 

	
 
		/// Destroys UserManager.
 
		~UserManager();
 
		virtual ~UserManager();
 

	
 
		virtual void sendVCard(unsigned int id, Swift::VCard::ref vcard) = 0;
 

	
 
		virtual UserRegistration *getUserRegistration() = 0;
 

	
 
		/// Returns user according to his bare JID.
 
		/// \param barejid bare JID of user
 
		/// \return User class associated with this user
 
		User *getUser(const std::string &barejid);
 

	
 
		/// Returns map with all connected users.
 
		/// \return All connected users.
 
		const std::map<std::string, User *> &getUsers() {
 
			return m_users;
 
		}
 

	
 
		/// Returns number of online users.
 
		/// \return number of online users
 
		int getUserCount();
 

	
 
		/// Removes user. This function disconnects user and safely removes
 
		/// User class. This does *not* remove user from StorageBackend.
 
		/// \param user User class to remove
 
		void removeUser(User *user, bool onUserBehalf = true);
 

	
 
		void removeAllUsers(bool onUserBehalf = true);
 

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

	
 
		DiscoItemsResponder *getDiscoResponder() { return m_discoItemsResponder; }
 
// 		Swift::DiscoInfo::ref getCaps(const Swift::JID&) const;
 

	
 
		/// Called when new User class is created.
 
		/// \param user newly created User class
 
		boost::signal<void (User *user)> onUserCreated;
 

	
 
		/// Called when User class is going to be removed
 
		/// \param user removed User class
 
		boost::signal<void (User *user)> onUserDestroyed;
 

	
 
		/// Returns true if user is connected.
 
		/// \return True if user is connected.
 
		bool isUserConnected(const std::string &barejid) const {
 
@@ -143,17 +146,16 @@ class UserManager : public Swift::EntityCapsProvider {
 
		void addUser(User *user);
 

	
 
		long m_onlineBuddies;
 
		User *m_cachedUser;
 
		std::map<std::string, User *> m_users;
 
		Component *m_component;
 
		StorageBackend *m_storageBackend;
 
		StorageResponder *m_storageResponder;
 
		UserRegistry *m_userRegistry;
 
		Swift::Timer::ref m_removeTimer;
 
		unsigned long m_sentToXMPP;
 
		unsigned long m_sentToBackend;
 
		DiscoItemsResponder *m_discoItemsResponder;
 
		friend class RosterResponder;
 
};
 

	
 
}
include/transport/userregistration.h
Show inline comments
 
@@ -27,63 +27,66 @@
 
#include <Swiften/Version.h>
 
#define HAVE_SWIFTEN_3  (SWIFTEN_VERSION >= 0x030000)
 

	
 
namespace Transport {
 

	
 
struct UserInfo;
 
class Component;
 
class StorageBackend;
 
class UserManager;
 
class Config;
 

	
 
/// Allows users to register the transport using service discovery.
 
class UserRegistration : public Swift::Responder<Swift::InBandRegistrationPayload> {
 
class UserRegistration {
 
	public:
 
		/// Creates new UserRegistration handler.
 
		/// \param component Component associated with this class
 
		/// \param userManager UserManager associated with this class
 
		/// \param storageBackend StorageBackend where the registered users will be stored
 
		UserRegistration(Component *component, UserManager *userManager, StorageBackend *storageBackend);
 

	
 
		/// Destroys UserRegistration.
 
		~UserRegistration();
 
		virtual ~UserRegistration();
 

	
 
		/// Registers new user. This function stores user into database and subscribe user to transport.
 
		/// \param userInfo UserInfo struct with informations about registered user
 
		/// \return false if user is already registered
 
		bool registerUser(const UserInfo &userInfo);
 

	
 
		/// Unregisters user. This function removes all data about user from databa, unsubscribe all buddies
 
		/// managed by this transport and disconnects user if he's connected.
 
		/// \param barejid bare JID of user to unregister
 
		/// \return false if there is no such user registered
 
		bool unregisterUser(const std::string &barejid);
 

	
 
		/// Registers new user. This function stores user into database and subscribe user to transport.
 
		/// \param userInfo UserInfo struct with informations about registered user
 
		/// \return false if user is already registered
 
		virtual bool doUserRegistration(const UserInfo &userInfo) = 0;
 

	
 
		/// Unregisters user. This function removes all data about user from databa, unsubscribe all buddies
 
		/// managed by this transport and disconnects user if he's connected.
 
		/// \param barejid bare JID of user to unregister
 
		/// \return false if there is no such user registered
 
		virtual bool doUserUnregistration(const UserInfo &userInfo) = 0;
 

	
 
		/// Called when new user has been registered.
 
		/// \param userInfo UserInfo struct with informations about user
 
		boost::signal<void (const UserInfo &userInfo)> onUserRegistered;
 

	
 
		/// Called when user has been unregistered.
 
		/// \param userInfo UserInfo struct with informations about user
 
		boost::signal<void (const UserInfo &userInfo)> onUserUnregistered;
 

	
 
		/// Called when user's registration has been updated.
 
		/// \param userInfo UserInfo struct with informations about user
 
		boost::signal<void (const UserInfo &userInfo)> onUserUpdated;
 

	
 
	private:
 
		virtual bool handleGetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr<Swift::InBandRegistrationPayload> payload);
 
		virtual bool handleSetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr<Swift::InBandRegistrationPayload> payload);
 

	
 
		void handleRegisterRemoteRosterResponse(boost::shared_ptr<Swift::RosterPayload> payload, Swift::ErrorPayload::ref error, const UserInfo &row);
 
		void handleUnregisterRemoteRosterResponse(boost::shared_ptr<Swift::RosterPayload> payload, Swift::ErrorPayload::ref error, const std::string &barejid);
 
		boost::shared_ptr<Swift::InBandRegistrationPayload> generateInBandRegistrationPayload(const Swift::JID& from);
 
		Swift::Form::ref generateRegistrationForm(const UserInfo &res, bool registered);
 
		
 
		Component *m_component;
 
		StorageBackend *m_storageBackend;
 
		UserManager *m_userManager;
 
		Config *m_config;
 

	
 
};
 

	
 
}
spectrum/src/CMakeLists.txt
Show inline comments
 
cmake_minimum_required(VERSION 2.6)
 
FILE(GLOB SRC *.cpp)
 
FILE(GLOB_RECURSE SRC frontends/*.cpp main.cpp)
 
include_directories(frontends/xmpp)
 

	
 
if (WIN32)
 
FILE(GLOB WIN_SRC win32/*.cpp)
 
include_directories(win32)
 
include_directories("${CMAKE_SOURCE_DIR}/msvc-deps/sqlite3")
 
ADD_EXECUTABLE(spectrum2 ${SRC} ${WIN_SRC})
 
else()
 
ADD_EXECUTABLE(spectrum2 ${SRC})
 
endif()
 

	
 

	
 

	
spectrum/src/frontends/xmpp/BlockParser.cpp
Show inline comments
 
file renamed from src/BlockParser.cpp to spectrum/src/frontends/xmpp/BlockParser.cpp
 
/*
 
 * Copyright (c) 2011 Jan Kaluza
 
 * Licensed under the Simplified BSD license.
 
 * See Documentation/Licenses/BSD-simplified.txt for more information.
 
 */
 

	
 
#include <transport/BlockParser.h>
 
#include <BlockParser.h>
 

	
 
namespace Transport {
 

	
 
// This payload is NOT part of ANY XEP and it is only
 
// libtransport related extension.
 
BlockParser::BlockParser() /*: level_(0)*/ {
 
}
 

	
 
void BlockParser::handleStartElement(const std::string& /*element*/, const std::string& /*ns*/, const Swift::AttributeMap& /*attributes*/) {
 
}
 

	
 
void BlockParser::handleEndElement(const std::string&, const std::string&) {
spectrum/src/frontends/xmpp/BlockParser.h
Show inline comments
 
file renamed from include/transport/BlockParser.h to spectrum/src/frontends/xmpp/BlockParser.h
 
/*
 
 * Copyright (c) 2011 Jan Kaluza
 
 * Licensed under the Simplified BSD license.
 
 * See Documentation/Licenses/BSD-simplified.txt for more information.
 
 */
 

	
 
#pragma once
 

	
 
#include <transport/BlockPayload.h>
 
#include <BlockPayload.h>
 
#include <Swiften/Parser/GenericPayloadParser.h>
 

	
 
// This payload is NOT part of ANY XEP and it is only
 
// libtransport related extension.
 
namespace Transport {
 
	class BlockParser : public Swift::GenericPayloadParser<BlockPayload> {
 
		public:
 
			BlockParser();
 

	
 
			virtual void handleStartElement(const std::string& element, const std::string&, const Swift::AttributeMap& attributes);
 
			virtual void handleEndElement(const std::string& element, const std::string&);
 
			virtual void handleCharacterData(const std::string& data);
spectrum/src/frontends/xmpp/BlockPayload.cpp
Show inline comments
 
file renamed from src/BlockPayload.cpp to spectrum/src/frontends/xmpp/BlockPayload.cpp
 
/*
 
 * Copyright (c) 2011 Jan Kaluza
 
 * Licensed under the Simplified BSD license.
 
 * See Documentation/Licenses/BSD-simplified.txt for more information.
 
 */
 

	
 
#include <transport/BlockPayload.h>
 
#include <BlockPayload.h>
 

	
 
namespace Transport {
 

	
 
// This payload is NOT part of ANY XEP and it is only
 
// libtransport related extension.
 
BlockPayload::BlockPayload() {
 
	
 
}
 

	
 
}
spectrum/src/frontends/xmpp/BlockPayload.h
Show inline comments
 
file renamed from include/transport/BlockPayload.h to spectrum/src/frontends/xmpp/BlockPayload.h
spectrum/src/frontends/xmpp/BlockSerializer.cpp
Show inline comments
 
file renamed from src/BlockSerializer.cpp to spectrum/src/frontends/xmpp/BlockSerializer.cpp
 
/*
 
 * Copyright (c) 2011 Jan Kaluza
 
 * Licensed under the Simplified BSD license.
 
 * See Documentation/Licenses/BSD-simplified.txt for more information.
 
 */
 

	
 
#include <transport/BlockSerializer.h>
 
#include <BlockSerializer.h>
 

	
 
#include <boost/shared_ptr.hpp>
 

	
 
#include <Swiften/Serializer/XML/XMLTextNode.h>
 
#include <Swiften/Serializer/XML/XMLRawTextNode.h>
 
#include <Swiften/Serializer/XML/XMLElement.h>
 

	
 
namespace Transport {
 

	
 
// This payload is NOT part of ANY XEP and it is only
 
// libtransport related extension.
 
BlockSerializer::BlockSerializer() : Swift::GenericPayloadSerializer<BlockPayload>() {
spectrum/src/frontends/xmpp/BlockSerializer.h
Show inline comments
 
file renamed from include/transport/BlockSerializer.h to spectrum/src/frontends/xmpp/BlockSerializer.h
 
/*
 
 * Copyright (c) 2011 Jan Kaluza
 
 * Licensed under the Simplified BSD license.
 
 * See Documentation/Licenses/BSD-simplified.txt for more information.
 
 */
 

	
 
#pragma once
 

	
 
#include <Swiften/Serializer/GenericPayloadSerializer.h>
 
#include <transport/BlockPayload.h>
 
#include <BlockPayload.h>
 

	
 
// This payload is NOT part of ANY XEP and it is only
 
// libtransport related extension.
 
namespace Transport {
 
	class BlockSerializer : public Swift::GenericPayloadSerializer<BlockPayload> {
 
		public:
 
			BlockSerializer();
 

	
 
			virtual std::string serializePayload(boost::shared_ptr<BlockPayload>)  const;
 
	};
 
}
spectrum/src/frontends/xmpp/XMPPFrontend.cpp
Show inline comments
 
new file 100644
 
/**
 
 * libtransport -- C++ library for easy XMPP Transports development
 
 *
 
 * Copyright (C) 2011, Jan Kaluza <hanzz.k@gmail.com>
 
 *
 
 * 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 "XMPPFrontend.h"
 
#include "XMPPRosterManager.h"
 
#include "XMPPUser.h"
 
#include "XMPPUserManager.h"
 
#include "transport/storagebackend.h"
 
#include <boost/bind.hpp>
 
#include <boost/smart_ptr/make_shared.hpp>
 
#include <boost/algorithm/string/predicate.hpp>
 
#include "transport/storagebackend.h"
 
#include "transport/factory.h"
 
#include "transport/userregistry.h"
 
#include "transport/logging.h"
 
#include "transport/config.h"
 
#include "discoitemsresponder.h"
 
#include "storageparser.h"
 
#ifdef _WIN32
 
#include <Swiften/TLS/CAPICertificate.h>
 
#include "Swiften/TLS/Schannel/SchannelServerContext.h"
 
#include "Swiften/TLS/Schannel/SchannelServerContextFactory.h"
 
#else
 
#include "Swiften/TLS/PKCS12Certificate.h"
 
#include "Swiften/TLS/CertificateWithKey.h"
 
#include "Swiften/TLS/OpenSSL/OpenSSLServerContext.h"
 
#include "Swiften/TLS/OpenSSL/OpenSSLServerContextFactory.h"
 
#endif
 
#include "Swiften/Parser/PayloadParsers/AttentionParser.h"
 
#include "Swiften/Serializer/PayloadSerializers/AttentionSerializer.h"
 
#include "Swiften/Parser/PayloadParsers/XHTMLIMParser.h"
 
#include "Swiften/Serializer/PayloadSerializers/XHTMLIMSerializer.h"
 
#include "Swiften/Parser/PayloadParsers/StatsParser.h"
 
#include "Swiften/Serializer/PayloadSerializers/StatsSerializer.h"
 
#include "Swiften/Parser/PayloadParsers/GatewayPayloadParser.h"
 
#include "Swiften/Serializer/PayloadSerializers/GatewayPayloadSerializer.h"
 
#include "Swiften/Serializer/PayloadSerializers/SpectrumErrorSerializer.h"
 
#include "Swiften/Parser/PayloadParsers/MUCPayloadParser.h"
 
#include "BlockParser.h"
 
#include "BlockSerializer.h"
 
#include "Swiften/Parser/PayloadParsers/InvisibleParser.h"
 
#include "Swiften/Serializer/PayloadSerializers/InvisibleSerializer.h"
 
#include "Swiften/Parser/GenericPayloadParserFactory.h"
 
#include "Swiften/Queries/IQRouter.h"
 
#include "Swiften/Elements/RosterPayload.h"
 
#include "Swiften/Elements/InBandRegistrationPayload.h"
 

	
 
using namespace Swift;
 
using namespace boost;
 

	
 
namespace Transport {
 
	
 
DEFINE_LOGGER(logger, "XMPPFrontend");
 

	
 
XMPPFrontend::XMPPFrontend() {
 
}
 

	
 
void XMPPFrontend::init(Component *transport, Swift::EventLoop *loop, Swift::NetworkFactories *factories, Config *config, Transport::UserRegistry *userRegistry) {
 
	m_transport = transport;
 
	m_component = NULL;
 
	m_server = NULL;
 
	m_rawXML = false;
 
	m_config = transport->getConfig();
 
	m_jid = Swift::JID(CONFIG_STRING(m_config, "service.jid"));
 

	
 
	m_config->onBackendConfigUpdated.connect(boost::bind(&XMPPFrontend::handleBackendConfigChanged, this));
 

	
 
	if (CONFIG_BOOL(m_config, "service.server_mode")) {
 
		LOG4CXX_INFO(logger, "Creating component in server mode on port " << CONFIG_INT(m_config, "service.port"));
 
		m_server = new Swift::Server(loop, factories, userRegistry, m_jid, CONFIG_STRING(m_config, "service.server"), CONFIG_INT(m_config, "service.port"));
 
		if (!CONFIG_STRING(m_config, "service.cert").empty()) {
 
#ifndef _WIN32
 
//TODO: fix
 
			LOG4CXX_INFO(logger, "Using PKCS#12 certificate " << CONFIG_STRING(m_config, "service.cert"));
 
			LOG4CXX_INFO(logger, "SSLv23_server_method used.");
 
			TLSServerContextFactory *f = new OpenSSLServerContextFactory();
 
			CertificateWithKey::ref certificate = boost::make_shared<PKCS12Certificate>(CONFIG_STRING(m_config, "service.cert"), createSafeByteArray(CONFIG_STRING(m_config, "service.cert_password")));
 
			m_server->addTLSEncryption(f, certificate);
 
#endif
 
			
 
		}
 
		else {
 
			LOG4CXX_WARN(logger, "No PKCS#12 certificate used. TLS is disabled.");
 
		}
 
// 		m_server->start();
 
		m_stanzaChannel = m_server->getStanzaChannel();
 
		m_iqRouter = m_server->getIQRouter();
 

	
 
		m_server->addPayloadParserFactory(new GenericPayloadParserFactory<StorageParser>("private", "jabber:iq:private"));
 
		m_server->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::AttentionParser>("attention", "urn:xmpp:attention:0"));
 
		m_server->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::XHTMLIMParser>("html", "http://jabber.org/protocol/xhtml-im"));
 
		m_server->addPayloadParserFactory(new GenericPayloadParserFactory<Transport::BlockParser>("block", "urn:xmpp:block:0"));
 
		m_server->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::InvisibleParser>("invisible", "urn:xmpp:invisible:0"));
 
		m_server->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::StatsParser>("query", "http://jabber.org/protocol/stats"));
 
		m_server->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::GatewayPayloadParser>("query", "jabber:iq:gateway"));
 
		m_server->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::MUCPayloadParser>("x", "http://jabber.org/protocol/muc"));
 

	
 
		m_server->addPayloadSerializer(new Swift::AttentionSerializer());
 
		m_server->addPayloadSerializer(new Swift::XHTMLIMSerializer());
 
		m_server->addPayloadSerializer(new Transport::BlockSerializer());
 
		m_server->addPayloadSerializer(new Swift::InvisibleSerializer());
 
		m_server->addPayloadSerializer(new Swift::StatsSerializer());
 
		m_server->addPayloadSerializer(new Swift::SpectrumErrorSerializer());
 
		m_server->addPayloadSerializer(new Swift::GatewayPayloadSerializer());
 

	
 
		m_server->onDataRead.connect(boost::bind(&XMPPFrontend::handleDataRead, this, _1));
 
		m_server->onDataWritten.connect(boost::bind(&XMPPFrontend::handleDataWritten, this, _1));
 
	}
 
	else {
 
		LOG4CXX_INFO(logger, "Creating component in gateway mode");
 
#if HAVE_SWIFTEN_3
 
		m_component = new Swift::Component(m_jid, CONFIG_STRING(m_config, "service.password"), factories);
 
#else
 
		m_component = new Swift::Component(loop, factories, m_jid, CONFIG_STRING(m_config, "service.password"));
 
#endif
 
		m_component->setSoftwareVersion("Spectrum", SPECTRUM_VERSION);
 
		m_component->onConnected.connect(bind(&XMPPFrontend::handleConnected, this));
 
		m_component->onError.connect(boost::bind(&XMPPFrontend::handleConnectionError, this, _1));
 
		m_component->onDataRead.connect(boost::bind(&XMPPFrontend::handleDataRead, this, _1));
 
		m_component->onDataWritten.connect(boost::bind(&XMPPFrontend::handleDataWritten, this, _1));
 

	
 
		m_component->addPayloadParserFactory(new GenericPayloadParserFactory<StorageParser>("private", "jabber:iq:private"));
 
		m_component->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::AttentionParser>("attention", "urn:xmpp:attention:0"));
 
		m_component->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::XHTMLIMParser>("html", "http://jabber.org/protocol/xhtml-im"));
 
		m_component->addPayloadParserFactory(new GenericPayloadParserFactory<Transport::BlockParser>("block", "urn:xmpp:block:0"));
 
		m_component->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::InvisibleParser>("invisible", "urn:xmpp:invisible:0"));
 
		m_component->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::StatsParser>("query", "http://jabber.org/protocol/stats"));
 
		m_component->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::GatewayPayloadParser>("query", "jabber:iq:gateway"));
 
		m_component->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::MUCPayloadParser>("x", "http://jabber.org/protocol/muc"));
 

	
 
		m_component->addPayloadSerializer(new Swift::AttentionSerializer());
 
		m_component->addPayloadSerializer(new Swift::XHTMLIMSerializer());
 
		m_component->addPayloadSerializer(new Transport::BlockSerializer());
 
		m_component->addPayloadSerializer(new Swift::InvisibleSerializer());
 
		m_component->addPayloadSerializer(new Swift::StatsSerializer());
 
		m_component->addPayloadSerializer(new Swift::SpectrumErrorSerializer());
 
		m_component->addPayloadSerializer(new Swift::GatewayPayloadSerializer());
 

	
 
		m_stanzaChannel = m_component->getStanzaChannel();
 
		m_iqRouter = m_component->getIQRouter();
 
	}
 

	
 
	m_capsMemoryStorage = new CapsMemoryStorage();
 
#if HAVE_SWIFTEN_3
 
	m_capsManager = new CapsManager(m_capsMemoryStorage, m_stanzaChannel, m_iqRouter, factories->getCryptoProvider());
 
#else
 
	m_capsManager = new CapsManager(m_capsMemoryStorage, m_stanzaChannel, m_iqRouter);
 
#endif
 
	m_entityCapsManager = new EntityCapsManager(m_capsManager, m_stanzaChannel);
 
	m_entityCapsManager->onCapsChanged.connect(boost::bind(&XMPPFrontend::handleCapsChanged, this, _1));
 

	
 
	m_stanzaChannel->onPresenceReceived.connect(bind(&XMPPFrontend::handleGeneralPresence, this, _1));
 
	m_stanzaChannel->onMessageReceived.connect(bind(&XMPPFrontend::handleMessage, this, _1));
 

	
 
	m_discoItemsResponder = new DiscoItemsResponder(transport);
 
	m_discoItemsResponder->start();
 
}
 

	
 
XMPPFrontend::~XMPPFrontend() {
 
	delete m_entityCapsManager;
 
	delete m_capsManager;
 
	delete m_capsMemoryStorage;
 
	if (m_component)
 
		delete m_component;
 
	if (m_server) {
 
		m_server->stop();
 
		delete m_server;
 
	}
 
}
 

	
 
void XMPPFrontend::handleGeneralPresence(Swift::Presence::ref presence) {
 
	onPresenceReceived(presence);
 
}
 

	
 
void XMPPFrontend::handleMessage(boost::shared_ptr<Swift::Message> message) {
 
	onMessageReceived(message);
 
}
 

	
 

	
 
void XMPPFrontend::clearRoomList() {
 
	m_discoItemsResponder->clearRooms();
 
}
 

	
 
void XMPPFrontend::addRoomToRoomList(const std::string &handle, const std::string &name) {
 
	m_discoItemsResponder->addRoom(handle, name);
 
}
 

	
 
void XMPPFrontend::sendPresence(Swift::Presence::ref presence) {
 
	if (!presence->getFrom().getNode().empty()) {
 
		presence->addPayload(boost::shared_ptr<Swift::Payload>(new Swift::CapsInfo(m_discoItemsResponder->getBuddyCapsInfo())));
 
	}
 

	
 
	m_stanzaChannel->sendPresence(presence);
 
}
 

	
 
void XMPPFrontend::sendVCard(Swift::VCard::ref vcard, Swift::JID to) {
 
	boost::shared_ptr<Swift::GenericRequest<Swift::VCard> > request(new Swift::GenericRequest<Swift::VCard>(Swift::IQ::Result, to, vcard, m_iqRouter));
 
	request->send();
 
}
 

	
 
void XMPPFrontend::sendRosterRequest(Swift::RosterPayload::ref payload, Swift::JID to) {
 
	Swift::SetRosterRequest::ref request = Swift::SetRosterRequest::create(payload, to, m_iqRouter);
 
	request->send();
 
}
 

	
 
void XMPPFrontend::sendMessage(boost::shared_ptr<Swift::Message> message) {
 
	m_stanzaChannel->sendMessage(message);
 
}
 

	
 
void XMPPFrontend::sendIQ(boost::shared_ptr<Swift::IQ> iq) {
 
	m_iqRouter->sendIQ(iq);
 
}
 

	
 
boost::shared_ptr<Swift::DiscoInfo> XMPPFrontend::sendCapabilitiesRequest(Swift::JID to) {
 
	Swift::DiscoInfo::ref caps = m_entityCapsManager->getCaps(to);
 
	if (caps != Swift::DiscoInfo::ref()) {
 
		onCapabilitiesReceived(to, caps);
 
		return caps;
 
	}
 
#ifdef SUPPORT_LEGACY_CAPS
 
	else {
 
		GetDiscoInfoRequest::ref discoInfoRequest = GetDiscoInfoRequest::create(to, m_iqRouter);
 
		discoInfoRequest->onResponse.connect(boost::bind(&XMPPFrontend::handleDiscoInfoResponse, this, _1, _2, to));
 
		discoInfoRequest->send();
 
	}
 
#endif
 

	
 
	return Swift::DiscoInfo::ref();
 
}
 

	
 
void XMPPFrontend::reconnectUser(const std::string &user) {
 
	LOG4CXX_INFO(logger, "Sending probe presence to " << user);
 
	Swift::Presence::ref response = Swift::Presence::create();
 
	try {
 
		response->setTo(user);
 
	}
 
	catch (...) { return; }
 
	
 
	response->setFrom(m_component->getJID());
 
	response->setType(Swift::Presence::Probe);
 

	
 
	m_stanzaChannel->sendPresence(response);
 
}
 

	
 
RosterManager *XMPPFrontend::createRosterManager(User *user, Component *component) {
 
	return new XMPPRosterManager(user, component);
 
}
 

	
 
User *XMPPFrontend::createUser(const Swift::JID &jid, UserInfo &userInfo, Component *component, UserManager *userManager) {
 
	return new XMPPUser(jid, userInfo, component, userManager);
 
}
 

	
 
UserManager *XMPPFrontend::createUserManager(Component *component, UserRegistry *userRegistry, StorageBackend *storageBackend) {
 
	return new XMPPUserManager(component, userRegistry, storageBackend);
 
}
 

	
 
bool XMPPFrontend::handleIQ(boost::shared_ptr<Swift::IQ> iq) {
 
	if (!m_rawXML) {
 
		return false;
 
	}
 

	
 
	if (iq->getPayload<Swift::RosterPayload>() != NULL) { return false; }
 
	if (iq->getPayload<Swift::InBandRegistrationPayload>() != NULL) { return false; }
 
	if (iq->getPayload<Swift::StatsPayload>() != NULL) { return false; }
 

	
 
	if (iq->getTo().getNode().empty()) {
 
		return false;
 
	}
 

	
 
	m_transport->onRawIQReceived(iq);
 
	return true;
 
}
 

	
 
void XMPPFrontend::handleBackendConfigChanged() {
 
	if (!m_rawXML && CONFIG_BOOL_DEFAULTED(m_config, "features.rawxml", false)) {
 
		m_rawXML = true;
 
		m_iqRouter->addHandler(this);
 
	}
 
}
 

	
 
Swift::StanzaChannel *XMPPFrontend::getStanzaChannel() {
 
	return m_stanzaChannel;
 
}
 

	
 
void XMPPFrontend::connectToServer() {
 
	if (m_component && !m_component->isAvailable()) {
 
		LOG4CXX_INFO(logger, "Connecting XMPP server " << CONFIG_STRING(m_config, "service.server") << " port " << CONFIG_INT(m_config, "service.port"));
 
		if (CONFIG_INT(m_config, "service.port") == 5222) {
 
			LOG4CXX_WARN(logger, "Port 5222 is usually used for client connections, not for component connections! Are you sure you are using right port?");
 
		}
 
		m_component->connect(CONFIG_STRING(m_config, "service.server"), CONFIG_INT(m_config, "service.port"));
 
	}
 
	else if (m_server) {
 
		LOG4CXX_INFO(logger, "Starting XMPPFrontend in server mode on port " << CONFIG_INT(m_config, "service.port"));
 
		m_server->start();
 

	
 
		//Type casting to BoostConnectionServer since onStopped signal is not defined in ConnectionServer
 
		//Ideally, onStopped must be defined in ConnectionServer
 
		if (boost::dynamic_pointer_cast<Swift::BoostConnectionServer>(m_server->getConnectionServer())) {
 
			boost::dynamic_pointer_cast<Swift::BoostConnectionServer>(m_server->getConnectionServer())->onStopped.connect(boost::bind(&XMPPFrontend::handleServerStopped, this, _1));
 
		}
 
		
 
		// We're connected right here, because we're in server mode...
 
		handleConnected();
 
	}
 
}
 

	
 
void XMPPFrontend::disconnectFromServer() {
 
	if (m_component) {
 
		// TODO: Call this once swiften will fix assert(!session_);
 
// 		m_component->disconnect();
 
	}
 
	else if (m_server) {
 
		LOG4CXX_INFO(logger, "Stopping component in server mode on port " << CONFIG_INT(m_config, "service.port"));
 
		m_server->stop();
 
	}
 
}
 

	
 
void XMPPFrontend::handleConnected() {
 
	m_transport->handleConnected();
 
}
 

	
 
void XMPPFrontend::handleServerStopped(boost::optional<Swift::BoostConnectionServer::Error> e) {
 
	if(e != NULL ) {
 
		if(*e == Swift::BoostConnectionServer::Conflict) {
 
			LOG4CXX_INFO(logger, "Port "<< CONFIG_INT(m_config, "service.port") << " already in use! Stopping server..");
 
			if (CONFIG_INT(m_config, "service.port") == 5347) {
 
				LOG4CXX_INFO(logger, "Port 5347 is usually used for components. You are using server_mode=1. Are you sure you don't want to use server_mode=0 and run spectrum as component?");
 
			}
 
		}
 
		if(*e == Swift::BoostConnectionServer::UnknownError)
 
			LOG4CXX_INFO(logger, "Unknown error occured! Stopping server..");
 
		exit(1);
 
	}
 
}
 

	
 

	
 
void XMPPFrontend::handleConnectionError(const ComponentError &error) {
 
	std::string str = "Unknown error";
 
	switch (error.getType()) {
 
		case ComponentError::UnknownError: str = "Unknown error"; break;
 
		case ComponentError::ConnectionError: str = "Connection error"; break;
 
		case ComponentError::ConnectionReadError: str = "Connection read error"; break;
 
		case ComponentError::ConnectionWriteError: str = "Connection write error"; break;
 
		case ComponentError::XMLError: str = "XML Error"; break;
 
		case ComponentError::AuthenticationFailedError: str = "Authentication failed error"; break;
 
		case ComponentError::UnexpectedElementError: str = "Unexpected element error"; break;
 
	}
 

	
 
	m_transport->handleConnectionError(str);
 
}
 

	
 
void XMPPFrontend::handleDataRead(const Swift::SafeByteArray &data) {
 
	std::string d = safeByteArrayToString(data);
 
	m_transport->handleDataRead(d);
 
}
 

	
 
void XMPPFrontend::handleDataWritten(const Swift::SafeByteArray &data) {
 
	std::string d = safeByteArrayToString(data);
 
	m_transport->handleDataWritten(d);
 
}
 

	
 
void XMPPFrontend::handleDiscoInfoResponse(boost::shared_ptr<Swift::DiscoInfo> info, Swift::ErrorPayload::ref error, const Swift::JID& jid) {
 
#ifdef SUPPORT_LEGACY_CAPS
 
	onCapabilitiesReceived(jid, info);
 
#endif
 
}
 

	
 
void XMPPFrontend::handleCapsChanged(const Swift::JID& jid) {
 
	onCapabilitiesReceived(jid, m_entityCapsManager->getCaps(jid));
 
}
 

	
 
}
spectrum/src/frontends/xmpp/XMPPFrontend.h
Show inline comments
 
new file 100644
 
/**
 
 * libtransport -- C++ library for easy XMPP Transports development
 
 *
 
 * Copyright (C) 2011, Jan Kaluza <hanzz.k@gmail.com>
 
 *
 
 * 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
 
 */
 

	
 
#pragma once
 

	
 
#include <vector>
 
#include "transport/frontend.h"
 
#include "Swiften/Server/Server.h"
 
#include "Swiften/Disco/GetDiscoInfoRequest.h"
 
#include "Swiften/Disco/EntityCapsManager.h"
 
#include "Swiften/Disco/CapsManager.h"
 
#include "Swiften/Disco/CapsMemoryStorage.h"
 
#include "Swiften/Network/BoostTimerFactory.h"
 
#include "Swiften/Network/BoostIOServiceThread.h"
 
#include "Swiften/Server/UserRegistry.h"
 
#include "Swiften/Base/SafeByteArray.h"
 
#include "Swiften/Queries/IQHandler.h"
 
#include "Swiften/Component/ComponentError.h"
 
#include "Swiften/Component/Component.h"
 
#include "Swiften/Queries/IQHandler.h"
 
#include "Swiften/Elements/Presence.h"
 

	
 
#include <boost/bind.hpp>
 
#include <Swiften/Network/BoostConnectionServer.h>
 

	
 
namespace Transport {
 
	class UserRegistry;
 
	class Frontend;
 
	class Config;
 
	class DiscoItemsResponder;
 
	class VCardResponder;
 

	
 
	class XMPPFrontend : public Frontend, Swift::IQHandler {
 
		public:
 
			XMPPFrontend();
 

	
 
			virtual ~XMPPFrontend();
 

	
 
			virtual void init(Component *component, Swift::EventLoop *loop, Swift::NetworkFactories *factories, Config *config, UserRegistry *userRegistry);
 

	
 
			virtual void connectToServer();
 

	
 
			virtual void disconnectFromServer();
 

	
 
			virtual void sendPresence(Swift::Presence::ref presence);
 

	
 
			virtual void sendVCard(Swift::VCard::ref vcard, Swift::JID to);
 

	
 
			virtual void sendRosterRequest(Swift::RosterPayload::ref, Swift::JID to);
 

	
 
			virtual void sendMessage(boost::shared_ptr<Swift::Message> message);
 

	
 
			virtual void sendIQ(boost::shared_ptr<Swift::IQ>);
 

	
 
			virtual void reconnectUser(const std::string &user);
 

	
 
			virtual RosterManager *createRosterManager(User *user, Component *component);
 
			virtual User *createUser(const Swift::JID &jid, UserInfo &userInfo, Component *component, UserManager *userManager);
 
			virtual UserManager *createUserManager(Component *component, UserRegistry *userRegistry, StorageBackend *storageBackend = NULL);
 
			virtual boost::shared_ptr<Swift::DiscoInfo> sendCapabilitiesRequest(Swift::JID to);
 
			virtual void clearRoomList();
 
			virtual void addRoomToRoomList(const std::string &handle, const std::string &name);
 
		
 
			void handleMessage(boost::shared_ptr<Swift::Message> message);
 

	
 

	
 
			Swift::StanzaChannel *getStanzaChannel();
 

	
 
			Swift::IQRouter *getIQRouter() { return m_iqRouter; }
 

	
 

	
 
			bool inServerMode() { return m_server != NULL; }
 

	
 
			bool isRawXMLEnabled() {
 
				return m_rawXML;
 
			}
 

	
 
			DiscoItemsResponder *getDiscoItemsResponder() {
 
				return m_discoItemsResponder;
 
			}
 

	
 
		private:
 
			void handleConnected();
 
			void handleConnectionError(const Swift::ComponentError &error);
 
			void handleServerStopped(boost::optional<Swift::BoostConnectionServer::Error> e);
 
			void handleGeneralPresence(Swift::Presence::ref presence);
 
			void handleDataRead(const Swift::SafeByteArray &data);
 
			void handleDataWritten(const Swift::SafeByteArray &data);
 

	
 
			void handleDiscoInfoResponse(boost::shared_ptr<Swift::DiscoInfo> info, Swift::ErrorPayload::ref error, const Swift::JID& jid);
 
			void handleCapsChanged(const Swift::JID& jid);
 

	
 
			void handleBackendConfigChanged();
 
			bool handleIQ(boost::shared_ptr<Swift::IQ>);
 

	
 
			Swift::NetworkFactories *m_factories;
 
			Swift::Component *m_component;
 
			Swift::Server *m_server;
 
			Swift::EntityCapsManager *m_entityCapsManager;
 
			Swift::CapsManager *m_capsManager;
 
			Swift::CapsMemoryStorage *m_capsMemoryStorage;
 
			Swift::StanzaChannel *m_stanzaChannel;
 
			Swift::IQRouter *m_iqRouter;
 
			DiscoItemsResponder *m_discoItemsResponder;
 
			VCardResponder *m_vcardResponder;
 
			
 
			Config* m_config;
 
			Swift::JID m_jid;
 
			bool m_rawXML;
 
			Component *m_transport;
 

	
 
		friend class XMPPUser;
 
		friend class UserRegistration;
 
		friend class NetworkPluginServer;
 
	};
 
}
spectrum/src/frontends/xmpp/XMPPRosterManager.cpp
Show inline comments
 
new file 100644
 
/**
 
 * XMPP - libpurple transport
 
 *
 
 * Copyright (C) 2009, Jan Kaluza <hanzz@soc.pidgin.im>
 
 *
 
 * 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 "XMPPRosterManager.h"
 
#include "XMPPFrontend.h"
 
#include "XMPPUser.h"
 
#include "transport/rostermanager.h"
 
#include "transport/rosterstorage.h"
 
#include "transport/storagebackend.h"
 
#include "transport/buddy.h"
 
#include "transport/usermanager.h"
 
#include "transport/buddy.h"
 
#include "transport/user.h"
 
#include "transport/logging.h"
 
#include "transport/factory.h"
 
#include "transport/presenceoracle.h"
 
#include "Swiften/Roster/SetRosterRequest.h"
 
#include "Swiften/Elements/RosterPayload.h"
 
#include "Swiften/Elements/RosterItemPayload.h"
 
#include "Swiften/Elements/RosterItemExchangePayload.h"
 
#include "Swiften/Elements/Nickname.h"
 
#include "Swiften/Queries/IQRouter.h"
 
#include <boost/foreach.hpp>
 
#include <boost/make_shared.hpp>
 

	
 
#include <map>
 
#include <iterator>
 

	
 
namespace Transport {
 

	
 
DEFINE_LOGGER(logger, "XMPPRosterManager");
 

	
 
XMPPRosterManager::XMPPRosterManager(User *user, Component *component) : RosterManager(user, component){
 
	m_user = user;
 
	m_component = component;
 

	
 
	m_supportRemoteRoster = false;
 
	m_RIETimer = m_component->getNetworkFactories()->getTimerFactory()->createTimer(5000);
 
	m_RIETimer->onTick.connect(boost::bind(&XMPPRosterManager::sendRIE, this));
 

	
 
	if (!m_component->inServerMode()) {
 
		m_remoteRosterRequest = AddressedRosterRequest::ref(new AddressedRosterRequest(static_cast<XMPPFrontend *>(m_component->getFrontend())->getIQRouter(), m_user->getJID().toBare()));
 
		m_remoteRosterRequest->onResponse.connect(boost::bind(&XMPPRosterManager::handleRemoteRosterResponse, this, _1, _2));
 
		m_remoteRosterRequest->send();
 
	}
 
}
 

	
 
XMPPRosterManager::~XMPPRosterManager() {
 
	m_RIETimer->stop();
 
	if (m_remoteRosterRequest) {
 
		m_remoteRosterRequest->onResponse.disconnect_all_slots();
 
		static_cast<XMPPFrontend *>(m_component->getFrontend())->getIQRouter()->removeHandler(m_remoteRosterRequest);
 
	}
 

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

	
 
void XMPPRosterManager::doRemoveBuddy(Buddy *buddy) {
 
	if (m_component->inServerMode() || m_supportRemoteRoster) {
 
		sendBuddyRosterRemove(buddy);
 
	}
 
	else {
 
		sendBuddyUnsubscribePresence(buddy);
 
	}
 
}
 

	
 
void XMPPRosterManager::sendBuddyRosterRemove(Buddy *buddy) {
 
	Swift::RosterPayload::ref p = Swift::RosterPayload::ref(new Swift::RosterPayload());
 
	Swift::RosterItemPayload item;
 
	item.setJID(buddy->getJID().toBare());
 
	item.setSubscription(Swift::RosterItemPayload::Remove);
 

	
 
	p->addItem(item);
 

	
 
	// In server mode we have to send pushes to all resources, but in gateway-mode we send it only to bare JID
 
	if (m_component->inServerMode()) {
 
		std::vector<Swift::Presence::ref> presences = m_component->getPresenceOracle()->getAllPresence(m_user->getJID().toBare());
 
		BOOST_FOREACH(Swift::Presence::ref presence, presences) {
 
			Swift::SetRosterRequest::ref request = Swift::SetRosterRequest::create(p, presence->getFrom(), static_cast<XMPPFrontend *>(m_component->getFrontend())->getIQRouter());
 
			request->send();
 
		}
 
	}
 
	else {
 
		Swift::SetRosterRequest::ref request = Swift::SetRosterRequest::create(p, m_user->getJID().toBare(), static_cast<XMPPFrontend *>(m_component->getFrontend())->getIQRouter());
 
		request->send();
 
	}
 
}
 

	
 
void XMPPRosterManager::sendBuddyRosterPush(Buddy *buddy) {
 
	// user can't receive anything in server mode if he's not logged in.
 
	// He will ask for roster later (handled in rosterreponsder.cpp)
 
	if (m_component->inServerMode() && (!m_user->isConnected() || m_user->shouldCacheMessages()))
 
		return;
 

	
 
	Swift::RosterPayload::ref payload = Swift::RosterPayload::ref(new Swift::RosterPayload());
 
	Swift::RosterItemPayload item;
 
	item.setJID(buddy->getJID().toBare());
 
	item.setName(buddy->getAlias());
 
	item.setGroups(buddy->getGroups());
 
	item.setSubscription(Swift::RosterItemPayload::Both);
 

	
 
	payload->addItem(item);
 

	
 
	// In server mode we have to send pushes to all resources, but in gateway-mode we send it only to bare JID
 
	if (m_component->inServerMode()) {
 
		std::vector<Swift::Presence::ref> presences = m_component->getPresenceOracle()->getAllPresence(m_user->getJID().toBare());
 
		BOOST_FOREACH(Swift::Presence::ref presence, presences) {
 
			Swift::SetRosterRequest::ref request = Swift::SetRosterRequest::create(payload, presence->getFrom(), static_cast<XMPPFrontend *>(m_component->getFrontend())->getIQRouter());
 
			request->onResponse.connect(boost::bind(&XMPPRosterManager::handleBuddyRosterPushResponse, this, _1, request, buddy->getName()));
 
			request->send();
 
			m_requests.push_back(request);
 
		}
 
	}
 
	else {
 
		Swift::SetRosterRequest::ref request = Swift::SetRosterRequest::create(payload, m_user->getJID().toBare(), static_cast<XMPPFrontend *>(m_component->getFrontend())->getIQRouter());
 
		request->onResponse.connect(boost::bind(&XMPPRosterManager::handleBuddyRosterPushResponse, this, _1, request, buddy->getName()));
 
		request->send();
 
		m_requests.push_back(request);
 
	}
 

	
 
	if (buddy->getSubscription() != Buddy::Both) {
 
		buddy->setSubscription(Buddy::Both);
 
		storeBuddy(buddy);
 
	}
 
}
 

	
 

	
 
void XMPPRosterManager::handleBuddyChanged(Buddy *buddy) {
 
}
 

	
 
void XMPPRosterManager::doAddBuddy(Buddy *buddy) {
 
	// In server mode the only way is to send jabber:iq:roster push.
 
	// In component mode we send RIE or Subscribe presences, based on features.
 
	if (m_component->inServerMode()) {
 
		sendBuddyRosterPush(buddy);
 
	}
 
	else {
 
		if (buddy->getSubscription() == Buddy::Both) {
 
			LOG4CXX_INFO(logger, m_user->getJID().toString() << ": Not forwarding this buddy, because subscription=both");
 
			return;
 
		}
 

	
 
		if (m_supportRemoteRoster) {
 
			sendBuddyRosterPush(buddy);
 
		}
 
		else {
 
			m_RIETimer->start();
 
		}
 
	}
 
}
 

	
 
void XMPPRosterManager::doUpdateBuddy(Buddy *buddy) {
 
	if (m_component->inServerMode() || m_supportRemoteRoster) {
 
		sendBuddyRosterPush(buddy);
 
	}
 
}
 

	
 
void XMPPRosterManager::handleBuddyRosterPushResponse(Swift::ErrorPayload::ref error, Swift::SetRosterRequest::ref request, const std::string &key) {
 
	LOG4CXX_INFO(logger, "handleBuddyRosterPushResponse called for buddy " << key);
 
	if (m_buddies[key] != NULL) {
 
		if (m_buddies[key]->isAvailable()) {
 
			std::vector<Swift::Presence::ref> &presences = m_buddies[key]->generatePresenceStanzas(255);
 
			BOOST_FOREACH(Swift::Presence::ref &presence, presences) {
 
				m_component->getFrontend()->sendPresence(presence);
 
			}
 
		}
 
	}
 
	else {
 
		LOG4CXX_WARN(logger, "handleBuddyRosterPushResponse called for unknown buddy " << key);
 
	}
 

	
 
	m_requests.remove(request);
 
	request->onResponse.disconnect_all_slots();
 
}
 

	
 
void XMPPRosterManager::handleRemoteRosterResponse(boost::shared_ptr<Swift::RosterPayload> payload, Swift::ErrorPayload::ref error) {
 
	m_remoteRosterRequest.reset();
 
	if (error) {
 
		m_supportRemoteRoster = false;
 
		LOG4CXX_INFO(logger, m_user->getJID().toString() << ": This server does not support remote roster protoXEP");
 
		return;
 
	}
 

	
 
	LOG4CXX_INFO(logger, m_user->getJID().toString() << ": This server supports remote roster protoXEP");
 
	m_supportRemoteRoster = true;
 

	
 
	//If we receive empty RosterPayload on login (not register) initiate full RosterPush
 
	if(!m_buddies.empty() && payload->getItems().empty()){
 
			LOG4CXX_INFO(logger, "Received empty Roster upon login. Pushing full Roster.");
 
			for(std::map<std::string, Buddy *, std::less<std::string>, boost::pool_allocator< std::pair<std::string, Buddy *> > >::const_iterator c_it = m_buddies.begin();
 
					c_it != m_buddies.end(); c_it++) {
 
				sendBuddyRosterPush(c_it->second);
 
			}
 
	}
 
	return;
 

	
 
	BOOST_FOREACH(const Swift::RosterItemPayload &item, payload->getItems()) {
 
		std::string legacyName = Buddy::JIDToLegacyName(item.getJID());
 
		if (m_buddies.find(legacyName) != m_buddies.end()) {
 
			continue;
 
		}
 

	
 
		if (legacyName.empty()) {
 
			continue;
 
		}
 

	
 
		BuddyInfo buddyInfo;
 
		buddyInfo.id = -1;
 
		buddyInfo.alias = item.getName();
 
		buddyInfo.legacyName = legacyName;
 
		buddyInfo.subscription = "both";
 
		buddyInfo.flags = Buddy::buddyFlagsFromJID(item.getJID());
 
		buddyInfo.groups = item.getGroups();
 

	
 
		Buddy *buddy = m_component->getFactory()->createBuddy(this, buddyInfo);
 
		if (buddy) {
 
			setBuddy(buddy);
 
		}
 
	}
 
}
 

	
 

	
 
void XMPPRosterManager::sendRIE() {
 
	m_RIETimer->stop();
 

	
 
	// Check the feature, because proper resource could logout during RIETimer.
 
	std::vector<Swift::JID> jidWithRIE = static_cast<XMPPUser *>(m_user)->getJIDWithFeature("http://jabber.org/protocol/rosterx");
 

	
 
	// fallback to normal subscribe
 
	if (jidWithRIE.empty()) {
 
		for (std::map<std::string, Buddy *, std::less<std::string>, boost::pool_allocator< std::pair<std::string, Buddy *> > >::iterator it = m_buddies.begin(); it != m_buddies.end(); it++) {
 
			Buddy *buddy = (*it).second;
 
			if (!buddy) {
 
				continue;
 
			}
 
			sendBuddySubscribePresence(buddy);
 
		}
 
		return;
 
	}
 

	
 
	Swift::RosterItemExchangePayload::ref payload = Swift::RosterItemExchangePayload::ref(new Swift::RosterItemExchangePayload());
 
	for (std::map<std::string, Buddy *, std::less<std::string>, boost::pool_allocator< std::pair<std::string, Buddy *> > >::iterator it = m_buddies.begin(); it != m_buddies.end(); it++) {
 
		Buddy *buddy = (*it).second;
 
		if (!buddy) {
 
			continue;
 
		}
 
		Swift::RosterItemExchangePayload::Item item;
 
		item.setJID(buddy->getJID().toBare());
 
		item.setName(buddy->getAlias());
 
		item.setAction(Swift::RosterItemExchangePayload::Item::Add);
 
		item.setGroups(buddy->getGroups());
 

	
 
		payload->addItem(item);
 
	}
 

	
 
	BOOST_FOREACH(Swift::JID &jid, jidWithRIE) {
 
		LOG4CXX_INFO(logger, "Sending RIE stanza to " << jid.toString());
 
		boost::shared_ptr<Swift::GenericRequest<Swift::RosterItemExchangePayload> > request(new Swift::GenericRequest<Swift::RosterItemExchangePayload>(Swift::IQ::Set, jid, payload, static_cast<XMPPFrontend *>(m_component->getFrontend())->getIQRouter()));
 
		request->send();
 
	}
 
}
 

	
 

	
 
}
spectrum/src/frontends/xmpp/XMPPRosterManager.h
Show inline comments
 
new file 100644
 
/**
 
 * XMPP - libpurple transport
 
 *
 
 * Copyright (C) 2009, Jan Kaluza <hanzz@soc.pidgin.im>
 
 *
 
 * 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
 
 */
 

	
 
#pragma once
 

	
 
#include <string>
 
#include <algorithm>
 
#include <map>
 
#include <boost/pool/pool_alloc.hpp>
 
#include <boost/pool/object_pool.hpp>
 
// #include "rosterstorage.h"
 
#include "Swiften/Elements/RosterPayload.h"
 
#include "Swiften/Queries/GenericRequest.h"
 
#include "Swiften/Roster/SetRosterRequest.h"
 
#include "Swiften/Elements/Presence.h"
 
#include "transport/rostermanager.h"
 
#include "Swiften/Network/Timer.h"
 

	
 
namespace Transport {
 

	
 
class Buddy;
 
class User;
 
class Component;
 
class StorageBackend;
 
class RosterStorage;
 

	
 
// TODO: Once Swiften GetRosterRequest will support setting to="", this can be removed
 
class AddressedRosterRequest : public Swift::GenericRequest<Swift::RosterPayload> {
 
	public:
 
		typedef boost::shared_ptr<AddressedRosterRequest> ref;
 

	
 
		AddressedRosterRequest(Swift::IQRouter* router, Swift::JID to) :
 
				Swift::GenericRequest<Swift::RosterPayload>(Swift::IQ::Get, to, boost::shared_ptr<Swift::Payload>(new Swift::RosterPayload()), router) {
 
		}
 
};
 

	
 
/// Manages roster of one XMPP user.
 
class XMPPRosterManager : public RosterManager {
 
	public:
 
		typedef std::map<std::string, Buddy *, std::less<std::string>, boost::pool_allocator< std::pair<std::string, Buddy *> > > BuddiesMap;
 
		/// Creates new XMPPRosterManager.
 
		/// \param user User associated with this XMPPRosterManager.
 
		/// \param component Transport instance associated with this roster.
 
		XMPPRosterManager(User *user, Component *component);
 

	
 
		/// Destructor.
 
		virtual ~XMPPRosterManager();
 

	
 
		virtual void doRemoveBuddy(Buddy *buddy);
 
		virtual void doAddBuddy(Buddy *buddy);
 
		virtual void doUpdateBuddy(Buddy *buddy);
 

	
 

	
 

	
 
		bool isRemoteRosterSupported() {
 
			return m_supportRemoteRoster;
 
		}
 

	
 
		boost::signal<void (Buddy *buddy)> onBuddyAdded;
 
		
 
		boost::signal<void (Buddy *buddy)> onBuddyRemoved;
 

	
 
		void handleBuddyChanged(Buddy *buddy);
 

	
 
		void sendBuddyRosterPush(Buddy *buddy);
 

	
 
		void sendBuddyRosterRemove(Buddy *buddy);
 

	
 
	private:
 
		void sendRIE();
 
		void handleBuddyRosterPushResponse(Swift::ErrorPayload::ref error, Swift::SetRosterRequest::ref request, const std::string &key);
 
		void handleRemoteRosterResponse(boost::shared_ptr<Swift::RosterPayload> roster, Swift::ErrorPayload::ref error);
 

	
 
		Component *m_component;
 
		RosterStorage *m_rosterStorage;
 
		User *m_user;
 
		Swift::Timer::ref m_setBuddyTimer;
 
		Swift::Timer::ref m_RIETimer;
 
		std::list <Swift::SetRosterRequest::ref> m_requests;
 
		bool m_supportRemoteRoster;
 
		AddressedRosterRequest::ref m_remoteRosterRequest;
 
};
 

	
 
}
spectrum/src/frontends/xmpp/XMPPUser.cpp
Show inline comments
 
new file 100644
 
/**
 
 * libtransport -- C++ library for easy XMPP Transports development
 
 *
 
 * Copyright (C) 2011, Jan Kaluza <hanzz.k@gmail.com>
 
 *
 
 * 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/user.h"
 
#include "transport/frontend.h"
 
#include "transport/transport.h"
 
#include "transport/rostermanager.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 <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
 
	}
 
}
 

	
 
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
 
	}
 
}
 

	
 

	
 
}
spectrum/src/frontends/xmpp/XMPPUser.h
Show inline comments
 
new file 100644
 
/**
 
 * libtransport -- C++ library for easy XMPP Transports development
 
 *
 
 * Copyright (C) 2011, Jan Kaluza <hanzz.k@gmail.com>
 
 *
 
 * 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
 
 */
 

	
 
#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"
 

	
 
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);
 

	
 

	
 

	
 
	private:
 
		void onConnectingTimeout();
 

	
 
		Swift::JID m_jid;
 
		Component *m_component;
 
		UserManager *m_userManager;
 
		UserInfo m_userInfo;
 
};
 

	
 
}
spectrum/src/frontends/xmpp/XMPPUserManager.cpp
Show inline comments
 
new file 100644
 
/**
 
 * libtransport -- C++ library for easy XMPP Transports development
 
 *
 
 * Copyright (C) 2011, Jan Kaluza <hanzz.k@gmail.com>
 
 *
 
 * 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 "XMPPUserManager.h"
 
#include "XMPPUserRegistration.h"
 
#include "transport/user.h"
 
#include "transport/transport.h"
 
#include "transport/storagebackend.h"
 
#include "transport/conversationmanager.h"
 
#include "transport/rostermanager.h"
 
#include "transport/userregistry.h"
 
#include "transport/logging.h"
 
#include "transport/frontend.h"
 
#include "transport/presenceoracle.h"
 
#include "storageresponder.h"
 
#include "vcardresponder.h"
 
#include "transport/frontend.h"
 
#include "XMPPFrontend.h"
 
#include "gatewayresponder.h"
 
#include "adhocmanager.h"
 
#include "settingsadhoccommand.h"
 

	
 
#include "Swiften/Server/ServerStanzaChannel.h"
 
#include "Swiften/Elements/StreamError.h"
 
#include "Swiften/Elements/MUCPayload.h"
 
#include "Swiften/Elements/ChatState.h"
 
#ifndef __FreeBSD__ 
 
#ifndef __MACH__
 
#include "malloc.h"
 
#endif
 
#endif
 
// #include "valgrind/memcheck.h"
 

	
 
namespace Transport {
 

	
 
DEFINE_LOGGER(logger, "XMPPUserManager");
 

	
 
XMPPUserManager::XMPPUserManager(Component *component, UserRegistry *userRegistry, StorageBackend *storageBackend) : UserManager(component, userRegistry, storageBackend) {
 
	m_component = component;
 

	
 
	XMPPFrontend *frontend = static_cast<XMPPFrontend *>(component->getFrontend());
 
	if (storageBackend) {
 
		m_storageResponder = new StorageResponder(frontend->getIQRouter(), storageBackend, this);
 
		m_storageResponder->start();
 
	}
 

	
 
	m_vcardResponder = new VCardResponder(frontend->getIQRouter(), component->getNetworkFactories(), this);
 
	m_vcardResponder->onVCardRequired.connect(boost::bind(&XMPPUserManager::handleVCardRequired, this, _1, _2, _3));
 
	m_vcardResponder->onVCardUpdated.connect(boost::bind(&XMPPUserManager::handleVCardUpdated, this, _1, _2));
 
	m_vcardResponder->start();
 

	
 
	if (storageBackend) {
 
		m_userRegistration = new XMPPUserRegistration(component, this, storageBackend);
 
		m_userRegistration->start();
 
	}
 
	else {
 
		m_userRegistration = NULL;
 
	}
 

	
 
// 	StatsResponder statsResponder(component, this, &plugin, storageBackend);
 
// 	statsResponder.start();
 

	
 
	m_gatewayResponder = new GatewayResponder(frontend->getIQRouter(), this);
 
	m_gatewayResponder->start();
 

	
 
	m_adHocManager = new AdHocManager(component, frontend->getDiscoItemsResponder(), this, storageBackend);
 
	m_adHocManager->start();
 

	
 
	SettingsAdHocCommandFactory *m_settings = new SettingsAdHocCommandFactory();
 
	m_adHocManager->addAdHocCommand(m_settings);
 
}
 

	
 
XMPPUserManager::~XMPPUserManager() {
 
	if (m_storageResponder) {
 
		m_storageResponder->stop();
 
		delete m_storageResponder;
 
	}
 

	
 
	if (m_userRegistration) {
 
		m_userRegistration->stop();
 
		delete m_userRegistration;
 
	}
 

	
 
	delete m_gatewayResponder;
 
	delete m_adHocManager;
 
	delete m_settings;
 
	delete m_vcardResponder;
 
}
 

	
 
void XMPPUserManager::sendVCard(unsigned int id, Swift::VCard::ref vcard) {
 
	m_vcardResponder->sendVCard(id, vcard);
 
}
 

	
 
void XMPPUserManager::handleVCardRequired(User *user, const std::string &name, unsigned int id) {
 
	m_component->getFrontend()->onVCardRequired(user, name, id);
 
}
 

	
 
void XMPPUserManager::handleVCardUpdated(User *user, boost::shared_ptr<Swift::VCard> vcard) {
 
	m_component->getFrontend()->onVCardUpdated(user, vcard);
 
}
 

	
 
UserRegistration *XMPPUserManager::getUserRegistration() {
 
	return m_userRegistration;
 
}
 

	
 
}
spectrum/src/frontends/xmpp/XMPPUserManager.h
Show inline comments
 
new file 100644
 
/**
 
 * libtransport -- C++ library for easy XMPP Transports development
 
 *
 
 * Copyright (C) 2011, Jan Kaluza <hanzz.k@gmail.com>
 
 *
 
 * 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
 
 */
 

	
 
#pragma once
 

	
 
#include <string>
 
#include <map>
 
#include "transport/usermanager.h"
 
#include "Swiften/Elements/Message.h"
 
#include "Swiften/Elements/Presence.h"
 
#include "Swiften/Disco/EntityCapsProvider.h"
 
#include "Swiften/Elements/DiscoInfo.h"
 
#include "Swiften/Network/Timer.h"
 

	
 
namespace Transport {
 

	
 
class Component;
 
class StorageBackend;
 
class StorageResponder;
 
class VCardResponder;
 
class XMPPUserRegistration;
 
class GatewayResponder;
 
class AdHocManager;
 
class SettingsAdHocCommandFactory;
 

	
 
class XMPPUserManager : public UserManager {
 
	public:
 
		XMPPUserManager(Component *component, UserRegistry *userRegistry, StorageBackend *storageBackend = NULL);
 

	
 
		virtual ~XMPPUserManager();
 

	
 
		virtual void sendVCard(unsigned int id, Swift::VCard::ref vcard);
 

	
 
		UserRegistration *getUserRegistration();
 

	
 
	private:
 
		void handleVCardRequired(User *, const std::string &name, unsigned int id);
 
		void handleVCardUpdated(User *, boost::shared_ptr<Swift::VCard> vcard);
 

	
 
		StorageResponder *m_storageResponder;
 
		VCardResponder *m_vcardResponder;
 
		Component *m_component;
 
		XMPPUserRegistration *m_userRegistration;
 
		GatewayResponder *m_gatewayResponder;
 
		AdHocManager *m_adHocManager;
 
		SettingsAdHocCommandFactory *m_settings;
 
};
 

	
 
}
spectrum/src/frontends/xmpp/XMPPUserRegistration.cpp
Show inline comments
 
new file 100644
 
/**
 
 * libtransport -- C++ library for easy XMPP Transports development
 
 *
 
 * Copyright (C) 2011, Jan Kaluza <hanzz.k@gmail.com>
 
 *
 
 * 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 "XMPPUserRegistration.h"
 
#include "XMPPRosterManager.h"
 
#include "transport/userregistration.h"
 
#include "transport/usermanager.h"
 
#include "transport/storagebackend.h"
 
#include "transport/transport.h"
 
#include "transport/rostermanager.h"
 
#include "transport/user.h"
 
#include "transport/logging.h"
 
#include "formutils.h"
 
#include "transport/buddy.h"
 
#include "Swiften/Elements/ErrorPayload.h"
 
#include "Swiften/EventLoop/SimpleEventLoop.h"
 
#include "Swiften/Network/BoostNetworkFactories.h"
 
#include "Swiften/Client/Client.h"
 
#include <boost/shared_ptr.hpp>
 
#include <boost/thread.hpp>
 
#include <boost/date_time/posix_time/posix_time.hpp>
 
#include <boost/regex.hpp> 
 
#if HAVE_SWIFTEN_3
 
#include <Swiften/Elements/Form.h>
 
#endif
 
#include "XMPPFrontend.h"
 

	
 
using namespace Swift;
 

	
 
namespace Transport {
 

	
 
DEFINE_LOGGER(logger, "XMPPUserRegistration");
 

	
 
XMPPUserRegistration::XMPPUserRegistration(Component *component, UserManager *userManager,
 
								   StorageBackend *storageBackend)
 
: UserRegistration(component, userManager, storageBackend), Swift::Responder<Swift::InBandRegistrationPayload>(static_cast<XMPPFrontend *>(component->getFrontend())->getIQRouter()) {
 
	m_component = component;
 
	m_config = m_component->getConfig();
 
	m_storageBackend = storageBackend;
 
	m_userManager = userManager;
 
}
 

	
 
XMPPUserRegistration::~XMPPUserRegistration(){
 
}
 

	
 
bool XMPPUserRegistration::doUserRegistration(const UserInfo &row) {
 
	// Check if the server supports remoteroster XEP by sending request for the registered user's roster.
 
	AddressedRosterRequest::ref request = AddressedRosterRequest::ref(new AddressedRosterRequest(static_cast<XMPPFrontend *>(m_component->getFrontend())->getIQRouter(), row.jid));
 
	request->onResponse.connect(boost::bind(&XMPPUserRegistration::handleRegisterRemoteRosterResponse, this, _1, _2, row));
 
	request->send();
 

	
 
	return true;
 
}
 

	
 
bool XMPPUserRegistration::doUserUnregistration(const UserInfo &row) {
 
	// Check if the server supports remoteroster XEP by sending request for the registered user's roster.
 
	AddressedRosterRequest::ref request = AddressedRosterRequest::ref(new AddressedRosterRequest(static_cast<XMPPFrontend *>(m_component->getFrontend())->getIQRouter(), row.jid));
 
	request->onResponse.connect(boost::bind(&XMPPUserRegistration::handleUnregisterRemoteRosterResponse, this, _1, _2, row));
 
	request->send();
 

	
 
	return true;
 
}
 

	
 
void XMPPUserRegistration::handleRegisterRemoteRosterResponse(boost::shared_ptr<Swift::RosterPayload> payload, Swift::ErrorPayload::ref remoteRosterNotSupported, const UserInfo &row){
 
	if (remoteRosterNotSupported || !payload) {
 
		// Remote roster is not support, so send normal Subscribe presence to add transport.
 
		Swift::Presence::ref response = Swift::Presence::create();
 
		response->setFrom(m_component->getJID());
 
		response->setTo(Swift::JID(row.jid));
 
		response->setType(Swift::Presence::Subscribe);
 
		m_component->getFrontend()->sendPresence(response);
 
	}
 
	else {
 
		// Remote roster is support, so use remoteroster XEP to add transport.
 
		Swift::RosterPayload::ref payload = Swift::RosterPayload::ref(new Swift::RosterPayload());
 
		Swift::RosterItemPayload item;
 
		item.setJID(m_component->getJID());
 
		item.setSubscription(Swift::RosterItemPayload::Both);
 
		payload->addItem(item);
 
		Swift::SetRosterRequest::ref request = Swift::SetRosterRequest::create(payload, row.jid, static_cast<XMPPFrontend *>(m_component->getFrontend())->getIQRouter());
 
		request->send();
 
	}
 

	
 
	onUserRegistered(row);
 

	
 
	// If the JID for registration notification is configured, send the notification message.
 
	std::vector<std::string> const &x = CONFIG_VECTOR(m_component->getConfig(),"registration.notify_jid");
 
	BOOST_FOREACH(const std::string &notify_jid, x) {
 
		boost::shared_ptr<Swift::Message> msg(new Swift::Message());
 
		msg->setBody(std::string("registered: ") + row.jid);
 
		msg->setTo(notify_jid);
 
		msg->setFrom(m_component->getJID());
 
		m_component->getFrontend()->sendMessage(msg);
 
	}
 
}
 

	
 
void XMPPUserRegistration::handleUnregisterRemoteRosterResponse(boost::shared_ptr<Swift::RosterPayload> payload, Swift::ErrorPayload::ref remoteRosterNotSupported, const UserInfo &userInfo) {
 
	if (remoteRosterNotSupported || !payload) {
 
		// Remote roster is ont support, so get the buddies from database
 
		// and send Unsubsribe and Unsubscribed presence to them.
 
		std::list<BuddyInfo> roster;
 
		m_storageBackend->getBuddies(userInfo.id, roster);
 
		for(std::list<BuddyInfo>::iterator u = roster.begin(); u != roster.end() ; u++){
 
			std::string name = (*u).legacyName;
 
			if ((*u).flags & BUDDY_JID_ESCAPING) {
 
				name = Swift::JID::getEscapedNode((*u).legacyName);
 
			}
 
			else {
 
				if (name.find_last_of("@") != std::string::npos) {
 
					name.replace(name.find_last_of("@"), 1, "%");
 
				}
 
			}
 

	
 
			Swift::Presence::ref response;
 
			response = Swift::Presence::create();
 
			response->setTo(Swift::JID(userInfo.jid));
 
			response->setFrom(Swift::JID(name, m_component->getJID().toString()));
 
			response->setType(Swift::Presence::Unsubscribe);
 
			m_component->getFrontend()->sendPresence(response);
 

	
 
			response = Swift::Presence::create();
 
			response->setTo(Swift::JID(userInfo.jid));
 
			response->setFrom(Swift::JID(name, m_component->getJID().toString()));
 
			response->setType(Swift::Presence::Unsubscribed);
 
			m_component->getFrontend()->sendPresence(response);
 
		}
 
	}
 
	else {
 
		// Remote roster is support, so iterate over all buddies we received
 
		// from the XMPP server and remove them using remote roster.
 
		BOOST_FOREACH(Swift::RosterItemPayload it, payload->getItems()) {
 
			Swift::RosterPayload::ref p = Swift::RosterPayload::ref(new Swift::RosterPayload());
 
			Swift::RosterItemPayload item;
 
			item.setJID(it.getJID());
 
			item.setSubscription(Swift::RosterItemPayload::Remove);
 

	
 
			p->addItem(item);
 

	
 
			Swift::SetRosterRequest::ref request = Swift::SetRosterRequest::create(p, userInfo.jid, static_cast<XMPPFrontend *>(m_component->getFrontend())->getIQRouter());
 
			request->send();
 
		}
 
	}
 

	
 
	// Remove user from database
 
	m_storageBackend->removeUser(userInfo.id);
 

	
 
	// Disconnect the user
 
	User *user = m_userManager->getUser(userInfo.jid);
 
	if (user) {
 
		m_userManager->removeUser(user);
 
	}
 

	
 
	// Remove the transport contact itself the same way as the buddies.
 
	if (remoteRosterNotSupported || !payload) {
 
		Swift::Presence::ref response;
 
		response = Swift::Presence::create();
 
		response->setTo(Swift::JID(userInfo.jid));
 
		response->setFrom(m_component->getJID());
 
		response->setType(Swift::Presence::Unsubscribe);
 
		m_component->getFrontend()->sendPresence(response);
 

	
 
		response = Swift::Presence::create();
 
		response->setTo(Swift::JID(userInfo.jid));
 
		response->setFrom(m_component->getJID());
 
		response->setType(Swift::Presence::Unsubscribed);
 
		m_component->getFrontend()->sendPresence(response);
 
	}
 
	else {
 
		Swift::RosterPayload::ref payload = Swift::RosterPayload::ref(new Swift::RosterPayload());
 
		Swift::RosterItemPayload item;
 
		item.setJID(m_component->getJID());
 
		item.setSubscription(Swift::RosterItemPayload::Remove);
 
		payload->addItem(item);
 

	
 
		Swift::SetRosterRequest::ref request = Swift::SetRosterRequest::create(payload, userInfo.jid, static_cast<XMPPFrontend *>(m_component->getFrontend())->getIQRouter());
 
		request->send();
 
	}
 

	
 
	// If the JID for registration notification is configured, send the notification message.
 
	std::vector<std::string> const &x = CONFIG_VECTOR(m_component->getConfig(),"registration.notify_jid");
 
	BOOST_FOREACH(const std::string &notify_jid, x) {
 
		boost::shared_ptr<Swift::Message> msg(new Swift::Message());
 
		msg->setBody(std::string("unregistered: ") + userInfo.jid);
 
		msg->setTo(notify_jid);
 
		msg->setFrom(m_component->getJID());
 
		m_component->getFrontend()->sendMessage(msg);
 
	}
 
}
 

	
 
Form::ref XMPPUserRegistration::generateRegistrationForm(const UserInfo &res, bool registered) {
 
	Form::ref form(new Form(Form::FormType));
 
	form->setTitle("Registration");
 
	form->setInstructions(CONFIG_STRING(m_config, "registration.instructions"));
 

	
 
	FormUtils::addHiddenField(form, "FORM_TYPE", "jabber:iq:register");
 
	FormUtils::addTextSingleField(form, "username", res.uin,
 
								  CONFIG_STRING(m_config, "registration.username_label"),
 
								  true);
 

	
 
	if (CONFIG_BOOL_DEFAULTED(m_config, "registration.needPassword", true)) {
 
		FormUtils::addTextPrivateField(form, "password", "Password", true);
 
	}
 

	
 
	std::string defLanguage = CONFIG_STRING(m_config, "registration.language");
 
	Swift::FormField::Option languages(defLanguage, defLanguage);
 
	FormUtils::addListSingleField(form, "language", languages, "Language",
 
								  registered ? res.language : defLanguage);
 

	
 

	
 
	if (registered) {
 
		FormUtils::addBooleanField(form, "unregister", "0", "Remove your registration");
 
	}
 
	else if (CONFIG_BOOL(m_config,"registration.require_local_account")) {
 
		std::string localUsernameField = CONFIG_STRING(m_config, "registration.local_username_label");
 
		FormUtils::addTextSingleField(form, "local_username", "", localUsernameField, true);
 
		FormUtils::addTextSingleField(form, "local_password", "", "Local password", true);
 
	}
 

	
 
	return form;
 
}
 

	
 
boost::shared_ptr<InBandRegistrationPayload> XMPPUserRegistration::generateInBandRegistrationPayload(const Swift::JID& from) {
 
	boost::shared_ptr<InBandRegistrationPayload> reg(new InBandRegistrationPayload());
 

	
 
	UserInfo res;
 
	bool registered = m_storageBackend->getUser(from.toBare().toString(), res);
 

	
 
	reg->setInstructions(CONFIG_STRING(m_config, "registration.instructions"));
 
	reg->setRegistered(registered);
 
	reg->setUsername(res.uin);
 

	
 
	if (CONFIG_BOOL_DEFAULTED(m_config, "registration.needPassword", true)) {
 
		reg->setPassword("");
 
	}
 

	
 
	Form::ref form = generateRegistrationForm(res, registered);
 
	reg->setForm(form);
 

	
 
	return reg;
 
}
 

	
 
bool XMPPUserRegistration::handleGetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr<Swift::InBandRegistrationPayload> payload) {
 
	// TODO: backend should say itself if registration is needed or not...
 
	if (CONFIG_STRING(m_config, "service.protocol") == "irc") {
 
		sendError(from, id, ErrorPayload::BadRequest, ErrorPayload::Modify);
 
		return true;
 
	}
 

	
 
	if (!CONFIG_BOOL(m_config,"registration.enable_public_registration")) {
 
		std::vector<std::string> const &x = CONFIG_VECTOR(m_config,"service.allowed_servers");
 
		if (std::find(x.begin(), x.end(), from.getDomain()) == x.end()) {
 
			LOG4CXX_INFO(logger, from.toBare().toString() << ": This user has no permissions to register an account")
 
			sendError(from, id, ErrorPayload::BadRequest, ErrorPayload::Modify);
 
			return true;
 
		}
 
	}
 

	
 
	boost::shared_ptr<InBandRegistrationPayload> reg = generateInBandRegistrationPayload(from);
 
	sendResponse(from, id, reg);
 

	
 
	return true;
 
}
 

	
 
bool XMPPUserRegistration::handleSetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr<Swift::InBandRegistrationPayload> payload) {
 
	// TODO: backend should say itself if registration is needed or not...
 
	if (CONFIG_STRING(m_config, "service.protocol") == "irc") {
 
		sendError(from, id, ErrorPayload::BadRequest, ErrorPayload::Modify);
 
		return true;
 
	}
 

	
 
	std::string barejid = from.toBare().toString();
 

	
 
	if (!CONFIG_BOOL(m_config,"registration.enable_public_registration")) {
 
		std::vector<std::string> const &x = CONFIG_VECTOR(m_config,"service.allowed_servers");
 
		if (std::find(x.begin(), x.end(), from.getDomain()) == x.end()) {
 
			LOG4CXX_INFO(logger, barejid << ": This user has no permissions to register an account")
 
			sendError(from, id, ErrorPayload::BadRequest, ErrorPayload::Modify);
 
			return true;
 
		}
 
	}
 

	
 
	UserInfo res;
 
	bool registered = m_storageBackend->getUser(barejid, res);
 

	
 
	std::string encoding;
 
	std::string language;
 
	std::string local_username;
 
	std::string local_password;
 

	
 
	Form::ref form = payload->getForm();
 
	if (form) {
 
		std::string value;
 

	
 
		value = FormUtils::fieldValue(form, "username", "");
 
		if (!value.empty()) {
 
			payload->setUsername(value);
 
		}
 

	
 
		value = FormUtils::fieldValue(form, "password", "");
 
		if (!value.empty()) {
 
			payload->setPassword(value);
 
		}
 

	
 
		value = FormUtils::fieldValue(form, "unregister", "");
 
		if (value == "1" || value == "true") {
 
			payload->setRemove(true);
 
		}
 

	
 
		encoding = FormUtils::fieldValue(form, "encoding", "");
 
		local_username = FormUtils::fieldValue(form, "local_username", "");
 
		local_password = FormUtils::fieldValue(form, "local_password", "");
 
		language = FormUtils::fieldValue(form, "language", "");
 
	}
 

	
 
	if (payload->isRemove()) {
 
		unregisterUser(barejid);
 
		sendResponse(from, id, InBandRegistrationPayload::ref());
 
		return true;
 
	}
 

	
 
	if (CONFIG_BOOL(m_config,"registration.require_local_account")) {
 
	/*	if (!local_username || !local_password) {
 
			sendResponse(from, id, InBandRegistrationPayload::ref());
 
			return true
 
		} else */ if (local_username == "" || local_password == "") {
 
			sendResponse(from, id, InBandRegistrationPayload::ref());
 
			return true;
 
		} 
 
//		Swift::logging = true;
 
		bool validLocal = false;
 
		std::string localLookupServer = CONFIG_STRING(m_config, "registration.local_account_server");
 
		std::string localLookupJID = local_username + std::string("@") + localLookupServer;
 
		SimpleEventLoop localLookupEventLoop;
 
		BoostNetworkFactories localLookupNetworkFactories(&localLookupEventLoop);
 
		Client localLookupClient(localLookupJID, local_password, &localLookupNetworkFactories);
 
		
 
		// TODO: this is neccessary on my server ... but should maybe omitted
 
		localLookupClient.setAlwaysTrustCertificates();
 
		localLookupClient.connect();
 

	
 
		class SimpleLoopRunner {
 
			public:
 
				SimpleLoopRunner() {};
 

	
 
				static void run(SimpleEventLoop * loop) {
 
					loop->run();
 
				};
 
		};
 

	
 
		// TODO: Really ugly and hacky solution, any other ideas more than welcome!
 
		boost::thread thread(boost::bind(&(SimpleLoopRunner::run), &localLookupEventLoop));
 
		thread.timed_join(boost::posix_time::millisec(CONFIG_INT(m_config, "registration.local_account_server_timeout")));
 
		localLookupEventLoop.stop();
 
		thread.join();
 
		validLocal = localLookupClient.isAvailable();
 
		localLookupClient.disconnect();
 
		if (!validLocal) {
 
			sendError(from, id, ErrorPayload::NotAuthorized, ErrorPayload::Modify);
 
			return true;
 
		}
 
	}
 

	
 
	if (!payload->getUsername() || (!payload->getPassword() && CONFIG_BOOL_DEFAULTED(m_config, "registration.needPassword", true))) {
 
		sendError(from, id, ErrorPayload::NotAcceptable, ErrorPayload::Modify);
 
		return true;
 
	}
 

	
 
	if (!payload->getPassword()) {
 
		payload->setPassword("");
 
	}
 

	
 
	// Register or change password
 
	if (payload->getUsername()->empty()) {
 
		sendError(from, id, ErrorPayload::NotAcceptable, ErrorPayload::Modify);
 
		return true;
 
	}
 

	
 
	// TODO: Move this check to backend somehow
 
	if (CONFIG_STRING(m_config, "service.protocol") == "prpl-jabber") {
 
		// User tries to register himself.
 
		if ((Swift::JID(*payload->getUsername()).toBare() == from.toBare())) {
 
			sendError(from, id, ErrorPayload::NotAcceptable, ErrorPayload::Modify);
 
			return true;
 
		}
 

	
 
		// User tries to register someone who's already registered.
 
		UserInfo user_row;
 
		bool registered = m_storageBackend->getUser(Swift::JID(*payload->getUsername()).toBare().toString(), user_row);
 
		if (registered) {
 
			sendError(from, id, ErrorPayload::NotAcceptable, ErrorPayload::Modify);
 
			return true;
 
		}
 
	}
 

	
 
	std::string username = *payload->getUsername();
 

	
 
	std::string newUsername(username);
 
	if (!CONFIG_STRING(m_config, "registration.username_mask").empty()) {
 
		newUsername = CONFIG_STRING(m_config, "registration.username_mask");
 
		boost::replace_all(newUsername, "$username", username);
 
	}
 

	
 
//TODO: Part of spectrum1 registration stuff, this should be potentially rewritten for S2 too
 
// 	if (!m_component->protocol()->isValidUsername(newUsername)) {
 
// 		Log("XMPPUserRegistration", "This is not valid username: "<< newUsername);
 
// 		sendError(from, id, ErrorPayload::NotAcceptable, ErrorPayload::Modify);
 
// 		return true;
 
// 	}
 

	
 
	if (!CONFIG_STRING(m_config, "registration.allowed_usernames").empty()) {
 
		boost::regex expression(CONFIG_STRING(m_config, "registration.allowed_usernames"));
 
		if (!regex_match(newUsername, expression)) {
 
			LOG4CXX_INFO(logger, "This is not valid username: " << newUsername);
 
			sendError(from, id, ErrorPayload::NotAcceptable, ErrorPayload::Modify);
 
			return true;
 
		}
 
	}
 

	
 
	if (!registered) {
 
		res.jid = barejid;
 
		res.uin = newUsername;
 
		res.password = *payload->getPassword();
 
		res.language = language;
 
		res.encoding = encoding;
 
		res.vip = 0;
 
		res.id = 0;
 
		registerUser(res);
 
	}
 
	else {
 
		res.jid = barejid;
 
		res.uin = newUsername;
 
		res.password = *payload->getPassword();
 
		res.language = language;
 
		res.encoding = encoding;
 
		m_storageBackend->setUser(res);
 
// 		onUserUpdated(res);
 
	}
 

	
 
	sendResponse(from, id, InBandRegistrationPayload::ref());
 
	return true;
 
}
 

	
 
}
spectrum/src/frontends/xmpp/XMPPUserRegistration.h
Show inline comments
 
new file 100644
 
/**
 
 * libtransport -- C++ library for easy XMPP Transports development
 
 *
 
 * Copyright (C) 2011, Jan Kaluza <hanzz.k@gmail.com>
 
 *
 
 * 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
 
 */
 

	
 
#pragma once
 

	
 
#include "Swiften/Queries/Responder.h"
 
#include "Swiften/Elements/InBandRegistrationPayload.h"
 
#include "Swiften/Elements/RosterPayload.h"
 
#include <boost/signal.hpp>
 
#include <Swiften/Version.h>
 
#include "transport/userregistration.h"
 
#define HAVE_SWIFTEN_3  (SWIFTEN_VERSION >= 0x030000)
 

	
 
namespace Transport {
 

	
 
struct UserInfo;
 
class Component;
 
class StorageBackend;
 
class UserManager;
 
class Config;
 

	
 
/// Allows users to register the transport using service discovery.
 
class XMPPUserRegistration : public UserRegistration, public Swift::Responder<Swift::InBandRegistrationPayload> {
 
	public:
 
		/// Creates new XMPPUserRegistration handler.
 
		/// \param component Component associated with this class
 
		/// \param userManager UserManager associated with this class
 
		/// \param storageBackend StorageBackend where the registered users will be stored
 
		XMPPUserRegistration(Component *component, UserManager *userManager, StorageBackend *storageBackend);
 

	
 
		/// Destroys XMPPUserRegistration.
 
		~XMPPUserRegistration();
 

	
 
		/// Registers new user. This function stores user into database and subscribe user to transport.
 
		/// \param userInfo UserInfo struct with informations about registered user
 
		/// \return false if user is already registered
 
		virtual bool doUserRegistration(const UserInfo &userInfo);
 

	
 
		/// Unregisters user. This function removes all data about user from databa, unsubscribe all buddies
 
		/// managed by this transport and disconnects user if he's connected.
 
		/// \param barejid bare JID of user to unregister
 
		/// \return false if there is no such user registered
 
		virtual bool doUserUnregistration(const UserInfo &userInfo);
 

	
 
	private:
 
		virtual bool handleGetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr<Swift::InBandRegistrationPayload> payload);
 
		virtual bool handleSetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr<Swift::InBandRegistrationPayload> payload);
 

	
 
		void handleRegisterRemoteRosterResponse(boost::shared_ptr<Swift::RosterPayload> payload, Swift::ErrorPayload::ref error, const UserInfo &row);
 
		void handleUnregisterRemoteRosterResponse(boost::shared_ptr<Swift::RosterPayload> payload, Swift::ErrorPayload::ref error, const UserInfo &row);
 
		boost::shared_ptr<Swift::InBandRegistrationPayload> generateInBandRegistrationPayload(const Swift::JID& from);
 
		Swift::Form::ref generateRegistrationForm(const UserInfo &res, bool registered);
 
		
 
		Component *m_component;
 
		StorageBackend *m_storageBackend;
 
		UserManager *m_userManager;
 
		Config *m_config;
 

	
 
};
 

	
 
}
spectrum/src/frontends/xmpp/adhoccommand.cpp
Show inline comments
 
file renamed from src/adhoccommand.cpp to spectrum/src/frontends/xmpp/adhoccommand.cpp
 
@@ -9,26 +9,26 @@
 
 * (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 "transport/adhoccommand.h"
 
#include "transport/adhoccommandfactory.h"
 
#include "adhoccommand.h"
 
#include "adhoccommandfactory.h"
 
#include "transport/conversation.h"
 
#include "transport/usermanager.h"
 
#include "transport/storagebackend.h"
 
#include "transport/buddy.h"
 
#include "transport/factory.h"
 
#include "transport/user.h"
 
#include "transport/logging.h"
 

	
 
namespace Transport {
 

	
 
DEFINE_LOGGER(logger, "AdHocCommand");
 

	
spectrum/src/frontends/xmpp/adhoccommand.h
Show inline comments
 
file renamed from include/transport/adhoccommand.h to spectrum/src/frontends/xmpp/adhoccommand.h
spectrum/src/frontends/xmpp/adhoccommandfactory.h
Show inline comments
 
file renamed from include/transport/adhoccommandfactory.h to spectrum/src/frontends/xmpp/adhoccommandfactory.h
 
@@ -14,25 +14,25 @@
 
 * 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 <string>
 
#include <algorithm>
 
#include <map>
 
#include "transport/adhoccommand.h"
 
#include "adhoccommand.h"
 

	
 
namespace Transport {
 

	
 
class Component;
 
class UserManager;
 
class StorageBackend;
 

	
 
class AdHocCommandFactory {
 
	public:
 
		AdHocCommandFactory() {}
 

	
 
		/// Destructor.
spectrum/src/frontends/xmpp/adhocmanager.cpp
Show inline comments
 
file renamed from src/adhocmanager.cpp to spectrum/src/frontends/xmpp/adhocmanager.cpp
 
@@ -9,40 +9,42 @@
 
 * (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 "transport/adhocmanager.h"
 
#include "transport/adhoccommandfactory.h"
 
#include "transport/discoitemsresponder.h"
 
#include "XMPPFrontend.h"
 

	
 
#include "adhocmanager.h"
 
#include "adhoccommandfactory.h"
 
#include "discoitemsresponder.h"
 
#include "transport/conversation.h"
 
#include "transport/usermanager.h"
 
#include "transport/buddy.h"
 
#include "transport/factory.h"
 
#include "transport/user.h"
 
#include "transport/logging.h"
 
#include "transport/storagebackend.h"
 

	
 
namespace Transport {
 

	
 
DEFINE_LOGGER(logger, "AdHocManager");
 

	
 
AdHocManager::AdHocManager(Component *component, DiscoItemsResponder *discoItemsResponder, UserManager *userManager, StorageBackend *storageBackend) : Swift::Responder<Swift::Command>(component->getIQRouter()){
 
AdHocManager::AdHocManager(Component *component, DiscoItemsResponder *discoItemsResponder, UserManager *userManager, StorageBackend *storageBackend) : Swift::Responder<Swift::Command>(static_cast<XMPPFrontend *>(component->getFrontend())->getIQRouter()){
 
	m_component = component;
 
	m_discoItemsResponder = discoItemsResponder;
 
	m_userManager = userManager;
 
	m_storageBackend = storageBackend;
 

	
 
	m_collectTimer = m_component->getNetworkFactories()->getTimerFactory()->createTimer(20);
 
	m_collectTimer->onTick.connect(boost::bind(&AdHocManager::removeOldSessions, this));
 
	m_collectTimer->start();
 

	
 
	m_userManager->onUserCreated.connect(boost::bind(&AdHocManager::handleUserCreated, this, _1));
 
}
 

	
spectrum/src/frontends/xmpp/adhocmanager.h
Show inline comments
 
file renamed from include/transport/adhocmanager.h to spectrum/src/frontends/xmpp/adhocmanager.h
spectrum/src/frontends/xmpp/blockresponder.cpp
Show inline comments
 
file renamed from src/blockresponder.cpp to spectrum/src/frontends/xmpp/blockresponder.cpp
 
@@ -14,25 +14,25 @@
 
 * 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 "blockresponder.h"
 

	
 
#include <iostream>
 
#include <boost/bind.hpp>
 
#include "Swiften/Queries/IQRouter.h"
 
#include "transport/BlockPayload.h"
 
#include "BlockPayload.h"
 
#include "transport/usermanager.h"
 
#include "transport/user.h"
 
#include "transport/buddy.h"
 
#include "transport/rostermanager.h"
 
#include "transport/logging.h"
 

	
 
using namespace Swift;
 
using namespace boost;
 

	
 
namespace Transport {
 

	
 
DEFINE_LOGGER(logger, "BlockResponder");
spectrum/src/frontends/xmpp/blockresponder.h
Show inline comments
 
file renamed from src/blockresponder.h to spectrum/src/frontends/xmpp/blockresponder.h
 
@@ -13,25 +13,25 @@
 
 * 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 <vector>
 
#include "Swiften/Queries/SetResponder.h"
 
#include "transport/BlockPayload.h"
 
#include "BlockPayload.h"
 
#include <boost/signal.hpp>
 

	
 
namespace Transport {
 

	
 
class UserManager;
 
class Buddy;
 

	
 
class BlockResponder : public Swift::SetResponder<Transport::BlockPayload> {
 
	public:
 
		BlockResponder(Swift::IQRouter *router, UserManager *userManager);
 
		~BlockResponder();
 

	
spectrum/src/frontends/xmpp/discoinforesponder.cpp
Show inline comments
 
file renamed from src/discoinforesponder.cpp to spectrum/src/frontends/xmpp/discoinforesponder.cpp
 
@@ -20,24 +20,25 @@
 

	
 
#include "discoinforesponder.h"
 

	
 
#include <iostream>
 
#include <boost/bind.hpp>
 
#include <boost/algorithm/string.hpp>
 
#include "Swiften/Disco/DiscoInfoResponder.h"
 
#include "Swiften/Queries/IQRouter.h"
 
#include "Swiften/Elements/DiscoInfo.h"
 
#include "transport/config.h"
 
#include "transport/logging.h"
 
#include "Swiften/Disco/CapsInfoGenerator.h"
 
#include "XMPPFrontend.h"
 

	
 
using namespace Swift;
 
using namespace boost;
 

	
 
DEFINE_LOGGER(logger, "DiscoInfoResponder");
 

	
 
namespace Transport {
 

	
 
DiscoInfoResponder::DiscoInfoResponder(Swift::IQRouter *router, Config *config) : Swift::GetResponder<DiscoInfo>(router) {
 
	m_config = config;
 
	m_config->onBackendConfigUpdated.connect(boost::bind(&DiscoInfoResponder::updateFeatures, this));
 
	m_buddyInfo = NULL;
spectrum/src/frontends/xmpp/discoinforesponder.h
Show inline comments
 
file renamed from src/discoinforesponder.h to spectrum/src/frontends/xmpp/discoinforesponder.h
spectrum/src/frontends/xmpp/discoitemsresponder.cpp
Show inline comments
 
file renamed from src/discoitemsresponder.cpp to spectrum/src/frontends/xmpp/discoitemsresponder.cpp
 
@@ -9,47 +9,50 @@
 
 * (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 "transport/discoitemsresponder.h"
 
#include "discoitemsresponder.h"
 

	
 
#include <iostream>
 
#include <boost/bind.hpp>
 
#include "Swiften/Queries/IQRouter.h"
 
#include "transport/transport.h"
 
#include "transport/logging.h"
 
#include "transport/config.h"
 
#include "discoinforesponder.h"
 
#include "XMPPFrontend.h"
 
#include "transport/frontend.h"
 

	
 
using namespace Swift;
 
using namespace boost;
 

	
 
namespace Transport {
 

	
 
DEFINE_LOGGER(logger, "DiscoItemsResponder");
 

	
 
DiscoItemsResponder::DiscoItemsResponder(Component *component) : Swift::GetResponder<DiscoItems>(component->getIQRouter()) {
 
DiscoItemsResponder::DiscoItemsResponder(Component *component) : Swift::GetResponder<DiscoItems>(static_cast<XMPPFrontend *>(component->getFrontend())->getIQRouter()) {
 
	m_component = component;
 
	m_commands = boost::shared_ptr<DiscoItems>(new DiscoItems());
 
	m_commands->setNode("http://jabber.org/protocol/commands");
 

	
 
	m_rooms = boost::shared_ptr<DiscoItems>(new DiscoItems());
 
	m_discoInfoResponder = new DiscoInfoResponder(component->getIQRouter(), component->getConfig());
 
	m_discoInfoResponder = new DiscoInfoResponder(static_cast<XMPPFrontend *>(component->getFrontend())->getIQRouter(), component->getConfig());
 
	m_discoInfoResponder->start();
 
}
 

	
 
DiscoItemsResponder::~DiscoItemsResponder() {
 
	delete m_discoInfoResponder;
 
}
 

	
 
void DiscoItemsResponder::addAdHocCommand(const std::string &node, const std::string &name) {
 
	m_commands->addItem(DiscoItems::Item(name, m_component->getJID(), node));
 
	m_discoInfoResponder->addAdHocCommand(node, name);
 
}
 

	
spectrum/src/frontends/xmpp/discoitemsresponder.h
Show inline comments
 
file renamed from include/transport/discoitemsresponder.h to spectrum/src/frontends/xmpp/discoitemsresponder.h
spectrum/src/frontends/xmpp/formutils.cpp
Show inline comments
 
file renamed from src/formutils.cpp to spectrum/src/frontends/xmpp/formutils.cpp
 
@@ -9,26 +9,26 @@
 
 * (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 "transport/formutils.h"
 
#include "transport/adhoccommand.h"
 
#include "formutils.h"
 
#include "adhoccommand.h"
 

	
 
#if HAVE_SWIFTEN_3
 
#include <Swiften/Elements/Form.h>
 
#endif
 

	
 
using namespace Swift;
 

	
 
namespace Transport {
 
namespace FormUtils {
 

	
 
static 
 
#if HAVE_SWIFTEN_3
spectrum/src/frontends/xmpp/formutils.h
Show inline comments
 
file renamed from include/transport/formutils.h to spectrum/src/frontends/xmpp/formutils.h
spectrum/src/frontends/xmpp/gatewayresponder.cpp
Show inline comments
 
file renamed from src/gatewayresponder.cpp to spectrum/src/frontends/xmpp/gatewayresponder.cpp
 
@@ -9,25 +9,25 @@
 
 * (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 "transport/gatewayresponder.h"
 
#include "gatewayresponder.h"
 

	
 
#include <iostream>
 
#include <boost/bind.hpp>
 
#include "Swiften/Queries/IQRouter.h"
 
#include "Swiften/Elements/RawXMLPayload.h"
 
#include "transport/usermanager.h"
 
#include "transport/user.h"
 
#include "transport/transport.h"
 
#include "transport/logging.h"
 

	
 
using namespace Swift;
 
using namespace boost;
spectrum/src/frontends/xmpp/gatewayresponder.h
Show inline comments
 
file renamed from include/transport/gatewayresponder.h to spectrum/src/frontends/xmpp/gatewayresponder.h
spectrum/src/frontends/xmpp/rosterresponder.cpp
Show inline comments
 
file renamed from src/rosterresponder.cpp to spectrum/src/frontends/xmpp/rosterresponder.cpp
 
@@ -19,34 +19,38 @@
 
 */
 

	
 
#include "transport/rosterresponder.h"
 

	
 
#include <iostream>
 
#include <boost/bind.hpp>
 
#include "Swiften/Queries/IQRouter.h"
 
#include "transport/user.h"
 
#include "transport/usermanager.h"
 
#include "transport/rostermanager.h"
 
#include "transport/buddy.h"
 
#include "transport/logging.h"
 
#include "transport/factory.h"
 
#include "XMPPFrontend.h"
 
#include "transport/frontend.h"
 

	
 
using namespace Swift;
 
using namespace boost;
 

	
 
namespace Transport {
 

	
 
DEFINE_LOGGER(logger, "RosterResponder");
 

	
 
RosterResponder::RosterResponder(Swift::IQRouter *router, UserManager *userManager) : Swift::Responder<RosterPayload>(router) {
 
	m_userManager = userManager;
 
	m_router = router;
 
}
 

	
 
RosterResponder::~RosterResponder() {
 
}
 

	
 
bool RosterResponder::handleGetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr<Swift::RosterPayload> payload) {
 
	// Get means we're in server mode and user wants to fetch his roster.
 
	// For now we send empty reponse, but TODO: Get buddies from database and send proper stored roster.
 
	User *user = m_userManager->getUser(from.toBare().toString());
 
	if (!user) {
 
		sendResponse(from, id, boost::shared_ptr<RosterPayload>(new RosterPayload()));
 
		LOG4CXX_WARN(logger, from.toBare().toString() << ": User is not logged in");
 
@@ -72,42 +76,42 @@ bool RosterResponder::handleSetRequest(const Swift::JID& from, const Swift::JID&
 
	}
 

	
 
	Swift::RosterItemPayload item = payload->getItems()[0];
 

	
 
	if (item.getJID().getNode().empty()) {
 
		return true;
 
	}
 

	
 
	Buddy *buddy = user->getRosterManager()->getBuddy(Buddy::JIDToLegacyName(item.getJID()));
 
	if (buddy) {
 
		if (item.getSubscription() == Swift::RosterItemPayload::Remove) {
 
			LOG4CXX_INFO(logger, from.toBare().toString() << ": Removing buddy " << buddy->getName());
 
			onBuddyRemoved(buddy);
 
			user->getComponent()->getFrontend()->onBuddyRemoved(buddy);
 

	
 
			// send roster push here
 
			Swift::SetRosterRequest::ref request = Swift::SetRosterRequest::create(payload, user->getJID().toBare(), user->getComponent()->getIQRouter());
 
			Swift::SetRosterRequest::ref request = Swift::SetRosterRequest::create(payload, user->getJID().toBare(), m_router);
 
			request->send();
 
		}
 
		else {
 
			LOG4CXX_INFO(logger, from.toBare().toString() << ": Updating buddy " << buddy->getName());
 
			onBuddyUpdated(buddy, item);
 
			user->getComponent()->getFrontend()->onBuddyUpdated(buddy, item);
 
		}
 
	}
 
	else if (item.getSubscription() != Swift::RosterItemPayload::Remove) {
 
		// Roster push for this new buddy is sent by RosterManager
 
		BuddyInfo buddyInfo;
 
		buddyInfo.id = -1;
 
		buddyInfo.alias = item.getName();
 
		buddyInfo.legacyName = Buddy::JIDToLegacyName(item.getJID());
 
		buddyInfo.subscription = "both";
 
		buddyInfo.flags = Buddy::buddyFlagsFromJID(item.getJID());
 
		LOG4CXX_INFO(logger, from.toBare().toString() << ": Adding buddy " << buddyInfo.legacyName);
 

	
 
		buddy = user->getComponent()->getFactory()->createBuddy(user->getRosterManager(), buddyInfo);
 
		user->getRosterManager()->setBuddy(buddy);
 
		onBuddyAdded(buddy, item);
 
		user->getComponent()->getFrontend()->onBuddyAdded(buddy, item);
 
	}
 

	
 
	return true;
 
}
 

	
 
}
spectrum/src/frontends/xmpp/settingsadhoccommand.cpp
Show inline comments
 
file renamed from src/settingsadhoccommand.cpp to spectrum/src/frontends/xmpp/settingsadhoccommand.cpp
 
@@ -9,33 +9,33 @@
 
 * (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 "transport/settingsadhoccommand.h"
 
#include "settingsadhoccommand.h"
 
#include "transport/conversation.h"
 
#include "transport/usermanager.h"
 
#include "transport/buddy.h"
 
#include "transport/factory.h"
 
#include "transport/user.h"
 
#include "transport/logging.h"
 
#include "transport/storagebackend.h"
 
#include "transport/formutils.h"
 
#include "formutils.h"
 

	
 

	
 
namespace Transport {
 

	
 
DEFINE_LOGGER(logger, "SettingsAdHocCommand");
 

	
 
SettingsAdHocCommand::SettingsAdHocCommand(Component *component, UserManager *userManager, StorageBackend *storageBackend, const Swift::JID &initiator, const Swift::JID &to) : AdHocCommand(component, userManager, storageBackend, initiator, to) {
 
	m_state = Init;
 
}
 

	
 
SettingsAdHocCommand::~SettingsAdHocCommand() {
 
}
spectrum/src/frontends/xmpp/settingsadhoccommand.h
Show inline comments
 
file renamed from include/transport/settingsadhoccommand.h to spectrum/src/frontends/xmpp/settingsadhoccommand.h
 
@@ -14,26 +14,26 @@
 
 * 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 <string>
 
#include <algorithm>
 
#include <map>
 
#include "transport/adhoccommand.h"
 
#include "transport/adhoccommandfactory.h"
 
#include "adhoccommand.h"
 
#include "adhoccommandfactory.h"
 
#include <Swiften/Version.h>
 
#define HAVE_SWIFTEN_3  (SWIFTEN_VERSION >= 0x030000)
 

	
 

	
 
namespace Transport {
 

	
 
class Component;
 
class UserManager;
 
class StorageBackend;
 
class UserInfo;
 

	
 
class SettingsAdHocCommand : public AdHocCommand {
spectrum/src/frontends/xmpp/statsresponder.cpp
Show inline comments
 
file renamed from src/statsresponder.cpp to spectrum/src/frontends/xmpp/statsresponder.cpp
 
@@ -9,49 +9,50 @@
 
 * (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 "transport/statsresponder.h"
 
#include "statsresponder.h"
 

	
 
#include <iostream>
 
#include <boost/bind.hpp>
 
#include "Swiften/Queries/IQRouter.h"
 
#include "transport/BlockPayload.h"
 
#include "transport/usermanager.h"
 
#include "transport/user.h"
 
#include "transport/buddy.h"
 
#include "transport/rostermanager.h"
 
#include "transport/memoryusage.h"
 
#include "transport/conversationmanager.h"
 
#include "transport/rostermanager.h"
 
#include "transport/usermanager.h"
 
#include "transport/networkpluginserver.h"
 
#include "transport/logging.h"
 
#include "transport/frontend.h"
 
#include "XMPPFrontend.h"
 

	
 
using namespace Swift;
 
using namespace boost;
 

	
 
namespace Transport {
 

	
 
DEFINE_LOGGER(logger, "StatsResponder");
 

	
 
StatsResponder::StatsResponder(Component *component, UserManager *userManager, NetworkPluginServer *server, StorageBackend *storageBackend) : Swift::Responder<StatsPayload>(component->getIQRouter()) {
 
StatsResponder::StatsResponder(Component *component, UserManager *userManager, NetworkPluginServer *server, StorageBackend *storageBackend) : Swift::Responder<StatsPayload>(static_cast<XMPPFrontend *>(component->getFrontend())->getIQRouter()) {
 
	m_component = component;
 
	m_userManager = userManager;
 
	m_server = server;
 
	m_storageBackend = storageBackend;
 
	m_start = time(0);
 
}
 

	
 
StatsResponder::~StatsResponder() {
 
	
 
}
 

	
 
unsigned long StatsResponder::usedMemory() {
spectrum/src/frontends/xmpp/statsresponder.h
Show inline comments
 
file renamed from include/transport/statsresponder.h to spectrum/src/frontends/xmpp/statsresponder.h
spectrum/src/frontends/xmpp/storageparser.cpp
Show inline comments
 
file renamed from src/storageparser.cpp to spectrum/src/frontends/xmpp/storageparser.cpp
spectrum/src/frontends/xmpp/storageparser.h
Show inline comments
 
file renamed from src/storageparser.h to spectrum/src/frontends/xmpp/storageparser.h
spectrum/src/frontends/xmpp/storageresponder.cpp
Show inline comments
 
file renamed from src/storageresponder.cpp to spectrum/src/frontends/xmpp/storageresponder.cpp
spectrum/src/frontends/xmpp/storageresponder.h
Show inline comments
 
file renamed from src/storageresponder.h to spectrum/src/frontends/xmpp/storageresponder.h
spectrum/src/frontends/xmpp/vcardresponder.cpp
Show inline comments
 
file renamed from src/vcardresponder.cpp to spectrum/src/frontends/xmpp/vcardresponder.cpp
 
@@ -9,34 +9,35 @@
 
 * (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 "transport/vcardresponder.h"
 
#include "vcardresponder.h"
 

	
 
#include <iostream>
 
#include <boost/bind.hpp>
 
#include "Swiften/Queries/IQRouter.h"
 
#include "transport/user.h"
 
#include "transport/buddy.h"
 
#include "transport/usermanager.h"
 
#include "transport/rostermanager.h"
 
#include "transport/transport.h"
 
#include "transport/logging.h"
 
#include "Swiften/Queries/IQRouter.h"
 

	
 
using namespace Swift;
 
using namespace boost;
 

	
 
namespace Transport {
 

	
 
DEFINE_LOGGER(logger, "VCardResponder");
 

	
 
VCardResponder::VCardResponder(Swift::IQRouter *router, Swift::NetworkFactories *factories, UserManager *userManager) : Swift::Responder<VCard>(router) {
 
	m_id = 0;
 
	m_userManager = userManager;
 
	m_collectTimer = factories->getTimerFactory()->createTimer(20000);
spectrum/src/frontends/xmpp/vcardresponder.h
Show inline comments
 
file renamed from include/transport/vcardresponder.h to spectrum/src/frontends/xmpp/vcardresponder.h
spectrum/src/main.cpp
Show inline comments
 
#include "transport/config.h"
 
#include "transport/transport.h"
 
#include "transport/filetransfermanager.h"
 
#include "transport/usermanager.h"
 
#include "transport/sqlite3backend.h"
 
#include "transport/mysqlbackend.h"
 
#include "transport/pqxxbackend.h"
 
#include "transport/userregistration.h"
 
#include "transport/networkpluginserver.h"
 
#include "transport/admininterface.h"
 
#include "transport/statsresponder.h"
 
#include "transport/usersreconnecter.h"
 
#include "transport/util.h"
 
#include "transport/gatewayresponder.h"
 
#include "transport/logging.h"
 
#include "transport/discoitemsresponder.h"
 
#include "transport/adhocmanager.h"
 
#include "transport/settingsadhoccommand.h"
 
#include "frontends/xmpp/XMPPFrontend.h"
 
#include "Swiften/EventLoop/SimpleEventLoop.h"
 
#include "Swiften/Network/BoostNetworkFactories.h"
 
#include <boost/filesystem.hpp>
 
#include <boost/algorithm/string.hpp>
 
#ifndef WIN32
 
#include "sys/signal.h"
 
#include "sys/stat.h"
 
#include <pwd.h>
 
#include <grp.h>
 
#include <sys/resource.h>
 
#include "libgen.h"
 
#ifndef __FreeBSD__
 
@@ -37,29 +33,29 @@
 
#define getpid _getpid
 
#include "win32/ServiceWrapper.h"
 
#endif
 
#include <sys/stat.h>
 

	
 
using namespace Transport;
 
using namespace Transport::Util;
 

	
 
DEFINE_LOGGER(logger, "Spectrum");
 

	
 
Swift::SimpleEventLoop *eventLoop_ = NULL;
 
Component *component_ = NULL;
 
UserManager *userManager_ = NULL;
 
UserManager *userManager = NULL;
 
Config *config_ = NULL;
 

	
 
static void stop_spectrum() {
 
	userManager_->removeAllUsers(false);
 
	userManager->removeAllUsers(false);
 
	component_->stop();
 
	eventLoop_->stop();
 
}
 

	
 
static void spectrum_sigint_handler(int sig) {
 
	eventLoop_->postEvent(&stop_spectrum);
 
}
 

	
 
static void spectrum_sigterm_handler(int sig) {
 
	eventLoop_->postEvent(&stop_spectrum);
 
}
 

	
 
@@ -203,93 +199,72 @@ int mainloop() {
 

	
 
	struct rlimit limit;
 
	limit.rlim_max = RLIM_INFINITY;
 
	limit.rlim_cur = RLIM_INFINITY;
 
	setrlimit(RLIMIT_CORE, &limit);
 
#endif
 

	
 
	Swift::SimpleEventLoop eventLoop;
 

	
 
	Swift::BoostNetworkFactories *factories = new Swift::BoostNetworkFactories(&eventLoop);
 
	UserRegistry userRegistry(config_, factories);
 

	
 
	Component transport(&eventLoop, factories, config_, NULL, &userRegistry);
 
	XMPPFrontend frontend;
 

	
 
	Component transport(&frontend, &eventLoop, factories, config_, NULL, &userRegistry);
 
	component_ = &transport;
 
// 	Logger logger(&transport);
 

	
 
	std::string error;
 
	StorageBackend *storageBackend = StorageBackend::createBackend(config_, error);
 
	if (storageBackend == NULL) {
 
		if (!error.empty()) {
 
			std::cerr << error << "\n";
 
			return -2;
 
		}
 
	}
 
	else if (!storageBackend->connect()) {
 
		std::cerr << "Can't connect to database. Check the log to find out the reason.\n";
 
		return -1;
 
	}
 

	
 
	Logging::redirect_stderr();
 

	
 
	DiscoItemsResponder discoItemsResponder(&transport);
 
	discoItemsResponder.start();
 

	
 
	UserManager userManager(&transport, &userRegistry, &discoItemsResponder, storageBackend);
 
	userManager_ = &userManager;
 
	userManager = frontend.createUserManager(&transport, &userRegistry, storageBackend);;
 
	UserRegistration *userRegistration = userManager->getUserRegistration();
 

	
 
	UserRegistration *userRegistration = NULL;
 
	UsersReconnecter *usersReconnecter = NULL;
 
	if (storageBackend) {
 
		userRegistration = new UserRegistration(&transport, &userManager, storageBackend);
 
		userRegistration->start();
 

	
 
		usersReconnecter = new UsersReconnecter(&transport, storageBackend);
 
	}
 
	else if (!CONFIG_BOOL(config_, "service.server_mode")) {
 
		LOG4CXX_WARN(logger, "Registrations won't work, you have specified [database] type=none in config file.");
 
	}
 

	
 
	FileTransferManager ftManager(&transport, &userManager);
 
	FileTransferManager ftManager(&transport, userManager);
 

	
 
	NetworkPluginServer plugin(&transport, config_, &userManager, &ftManager, &discoItemsResponder);
 
	NetworkPluginServer plugin(&transport, config_, userManager, &ftManager);
 
	plugin.start();
 

	
 
	AdminInterface adminInterface(&transport, &userManager, &plugin, storageBackend, userRegistration);
 
	AdminInterface adminInterface(&transport, userManager, &plugin, storageBackend, userRegistration);
 
	plugin.setAdminInterface(&adminInterface);
 

	
 
	StatsResponder statsResponder(&transport, &userManager, &plugin, storageBackend);
 
	statsResponder.start();
 

	
 
	GatewayResponder gatewayResponder(transport.getIQRouter(), &userManager);
 
	gatewayResponder.start();
 

	
 
	AdHocManager adhocmanager(&transport, &discoItemsResponder, &userManager, storageBackend);
 
	adhocmanager.start();
 

	
 
	SettingsAdHocCommandFactory settings;
 
	adhocmanager.addAdHocCommand(&settings);
 

	
 
	eventLoop_ = &eventLoop;
 

	
 
	eventLoop.run();
 

	
 
#ifndef WIN32
 
	umask(old_cmask);
 
#endif
 

	
 
	if (userRegistration) {
 
		userRegistration->stop();
 
		delete userRegistration;
 
	}
 
	delete userManager;
 

	
 
	if (usersReconnecter) {
 
		delete usersReconnecter;
 
	}
 

	
 
	delete storageBackend;
 
	delete factories;
 
	return 0;
 
}
 

	
 

	
 
int main(int argc, char **argv)
src/CMakeLists.txt
Show inline comments
 
@@ -4,27 +4,30 @@ FILE(GLOB_RECURSE SWIFTEN_SRC ../include/Swiften/*.cpp)
 

	
 
# Build without openssl on msvc
 
if (NOT MSVC)
 
	string(REGEX REPLACE "[^;]+;?/Schannel/[^;]+;?" "" SWIFTEN_SRC "${SWIFTEN_SRC}") 
 
else()
 
	string(REGEX REPLACE "[^;]+;?/OpenSSL/[^;]+;?" "" SWIFTEN_SRC "${SWIFTEN_SRC}") 
 
endif()
 

	
 
FILE(GLOB HEADERS ../include/transport/*.h)
 

	
 
if (CPPUNIT_FOUND)
 
	FILE(GLOB SRC_TEST tests/*.cpp)
 
	FILE(GLOB SRC_TEST_FRONTEND ../spectrum/src/frontends/xmpp/*.cpp)
 
	include_directories(../spectrum/src/frontends/xmpp/)
 

	
 
	ADD_EXECUTABLE(libtransport_test ${SRC_TEST})
 
	ADD_EXECUTABLE(libtransport_test ${SRC_TEST} ${SRC_TEST_FRONTEND})
 
	set_target_properties(libtransport_test PROPERTIES COMPILE_DEFINITIONS LIBTRANSPORT_TEST=1)
 
	
 

	
 
	target_link_libraries(libtransport_test transport ${CPPUNIT_LIBRARY} ${Boost_LIBRARIES})
 
endif()
 

	
 
if (NOT WIN32)
 
include_directories(${POPT_INCLUDE_DIR})
 
endif()
 

	
 
# SOURCE_GROUP(headers FILES ${HEADERS})
 

	
 

	
 
if (PROTOBUF_FOUND)
src/admininterface.cpp
Show inline comments
 
@@ -19,49 +19,50 @@
 
 */
 

	
 
#include "transport/admininterface.h"
 
#include "transport/user.h"
 
#include "transport/transport.h"
 
#include "transport/storagebackend.h"
 
#include "transport/conversationmanager.h"
 
#include "transport/rostermanager.h"
 
#include "transport/usermanager.h"
 
#include "transport/networkpluginserver.h"
 
#include "transport/logging.h"
 
#include "transport/userregistration.h"
 
#include "transport/frontend.h"
 
#include "storageresponder.h"
 
#include "transport/memoryusage.h"
 
#include <boost/foreach.hpp>
 

	
 
namespace Transport {
 

	
 
DEFINE_LOGGER(logger, "AdminInterface");
 

	
 
static std::string getArg(const std::string &body) {
 
	std::string ret;
 
	if (body.find(" ") == std::string::npos)
 
		return ret;
 

	
 
	return body.substr(body.find(" ") + 1);
 
}
 

	
 
AdminInterface::AdminInterface(Component *component, UserManager *userManager, NetworkPluginServer *server, StorageBackend *storageBackend, UserRegistration *userRegistration) {
 
	m_component = component;
 
	m_storageBackend = storageBackend;
 
	m_userManager = userManager;
 
	m_server = server;
 
	m_userRegistration = userRegistration;
 
	m_start = time(NULL);
 

	
 
	m_component->getStanzaChannel()->onMessageReceived.connect(bind(&AdminInterface::handleMessageReceived, this, _1));
 
	m_component->getFrontend()->onMessageReceived.connect(bind(&AdminInterface::handleMessageReceived, this, _1));
 
}
 

	
 
AdminInterface::~AdminInterface() {
 
}
 

	
 
void AdminInterface::handleQuery(Swift::Message::ref message) {
 
	LOG4CXX_INFO(logger, "Message from admin received: '" << message->getBody() << "'");
 
	message->setTo(message->getFrom());
 
	message->setFrom(m_component->getJID());
 

	
 
	if (message->getBody() == "status") {
 
		int users = m_userManager->getUserCount();
 
@@ -344,16 +345,16 @@ void AdminInterface::handleMessageReceived(Swift::Message::ref message) {
 
	    LOG4CXX_WARN(logger, "Message not from admin user, but from " << message->getFrom().toBare().toString());
 
	    return;
 
	
 
	}
 
	
 
	// Ignore empty messages
 
	if (message->getBody().empty()) {
 
		return;
 
	}
 

	
 
	handleQuery(message);
 

	
 
	m_component->getStanzaChannel()->sendMessage(message);
 
	m_component->getFrontend()->sendMessage(message);
 
}
 

	
 
}
src/buddy.cpp
Show inline comments
 
@@ -13,45 +13,42 @@
 
 * 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/buddy.h"
 
#include "transport/rostermanager.h"
 
#include "transport/user.h"
 
#include "transport/transport.h"
 
#include "transport/BlockPayload.h"
 
#include "transport/usermanager.h"
 
#include "transport/discoitemsresponder.h"
 
#include "transport/frontend.h"
 

	
 
#include "Swiften/Elements/VCardUpdate.h"
 

	
 
namespace Transport {
 

	
 
Buddy::Buddy(RosterManager *rosterManager, long id, BuddyFlag flags) : m_id(id), m_flags(flags), m_rosterManager(rosterManager),
 
	m_subscription(Ask) {
 
// 	m_rosterManager->setBuddy(this);
 
}
 

	
 
Buddy::~Buddy() {
 
// 	m_rosterManager->unsetBuddy(this);
 
}
 

	
 
void Buddy::sendPresence() {
 
	std::vector<Swift::Presence::ref> &presences = generatePresenceStanzas(255);
 
	BOOST_FOREACH(Swift::Presence::ref presence, presences) {
 
		m_rosterManager->getUser()->getComponent()->getStanzaChannel()->sendPresence(presence);
 
		m_rosterManager->getUser()->getComponent()->getFrontend()->sendPresence(presence);
 
	}
 
}
 

	
 
void Buddy::generateJID() {
 
	m_jid = Swift::JID();
 
	m_jid = Swift::JID(getSafeName(), m_rosterManager->getUser()->getComponent()->getJID().toString(), "bot");
 
}
 

	
 
void Buddy::setID(long id) {
 
	m_id = id;
 
}
 

	
 
@@ -89,25 +86,25 @@ Buddy::Subscription Buddy::getSubscription() {
 
	return m_subscription;
 
}
 

	
 
void Buddy::handleRawPresence(Swift::Presence::ref presence) {
 
	for (std::vector<Swift::Presence::ref>::iterator it = m_presences.begin(); it != m_presences.end(); it++) {
 
		if ((*it)->getFrom() == presence->getFrom()) {
 
			m_presences.erase(it);
 
			break;
 
		}
 
	}
 

	
 
	m_presences.push_back(presence);
 
	m_rosterManager->getUser()->getComponent()->getStanzaChannel()->sendPresence(presence);
 
	m_rosterManager->getUser()->getComponent()->getFrontend()->sendPresence(presence);
 
}
 

	
 
std::vector<Swift::Presence::ref> &Buddy::generatePresenceStanzas(int features, bool only_new) {
 
	if (m_jid.getNode().empty()) {
 
		generateJID();
 
	}
 

	
 
	Swift::StatusShow s;
 
	std::string statusMessage;
 
	if (!getStatus(s, statusMessage)) {
 
		for (std::vector<Swift::Presence::ref>::iterator it = m_presences.begin(); it != m_presences.end(); it++) {
 
			if ((*it)->getFrom() == m_jid) {
 
@@ -124,33 +121,32 @@ std::vector<Swift::Presence::ref> &Buddy::generatePresenceStanzas(int features,
 
	presence->setType(Swift::Presence::Available);
 

	
 
	if (!statusMessage.empty())
 
		presence->setStatus(statusMessage);
 

	
 
	if (s.getType() == Swift::StatusShow::None)
 
		presence->setType(Swift::Presence::Unavailable);
 

	
 
	presence->setShow(s.getType());
 

	
 
	if (presence->getType() != Swift::Presence::Unavailable) {
 
		// caps
 
		
 
		presence->addPayload(boost::shared_ptr<Swift::Payload>(new Swift::CapsInfo(m_rosterManager->getUser()->getUserManager()->getDiscoResponder()->getBuddyCapsInfo())));
 
	
 

	
 
// 		if (features & 0/*TRANSPORT_FEATURE_AVATARS*/) {
 
			presence->addPayload(boost::shared_ptr<Swift::Payload>(new Swift::VCardUpdate (getIconHash())));
 
// 		}
 
		if (isBlocked()) {
 
			presence->addPayload(boost::shared_ptr<Swift::Payload>(new Transport::BlockPayload ()));
 
		}
 
// 		if (isBlocked()) {
 
// 			presence->addPayload(boost::shared_ptr<Swift::Payload>(new Transport::BlockPayload ()));
 
// 		}
 
	}
 

	
 
	BOOST_FOREACH(Swift::Presence::ref &p, m_presences) {
 
		if (p->getFrom() == presence->getFrom()) {
 
			p = presence;
 
			return m_presences;
 
		}
 
	}
 

	
 
	m_presences.push_back(presence);
 

	
 
// 	if (only_new) {
 
@@ -177,26 +173,25 @@ std::string Buddy::getSafeName() {
 
	else {
 
		if (name.find_last_of("@") != std::string::npos) {
 
			name.replace(name.find_last_of("@"), 1, "%"); // OK
 
		}
 
	}
 
// 	if (name.empty()) {
 
// 		Log("SpectrumBuddy::getSafeName", "Name is EMPTY! Previous was " << getName() << ".");
 
// 	}
 
	return name;
 
}
 

	
 
void Buddy::handleVCardReceived(const std::string &id, Swift::VCard::ref vcard) {
 
	boost::shared_ptr<Swift::GenericRequest<Swift::VCard> > request(new Swift::GenericRequest<Swift::VCard>(Swift::IQ::Result, m_rosterManager->getUser()->getJID(), vcard, m_rosterManager->getUser()->getComponent()->getIQRouter()));
 
	request->send();
 
	m_rosterManager->getUser()->getComponent()->getFrontend()->sendVCard(vcard, m_rosterManager->getUser()->getJID());
 
}
 

	
 
std::string Buddy::JIDToLegacyName(const Swift::JID &jid) {
 
	std::string name;
 
	if (jid.getUnescapedNode() == jid.getNode()) {
 
		name = jid.getNode();
 
		if (name.find_last_of("%") != std::string::npos) {
 
			name.replace(name.find_last_of("%"), 1, "@"); // OK
 
		}
 
	}
 
	else {
 
		name = jid.getUnescapedNode();
src/conversation.cpp
Show inline comments
 
@@ -16,24 +16,26 @@
 
 * 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 <iostream>
 
#include "transport/conversation.h"
 
#include "transport/conversationmanager.h"
 
#include "transport/user.h"
 
#include "transport/transport.h"
 
#include "transport/buddy.h"
 
#include "transport/rostermanager.h"
 
#include "transport/frontend.h"
 
#include "transport/config.h"
 

	
 
#include "Swiften/Elements/MUCItem.h"
 
#include "Swiften/Elements/MUCOccupant.h"
 
#include "Swiften/Elements/MUCUserPayload.h"
 
#include "Swiften/Elements/Delay.h"
 
#include "Swiften/Elements/MUCPayload.h"
 

	
 
namespace Transport {
 

	
 
Conversation::Conversation(ConversationManager *conversationManager, const std::string &legacyName, bool isMUC) : m_conversationManager(conversationManager) {
 
	m_legacyName = legacyName;
 
	m_muc = isMUC;
 
@@ -68,25 +70,25 @@ void Conversation::destroyRoom() {
 
		p->addItem(item);
 

	
 
		Swift::MUCUserPayload::StatusCode c;
 
		c.code = 332;
 
		p->addStatusCode(c);
 
		Swift::MUCUserPayload::StatusCode c2;
 
		c2.code = 307;
 
		p->addStatusCode(c2);
 

	
 
		presence->addPayload(boost::shared_ptr<Swift::Payload>(p));
 
		BOOST_FOREACH(const Swift::JID &jid, m_jids) {
 
			presence->setTo(jid);
 
			m_conversationManager->getComponent()->getStanzaChannel()->sendPresence(presence);
 
			m_conversationManager->getComponent()->getFrontend()->sendPresence(presence);
 
		}
 
	}
 
}
 

	
 
void Conversation::setRoom(const std::string &room) {
 
	m_room = room;
 
	m_legacyName = m_room + "/" + m_legacyName;
 
}
 

	
 
void Conversation::cacheMessage(boost::shared_ptr<Swift::Message> &message) {
 
	boost::posix_time::ptime timestamp = boost::posix_time::second_clock::universal_time();
 
	boost::shared_ptr<Swift::Delay> delay(boost::make_shared<Swift::Delay>());
 
@@ -95,40 +97,40 @@ void Conversation::cacheMessage(boost::shared_ptr<Swift::Message> &message) {
 
	m_cachedMessages.push_back(message);
 
	if (m_cachedMessages.size() > 100) {
 
		m_cachedMessages.pop_front();
 
	}
 
}
 

	
 
void Conversation::handleRawMessage(boost::shared_ptr<Swift::Message> &message) {
 
	if (message->getType() != Swift::Message::Groupchat) {
 
		if (m_conversationManager->getComponent()->inServerMode() && m_conversationManager->getUser()->shouldCacheMessages()) {
 
			cacheMessage(message);
 
		}
 
		else {
 
			m_conversationManager->getComponent()->getStanzaChannel()->sendMessage(message);
 
			m_conversationManager->getComponent()->getFrontend()->sendMessage(message);
 
		}
 
	}
 
	else {
 
		if (m_jids.empty()) {
 
			cacheMessage(message);
 
		}
 
		else {
 
			BOOST_FOREACH(const Swift::JID &jid, m_jids) {
 
				message->setTo(jid);
 
				// Subject has to be sent after our own presence (the one with code 110)
 
				if (!message->getSubject().empty() && m_sentInitialPresence == false) {
 
					m_subject = message;
 
					return;
 
				}
 
				m_conversationManager->getComponent()->getStanzaChannel()->sendMessage(message);
 
				m_conversationManager->getComponent()->getFrontend()->sendMessage(message);
 
			}
 
		}
 
	}
 
}
 

	
 
void Conversation::handleMessage(boost::shared_ptr<Swift::Message> &message, const std::string &nickname) {
 
	if (m_muc) {
 
		message->setType(Swift::Message::Groupchat);
 
	}
 
	else {
 
		if (message->getType() == Swift::Message::Headline) {
 
			if (m_conversationManager->getUser()->getUserSetting("send_headlines") != "1") {
 
@@ -192,47 +194,47 @@ void Conversation::handleMessage(boost::shared_ptr<Swift::Message> &message, con
 
			n = " ";
 
		}
 

	
 
		message->setFrom(Swift::JID(legacyName, m_conversationManager->getComponent()->getJID().toBare(), n));
 
	}
 

	
 
	handleRawMessage(message);
 
}
 

	
 
void Conversation::sendParticipants(const Swift::JID &to) {
 
	for (std::map<std::string, Swift::Presence::ref>::iterator it = m_participants.begin(); it != m_participants.end(); it++) {
 
		(*it).second->setTo(to);
 
		m_conversationManager->getComponent()->getStanzaChannel()->sendPresence((*it).second);
 
		m_conversationManager->getComponent()->getFrontend()->sendPresence((*it).second);
 
	}
 
}
 

	
 
void Conversation::sendCachedMessages(const Swift::JID &to) {
 
	for (std::list<boost::shared_ptr<Swift::Message> >::const_iterator it = m_cachedMessages.begin(); it != m_cachedMessages.end(); it++) {
 
		if (to.isValid()) {
 
			(*it)->setTo(to);
 
		}
 
		else {
 
			(*it)->setTo(m_jid.toBare());
 
		}
 
		m_conversationManager->getComponent()->getStanzaChannel()->sendMessage(*it);
 
		m_conversationManager->getComponent()->getFrontend()->sendMessage(*it);
 
	}
 

	
 
	if (m_subject) {
 
		if (to.isValid()) {
 
			m_subject->setTo(to);
 
		}
 
		else {
 
			m_subject->setTo(m_jid.toBare());
 
		}
 
		m_conversationManager->getComponent()->getStanzaChannel()->sendMessage(m_subject);
 
		m_conversationManager->getComponent()->getFrontend()->sendMessage(m_subject);
 
	}
 

	
 
	m_cachedMessages.clear();
 
}
 

	
 
Swift::Presence::ref Conversation::generatePresence(const std::string &nick, int flag, int status, const std::string &statusMessage, const std::string &newname) {
 
	std::string nickname = nick;
 
	Swift::Presence::ref presence = Swift::Presence::create();
 
	std::string legacyName = m_legacyName;
 
	if (m_muc) {
 
		if (legacyName.find_last_of("@") != std::string::npos) {
 
			legacyName.replace(legacyName.find_last_of("@"), 1, "%"); // OK
 
@@ -313,42 +315,42 @@ Swift::Presence::ref Conversation::generatePresence(const std::string &nick, int
 
}
 

	
 

	
 
void Conversation::setNickname(const std::string &nickname) {
 
	if (!nickname.empty() && m_nickname != nickname) {
 
		m_nicknameChanged = true;
 
	}
 
	m_nickname = nickname;
 
}
 

	
 
void Conversation::handleRawPresence(Swift::Presence::ref presence) {
 
	// TODO: Detect nickname change.
 
	m_conversationManager->getComponent()->getStanzaChannel()->sendPresence(presence);
 
	m_conversationManager->getComponent()->getFrontend()->sendPresence(presence);
 
	m_participants[presence->getFrom().getResource()] = presence;
 
}
 

	
 
void Conversation::handleParticipantChanged(const std::string &nick, Conversation::ParticipantFlag flag, int status, const std::string &statusMessage, const std::string &newname) {
 
	Swift::Presence::ref presence = generatePresence(nick, flag, status, statusMessage, newname);
 

	
 
	if (presence->getType() == Swift::Presence::Unavailable) {
 
		m_participants.erase(nick);
 
	}
 
	else {
 
		m_participants[nick] = presence;
 
	}
 

	
 

	
 
	BOOST_FOREACH(const Swift::JID &jid, m_jids) {
 
		presence->setTo(jid);
 
		m_conversationManager->getComponent()->getStanzaChannel()->sendPresence(presence);
 
		m_conversationManager->getComponent()->getFrontend()->sendPresence(presence);
 
	}
 
	if (!newname.empty()) {
 
		handleParticipantChanged(newname, flag, status, statusMessage);
 
	}
 

	
 
	if (m_sentInitialPresence && m_subject) {
 
		m_conversationManager->getComponent()->getStanzaChannel()->sendMessage(m_subject);
 
		m_conversationManager->getComponent()->getFrontend()->sendMessage(m_subject);
 
		m_subject.reset();
 
	}
 
}
 

	
 
}
src/filetransfermanager.cpp
Show inline comments
 
@@ -22,81 +22,81 @@
 
#include "transport/transport.h"
 
#include "transport/usermanager.h"
 
#include "transport/user.h"
 
#include "transport/buddy.h"
 
#include "transport/logging.h"
 
#include "Swiften/Network/ConnectionServerFactory.h"
 

	
 
namespace Transport {
 

	
 
DEFINE_LOGGER(logger, "FileTransferManager");
 

	
 
FileTransferManager::FileTransferManager(Component *component, UserManager *userManager) {
 
	m_component = component;
 
	m_userManager = userManager;
 

	
 
	m_jingleSessionManager = new Swift::JingleSessionManager(m_component->getIQRouter());
 
#if !HAVE_SWIFTEN_3
 
	m_connectivityManager = new Swift::ConnectivityManager(m_component->getNetworkFactories()->getNATTraverser());
 
#endif
 
	m_bytestreamRegistry = new Swift::SOCKS5BytestreamRegistry();
 
#if !HAVE_SWIFTEN_3
 
	m_bytestreamProxy = new Swift::SOCKS5BytestreamProxy(m_component->getNetworkFactories()->getConnectionFactory(), m_component->getNetworkFactories()->getTimerFactory());
 
	m_localCandidateGeneratorFactory = new Swift::DefaultLocalJingleTransportCandidateGeneratorFactory(m_connectivityManager, m_bytestreamRegistry, m_bytestreamProxy, "thishouldnotbeused");
 
	m_remoteCandidateSelectorFactory = new Swift::DefaultRemoteJingleTransportCandidateSelectorFactory(m_component->getNetworkFactories()->getConnectionFactory(), m_component->getNetworkFactories()->getTimerFactory());
 
#else
 
	m_proxyManager = new Swift::SOCKS5BytestreamProxiesManager(m_component->getNetworkFactories()->getConnectionFactory(), m_component->getNetworkFactories()->getTimerFactory(), m_component->getNetworkFactories()->getDomainNameResolver(), m_component->getIQRouter(), "bar.com");
 
#endif
 
	boost::shared_ptr<Swift::ConnectionServer> server = m_component->getNetworkFactories()->getConnectionServerFactory()->createConnectionServer(19645);
 
	server->start();
 
#if HAVE_SWIFTEN_3
 
	m_proxyServerManager = new Swift::SOCKS5BytestreamServerManager(m_bytestreamRegistry, m_component->getNetworkFactories()->getConnectionServerFactory(), m_component->getNetworkFactories()->getNetworkEnvironment(), m_component->getNetworkFactories()->getNATTraverser());
 
#else
 
	m_bytestreamServer = new Swift::SOCKS5BytestreamServer(server, m_bytestreamRegistry);
 
	m_bytestreamServer->start();
 
	m_outgoingFTManager = new Swift::CombinedOutgoingFileTransferManager(m_jingleSessionManager, m_component->getIQRouter(),
 
		m_userManager, m_remoteCandidateSelectorFactory,
 
		m_localCandidateGeneratorFactory, m_bytestreamRegistry,
 
		m_bytestreamProxy, m_component->getPresenceOracle(),
 
		m_bytestreamServer);
 
#endif
 
// 	m_component = component;
 
// 	m_userManager = userManager;
 
// 
 
// 	m_jingleSessionManager = new Swift::JingleSessionManager(m_component->getIQRouter());
 
// #if !HAVE_SWIFTEN_3
 
// 	m_connectivityManager = new Swift::ConnectivityManager(m_component->getNetworkFactories()->getNATTraverser());
 
// #endif
 
// 	m_bytestreamRegistry = new Swift::SOCKS5BytestreamRegistry();
 
// #if !HAVE_SWIFTEN_3
 
// 	m_bytestreamProxy = new Swift::SOCKS5BytestreamProxy(m_component->getNetworkFactories()->getConnectionFactory(), m_component->getNetworkFactories()->getTimerFactory());
 
// 	m_localCandidateGeneratorFactory = new Swift::DefaultLocalJingleTransportCandidateGeneratorFactory(m_connectivityManager, m_bytestreamRegistry, m_bytestreamProxy, "thishouldnotbeused");
 
// 	m_remoteCandidateSelectorFactory = new Swift::DefaultRemoteJingleTransportCandidateSelectorFactory(m_component->getNetworkFactories()->getConnectionFactory(), m_component->getNetworkFactories()->getTimerFactory());
 
// #else
 
// 	m_proxyManager = new Swift::SOCKS5BytestreamProxiesManager(m_component->getNetworkFactories()->getConnectionFactory(), m_component->getNetworkFactories()->getTimerFactory(), m_component->getNetworkFactories()->getDomainNameResolver(), m_component->getIQRouter(), "bar.com");
 
// #endif
 
// 	boost::shared_ptr<Swift::ConnectionServer> server = m_component->getNetworkFactories()->getConnectionServerFactory()->createConnectionServer(19645);
 
// 	server->start();
 
// #if HAVE_SWIFTEN_3
 
// 	m_proxyServerManager = new Swift::SOCKS5BytestreamServerManager(m_bytestreamRegistry, m_component->getNetworkFactories()->getConnectionServerFactory(), m_component->getNetworkFactories()->getNetworkEnvironment(), m_component->getNetworkFactories()->getNATTraverser());
 
// #else
 
// 	m_bytestreamServer = new Swift::SOCKS5BytestreamServer(server, m_bytestreamRegistry);
 
// 	m_bytestreamServer->start();
 
// 	m_outgoingFTManager = new Swift::CombinedOutgoingFileTransferManager(m_jingleSessionManager, m_component->getIQRouter(),
 
// 		m_userManager, m_remoteCandidateSelectorFactory,
 
// 		m_localCandidateGeneratorFactory, m_bytestreamRegistry,
 
// 		m_bytestreamProxy, m_component->getPresenceOracle(),
 
// 		m_bytestreamServer);
 
// #endif
 

	
 
	
 

	
 
// WARNING: Swiften crashes when this is uncommented... But we probably need it for working Jingle FT
 
// 	m_connectivityManager->addListeningPort(19645);
 
}
 

	
 
FileTransferManager::~FileTransferManager() {
 
#if !HAVE_SWIFTEN_3
 
	m_bytestreamServer->stop();
 
	delete m_remoteCandidateSelectorFactory;
 
	delete m_localCandidateGeneratorFactory;
 
#endif
 
	delete m_outgoingFTManager;
 
	delete m_jingleSessionManager;
 
	delete m_bytestreamRegistry;
 
#if !HAVE_SWIFTEN_3
 
	delete m_bytestreamServer;
 
	delete m_bytestreamProxy;
 
	delete m_connectivityManager;
 
#endif
 
// #if !HAVE_SWIFTEN_3
 
// 	m_bytestreamServer->stop();
 
// 	delete m_remoteCandidateSelectorFactory;
 
// 	delete m_localCandidateGeneratorFactory;
 
// #endif
 
// 	delete m_outgoingFTManager;
 
// 	delete m_jingleSessionManager;
 
// 	delete m_bytestreamRegistry;
 
// #if !HAVE_SWIFTEN_3
 
// 	delete m_bytestreamServer;
 
// 	delete m_bytestreamProxy;
 
// 	delete m_connectivityManager;
 
// #endif
 
}
 

	
 
FileTransferManager::Transfer FileTransferManager::sendFile(User *user, Buddy *buddy, boost::shared_ptr<Swift::ReadBytestream> byteStream, const Swift::StreamInitiationFileInfo &info) {
 
	FileTransferManager::Transfer transfer;
 
	transfer.from = buddy->getJID();
 
	transfer.to = user->getJID();
 
	transfer.readByteStream = byteStream;
 

	
 
	LOG4CXX_INFO(logger, "Starting FT from '" << transfer.from << "' to '" << transfer.to << "'")
 

	
 
	transfer.ft = m_outgoingFTManager->createOutgoingFileTransfer(transfer.from, transfer.to, transfer.readByteStream, info);
 
// 	if (transfer.ft) {
 
// 		m_filetransfers.push_back(ft);
 
// 		ft->onStateChange.connect(boost::bind(&User::handleFTStateChanged, this, _1, Buddy::JIDToLegacyName(from), info.getName(), info.getSize(), id));
 
// 		transfer.ft->start();
 
// 	}
 
	return transfer;
 
// 	FileTransferManager::Transfer transfer;
 
// 	transfer.from = buddy->getJID();
 
// 	transfer.to = user->getJID();
 
// 	transfer.readByteStream = byteStream;
 
// 
 
// 	LOG4CXX_INFO(logger, "Starting FT from '" << transfer.from << "' to '" << transfer.to << "'")
 
// 
 
// 	transfer.ft = m_outgoingFTManager->createOutgoingFileTransfer(transfer.from, transfer.to, transfer.readByteStream, info);
 
// // 	if (transfer.ft) {
 
// // 		m_filetransfers.push_back(ft);
 
// // 		ft->onStateChange.connect(boost::bind(&User::handleFTStateChanged, this, _1, Buddy::JIDToLegacyName(from), info.getName(), info.getSize(), id));
 
// // 		transfer.ft->start();
 
// // 	}
 
// 	return transfer;
 
}
 

	
 
}
src/localbuddy.cpp
Show inline comments
 
@@ -66,47 +66,43 @@ bool LocalBuddy::setName(const std::string &name) {
 
		return m_jid.isValid();
 
	} catch (...) {
 
		m_name = oldName;
 
		return false;
 
	}
 
}
 

	
 
void LocalBuddy::setAlias(const std::string &alias) {
 
	bool changed = m_alias != alias;
 
	m_alias = alias;
 

	
 
	if (changed) {
 
		if (getRosterManager()->getUser()->getComponent()->inServerMode() || getRosterManager()->isRemoteRosterSupported()) {
 
			getRosterManager()->sendBuddyRosterPush(this);
 
		}
 
		getRosterManager()->doUpdateBuddy(this);
 
		getRosterManager()->storeBuddy(this);
 
	}
 
}
 

	
 
void LocalBuddy::setGroups(const std::vector<std::string> &groups) {
 
	bool changed = m_groups.size() != groups.size();
 
	if (!changed) {
 
		for (int i = 0; i != m_groups.size(); i++) {
 
			if (m_groups[i] != groups[i]) {
 
				changed = true;
 
				break;
 
			}
 
		}
 
	}
 

	
 
	m_groups = groups;
 
	if (changed) {
 
		if (getRosterManager()->getUser()->getComponent()->inServerMode() || getRosterManager()->isRemoteRosterSupported()) {
 
			getRosterManager()->sendBuddyRosterPush(this);
 
		}
 
		getRosterManager()->doUpdateBuddy(this);
 
		getRosterManager()->storeBuddy(this);
 
	}
 
}
 

	
 
bool LocalBuddy::getStatus(Swift::StatusShow &status, std::string &statusMessage) {
 
	if (getRosterManager()->getUser()->getComponent()->isRawXMLEnabled()) {
 
		return false;
 
	}
 
	status = m_status;
 
	statusMessage = m_statusMessage;
 
	return true;
 
}
src/networkpluginserver.cpp
Show inline comments
 
@@ -19,44 +19,44 @@
 
 */
 

	
 
#include "transport/networkpluginserver.h"
 
#include "transport/user.h"
 
#include "transport/transport.h"
 
#include "transport/storagebackend.h"
 
#include "transport/rostermanager.h"
 
#include "transport/usermanager.h"
 
#include "transport/conversationmanager.h"
 
#include "transport/localbuddy.h"
 
#include "transport/config.h"
 
#include "transport/conversation.h"
 
#include "transport/vcardresponder.h"
 
#include "transport/rosterresponder.h"
 
#include "transport/memoryreadbytestream.h"
 
#include "transport/logging.h"
 
#include "transport/admininterface.h"
 
#include "transport/frontend.h"
 
#include "transport/factory.h"
 
#include "blockresponder.h"
 
#include "Swiften/Server/ServerStanzaChannel.h"
 
#include "Swiften/Elements/StreamError.h"
 
#include "Swiften/Network/BoostConnectionServer.h"
 
#include "Swiften/Network/ConnectionServerFactory.h"
 
#include "Swiften/Elements/AttentionPayload.h"
 
#include "Swiften/Elements/XHTMLIMPayload.h"
 
#include "Swiften/Elements/Delay.h"
 
#include "Swiften/Elements/DeliveryReceipt.h"
 
#include "Swiften/Elements/DeliveryReceiptRequest.h"
 
#include "Swiften/Elements/InvisiblePayload.h"
 
#include "Swiften/Elements/SpectrumErrorPayload.h"
 
#include "transport/protocol.pb.h"
 
#include "transport/util.h"
 
#include "transport/discoitemsresponder.h"
 

	
 
#include "boost/date_time/posix_time/posix_time.hpp"
 
#include "boost/signal.hpp"
 

	
 
#include "transport/utf8.h"
 

	
 
#include <Swiften/FileTransfer/ReadBytestream.h>
 
#include <Swiften/Elements/StreamInitiationFileInfo.h>
 

	
 
#ifdef _WIN32
 
#include "windows.h"
 
#include <stdint.h>
 
@@ -250,100 +250,95 @@ static void handleBuddyPayload(LocalBuddy *buddy, const pbnetwork::Buddy &payloa
 
		utf8::replace_invalid(payload.group(i).begin(), payload.group(i).end(), std::back_inserter(group), '_');
 
		groups.push_back(group);
 
	}
 
	if (!groups.empty()) {
 
		buddy->setGroups(groups);
 
	}
 

	
 
	buddy->setStatus(Swift::StatusShow((Swift::StatusShow::Type) payload.status()), payload.statusmessage());
 
	buddy->setIconHash(payload.iconhash());
 
	buddy->setBlocked(payload.blocked());
 
}
 

	
 
NetworkPluginServer::NetworkPluginServer(Component *component, Config *config, UserManager *userManager, FileTransferManager *ftManager, DiscoItemsResponder *discoItemsResponder) {
 
NetworkPluginServer::NetworkPluginServer(Component *component, Config *config, UserManager *userManager, FileTransferManager *ftManager) {
 
	_server = this;
 
	m_ftManager = ftManager;
 
	m_userManager = userManager;
 
	m_config = config;
 
	m_component = component;
 
	m_isNextLongRun = false;
 
	m_adminInterface = NULL;
 
	m_startingBackend = false;
 
	m_lastLogin = 0;
 
	m_xmppParser = new Swift::XMPPParser(this, &m_collection, component->getNetworkFactories()->getXMLParserFactory());
 
	m_xmppParser->parse("<stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' to='localhost' version='1.0'>");
 
#if HAVE_SWIFTEN_3
 
	m_serializer = new Swift::XMPPSerializer(&m_collection2, Swift::ClientStreamType, false);
 
#else
 
	m_serializer = new Swift::XMPPSerializer(&m_collection2, Swift::ClientStreamType);
 
#endif
 
	m_discoItemsResponder = discoItemsResponder;
 
	m_component->m_factory = new NetworkFactory(this);
 
	m_userManager->onUserCreated.connect(boost::bind(&NetworkPluginServer::handleUserCreated, this, _1));
 
	m_userManager->onUserDestroyed.connect(boost::bind(&NetworkPluginServer::handleUserDestroyed, this, _1));
 

	
 
	m_component->onRawIQReceived.connect(boost::bind(&NetworkPluginServer::handleRawIQReceived, this, _1));
 

	
 
	m_pingTimer = component->getNetworkFactories()->getTimerFactory()->createTimer(20000);
 
	m_pingTimer->onTick.connect(boost::bind(&NetworkPluginServer::pingTimeout, this));
 
	m_pingTimer->start();
 

	
 
	m_loginTimer = component->getNetworkFactories()->getTimerFactory()->createTimer(CONFIG_INT(config, "service.login_delay") * 1000);
 
	m_loginTimer->onTick.connect(boost::bind(&NetworkPluginServer::loginDelayFinished, this));
 
	m_loginTimer->start();
 

	
 
	if (CONFIG_INT(m_config, "service.memory_collector_time") != 0) {
 
		m_collectTimer = component->getNetworkFactories()->getTimerFactory()->createTimer(CONFIG_INT(m_config, "service.memory_collector_time"));
 
		m_collectTimer->onTick.connect(boost::bind(&NetworkPluginServer::collectBackend, this));
 
		m_collectTimer->start();
 
	}
 

	
 
	m_vcardResponder = new VCardResponder(component->getIQRouter(), component->getNetworkFactories(), userManager);
 
	m_vcardResponder->onVCardRequired.connect(boost::bind(&NetworkPluginServer::handleVCardRequired, this, _1, _2, _3));
 
	m_vcardResponder->onVCardUpdated.connect(boost::bind(&NetworkPluginServer::handleVCardUpdated, this, _1, _2));
 
	m_vcardResponder->start();
 
	m_component->getFrontend()->onVCardRequired.connect(boost::bind(&NetworkPluginServer::handleVCardRequired, this, _1, _2, _3));
 
	m_component->getFrontend()->onVCardUpdated.connect(boost::bind(&NetworkPluginServer::handleVCardUpdated, this, _1, _2));
 

	
 
	m_rosterResponder = new RosterResponder(component->getIQRouter(), userManager);
 
	m_rosterResponder->onBuddyAdded.connect(boost::bind(&NetworkPluginServer::handleBuddyAdded, this, _1, _2));
 
	m_rosterResponder->onBuddyRemoved.connect(boost::bind(&NetworkPluginServer::handleBuddyRemoved, this, _1));
 
	m_rosterResponder->onBuddyUpdated.connect(boost::bind(&NetworkPluginServer::handleBuddyUpdated, this, _1, _2));
 
	m_rosterResponder->start();
 
	m_component->getFrontend()->onBuddyAdded.connect(boost::bind(&NetworkPluginServer::handleBuddyAdded, this, _1, _2));
 
	m_component->getFrontend()->onBuddyRemoved.connect(boost::bind(&NetworkPluginServer::handleBuddyRemoved, this, _1));
 
	m_component->getFrontend()->onBuddyUpdated.connect(boost::bind(&NetworkPluginServer::handleBuddyUpdated, this, _1, _2));
 

	
 
	m_blockResponder = new BlockResponder(component->getIQRouter(), userManager);
 
	m_blockResponder->onBlockToggled.connect(boost::bind(&NetworkPluginServer::handleBlockToggled, this, _1));
 
	m_blockResponder->start();
 
// // 	m_blockResponder = new BlockResponder(component->getIQRouter(), userManager);
 
// // 	m_blockResponder->onBlockToggled.connect(boost::bind(&NetworkPluginServer::handleBlockToggled, this, _1));
 
// // 	m_blockResponder->start();
 

	
 
	m_server = component->getNetworkFactories()->getConnectionServerFactory()->createConnectionServer(Swift::HostAddress(CONFIG_STRING(m_config, "service.backend_host")), boost::lexical_cast<int>(CONFIG_STRING(m_config, "service.backend_port")));
 
	m_server->onNewConnection.connect(boost::bind(&NetworkPluginServer::handleNewClientConnection, this, _1));
 
}
 

	
 
NetworkPluginServer::~NetworkPluginServer() {
 
	for (std::list<Backend *>::const_iterator it = m_clients.begin(); it != m_clients.end(); it++) {
 
		LOG4CXX_INFO(logger, "Stopping backend " << *it);
 
		std::string message;
 
		pbnetwork::WrapperMessage wrap;
 
		wrap.set_type(pbnetwork::WrapperMessage_Type_TYPE_EXIT);
 
		wrap.SerializeToString(&message);
 

	
 
		Backend *c = (Backend *) *it;
 
		send(c->connection, message);
 
	}
 

	
 
	m_pingTimer->stop();
 
	m_server->stop();
 
	m_server.reset();
 
	delete m_component->m_factory;
 
	delete m_vcardResponder;
 
	delete m_rosterResponder;
 
	delete m_blockResponder;
 
// 	delete m_vcardResponder;
 
// 	delete m_rosterResponder;
 
// 	delete m_blockResponder;
 
}
 

	
 
void NetworkPluginServer::start() {
 
	m_server->start();
 

	
 
	LOG4CXX_INFO(logger, "Listening on host " << CONFIG_STRING(m_config, "service.backend_host") << " port " << CONFIG_STRING(m_config, "service.backend_port"));
 

	
 
	while (true) {
 
		unsigned long pid = exec_(CONFIG_STRING(m_config, "service.backend"), CONFIG_STRING(m_config, "service.backend_host").c_str(), CONFIG_STRING(m_config, "service.backend_port").c_str(), "1", m_config->getCommandLineArgs().c_str());
 
		LOG4CXX_INFO(logger, "Tried to spawn first backend with pid " << pid);
 
		LOG4CXX_INFO(logger, "Backend should now connect to Spectrum2 instance. Spectrum2 won't accept any connection before backend connects");
 

	
 
@@ -499,25 +494,25 @@ void NetworkPluginServer::handleVCardPayload(const std::string &data) {
 
	boost::shared_ptr<Swift::VCard> vcard(new Swift::VCard());
 

	
 
	utf8::replace_invalid(payload.fullname().begin(), payload.fullname().end(), std::back_inserter(field), '_');
 
	vcard->setFullName(field);
 

	
 
	field.clear();
 

	
 
	utf8::replace_invalid(payload.nickname().begin(), payload.nickname().end(), std::back_inserter(field), '_');
 
	vcard->setNickname(field);
 

	
 
	vcard->setPhoto(Swift::createByteArray(payload.photo()));
 

	
 
	m_vcardResponder->sendVCard(payload.id(), vcard);
 
	m_userManager->sendVCard(payload.id(), vcard);
 
}
 

	
 
void NetworkPluginServer::handleAuthorizationPayload(const std::string &data) {
 
	pbnetwork::Buddy payload;
 
	if (payload.ParseFromString(data) == false) {
 
		// TODO: ERROR
 
		return;
 
	}
 

	
 
	User *user = m_userManager->getUser(payload.username());
 
	if (!user)
 
		return;
 
@@ -529,25 +524,25 @@ void NetworkPluginServer::handleAuthorizationPayload(const std::string &data) {
 

	
 
	if (CONFIG_BOOL_DEFAULTED(m_config, "service.jid_escaping", true)) {
 
		name = Swift::JID::getEscapedNode(name);
 
	}
 
	else {
 
		if (name.find_last_of("@") != std::string::npos) {
 
			name.replace(name.find_last_of("@"), 1, "%");
 
		}
 
	}
 

	
 
	response->setFrom(Swift::JID(name, m_component->getJID().toString()));
 
	response->setType(Swift::Presence::Subscribe);
 
	m_component->getStanzaChannel()->sendPresence(response);
 
	m_component->getFrontend()->sendPresence(response);
 
}
 

	
 
void NetworkPluginServer::handleChatStatePayload(const std::string &data, Swift::ChatState::ChatStateType type) {
 
	pbnetwork::Buddy payload;
 
	if (payload.ParseFromString(data) == false) {
 
		// TODO: ERROR
 
		return;
 
	}
 

	
 
	User *user = m_userManager->getUser(payload.username());
 
	if (!user)
 
		return;
 
@@ -983,27 +978,27 @@ void NetworkPluginServer::handleBackendConfigPayload(const std::string &data) {
 
	}
 

	
 
	m_config->updateBackendConfig(payload.config());
 
}
 

	
 
void NetworkPluginServer::handleRoomListPayload(const std::string &data) {
 
	pbnetwork::RoomList payload;
 
	if (payload.ParseFromString(data) == false) {
 
		// TODO: ERROR
 
		return;
 
	}
 

	
 
	m_discoItemsResponder->clearRooms();
 
	m_component->getFrontend()->clearRoomList();
 
	for (int i = 0; i < payload.room_size() && i < payload.name_size(); i++) {
 
		m_discoItemsResponder->addRoom(Swift::JID::getEscapedNode(payload.room(i)) + "@" + m_component->getJID().toString(), payload.name(i));
 
		m_component->getFrontend()->addRoomToRoomList(Swift::JID::getEscapedNode(payload.room(i)) + "@" + m_component->getJID().toString(), payload.name(i));
 
	}
 
}
 
#if HAVE_SWIFTEN_3
 
void NetworkPluginServer::handleElement(boost::shared_ptr<Swift::ToplevelElement> element) {
 
#else
 
void NetworkPluginServer::handleElement(boost::shared_ptr<Swift::Element> element) {
 
#endif
 
	boost::shared_ptr<Swift::Stanza> stanza = boost::dynamic_pointer_cast<Swift::Stanza>(element);
 
	if (!stanza) {
 
		return;
 
	}
 

	
 
@@ -1047,63 +1042,64 @@ void NetworkPluginServer::handleElement(boost::shared_ptr<Swift::Element> elemen
 
		else {
 
			stanza->setFrom(Swift::JID(name, m_component->getJID().toString(), stanza->getFrom().getResource()));
 
		}
 
	}
 

	
 
	boost::shared_ptr<Swift::Message> message = boost::dynamic_pointer_cast<Swift::Message>(stanza);
 
	if (message) {
 
		if (conv) {
 
			conv->handleRawMessage(message);
 
			return;
 
		}
 

	
 
		m_component->getStanzaChannel()->sendMessage(message);
 
		m_component->getFrontend()->sendMessage(message);
 
		return;
 
	}
 

	
 
	boost::shared_ptr<Swift::Presence> presence = boost::dynamic_pointer_cast<Swift::Presence>(stanza);
 
	if (presence) {
 
		if (buddy) {
 
			if (!buddy->isAvailable() && presence->getType() != Swift::Presence::Unavailable) {
 
				buddy->m_status.setType(Swift::StatusShow::Online);
 
			}
 
			buddy->handleRawPresence(presence);
 
		}
 
		else if (conv) {
 
			conv->handleRawPresence(presence);
 
		}
 
		else {
 
			m_component->getStanzaChannel()->sendPresence(presence);
 
			m_component->getFrontend()->sendPresence(presence);
 
		}
 

	
 
		return;
 
	}
 

	
 
	boost::shared_ptr<Swift::IQ> iq = boost::dynamic_pointer_cast<Swift::IQ>(stanza);
 
	if (iq) {
 
		if (m_id2resource.find(stanza->getTo().toBare().toString() + stanza->getID()) != m_id2resource.end()) {
 
			iq->setTo(Swift::JID(iq->getTo().getNode(), iq->getTo().getDomain(), m_id2resource[stanza->getTo().toBare().toString() + stanza->getID()]));
 
			m_id2resource.erase(stanza->getTo().toBare().toString() + stanza->getID());
 
		}
 
		else {
 
			Swift::Presence::ref highest = m_component->getPresenceOracle()->getHighestPriorityPresence(user->getJID());
 
			if (highest) {
 
			    iq->setTo(highest->getFrom());
 
			} else {
 
			    iq->setTo(user->getJID());
 
			}
 
		}
 
		m_component->getIQRouter()->sendIQ(iq);
 
		return;
 
	}
 
	// TODO: FIX TO MAKE RAW XML BACKENDS WORKING AGAIN.
 
// 	boost::shared_ptr<Swift::IQ> iq = boost::dynamic_pointer_cast<Swift::IQ>(stanza);
 
// 	if (iq) {
 
// 		if (m_id2resource.find(stanza->getTo().toBare().toString() + stanza->getID()) != m_id2resource.end()) {
 
// 			iq->setTo(Swift::JID(iq->getTo().getNode(), iq->getTo().getDomain(), m_id2resource[stanza->getTo().toBare().toString() + stanza->getID()]));
 
// 			m_id2resource.erase(stanza->getTo().toBare().toString() + stanza->getID());
 
// 		}
 
// 		else {
 
// 			Swift::Presence::ref highest = m_component->getPresenceOracle()->getHighestPriorityPresence(user->getJID());
 
// 			if (highest) {
 
// 			    iq->setTo(highest->getFrom());
 
// 			} else {
 
// 			    iq->setTo(user->getJID());
 
// 			}
 
// 		}
 
// 		m_component->getFrontend()->sendIQ(iq);
 
// 		return;
 
// 	}
 
}
 

	
 
void NetworkPluginServer::handleRawXML(const std::string &xml) {
 
	m_xmppParser->parse(xml);
 
}
 

	
 
void NetworkPluginServer::handleRawPresenceReceived(boost::shared_ptr<Swift::Presence> presence) {
 
	User *user = m_userManager->getUser(presence->getFrom().toBare());
 
	if (!user)
 
		return;
 

	
 
	Backend *c = (Backend *) user->getData();
src/presenceoracle.cpp
Show inline comments
 
@@ -10,41 +10,42 @@
 
 *
 
 * 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 "transport/presenceoracle.h"
 
#include "transport/frontend.h"
 
#include "Swiften/Elements/MUCPayload.h"
 

	
 
#include <boost/bind.hpp>
 

	
 
using namespace Swift;
 

	
 
namespace Transport {
 

	
 
PresenceOracle::PresenceOracle(StanzaChannel* stanzaChannel) {
 
	stanzaChannel_ = stanzaChannel;
 
	stanzaChannel_->onPresenceReceived.connect(boost::bind(&PresenceOracle::handleIncomingPresence, this, _1));
 
	stanzaChannel_->onAvailableChanged.connect(boost::bind(&PresenceOracle::handleStanzaChannelAvailableChanged, this, _1));
 
PresenceOracle::PresenceOracle(Frontend* frontend) {
 
	frontend_ = frontend;
 
	frontend_->onPresenceReceived.connect(boost::bind(&PresenceOracle::handleIncomingPresence, this, _1));
 
	frontend_->onAvailableChanged.connect(boost::bind(&PresenceOracle::handleStanzaChannelAvailableChanged, this, _1));
 
}
 

	
 
PresenceOracle::~PresenceOracle() {
 
	stanzaChannel_->onPresenceReceived.disconnect(boost::bind(&PresenceOracle::handleIncomingPresence, this, _1));
 
	stanzaChannel_->onAvailableChanged.disconnect(boost::bind(&PresenceOracle::handleStanzaChannelAvailableChanged, this, _1));
 
	frontend_->onPresenceReceived.disconnect(boost::bind(&PresenceOracle::handleIncomingPresence, this, _1));
 
	frontend_->onAvailableChanged.disconnect(boost::bind(&PresenceOracle::handleStanzaChannelAvailableChanged, this, _1));
 
}
 

	
 
void PresenceOracle::handleStanzaChannelAvailableChanged(bool available) {
 
	if (available) {
 
		entries_.clear();
 
	}
 
}
 

	
 
void PresenceOracle::clearPresences(const Swift::JID& bareJID) {
 
	std::map<JID, boost::shared_ptr<Presence> > jidMap = entries_[bareJID];
 
	jidMap.clear();
 
	entries_[bareJID] = jidMap;
src/rostermanager.cpp
Show inline comments
 
@@ -17,357 +17,142 @@
 
 * 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/rostermanager.h"
 
#include "transport/rosterstorage.h"
 
#include "transport/storagebackend.h"
 
#include "transport/buddy.h"
 
#include "transport/usermanager.h"
 
#include "transport/buddy.h"
 
#include "transport/user.h"
 
#include "transport/logging.h"
 
#include "transport/frontend.h"
 
#include "transport/factory.h"
 
#include "Swiften/Roster/SetRosterRequest.h"
 
#include "Swiften/Elements/RosterPayload.h"
 
#include "Swiften/Elements/RosterItemPayload.h"
 
#include "Swiften/Elements/RosterItemExchangePayload.h"
 
#include "Swiften/Elements/Nickname.h"
 
#include "Swiften/Queries/IQRouter.h"
 
#include <boost/foreach.hpp>
 
#include <boost/make_shared.hpp>
 

	
 
#include <map>
 
#include <iterator>
 

	
 
namespace Transport {
 

	
 
DEFINE_LOGGER(logger, "RosterManager");
 

	
 
RosterManager::RosterManager(User *user, Component *component){
 
	m_rosterStorage = NULL;
 
	m_user = user;
 
	m_component = component;
 
	m_setBuddyTimer = m_component->getNetworkFactories()->getTimerFactory()->createTimer(1000);
 
	m_RIETimer = m_component->getNetworkFactories()->getTimerFactory()->createTimer(5000);
 
	m_RIETimer->onTick.connect(boost::bind(&RosterManager::sendRIE, this));
 

	
 
	m_supportRemoteRoster = false;
 

	
 
	if (!m_component->inServerMode()) {
 
		m_remoteRosterRequest = AddressedRosterRequest::ref(new AddressedRosterRequest(m_component->getIQRouter(), m_user->getJID().toBare()));
 
		m_remoteRosterRequest->onResponse.connect(boost::bind(&RosterManager::handleRemoteRosterResponse, this, _1, _2));
 
		m_remoteRosterRequest->send();
 
	}
 
}
 

	
 
RosterManager::~RosterManager() {
 
	m_setBuddyTimer->stop();
 
	m_RIETimer->stop();
 
	if (m_rosterStorage) {
 
		m_rosterStorage->storeBuddies();
 
	}
 

	
 
	sendUnavailablePresences(m_user->getJID().toBare());
 

	
 
	if (m_remoteRosterRequest) {
 
		m_remoteRosterRequest->onResponse.disconnect_all_slots();
 
		m_component->getIQRouter()->removeHandler(m_remoteRosterRequest);
 
	}
 

	
 
	for (std::map<std::string, Buddy *, std::less<std::string>, boost::pool_allocator< std::pair<std::string, Buddy *> > >::iterator it = m_buddies.begin(); it != m_buddies.end(); it++) {
 
		Buddy *buddy = (*it).second;
 
		if (!buddy) {
 
			continue;
 
		}
 
		delete buddy;
 
	}
 

	
 
	if (m_requests.size() != 0) {
 
		LOG4CXX_INFO(logger, m_user->getJID().toString() <<  ": Removing " << m_requests.size() << " unresponded IQs");
 
		BOOST_FOREACH(Swift::SetRosterRequest::ref request, m_requests) {
 
			request->onResponse.disconnect_all_slots();
 
			m_component->getIQRouter()->removeHandler(request);
 
		}
 
		m_requests.clear();
 
	}
 

	
 
	boost::singleton_pool<boost::pool_allocator_tag, sizeof(unsigned int)>::release_memory();
 

	
 
	if (m_rosterStorage)
 
		delete m_rosterStorage;
 
}
 

	
 
void RosterManager::setBuddy(Buddy *buddy) {
 
// 	m_setBuddyTimer->onTick.connect(boost::bind(&RosterManager::setBuddyCallback, this, buddy));
 
// 	m_setBuddyTimer->start();
 
	setBuddyCallback(buddy);
 
}
 

	
 
void RosterManager::removeBuddy(const std::string &name) {
 
	Buddy *buddy = getBuddy(name);
 
	if (!buddy) {
 
		LOG4CXX_WARN(logger, m_user->getJID().toString() << ": Tried to remove unknown buddy " << name);
 
		return;
 
	}
 

	
 
	if (m_component->inServerMode() || m_supportRemoteRoster) {
 
		sendBuddyRosterRemove(buddy);
 
	}
 
	else {
 
		sendBuddyUnsubscribePresence(buddy);
 
	}
 
	doRemoveBuddy(buddy);
 

	
 
	if (m_rosterStorage)
 
		m_rosterStorage->removeBuddy(buddy);
 

	
 
	unsetBuddy(buddy);
 
	delete buddy;
 
}
 

	
 
void RosterManager::sendBuddyRosterRemove(Buddy *buddy) {
 
	Swift::RosterPayload::ref p = Swift::RosterPayload::ref(new Swift::RosterPayload());
 
	Swift::RosterItemPayload item;
 
	item.setJID(buddy->getJID().toBare());
 
	item.setSubscription(Swift::RosterItemPayload::Remove);
 

	
 
	p->addItem(item);
 

	
 
	// In server mode we have to send pushes to all resources, but in gateway-mode we send it only to bare JID
 
	if (m_component->inServerMode()) {
 
		std::vector<Swift::Presence::ref> presences = m_component->getPresenceOracle()->getAllPresence(m_user->getJID().toBare());
 
		BOOST_FOREACH(Swift::Presence::ref presence, presences) {
 
			Swift::SetRosterRequest::ref request = Swift::SetRosterRequest::create(p, presence->getFrom(), m_component->getIQRouter());
 
			request->send();
 
		}
 
	}
 
	else {
 
		Swift::SetRosterRequest::ref request = Swift::SetRosterRequest::create(p, m_user->getJID().toBare(), m_component->getIQRouter());
 
		request->send();
 
	}
 
}
 

	
 
void RosterManager::sendBuddyRosterPush(Buddy *buddy) {
 
	// user can't receive anything in server mode if he's not logged in.
 
	// He will ask for roster later (handled in rosterreponsder.cpp)
 
	if (m_component->inServerMode() && (!m_user->isConnected() || m_user->shouldCacheMessages()))
 
		return;
 

	
 
	Swift::RosterPayload::ref payload = Swift::RosterPayload::ref(new Swift::RosterPayload());
 
	Swift::RosterItemPayload item;
 
	item.setJID(buddy->getJID().toBare());
 
	item.setName(buddy->getAlias());
 
	item.setGroups(buddy->getGroups());
 
	item.setSubscription(Swift::RosterItemPayload::Both);
 

	
 
	payload->addItem(item);
 

	
 
	// In server mode we have to send pushes to all resources, but in gateway-mode we send it only to bare JID
 
	if (m_component->inServerMode()) {
 
		std::vector<Swift::Presence::ref> presences = m_component->getPresenceOracle()->getAllPresence(m_user->getJID().toBare());
 
		BOOST_FOREACH(Swift::Presence::ref presence, presences) {
 
			Swift::SetRosterRequest::ref request = Swift::SetRosterRequest::create(payload, presence->getFrom(), m_component->getIQRouter());
 
			request->onResponse.connect(boost::bind(&RosterManager::handleBuddyRosterPushResponse, this, _1, request, buddy->getName()));
 
			request->send();
 
			m_requests.push_back(request);
 
		}
 
	}
 
	else {
 
		Swift::SetRosterRequest::ref request = Swift::SetRosterRequest::create(payload, m_user->getJID().toBare(), m_component->getIQRouter());
 
		request->onResponse.connect(boost::bind(&RosterManager::handleBuddyRosterPushResponse, this, _1, request, buddy->getName()));
 
		request->send();
 
		m_requests.push_back(request);
 
	}
 

	
 
	if (buddy->getSubscription() != Buddy::Both) {
 
		buddy->setSubscription(Buddy::Both);
 
		storeBuddy(buddy);
 
	}
 
}
 

	
 
void RosterManager::sendBuddyUnsubscribePresence(Buddy *buddy) {
 
	Swift::Presence::ref response = Swift::Presence::create();
 
	response->setTo(m_user->getJID());
 
	response->setFrom(buddy->getJID());
 
	response->setType(Swift::Presence::Unsubscribe);
 
	m_component->getStanzaChannel()->sendPresence(response);
 
	m_component->getFrontend()->sendPresence(response);
 

	
 
	response = Swift::Presence::create();
 
	response->setTo(m_user->getJID());
 
	response->setFrom(buddy->getJID());
 
	response->setType(Swift::Presence::Unsubscribed);
 
	m_component->getStanzaChannel()->sendPresence(response);
 
	m_component->getFrontend()->sendPresence(response);
 
}
 

	
 
void RosterManager::sendBuddySubscribePresence(Buddy *buddy) {
 
	Swift::Presence::ref response = Swift::Presence::create();
 
	response->setTo(m_user->getJID());
 
	response->setFrom(buddy->getJID().toBare());
 
	response->setType(Swift::Presence::Subscribe);
 
	if (!buddy->getAlias().empty()) {
 
		response->addPayload(boost::make_shared<Swift::Nickname>(buddy->getAlias()));
 
	}
 
	m_component->getStanzaChannel()->sendPresence(response);
 
	m_component->getFrontend()->sendPresence(response);
 
}
 

	
 
void RosterManager::handleBuddyChanged(Buddy *buddy) {
 
}
 

	
 
void RosterManager::setBuddyCallback(Buddy *buddy) {
 
void RosterManager::setBuddy(Buddy *buddy) {
 
	LOG4CXX_INFO(logger, "Associating buddy " << buddy->getName() << " with " << m_user->getJID().toString());
 
	m_buddies[buddy->getName()] = buddy;
 
	onBuddySet(buddy);
 

	
 
	// In server mode the only way is to send jabber:iq:roster push.
 
	// In component mode we send RIE or Subscribe presences, based on features.
 
	if (m_component->inServerMode()) {
 
		sendBuddyRosterPush(buddy);
 
	}
 
	else {
 
		if (buddy->getSubscription() == Buddy::Both) {
 
			LOG4CXX_INFO(logger, m_user->getJID().toString() << ": Not forwarding this buddy, because subscription=both");
 
			return;
 
		}
 

	
 
		if (m_supportRemoteRoster) {
 
			sendBuddyRosterPush(buddy);
 
		}
 
		else {
 
			m_RIETimer->start();
 
		}
 
	}
 
	doAddBuddy(buddy);
 

	
 
	if (m_rosterStorage)
 
		m_rosterStorage->storeBuddy(buddy);
 
}
 

	
 
void RosterManager::unsetBuddy(Buddy *buddy) {
 
	m_buddies.erase(buddy->getName());
 
	if (m_rosterStorage)
 
		m_rosterStorage->removeBuddyFromQueue(buddy);
 
	onBuddyUnset(buddy);
 
}
 

	
 
void RosterManager::storeBuddy(Buddy *buddy) {
 
	if (m_rosterStorage) {
 
		m_rosterStorage->storeBuddy(buddy);
 
	}
 
}
 

	
 
void RosterManager::handleBuddyRosterPushResponse(Swift::ErrorPayload::ref error, Swift::SetRosterRequest::ref request, const std::string &key) {
 
	LOG4CXX_INFO(logger, "handleBuddyRosterPushResponse called for buddy " << key);
 
	if (m_buddies[key] != NULL) {
 
		if (m_buddies[key]->isAvailable()) {
 
			std::vector<Swift::Presence::ref> &presences = m_buddies[key]->generatePresenceStanzas(255);
 
			BOOST_FOREACH(Swift::Presence::ref &presence, presences) {
 
				m_component->getStanzaChannel()->sendPresence(presence);
 
			}
 
		}
 
	}
 
	else {
 
		LOG4CXX_WARN(logger, "handleBuddyRosterPushResponse called for unknown buddy " << key);
 
	}
 

	
 
	m_requests.remove(request);
 
	request->onResponse.disconnect_all_slots();
 
}
 

	
 
void RosterManager::handleRemoteRosterResponse(boost::shared_ptr<Swift::RosterPayload> payload, Swift::ErrorPayload::ref error) {
 
	m_remoteRosterRequest.reset();
 
	if (error) {
 
		m_supportRemoteRoster = false;
 
		LOG4CXX_INFO(logger, m_user->getJID().toString() << ": This server does not support remote roster protoXEP");
 
		return;
 
	}
 

	
 
	LOG4CXX_INFO(logger, m_user->getJID().toString() << ": This server supports remote roster protoXEP");
 
	m_supportRemoteRoster = true;
 

	
 
	//If we receive empty RosterPayload on login (not register) initiate full RosterPush
 
	if(!m_buddies.empty() && payload->getItems().empty()){
 
			LOG4CXX_INFO(logger, "Received empty Roster upon login. Pushing full Roster.");
 
			for(std::map<std::string, Buddy *, std::less<std::string>, boost::pool_allocator< std::pair<std::string, Buddy *> > >::const_iterator c_it = m_buddies.begin();
 
					c_it != m_buddies.end(); c_it++) {
 
				sendBuddyRosterPush(c_it->second);
 
			}
 
	}
 
	return;
 

	
 
	BOOST_FOREACH(const Swift::RosterItemPayload &item, payload->getItems()) {
 
		std::string legacyName = Buddy::JIDToLegacyName(item.getJID());
 
		if (m_buddies.find(legacyName) != m_buddies.end()) {
 
			continue;
 
		}
 

	
 
		if (legacyName.empty()) {
 
			continue;
 
		}
 

	
 
		BuddyInfo buddyInfo;
 
		buddyInfo.id = -1;
 
		buddyInfo.alias = item.getName();
 
		buddyInfo.legacyName = legacyName;
 
		buddyInfo.subscription = "both";
 
		buddyInfo.flags = Buddy::buddyFlagsFromJID(item.getJID());
 
		buddyInfo.groups = item.getGroups();
 

	
 
		Buddy *buddy = m_component->getFactory()->createBuddy(this, buddyInfo);
 
		if (buddy) {
 
			setBuddy(buddy);
 
		}
 
	}
 
}
 

	
 
Buddy *RosterManager::getBuddy(const std::string &name) {
 
	return m_buddies[name];
 
}
 

	
 
void RosterManager::sendRIE() {
 
	m_RIETimer->stop();
 

	
 
	// Check the feature, because proper resource could logout during RIETimer.
 
	std::vector<Swift::JID> jidWithRIE = m_user->getJIDWithFeature("http://jabber.org/protocol/rosterx");
 

	
 
	// fallback to normal subscribe
 
	if (jidWithRIE.empty()) {
 
		for (std::map<std::string, Buddy *, std::less<std::string>, boost::pool_allocator< std::pair<std::string, Buddy *> > >::iterator it = m_buddies.begin(); it != m_buddies.end(); it++) {
 
			Buddy *buddy = (*it).second;
 
			if (!buddy) {
 
				continue;
 
			}
 
			sendBuddySubscribePresence(buddy);
 
		}
 
		return;
 
	}
 

	
 
	Swift::RosterItemExchangePayload::ref payload = Swift::RosterItemExchangePayload::ref(new Swift::RosterItemExchangePayload());
 
	for (std::map<std::string, Buddy *, std::less<std::string>, boost::pool_allocator< std::pair<std::string, Buddy *> > >::iterator it = m_buddies.begin(); it != m_buddies.end(); it++) {
 
		Buddy *buddy = (*it).second;
 
		if (!buddy) {
 
			continue;
 
		}
 
		Swift::RosterItemExchangePayload::Item item;
 
		item.setJID(buddy->getJID().toBare());
 
		item.setName(buddy->getAlias());
 
		item.setAction(Swift::RosterItemExchangePayload::Item::Add);
 
		item.setGroups(buddy->getGroups());
 

	
 
		payload->addItem(item);
 
	}
 

	
 
	BOOST_FOREACH(Swift::JID &jid, jidWithRIE) {
 
		LOG4CXX_INFO(logger, "Sending RIE stanza to " << jid.toString());
 
		boost::shared_ptr<Swift::GenericRequest<Swift::RosterItemExchangePayload> > request(new Swift::GenericRequest<Swift::RosterItemExchangePayload>(Swift::IQ::Set, jid, payload, m_component->getIQRouter()));
 
		request->send();
 
	}
 
}
 

	
 
void RosterManager::handleSubscription(Swift::Presence::ref presence) {
 
	std::string legacyName = Buddy::JIDToLegacyName(presence->getTo());
 
	if (legacyName.empty()) {
 
		return;
 
	}
 
	
 
	// For server mode the subscription changes are handler in rosterresponder.cpp
 
	// using roster pushes.
 
	if (m_component->inServerMode()) {
 
		Swift::Presence::ref response = Swift::Presence::create();
 
		response->setTo(presence->getFrom().toBare());
 
@@ -383,25 +168,25 @@ void RosterManager::handleSubscription(Swift::Presence::ref presence) {
 
				case Swift::Presence::Unsubscribe:
 
					onBuddyRemoved(buddy);
 
					removeBuddy(buddy->getName());
 
					buddy = NULL;
 
					response->setType(Swift::Presence::Unsubscribed);
 
					break;
 
				case Swift::Presence::Subscribed:
 
					onBuddyAdded(buddy);
 
					break;
 
				default:
 
					return;
 
			}
 
			m_component->getStanzaChannel()->sendPresence(response);
 
			m_component->getFrontend()->sendPresence(response);
 
			
 
		}
 
		else {
 
			BuddyInfo buddyInfo;
 
			switch (presence->getType()) {
 
				// buddy is not in roster, so add him
 
				case Swift::Presence::Subscribe:
 
					buddyInfo.id = -1;
 
					buddyInfo.alias = "";
 
					buddyInfo.legacyName = Buddy::JIDToLegacyName(presence->getTo());
 
					buddyInfo.subscription = "both";
 
					buddyInfo.flags = Buddy::buddyFlagsFromJID(presence->getTo());
 
@@ -422,44 +207,44 @@ void RosterManager::handleSubscription(Swift::Presence::ref presence) {
 
					buddyInfo.legacyName = Buddy::JIDToLegacyName(presence->getTo());
 
					buddyInfo.subscription = "both";
 
					buddyInfo.flags = Buddy::buddyFlagsFromJID(presence->getTo());
 

	
 
					buddy = m_component->getFactory()->createBuddy(this, buddyInfo);
 
					onBuddyRemoved(buddy);
 
					delete buddy;
 
					response->setType(Swift::Presence::Unsubscribed);
 
					break;
 
				default:
 
					return;
 
			}
 
			m_component->getStanzaChannel()->sendPresence(response);
 
			m_component->getFrontend()->sendPresence(response);
 
		}
 
	}
 
	else {
 
		Swift::Presence::ref response = Swift::Presence::create();
 
		Swift::Presence::ref currentPresence;
 
		response->setTo(presence->getFrom().toBare());
 
		response->setFrom(presence->getTo().toBare());
 

	
 
		Buddy *buddy = getBuddy(Buddy::JIDToLegacyName(presence->getTo()));
 
		if (buddy) {
 
			std::vector<Swift::Presence::ref> &presences = buddy->generatePresenceStanzas(255);
 
			switch (presence->getType()) {
 
				// buddy is already there, so nothing to do, just answer
 
				case Swift::Presence::Subscribe:
 
					onBuddyAdded(buddy);
 
					response->setType(Swift::Presence::Subscribed);
 
					BOOST_FOREACH(Swift::Presence::ref &currentPresence, presences) {
 
						currentPresence->setTo(presence->getFrom());
 
						m_component->getStanzaChannel()->sendPresence(currentPresence);
 
						m_component->getFrontend()->sendPresence(currentPresence);
 
					}
 
					if (buddy->getSubscription() != Buddy::Both) {
 
						buddy->setSubscription(Buddy::Both);
 
						storeBuddy(buddy);
 
					}
 
					break;
 
				// remove buddy
 
				case Swift::Presence::Unsubscribe:
 
					response->setType(Swift::Presence::Unsubscribed);
 
					onBuddyRemoved(buddy);
 
					removeBuddy(buddy->getName());
 
					buddy = NULL;
 
@@ -517,35 +302,35 @@ void RosterManager::handleSubscription(Swift::Presence::ref presence) {
 
					buddy = NULL;
 
					break;
 
				// just send response
 
				case Swift::Presence::Unsubscribed:
 
					response->setType(Swift::Presence::Unsubscribe);
 
					break;
 
				// just send response
 
				default:
 
					return;
 
			}
 
		}
 

	
 
		m_component->getStanzaChannel()->sendPresence(response);
 
		m_component->getFrontend()->sendPresence(response);
 

	
 
		// We have to act as buddy and send its subscribe/unsubscribe just to be sure...
 
		switch (response->getType()) {
 
			case Swift::Presence::Unsubscribed:
 
				response->setType(Swift::Presence::Unsubscribe);
 
				m_component->getStanzaChannel()->sendPresence(response);
 
				m_component->getFrontend()->sendPresence(response);
 
				break;
 
			case Swift::Presence::Subscribed:
 
				response->setType(Swift::Presence::Subscribe);
 
				m_component->getStanzaChannel()->sendPresence(response);
 
				m_component->getFrontend()->sendPresence(response);
 
				break;
 
			default:
 
				break;
 
		}
 
	}
 
}
 

	
 
void RosterManager::setStorageBackend(StorageBackend *storageBackend) {
 
	if (m_rosterStorage || !storageBackend) {
 
		return;
 
	}
 
	RosterStorage *storage = new RosterStorage(m_user, storageBackend);
 
@@ -586,66 +371,66 @@ Swift::RosterPayload::ref RosterManager::generateRosterPayload() {
 
void RosterManager::sendCurrentPresences(const Swift::JID &to) {
 
	for (std::map<std::string, Buddy *, std::less<std::string>, boost::pool_allocator< std::pair<std::string, Buddy *> > >::iterator it = m_buddies.begin(); it != m_buddies.end(); it++) {
 
		Buddy *buddy = (*it).second;
 
		if (!buddy) {
 
			continue;
 
		}
 
		if (!buddy->isAvailable()) {
 
			continue;
 
		}
 
		std::vector<Swift::Presence::ref> &presences = buddy->generatePresenceStanzas(255);
 
		BOOST_FOREACH(Swift::Presence::ref &presence, presences) {
 
			presence->setTo(to);
 
			m_component->getStanzaChannel()->sendPresence(presence);
 
			m_component->getFrontend()->sendPresence(presence);
 
		}
 
	}
 
}
 

	
 
void RosterManager::sendCurrentPresence(const Swift::JID &from, const Swift::JID &to) {
 
	Buddy *buddy = getBuddy(Buddy::JIDToLegacyName(from));
 
	if (buddy) {
 
		std::vector<Swift::Presence::ref> &presences = buddy->generatePresenceStanzas(255);
 
		BOOST_FOREACH(Swift::Presence::ref &presence, presences) {
 
			presence->setTo(to);
 
			m_component->getStanzaChannel()->sendPresence(presence);
 
			m_component->getFrontend()->sendPresence(presence);
 
		}
 
	}
 
	else {
 
		Swift::Presence::ref response = Swift::Presence::create();
 
		response->setTo(to);
 
		response->setFrom(from);
 
		response->setType(Swift::Presence::Unavailable);
 
		m_component->getStanzaChannel()->sendPresence(response);
 
		m_component->getFrontend()->sendPresence(response);
 
	}
 
}
 

	
 
void RosterManager::sendUnavailablePresences(const Swift::JID &to) {
 
	for (std::map<std::string, Buddy *, std::less<std::string>, boost::pool_allocator< std::pair<std::string, Buddy *> > >::iterator it = m_buddies.begin(); it != m_buddies.end(); it++) {
 
		Buddy *buddy = (*it).second;
 
		if (!buddy) {
 
			continue;
 
		}
 

	
 
		if (!buddy->isAvailable()) {
 
			continue;
 
		}
 

	
 
		std::vector<Swift::Presence::ref> &presences = buddy->generatePresenceStanzas(255);
 
		BOOST_FOREACH(Swift::Presence::ref &presence, presences) {
 
			Swift::Presence::Type type = presence->getType();
 
			presence->setTo(to);
 
			presence->setType(Swift::Presence::Unavailable);
 
			m_component->getStanzaChannel()->sendPresence(presence);
 
			m_component->getFrontend()->sendPresence(presence);
 
			presence->setType(type);
 
		}
 
	}
 

	
 
	// in gateway mode, we have to send unavailable presence for transport
 
	// contact
 
	Swift::Presence::ref response = Swift::Presence::create();
 
	response->setTo(to);
 
	response->setFrom(m_component->getJID());
 
	response->setType(Swift::Presence::Unavailable);
 
	m_component->getStanzaChannel()->sendPresence(response);
 
	m_component->getFrontend()->sendPresence(response);
 
}
 

	
 
}
src/tests/basictest.cpp
Show inline comments
 
#include "basictest.h"
 
#include "transport/userregistry.h"
 
#include "transport/config.h"
 
#include "transport/storagebackend.h"
 
#include "transport/userregistration.h"
 
#include "transport/user.h"
 
#include "transport/transport.h"
 
#include "transport/conversation.h"
 
#include "transport/usermanager.h"
 
#include "transport/localbuddy.h"
 
#include "XMPPFrontend.h"
 
#include "XMPPUserRegistration.h"
 
#include "XMPPUserManager.h"
 
#include <cppunit/TestFixture.h>
 
#include <cppunit/extensions/HelperMacros.h>
 
#include <Swiften/Swiften.h>
 
#include <Swiften/EventLoop/DummyEventLoop.h>
 
#include <Swiften/Server/Server.h>
 
#include <Swiften/Network/DummyNetworkFactories.h>
 
#include <Swiften/Network/DummyConnectionServer.h>
 
#include "Swiften/Server/ServerStanzaChannel.h"
 
#include "Swiften/Server/ServerFromClientSession.h"
 
#include "Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.h"
 

	
 
#include "Swiften/Serializer/GenericPayloadSerializer.h"
 

	
 
#include "../storageparser.h"
 
#include "storageparser.h"
 
#include "Swiften/Parser/PayloadParsers/AttentionParser.h"
 
#include "Swiften/Serializer/PayloadSerializers/AttentionSerializer.h"
 
#include "Swiften/Parser/PayloadParsers/XHTMLIMParser.h"
 
#include "Swiften/Serializer/PayloadSerializers/XHTMLIMSerializer.h"
 
#include "Swiften/Parser/PayloadParsers/StatsParser.h"
 
#include "Swiften/Serializer/PayloadSerializers/StatsSerializer.h"
 
#include "Swiften/Parser/PayloadParsers/GatewayPayloadParser.h"
 
#include "Swiften/Serializer/PayloadSerializers/GatewayPayloadSerializer.h"
 
#include "Swiften/Serializer/PayloadSerializers/SpectrumErrorSerializer.h"
 
#include "Swiften/Parser/PayloadParsers/MUCPayloadParser.h"
 
#include "transport/BlockParser.h"
 
#include "transport/BlockSerializer.h"
 
#include "BlockParser.h"
 
#include "BlockSerializer.h"
 
#include "Swiften/Parser/PayloadParsers/InvisibleParser.h"
 
#include "Swiften/Serializer/PayloadSerializers/InvisibleSerializer.h"
 

	
 
using namespace Transport;
 

	
 
void BasicTest::setMeUp (void) {
 
	streamEnded = false;
 
	std::istringstream ifs("service.server_mode = 1\nservice.jid=localhost\nservice.more_resources=1\n");
 
	cfg = new Config();
 
	cfg->load(ifs);
 

	
 
	factory = new TestingFactory();
 

	
 
	storage = new TestingStorageBackend();
 

	
 
	loop = new Swift::DummyEventLoop();
 
	factories = new Swift::DummyNetworkFactories(loop);
 

	
 
	userRegistry = new UserRegistry(cfg, factories);
 

	
 
	component = new Component(loop, factories, cfg, factory, userRegistry);
 
	component->start();
 
	frontend = new Transport::XMPPFrontend();
 

	
 
	itemsResponder = new DiscoItemsResponder(component);
 
	itemsResponder->start();
 
	component = new Component(frontend, loop, factories, cfg, factory, userRegistry);
 
	component->start();
 

	
 
	userManager = new UserManager(component, userRegistry, itemsResponder, storage);
 
	userManager = frontend->createUserManager(component, userRegistry, storage);
 

	
 
	userRegistration = new UserRegistration(component, userManager, storage);
 
	userRegistration->start();
 
	itemsResponder = frontend->getDiscoItemsResponder();
 

	
 
	payloadSerializers = new Swift::FullPayloadSerializerCollection();
 
	payloadParserFactories = new Swift::FullPayloadParserFactoryCollection();
 

	
 
	payloadParserFactories->addFactory(new Swift::GenericPayloadParserFactory<StorageParser>("private", "jabber:iq:private"));
 
	payloadParserFactories->addFactory(new Swift::GenericPayloadParserFactory<Swift::AttentionParser>("attention", "urn:xmpp:attention:0"));
 
	payloadParserFactories->addFactory(new Swift::GenericPayloadParserFactory<Swift::XHTMLIMParser>("html", "http://jabber.org/protocol/xhtml-im"));
 
	payloadParserFactories->addFactory(new Swift::GenericPayloadParserFactory<Transport::BlockParser>("block", "urn:xmpp:block:0"));
 
	payloadParserFactories->addFactory(new Swift::GenericPayloadParserFactory<Swift::InvisibleParser>("invisible", "urn:xmpp:invisible:0"));
 
	payloadParserFactories->addFactory(new Swift::GenericPayloadParserFactory<Swift::StatsParser>("query", "http://jabber.org/protocol/stats"));
 
	payloadParserFactories->addFactory(new Swift::GenericPayloadParserFactory<Swift::GatewayPayloadParser>("query", "jabber:iq:gateway"));
 
	payloadParserFactories->addFactory(new Swift::GenericPayloadParserFactory<Swift::MUCPayloadParser>("x", "http://jabber.org/protocol/muc"));
 
@@ -85,50 +86,50 @@ void BasicTest::setMeUp (void) {
 
	payloadSerializers->addSerializer(new Swift::SpectrumErrorSerializer());
 
	payloadSerializers->addSerializer(new Swift::GatewayPayloadSerializer());
 

	
 
	parser = new Swift::XMPPParser(this, payloadParserFactories, factories->getXMLParserFactory());
 
	parser2 = new Swift::XMPPParser(this, payloadParserFactories, factories->getXMLParserFactory());
 

	
 
	serverFromClientSession = boost::shared_ptr<Swift::ServerFromClientSession>(new Swift::ServerFromClientSession("id", factories->getConnectionFactory()->createConnection(),
 
			payloadParserFactories, payloadSerializers, userRegistry, factories->getXMLParserFactory(), Swift::JID("user@localhost/resource")));
 
	serverFromClientSession->startSession();
 

	
 
	serverFromClientSession->onDataWritten.connect(boost::bind(&BasicTest::handleDataReceived, this, _1));
 

	
 
	dynamic_cast<Swift::ServerStanzaChannel *>(component->getStanzaChannel())->addSession(serverFromClientSession);
 
	dynamic_cast<Swift::ServerStanzaChannel *>(static_cast<XMPPFrontend *>(component->getFrontend())->getStanzaChannel())->addSession(serverFromClientSession);
 
	parser->parse("<stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' to='localhost' version='1.0'>");
 
	parser2->parse("<stream:stream xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' to='localhost' version='1.0'>");
 
	received.clear();
 
	received2.clear();
 
	receivedData.clear();
 
	loop->processEvents();
 
}
 

	
 
void BasicTest::tearMeDown (void) {
 
	dynamic_cast<Swift::ServerStanzaChannel *>(component->getStanzaChannel())->removeSession(serverFromClientSession);
 
	dynamic_cast<Swift::ServerStanzaChannel *>(static_cast<XMPPFrontend *>(component->getFrontend())->getStanzaChannel())->removeSession(serverFromClientSession);
 
	if (serverFromClientSession2) {
 
		dynamic_cast<Swift::ServerStanzaChannel *>(component->getStanzaChannel())->removeSession(serverFromClientSession2);
 
		dynamic_cast<Swift::ServerStanzaChannel *>(static_cast<XMPPFrontend *>(component->getFrontend())->getStanzaChannel())->removeSession(serverFromClientSession2);
 
		serverFromClientSession2.reset();
 
	}
 
	delete component;
 
	delete frontend;
 
	delete userRegistry;
 
	delete factories;
 
	delete factory;
 
	delete loop;
 
	delete cfg;
 
	delete parser;
 
	delete parser2;
 
	delete storage;
 
	delete userRegistration;
 
	delete itemsResponder;
 
// 	delete userRegistration;
 
	received.clear();
 
	received2.clear();
 
	receivedData.clear();
 
	receivedData2.clear();
 
}
 

	
 
void BasicTest::handleDataReceived(const Swift::SafeByteArray &data) {
 
// 	std::cout << safeByteArrayToString(data) << "\n";
 
	stream1_active = true;
 
	receivedData += safeByteArrayToString(data) + "\n";
 
	parser->parse(safeByteArrayToString(data));
 
}
 
@@ -159,33 +160,33 @@ void BasicTest::handleElement(boost::shared_ptr<Swift::Element> element) {
 
		received.push_back(element);
 
	}
 
	else {
 
		received2.push_back(element);
 
	}
 
}
 

	
 
void BasicTest::handleStreamEnd() {
 
	streamEnded = true;
 
}
 

	
 
void BasicTest::injectPresence(boost::shared_ptr<Swift::Presence> &response) {
 
	dynamic_cast<Swift::ServerStanzaChannel *>(component->getStanzaChannel())->onPresenceReceived(response);
 
	dynamic_cast<Swift::ServerStanzaChannel *>(static_cast<XMPPFrontend *>(component->getFrontend())->getStanzaChannel())->onPresenceReceived(response);
 
}
 

	
 
void BasicTest::injectIQ(boost::shared_ptr<Swift::IQ> iq) {
 
	dynamic_cast<Swift::ServerStanzaChannel *>(component->getStanzaChannel())->onIQReceived(iq);
 
	dynamic_cast<Swift::ServerStanzaChannel *>(static_cast<XMPPFrontend *>(component->getFrontend())->getStanzaChannel())->onIQReceived(iq);
 
}
 

	
 
void BasicTest::injectMessage(boost::shared_ptr<Swift::Message> msg) {
 
	dynamic_cast<Swift::ServerStanzaChannel *>(component->getStanzaChannel())->onMessageReceived(msg);
 
	dynamic_cast<Swift::ServerStanzaChannel *>(static_cast<XMPPFrontend *>(component->getFrontend())->getStanzaChannel())->onMessageReceived(msg);
 
}
 

	
 
Swift::Stanza *BasicTest::getStanza(boost::shared_ptr<Swift::Element> element) {
 
	Swift::Stanza *stanza = dynamic_cast<Swift::Stanza *>(element.get());
 
	CPPUNIT_ASSERT(stanza);
 
	return stanza;
 
}
 

	
 
void BasicTest::connectUser() {
 
	CPPUNIT_ASSERT_EQUAL(0, userManager->getUserCount());
 
	userRegistry->isValidUserPassword(Swift::JID("user@localhost/resource"), serverFromClientSession.get(), Swift::createSafeByteArray("password"));
 
	userRegistry->onPasswordValid(Swift::JID("user@localhost/resource"));
 
@@ -208,25 +209,25 @@ void BasicTest::connectUser() {
 

	
 
	received.clear();
 
	receivedData.clear();
 
}
 

	
 
void BasicTest::connectSecondResource() {
 
	serverFromClientSession2 = boost::shared_ptr<Swift::ServerFromClientSession>(new Swift::ServerFromClientSession("id", factories->getConnectionFactory()->createConnection(),
 
			payloadParserFactories, payloadSerializers, userRegistry, factories->getXMLParserFactory(), Swift::JID("user@localhost/resource2")));
 
	serverFromClientSession2->startSession();
 

	
 
	serverFromClientSession2->onDataWritten.connect(boost::bind(&BasicTest::handleDataReceived2, this, _1));
 

	
 
	dynamic_cast<Swift::ServerStanzaChannel *>(component->getStanzaChannel())->addSession(serverFromClientSession2);
 
	dynamic_cast<Swift::ServerStanzaChannel *>(static_cast<XMPPFrontend *>(component->getFrontend())->getStanzaChannel())->addSession(serverFromClientSession2);
 

	
 
	userRegistry->isValidUserPassword(Swift::JID("user@localhost/resource2"), serverFromClientSession2.get(), Swift::createSafeByteArray("password"));
 
	userRegistry->onPasswordValid(Swift::JID("user@localhost/resource2"));
 

	
 
	loop->processEvents();
 

	
 
	Swift::Presence::ref response = Swift::Presence::create();
 
	response->setTo("localhost");
 
	response->setFrom("user@localhost/resource2");
 
	injectPresence(response);
 
	loop->processEvents();
 

	
src/tests/basictest.h
Show inline comments
 
@@ -24,27 +24,30 @@
 
#include "Swiften/Swiften.h"
 
#include "Swiften/Queries/SetResponder.h"
 
#include "transport/conversation.h"
 
#include "transport/conversationmanager.h"
 
#include "transport/userregistry.h"
 
#include "transport/config.h"
 
#include "transport/storagebackend.h"
 
#include "transport/user.h"
 
#include "transport/transport.h"
 
#include "transport/conversation.h"
 
#include "transport/usermanager.h"
 
#include "transport/userregistration.h"
 
#include "transport/discoitemsresponder.h"
 
#include "discoitemsresponder.h"
 
#include "transport/localbuddy.h"
 
#include "transport/storagebackend.h"
 
#include "transport/factory.h"
 
#include "XMPPFrontend.h"
 
#include "XMPPUserRegistration.h"
 

	
 
#include <Swiften/Swiften.h>
 
#include <Swiften/EventLoop/DummyEventLoop.h>
 
#include <Swiften/Server/Server.h>
 
#include <Swiften/Network/DummyNetworkFactories.h>
 
#include <Swiften/Network/DummyConnectionServer.h>
 
#include "Swiften/Server/ServerStanzaChannel.h"
 
#include "Swiften/Server/ServerFromClientSession.h"
 
#include "Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.h"
 
#define HAVE_SWIFTEN_3  (SWIFTEN_VERSION >= 0x030000)
 

	
 
using namespace Transport;
 
@@ -260,17 +263,18 @@ class BasicTest : public Swift::XMPPParserClient {
 
		UserRegistry *userRegistry;
 
		Config *cfg;
 
		Swift::Server *server;
 
		Swift::DummyNetworkFactories *factories;
 
		Swift::DummyEventLoop *loop;
 
		TestingFactory *factory;
 
		Component *component;
 
		std::vector<boost::shared_ptr<Swift::Element> > received;
 
		std::vector<boost::shared_ptr<Swift::Element> > received2;
 
		std::string receivedData;
 
		std::string receivedData2;
 
		StorageBackend *storage;
 
		UserRegistration *userRegistration;
 
		XMPPUserRegistration *userRegistration;
 
		DiscoItemsResponder *itemsResponder;
 
		bool stream1_active;
 
		Transport::XMPPFrontend *frontend;
 
};
 

	
src/tests/component.cpp
Show inline comments
 
@@ -19,70 +19,71 @@
 
using namespace Transport;
 

	
 
class ComponentTest : public CPPUNIT_NS :: TestFixture, public BasicTest {
 
	CPPUNIT_TEST_SUITE(ComponentTest);
 
	CPPUNIT_TEST(handlePresenceWithNode);
 
	CPPUNIT_TEST(handlePresenceWithoutNode);
 
	CPPUNIT_TEST(handleErrorPresence);
 
	CPPUNIT_TEST_SUITE_END();
 

	
 
	public:
 
		void setUp (void) {
 
			onUserPresenceReceived = false;
 
			onUserDiscoInfoReceived = false;
 
			onCapabilitiesReceived = false;
 

	
 
			setMeUp();
 
			component->onUserPresenceReceived.connect(boost::bind(&ComponentTest::handleUserPresenceReceived, this, _1));
 
			component->onUserDiscoInfoReceived.connect(boost::bind(&ComponentTest::handleUserDiscoInfoReceived, this, _1, _2));
 
			component->getFrontend()->onCapabilitiesReceived.connect(boost::bind(&ComponentTest::handleUserDiscoInfoReceived, this, _1, _2));
 
		}
 

	
 
		void tearDown (void) {
 
			tearMeDown();
 
		}
 

	
 
	void handleUserDiscoInfoReceived(const Swift::JID& jid, boost::shared_ptr<Swift::DiscoInfo> info) {
 
		onUserDiscoInfoReceived = true;
 
		onCapabilitiesReceived = true;
 
	}
 

	
 
	void handleUserPresenceReceived(Swift::Presence::ref presence) {
 
		onUserPresenceReceived = true;
 
	}
 

	
 
	void handlePresenceWithNode() {
 
		Swift::Presence::ref response = Swift::Presence::create();
 
		response->setTo("somebody@localhost");
 
		response->setFrom("user@localhost/resource");
 
		dynamic_cast<Swift::ServerStanzaChannel *>(component->getStanzaChannel())->onPresenceReceived(response);
 
		dynamic_cast<Swift::ServerStanzaChannel *>(static_cast<XMPPFrontend *>(component->getFrontend())->getStanzaChannel())->onPresenceReceived(response);
 
		
 
		loop->processEvents();
 
		CPPUNIT_ASSERT_EQUAL(0, (int) received.size());
 
	}
 

	
 
	// Error presence should be ignored
 
	void handleErrorPresence() {
 
		Swift::Presence::ref response = Swift::Presence::create();
 
		response->setTo("localhost");
 
		response->setFrom("user@localhost/resource");
 
		response->setType(Swift::Presence::Error);
 
		dynamic_cast<Swift::ServerStanzaChannel *>(component->getStanzaChannel())->onPresenceReceived(response);
 
		dynamic_cast<Swift::ServerStanzaChannel *>(static_cast<XMPPFrontend *>(component->getFrontend())->getStanzaChannel())->onPresenceReceived(response);
 
		
 
		loop->processEvents();
 
		CPPUNIT_ASSERT_EQUAL(0, (int) received.size());
 
	}
 

	
 
	void handlePresenceWithoutNode() {
 
		Swift::Presence::ref response = Swift::Presence::create();
 
		response->setTo("localhost");
 
		response->setFrom("user@localhost/resource");
 
		dynamic_cast<Swift::ServerStanzaChannel *>(component->getStanzaChannel())->onPresenceReceived(response);
 
		dynamic_cast<Swift::ServerStanzaChannel *>(static_cast<XMPPFrontend *>(component->getFrontend())->getStanzaChannel())->onPresenceReceived(response);
 
		
 
		loop->processEvents();
 
		CPPUNIT_ASSERT_EQUAL(1, (int) received.size());
 
		CPPUNIT_ASSERT(getStanza(received[0])->getPayload<Swift::DiscoInfo>());
 
		CPPUNIT_ASSERT(onUserPresenceReceived);
 
	}
 

	
 
	private:
 
		bool onUserPresenceReceived;
 
		bool onUserDiscoInfoReceived;
 
		bool onCapabilitiesReceived;
 
};
 

	
 
CPPUNIT_TEST_SUITE_REGISTRATION (ComponentTest);
src/tests/discoitemsresponder.cpp
Show inline comments
 
#include "transport/userregistry.h"
 
#include "transport/userregistration.h"
 
#include "transport/config.h"
 
#include "transport/storagebackend.h"
 
#include "transport/user.h"
 
#include "transport/transport.h"
 
#include "transport/conversation.h"
 
#include "transport/usermanager.h"
 
#include "transport/localbuddy.h"
 
#include "transport/settingsadhoccommand.h"
 
#include "transport/adhocmanager.h"
 
#include <cppunit/TestFixture.h>
 
#include <cppunit/extensions/HelperMacros.h>
 
#include <Swiften/Swiften.h>
 
#include <Swiften/EventLoop/DummyEventLoop.h>
 
#include <Swiften/Server/Server.h>
 
#include <Swiften/Network/DummyNetworkFactories.h>
 
#include <Swiften/Network/DummyConnectionServer.h>
 
#include "Swiften/Server/ServerStanzaChannel.h"
 
#include "Swiften/Server/ServerFromClientSession.h"
 
#include "Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.h"
 
#include "basictest.h"
 

	
src/tests/gatewayresponder.cpp
Show inline comments
 
#include "transport/userregistry.h"
 
#include "transport/config.h"
 
#include "transport/storagebackend.h"
 
#include "transport/user.h"
 
#include "transport/transport.h"
 
#include "transport/conversation.h"
 
#include "transport/rosterresponder.h"
 
#include "transport/usermanager.h"
 
#include "transport/localbuddy.h"
 
#include "transport/gatewayresponder.h"
 
#include "gatewayresponder.h"
 
#include <cppunit/TestFixture.h>
 
#include <cppunit/extensions/HelperMacros.h>
 
#include <Swiften/Swiften.h>
 
#include <Swiften/EventLoop/DummyEventLoop.h>
 
#include <Swiften/Server/Server.h>
 
#include <Swiften/Network/DummyNetworkFactories.h>
 
#include <Swiften/Network/DummyConnectionServer.h>
 
#include "Swiften/Server/ServerStanzaChannel.h"
 
#include "Swiften/Server/ServerFromClientSession.h"
 
#include "Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.h"
 
#include "basictest.h"
 

	
 
@@ -26,25 +26,25 @@ class GatewayResponderTest : public CPPUNIT_NS :: TestFixture, public BasicTest
 
	CPPUNIT_TEST_SUITE(GatewayResponderTest);
 
	CPPUNIT_TEST(escape);
 
	CPPUNIT_TEST(noEscapeEscaped);
 
	CPPUNIT_TEST_SUITE_END();
 

	
 
	public:
 
		GatewayResponder *m_gatewayResponder;
 

	
 
		void setUp (void) {
 
			setMeUp();
 
			connectUser();
 

	
 
			m_gatewayResponder = new GatewayResponder(component->getIQRouter(), userManager);
 
			m_gatewayResponder = new GatewayResponder(static_cast<XMPPFrontend *>(component->getFrontend())->getIQRouter(), userManager);
 
			m_gatewayResponder->start();
 

	
 
			received.clear();
 
		}
 

	
 
		void tearDown (void) {
 
			received.clear();
 
			disconnectUser();
 
			delete m_gatewayResponder;
 
			tearMeDown();
 
		}
 

	
src/tests/networkpluginserver.cpp
Show inline comments
 
#include "transport/userregistry.h"
 
#include "transport/userregistration.h"
 
#include "transport/config.h"
 
#include "transport/storagebackend.h"
 
#include "transport/user.h"
 
#include "transport/transport.h"
 
#include "transport/conversation.h"
 
#include "transport/usermanager.h"
 
#include "transport/localbuddy.h"
 
#include "transport/settingsadhoccommand.h"
 
#include "transport/adhocmanager.h"
 
#include "transport/protocol.pb.h"
 
#include "transport/networkpluginserver.h"
 
#include <cppunit/TestFixture.h>
 
#include <cppunit/extensions/HelperMacros.h>
 
#include <Swiften/Swiften.h>
 
#include <Swiften/EventLoop/DummyEventLoop.h>
 
#include <Swiften/Server/Server.h>
 
#include <Swiften/Network/DummyNetworkFactories.h>
 
#include <Swiften/Network/DummyConnectionServer.h>
 
#include "Swiften/Server/ServerStanzaChannel.h"
 
#include "Swiften/Server/ServerFromClientSession.h"
 
#include "Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.h"
 
@@ -45,38 +43,38 @@ class Clock {
 
		double elapsedTime() const {
 
			return m_elapsedTime;
 
		}
 
};
 

	
 
class NetworkPluginServerTest : public CPPUNIT_NS :: TestFixture, public BasicTest {
 
	CPPUNIT_TEST_SUITE(NetworkPluginServerTest);
 
	CPPUNIT_TEST(handleBuddyChangedPayload);
 
	CPPUNIT_TEST(handleBuddyChangedPayloadNoEscaping);
 
	CPPUNIT_TEST(handleBuddyChangedPayloadUserContactInRoster);
 
	CPPUNIT_TEST(handleMessageHeadline);
 
	CPPUNIT_TEST(handleConvMessageAckPayload);
 
	CPPUNIT_TEST(handleRawXML);
 
	CPPUNIT_TEST(handleRawXMLSplit);
 
// 	CPPUNIT_TEST(handleRawXML);
 
// 	CPPUNIT_TEST(handleRawXMLSplit);
 

	
 
	CPPUNIT_TEST(benchmarkHandleBuddyChangedPayload);
 
	CPPUNIT_TEST(benchmarkSendUnavailablePresence);
 
	CPPUNIT_TEST_SUITE_END();
 

	
 
	public:
 
		NetworkPluginServer *serv;
 

	
 
		void setUp (void) {
 
			setMeUp();
 

	
 
			serv = new NetworkPluginServer(component, cfg, userManager, NULL, NULL);
 
			serv = new NetworkPluginServer(component, cfg, userManager, NULL);
 
			connectUser();
 
			received.clear();
 
		}
 

	
 
		void tearDown (void) {
 
			received.clear();
 
			disconnectUser();
 
			delete serv;
 
			tearMeDown();
 
		}
 

	
 
		void handleConvMessageAckPayload() {
src/tests/rosterresponder.cpp
Show inline comments
 
@@ -26,25 +26,25 @@ class RosterResponderTest : public CPPUNIT_NS :: TestFixture, public BasicTest {
 
	CPPUNIT_TEST(addEmptyBuddy);
 
	CPPUNIT_TEST_SUITE_END();
 

	
 
	public:
 
		RosterResponder *m_rosterResponder;
 
		std::string m_buddy;
 

	
 
		void setUp (void) {
 
			m_buddy = "none";
 
			setMeUp();
 
			connectUser();
 

	
 
			m_rosterResponder = new RosterResponder(component->getIQRouter(), userManager);
 
			m_rosterResponder = new RosterResponder(static_cast<XMPPFrontend *>(component->getFrontend())->getIQRouter(), userManager);
 
			m_rosterResponder->onBuddyAdded.connect(boost::bind(&RosterResponderTest::handleBuddyAdded, this, _1, _2));
 
			m_rosterResponder->onBuddyRemoved.connect(boost::bind(&RosterResponderTest::handleBuddyRemoved, this, _1));
 
			m_rosterResponder->onBuddyUpdated.connect(boost::bind(&RosterResponderTest::handleBuddyUpdated, this, _1, _2));
 
			m_rosterResponder->start();
 

	
 
			received.clear();
 
		}
 

	
 
		void tearDown (void) {
 
			received.clear();
 
			disconnectUser();
 
			tearMeDown();
 
@@ -60,25 +60,25 @@ class RosterResponderTest : public CPPUNIT_NS :: TestFixture, public BasicTest {
 

	
 
	void handleBuddyUpdated(Buddy *buddy, const Swift::RosterItemPayload &item) {
 
		m_buddy = buddy->getName();
 
	}
 

	
 
	void addEmptyBuddy() {
 
		Swift::RosterPayload::ref p = Swift::RosterPayload::ref(new Swift::RosterPayload());
 
		Swift::RosterItemPayload item;
 
		item.setJID("icq.localhost");
 
		item.setSubscription(Swift::RosterItemPayload::Both);
 

	
 
		p->addItem(item);
 
		Swift::SetRosterRequest::ref request = Swift::SetRosterRequest::create(p, "user@localhost", component->getIQRouter());
 
		Swift::SetRosterRequest::ref request = Swift::SetRosterRequest::create(p, "user@localhost", static_cast<XMPPFrontend *>(component->getFrontend())->getIQRouter());
 

	
 
		boost::shared_ptr<Swift::IQ> iq(new Swift::IQ(Swift::IQ::Set));
 
		iq->setTo("icq.localhost");
 
		iq->setFrom("user@localhost");
 
		iq->addPayload(p);
 
		iq->setID("123");
 
		injectIQ(iq);
 

	
 
		CPPUNIT_ASSERT_EQUAL(std::string("none"), m_buddy);
 
	}
 

	
 
};
src/tests/settingsadhoccommand.cpp
Show inline comments
 
#include "transport/userregistry.h"
 
#include "transport/userregistration.h"
 
#include "transport/config.h"
 
#include "transport/storagebackend.h"
 
#include "transport/user.h"
 
#include "transport/transport.h"
 
#include "transport/conversation.h"
 
#include "transport/usermanager.h"
 
#include "transport/localbuddy.h"
 
#include "transport/settingsadhoccommand.h"
 
#include "transport/adhocmanager.h"
 
#include "settingsadhoccommand.h"
 
#include "adhocmanager.h"
 
#include <cppunit/TestFixture.h>
 
#include <cppunit/extensions/HelperMacros.h>
 
#include <Swiften/Swiften.h>
 
#include <Swiften/EventLoop/DummyEventLoop.h>
 
#include <Swiften/Server/Server.h>
 
#include <Swiften/Network/DummyNetworkFactories.h>
 
#include <Swiften/Network/DummyConnectionServer.h>
 
#include "Swiften/Server/ServerStanzaChannel.h"
 
#include "Swiften/Server/ServerFromClientSession.h"
 
#include "Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.h"
 
#include "Swiften/Version.h"
 
#include "basictest.h"
 
@@ -30,42 +30,31 @@ class SettingsAdHocCommandTest : public CPPUNIT_NS :: TestFixture, public BasicT
 
	CPPUNIT_TEST(getInfo);
 
	CPPUNIT_TEST(getInfoBare);
 
	CPPUNIT_TEST(execute);
 
	CPPUNIT_TEST(executeTwoCommands);
 
	CPPUNIT_TEST(executeBadSessionID);
 
	CPPUNIT_TEST(executeNotRegistered);
 
	CPPUNIT_TEST(cancel);
 
	CPPUNIT_TEST(propagateUserSetting);
 
	CPPUNIT_TEST(defaultAccordingToConfig);
 
	CPPUNIT_TEST_SUITE_END();
 

	
 
	public:
 
		AdHocManager *adhoc;
 
		SettingsAdHocCommandFactory *settings;
 

	
 
		void setUp (void) {
 
			setMeUp();
 

	
 
			adhoc = new AdHocManager(component, itemsResponder, userManager, storage);
 
			adhoc->start();
 
			settings = new SettingsAdHocCommandFactory();
 
			adhoc->addAdHocCommand(settings);
 

	
 
			received.clear();
 
		}
 

	
 
		void tearDown (void) {
 
			received.clear();
 
			delete adhoc;
 
			delete settings;
 
			tearMeDown();
 
		}
 

	
 
		void getItems() {
 
			boost::shared_ptr<Swift::DiscoItems> payload(new Swift::DiscoItems());
 
			payload->setNode("http://jabber.org/protocol/commands");
 
			boost::shared_ptr<Swift::IQ> iq = Swift::IQ::createRequest(Swift::IQ::Get, Swift::JID("localhost"), "id", payload);
 
			iq->setFrom("user@localhost");
 
			injectIQ(iq);
 
			loop->processEvents();
 

	
 
			CPPUNIT_ASSERT_EQUAL(1, (int) received.size());
src/tests/usermanager.cpp
Show inline comments
 
@@ -96,81 +96,81 @@ class UserManagerTest : public CPPUNIT_NS :: TestFixture, public BasicTest {
 
	}
 

	
 
	void handleProbePresence() {
 
		UserInfo info;
 
		info.id = 1;
 
		info.jid = "user@localhost";
 
		storage->setUser(info);
 

	
 
		Swift::Presence::ref response = Swift::Presence::create();
 
		response->setTo("localhost");
 
		response->setFrom("user@localhost/resource");
 
		response->setType(Swift::Presence::Probe);
 
		dynamic_cast<Swift::ServerStanzaChannel *>(component->getStanzaChannel())->onPresenceReceived(response);
 
		dynamic_cast<Swift::ServerStanzaChannel *>(static_cast<XMPPFrontend *>(component->getFrontend())->getStanzaChannel())->onPresenceReceived(response);
 
		loop->processEvents();
 

	
 
		CPPUNIT_ASSERT_EQUAL(3, (int) received.size());
 
		CPPUNIT_ASSERT(getStanza(received[0])->getPayload<Swift::DiscoInfo>());
 

	
 
		Swift::Presence *presence = dynamic_cast<Swift::Presence *>(getStanza(received[1]));
 
		CPPUNIT_ASSERT(presence);
 
		CPPUNIT_ASSERT_EQUAL(Swift::Presence::Unavailable, presence->getType());
 

	
 
		presence = dynamic_cast<Swift::Presence *>(getStanza(received[2]));
 
		CPPUNIT_ASSERT(presence);
 
		CPPUNIT_ASSERT_EQUAL(Swift::Presence::Probe, presence->getType());
 

	
 
		received.clear();
 
		response = Swift::Presence::create();
 
		response->setTo("localhost");
 
		response->setFrom("user@localhost");
 
		response->setType(Swift::Presence::Unsubscribed);
 
		dynamic_cast<Swift::ServerStanzaChannel *>(component->getStanzaChannel())->onPresenceReceived(response);
 
		dynamic_cast<Swift::ServerStanzaChannel *>(static_cast<XMPPFrontend *>(component->getFrontend())->getStanzaChannel())->onPresenceReceived(response);
 
		loop->processEvents();
 

	
 
		CPPUNIT_ASSERT_EQUAL(2, (int) received.size());
 
		presence = dynamic_cast<Swift::Presence *>(getStanza(received[1]));
 
		CPPUNIT_ASSERT(presence);
 
		CPPUNIT_ASSERT_EQUAL(Swift::Presence::Subscribe, presence->getType());
 

	
 
		received.clear();
 
		response = Swift::Presence::create();
 
		response->setTo("localhost");
 
		response->setFrom("user@localhost");
 
		response->setType(Swift::Presence::Error);
 
		dynamic_cast<Swift::ServerStanzaChannel *>(component->getStanzaChannel())->onPresenceReceived(response);
 
		dynamic_cast<Swift::ServerStanzaChannel *>(static_cast<XMPPFrontend *>(component->getFrontend())->getStanzaChannel())->onPresenceReceived(response);
 
		loop->processEvents();
 

	
 
		CPPUNIT_ASSERT_EQUAL(0, (int) received.size());
 

	
 
		response = Swift::Presence::create();
 
		response->setTo("localhost");
 
		response->setFrom("user@localhost");
 
		response->setType(Swift::Presence::Error);
 
		response->addPayload(boost::shared_ptr<Swift::ErrorPayload>(new Swift::ErrorPayload(Swift::ErrorPayload::SubscriptionRequired)));
 
		dynamic_cast<Swift::ServerStanzaChannel *>(component->getStanzaChannel())->onPresenceReceived(response);
 
		dynamic_cast<Swift::ServerStanzaChannel *>(static_cast<XMPPFrontend *>(component->getFrontend())->getStanzaChannel())->onPresenceReceived(response);
 
		loop->processEvents();
 

	
 
		CPPUNIT_ASSERT_EQUAL(1, (int) received.size());
 
		presence = dynamic_cast<Swift::Presence *>(getStanza(received[0]));
 
		CPPUNIT_ASSERT(presence);
 
		CPPUNIT_ASSERT_EQUAL(Swift::Presence::Subscribe, presence->getType());
 

	
 
		storage->removeUser(1);
 
		received.clear();
 
		response = Swift::Presence::create();
 
		response->setTo("localhost");
 
		response->setFrom("user@localhost");
 
		response->setType(Swift::Presence::Unsubscribed);
 
		dynamic_cast<Swift::ServerStanzaChannel *>(component->getStanzaChannel())->onPresenceReceived(response);
 
		dynamic_cast<Swift::ServerStanzaChannel *>(static_cast<XMPPFrontend *>(component->getFrontend())->getStanzaChannel())->onPresenceReceived(response);
 
		loop->processEvents();
 

	
 
		CPPUNIT_ASSERT_EQUAL(1, (int) received.size());
 
	}
 

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

	
 
	void connectTwoResources() {
 
		connectUser();
 
		add2Buddies();
src/transport.cpp
Show inline comments
 
@@ -9,315 +9,109 @@
 
 * (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 "transport/transport.h"
 
#include "transport/logging.h"
 
#include "transport/frontend.h"
 
#include "transport/presenceoracle.h"
 
#include "transport/config.h"
 

	
 
#include <boost/bind.hpp>
 
#include <boost/smart_ptr/make_shared.hpp>
 
#include <boost/algorithm/string/predicate.hpp>
 
#include "transport/storagebackend.h"
 
#include "transport/factory.h"
 
#include "transport/userregistry.h"
 
#include "transport/logging.h"
 
#include "storageparser.h"
 
#ifdef _WIN32
 
#include <Swiften/TLS/CAPICertificate.h>
 
#include "Swiften/TLS/Schannel/SchannelServerContext.h"
 
#include "Swiften/TLS/Schannel/SchannelServerContextFactory.h"
 
#else
 
#include "Swiften/TLS/PKCS12Certificate.h"
 
#include "Swiften/TLS/CertificateWithKey.h"
 
#include "Swiften/TLS/OpenSSL/OpenSSLServerContext.h"
 
#include "Swiften/TLS/OpenSSL/OpenSSLServerContextFactory.h"
 
#endif
 
#include "Swiften/Parser/PayloadParsers/AttentionParser.h"
 
#include "Swiften/Serializer/PayloadSerializers/AttentionSerializer.h"
 
#include "Swiften/Parser/PayloadParsers/XHTMLIMParser.h"
 
#include "Swiften/Serializer/PayloadSerializers/XHTMLIMSerializer.h"
 
#include "Swiften/Parser/PayloadParsers/StatsParser.h"
 
#include "Swiften/Serializer/PayloadSerializers/StatsSerializer.h"
 
#include "Swiften/Parser/PayloadParsers/GatewayPayloadParser.h"
 
#include "Swiften/Serializer/PayloadSerializers/GatewayPayloadSerializer.h"
 
#include "Swiften/Serializer/PayloadSerializers/SpectrumErrorSerializer.h"
 
#include "Swiften/Parser/PayloadParsers/MUCPayloadParser.h"
 
#include "transport/BlockParser.h"
 
#include "transport/BlockSerializer.h"
 
#include "Swiften/Parser/PayloadParsers/InvisibleParser.h"
 
#include "Swiften/Serializer/PayloadSerializers/InvisibleSerializer.h"
 
#include "Swiften/Parser/GenericPayloadParserFactory.h"
 
#include "Swiften/Queries/IQRouter.h"
 
#include "Swiften/Elements/RosterPayload.h"
 
#include "Swiften/Elements/InBandRegistrationPayload.h"
 

	
 
using namespace Swift;
 
using namespace boost;
 

	
 
namespace Transport {
 
	
 
DEFINE_LOGGER(logger, "Component");
 
DEFINE_LOGGER(logger_xml, "Component.XML");
 
DEFINE_LOGGER(logger_xml, "Component.RAW");
 

	
 
Component::Component(Swift::EventLoop *loop, Swift::NetworkFactories *factories, Config *config, Factory *factory, Transport::UserRegistry *userRegistry) {
 
	m_component = NULL;
 
Component::Component(Frontend *frontend, Swift::EventLoop *loop, Swift::NetworkFactories *factories, Config *config, Factory *factory, Transport::UserRegistry *userRegistry) {
 
	m_frontend = frontend;
 
	m_userRegistry = NULL;
 
	m_server = NULL;
 
	m_reconnectCount = 0;
 
	m_config = config;
 
	m_config->onBackendConfigUpdated.connect(boost::bind(&Component::handleBackendConfigChanged, this));
 
	m_factory = factory;
 
	m_loop = loop;
 
	m_userRegistry = userRegistry;
 
	m_rawXML = false;
 

	
 
	m_jid = Swift::JID(CONFIG_STRING(m_config, "service.jid"));
 

	
 
	m_factories = factories;
 

	
 
	m_reconnectTimer = m_factories->getTimerFactory()->createTimer(3000);
 
	m_reconnectTimer->onTick.connect(bind(&Component::start, this)); 
 

	
 
	if (CONFIG_BOOL(m_config, "service.server_mode")) {
 
		LOG4CXX_INFO(logger, "Creating component in server mode on port " << CONFIG_INT(m_config, "service.port"));
 
		m_server = new Swift::Server(loop, m_factories, m_userRegistry, m_jid, CONFIG_STRING(m_config, "service.server"), CONFIG_INT(m_config, "service.port"));
 
		if (!CONFIG_STRING(m_config, "service.cert").empty()) {
 
#ifndef _WIN32
 
//TODO: fix
 
			LOG4CXX_INFO(logger, "Using PKCS#12 certificate " << CONFIG_STRING(m_config, "service.cert"));
 
			LOG4CXX_INFO(logger, "SSLv23_server_method used.");
 
			TLSServerContextFactory *f = new OpenSSLServerContextFactory();
 
			CertificateWithKey::ref certificate = boost::make_shared<PKCS12Certificate>(CONFIG_STRING(m_config, "service.cert"), createSafeByteArray(CONFIG_STRING(m_config, "service.cert_password")));
 
			m_server->addTLSEncryption(f, certificate);
 
#endif
 
			
 
		}
 
		else {
 
			LOG4CXX_WARN(logger, "No PKCS#12 certificate used. TLS is disabled.");
 
		}
 
// 		m_server->start();
 
		m_stanzaChannel = m_server->getStanzaChannel();
 
		m_iqRouter = m_server->getIQRouter();
 

	
 
		m_server->addPayloadParserFactory(new GenericPayloadParserFactory<StorageParser>("private", "jabber:iq:private"));
 
		m_server->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::AttentionParser>("attention", "urn:xmpp:attention:0"));
 
		m_server->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::XHTMLIMParser>("html", "http://jabber.org/protocol/xhtml-im"));
 
		m_server->addPayloadParserFactory(new GenericPayloadParserFactory<Transport::BlockParser>("block", "urn:xmpp:block:0"));
 
		m_server->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::InvisibleParser>("invisible", "urn:xmpp:invisible:0"));
 
		m_server->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::StatsParser>("query", "http://jabber.org/protocol/stats"));
 
		m_server->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::GatewayPayloadParser>("query", "jabber:iq:gateway"));
 
		m_server->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::MUCPayloadParser>("x", "http://jabber.org/protocol/muc"));
 
	m_reconnectTimer->onTick.connect(boost::bind(&Component::start, this)); 
 

	
 
		m_server->addPayloadSerializer(new Swift::AttentionSerializer());
 
		m_server->addPayloadSerializer(new Swift::XHTMLIMSerializer());
 
		m_server->addPayloadSerializer(new Transport::BlockSerializer());
 
		m_server->addPayloadSerializer(new Swift::InvisibleSerializer());
 
		m_server->addPayloadSerializer(new Swift::StatsSerializer());
 
		m_server->addPayloadSerializer(new Swift::SpectrumErrorSerializer());
 
		m_server->addPayloadSerializer(new Swift::GatewayPayloadSerializer());
 

	
 
		m_server->onDataRead.connect(boost::bind(&Component::handleDataRead, this, _1));
 
		m_server->onDataWritten.connect(boost::bind(&Component::handleDataWritten, this, _1));
 
	}
 
	else {
 
		LOG4CXX_INFO(logger, "Creating component in gateway mode");
 
#if HAVE_SWIFTEN_3
 
		m_component = new Swift::Component(m_jid, CONFIG_STRING(m_config, "service.password"), m_factories);
 
#else
 
		m_component = new Swift::Component(loop, m_factories, m_jid, CONFIG_STRING(m_config, "service.password"));
 
#endif
 
		m_component->setSoftwareVersion("Spectrum", SPECTRUM_VERSION);
 
		m_component->onConnected.connect(bind(&Component::handleConnected, this));
 
		m_component->onError.connect(boost::bind(&Component::handleConnectionError, this, _1));
 
		m_component->onDataRead.connect(boost::bind(&Component::handleDataRead, this, _1));
 
		m_component->onDataWritten.connect(boost::bind(&Component::handleDataWritten, this, _1));
 

	
 
		m_component->addPayloadParserFactory(new GenericPayloadParserFactory<StorageParser>("private", "jabber:iq:private"));
 
		m_component->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::AttentionParser>("attention", "urn:xmpp:attention:0"));
 
		m_component->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::XHTMLIMParser>("html", "http://jabber.org/protocol/xhtml-im"));
 
		m_component->addPayloadParserFactory(new GenericPayloadParserFactory<Transport::BlockParser>("block", "urn:xmpp:block:0"));
 
		m_component->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::InvisibleParser>("invisible", "urn:xmpp:invisible:0"));
 
		m_component->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::StatsParser>("query", "http://jabber.org/protocol/stats"));
 
		m_component->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::GatewayPayloadParser>("query", "jabber:iq:gateway"));
 
		m_component->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::MUCPayloadParser>("x", "http://jabber.org/protocol/muc"));
 

	
 
		m_component->addPayloadSerializer(new Swift::AttentionSerializer());
 
		m_component->addPayloadSerializer(new Swift::XHTMLIMSerializer());
 
		m_component->addPayloadSerializer(new Transport::BlockSerializer());
 
		m_component->addPayloadSerializer(new Swift::InvisibleSerializer());
 
		m_component->addPayloadSerializer(new Swift::StatsSerializer());
 
		m_component->addPayloadSerializer(new Swift::SpectrumErrorSerializer());
 
		m_component->addPayloadSerializer(new Swift::GatewayPayloadSerializer());
 

	
 
		m_stanzaChannel = m_component->getStanzaChannel();
 
		m_iqRouter = m_component->getIQRouter();
 
	}
 
	m_presenceOracle = new Transport::PresenceOracle(frontend);
 
	m_presenceOracle->onPresenceChange.connect(boost::bind(&Component::handlePresence, this, _1));
 

	
 
	m_capsMemoryStorage = new CapsMemoryStorage();
 
#if HAVE_SWIFTEN_3
 
	m_capsManager = new CapsManager(m_capsMemoryStorage, m_stanzaChannel, m_iqRouter, m_factories->getCryptoProvider());
 
#else
 
	m_capsManager = new CapsManager(m_capsMemoryStorage, m_stanzaChannel, m_iqRouter);
 
#endif
 
	m_entityCapsManager = new EntityCapsManager(m_capsManager, m_stanzaChannel);
 
 	m_entityCapsManager->onCapsChanged.connect(boost::bind(&Component::handleCapsChanged, this, _1));
 
	
 
	m_presenceOracle = new Transport::PresenceOracle(m_stanzaChannel);
 
	m_presenceOracle->onPresenceChange.connect(bind(&Component::handlePresence, this, _1));
 

	
 

	
 

	
 
// 
 
// 	m_registerHandler = new SpectrumRegisterHandler(m_component);
 
// 	m_registerHandler->start();
 
	m_frontend->init(this, loop, factories, config, userRegistry);
 
}
 

	
 
Component::~Component() {
 
	delete m_presenceOracle;
 
	delete m_entityCapsManager;
 
	delete m_capsManager;
 
	delete m_capsMemoryStorage;
 
	if (m_component)
 
		delete m_component;
 
	if (m_server) {
 
		m_server->stop();
 
		delete m_server;
 
	}
 
}
 

	
 
bool Component::handleIQ(boost::shared_ptr<Swift::IQ> iq) {
 
	if (!m_rawXML) {
 
		return false;
 
	}
 

	
 
	if (iq->getPayload<Swift::RosterPayload>() != NULL) { return false; }
 
	if (iq->getPayload<Swift::InBandRegistrationPayload>() != NULL) { return false; }
 
	if (iq->getPayload<Swift::StatsPayload>() != NULL) { return false; }
 

	
 
	if (iq->getTo().getNode().empty()) {
 
		return false;
 
	}
 

	
 
	onRawIQReceived(iq);
 
	return true;
 
}
 

	
 
void Component::handleBackendConfigChanged() {
 
	if (!m_rawXML && CONFIG_BOOL_DEFAULTED(m_config, "features.rawxml", false)) {
 
		m_rawXML = true;
 
		m_iqRouter->addHandler(this);
 
	}
 
}
 

	
 
Swift::StanzaChannel *Component::getStanzaChannel() {
 
	return m_stanzaChannel;
 
}
 

	
 
Transport::PresenceOracle *Component::getPresenceOracle() {
 
	return m_presenceOracle;
 
}
 

	
 
void Component::start() {
 
	if (m_component && !m_component->isAvailable()) {
 
		LOG4CXX_INFO(logger, "Connecting XMPP server " << CONFIG_STRING(m_config, "service.server") << " port " << CONFIG_INT(m_config, "service.port"));
 
		if (CONFIG_INT(m_config, "service.port") == 5222) {
 
			LOG4CXX_WARN(logger, "Port 5222 is usually used for client connections, not for component connections! Are you sure you are using right port?");
 
		}
 
		m_reconnectCount++;
 
		m_component->connect(CONFIG_STRING(m_config, "service.server"), CONFIG_INT(m_config, "service.port"));
 
		m_reconnectTimer->stop();
 
	}
 
	else if (m_server) {
 
		LOG4CXX_INFO(logger, "Starting component in server mode on port " << CONFIG_INT(m_config, "service.port"));
 
		m_server->start();
 
bool Component::inServerMode() {
 
	 return CONFIG_BOOL_DEFAULTED(m_config, "service.server_mode", true);
 
}
 

	
 
		//Type casting to BoostConnectionServer since onStopped signal is not defined in ConnectionServer
 
		//Ideally, onStopped must be defined in ConnectionServer
 
		if (boost::dynamic_pointer_cast<Swift::BoostConnectionServer>(m_server->getConnectionServer())) {
 
			boost::dynamic_pointer_cast<Swift::BoostConnectionServer>(m_server->getConnectionServer())->onStopped.connect(boost::bind(&Component::handleServerStopped, this, _1));
 
		}
 
		
 
		// We're connected right here, because we're in server mode...
 
		handleConnected();
 
	}
 
void Component::start() {
 
	m_frontend->connectToServer();
 
	m_reconnectCount++;
 
	m_reconnectTimer->stop();
 
}
 

	
 
void Component::stop() {
 
	if (m_component) {
 
		m_reconnectCount = 0;
 
		// TODO: Call this once swiften will fix assert(!session_);
 
// 		m_component->disconnect();
 
		m_reconnectTimer->stop();
 
	}
 
	else if (m_server) {
 
		LOG4CXX_INFO(logger, "Stopping component in server mode on port " << CONFIG_INT(m_config, "service.port"));
 
		m_server->stop();
 
	}
 
	m_reconnectCount = 0;
 
	m_frontend->disconnectFromServer();
 
	m_reconnectTimer->stop();
 
}
 

	
 
void Component::handleConnected() {
 
	onConnected();
 
	m_reconnectCount = 0;
 
	m_reconnectTimer->stop();
 
}
 

	
 
void Component::handleServerStopped(boost::optional<Swift::BoostConnectionServer::Error> e) {
 
	if(e != NULL ) {
 
		if(*e == Swift::BoostConnectionServer::Conflict) {
 
			LOG4CXX_INFO(logger, "Port "<< CONFIG_INT(m_config, "service.port") << " already in use! Stopping server..");
 
			if (CONFIG_INT(m_config, "service.port") == 5347) {
 
				LOG4CXX_INFO(logger, "Port 5347 is usually used for components. You are using server_mode=1. Are you sure you don't want to use server_mode=0 and run spectrum as component?");
 
			}
 
		}
 
		if(*e == Swift::BoostConnectionServer::UnknownError)
 
			LOG4CXX_INFO(logger, "Unknown error occured! Stopping server..");
 
		exit(1);
 
	}
 
	LOG4CXX_INFO(logger, "Connected to Frontend server.");
 
}
 

	
 

	
 
void Component::handleConnectionError(const ComponentError &error) {
 
void Component::handleConnectionError(const std::string &error) {
 
	onConnectionError(error);
 
// 	if (m_reconnectCount == 2)
 
// 		Component::instance()->userManager()->removeAllUsers();
 
	std::string str = "Unknown error";
 
	switch (error.getType()) {
 
		case ComponentError::UnknownError: str = "Unknown error"; break;
 
		case ComponentError::ConnectionError: str = "Connection error"; break;
 
		case ComponentError::ConnectionReadError: str = "Connection read error"; break;
 
		case ComponentError::ConnectionWriteError: str = "Connection write error"; break;
 
		case ComponentError::XMLError: str = "XML Error"; break;
 
		case ComponentError::AuthenticationFailedError: str = "Authentication failed error"; break;
 
		case ComponentError::UnexpectedElementError: str = "Unexpected element error"; break;
 
	}
 
	LOG4CXX_INFO(logger, "Disconnected from XMPP server. Error: " << str);
 

	
 
	LOG4CXX_INFO(logger, "Disconnected from Frontend server. Error: " << error);
 
	m_reconnectTimer->start();
 
}
 

	
 
void Component::handleDataRead(const Swift::SafeByteArray &data) {
 
	std::string d = safeByteArrayToString(data);
 
	if (!boost::starts_with(d, "<auth")) {
 
		LOG4CXX_INFO(logger_xml, "XML IN " << d);
 
void Component::handleDataRead(const std::string &data) {
 
	if (!boost::starts_with(data, "<auth")) {
 
		LOG4CXX_INFO(logger_xml, "RAW DATA IN " << data);
 
	}
 
}
 

	
 
void Component::handleDataWritten(const Swift::SafeByteArray &data) {
 
	LOG4CXX_INFO(logger_xml, "XML OUT " << safeByteArrayToString(data));
 
void Component::handleDataWritten(const std::string &data) {
 
	LOG4CXX_INFO(logger_xml, "RAW DATA OUT " << data);
 
}
 

	
 
void Component::handlePresence(Swift::Presence::ref presence) {
 
	// filter out login/logout presence spam
 
	if (!presence->getTo().getNode().empty())
 
		return;
 

	
 
	// filter out bad presences
 
	if (!presence->getFrom().isValid()) {
 
		return;
 
	}
 

	
 
@@ -325,39 +119,19 @@ void Component::handlePresence(Swift::Presence::ref presence) {
 
		case Presence::Error:
 
		case Presence::Subscribe:
 
		case Presence::Subscribed:
 
		case Presence::Unsubscribe:
 
		case Presence::Unsubscribed:
 
			return;
 
		default:
 
			break;
 
	};
 

	
 
	// check if we have this client's capabilities and ask for them
 
	if (presence->getType() != Swift::Presence::Unavailable) {
 
		boost::shared_ptr<CapsInfo> capsInfo = presence->getPayload<CapsInfo>();
 
		if (capsInfo && capsInfo->getHash() == "sha-1") {
 
			/*haveFeatures = */m_entityCapsManager->getCaps(presence->getFrom()) != DiscoInfo::ref();
 
		}
 
#ifdef SUPPORT_LEGACY_CAPS
 
		else {
 
			GetDiscoInfoRequest::ref discoInfoRequest = GetDiscoInfoRequest::create(presence->getFrom(), m_iqRouter);
 
			discoInfoRequest->onResponse.connect(boost::bind(&Component::handleDiscoInfoResponse, this, _1, _2, presence->getFrom()));
 
			discoInfoRequest->send();
 
		}
 
#endif
 
		m_frontend->sendCapabilitiesRequest(presence->getFrom());
 
	}
 

	
 
	onUserPresenceReceived(presence);
 
}
 

	
 
void Component::handleDiscoInfoResponse(boost::shared_ptr<Swift::DiscoInfo> info, Swift::ErrorPayload::ref error, const Swift::JID& jid) {
 
#ifdef SUPPORT_LEGACY_CAPS
 
	onUserDiscoInfoReceived(jid, info);
 
#endif
 
}
 

	
 
void Component::handleCapsChanged(const Swift::JID& jid) {
 
	onUserDiscoInfoReceived(jid, m_entityCapsManager->getCaps(jid));
 
}
 

	
 
}

Changeset was too big and was cut off... Show full diff anyway

0 comments (0 inline, 0 general)