Changeset - f7dc91ccb482
backends/frotz/main.cpp
Show inline comments
 
@@ -224,49 +224,49 @@ class FrotzNetworkPlugin : public NetworkPlugin {
 
				repeated++;
 
				if (repeated > 30)
 
					return;
 
			}
 

	
 
			std::cout << "ignoring: " << buf << "\n";
 
		}
 

	
 
		std::vector<std::string> getGames() {
 
			std::vector<std::string> games;
 
			path p(".");
 
			directory_iterator end_itr;
 
			for (directory_iterator itr(p); itr != end_itr; ++itr) {
 
				if (extension(itr->path()) == ".z5") {
 
#if BOOST_FILESYSTEM_VERSION == 3
 
					games.push_back(itr->path().filename().string());
 
#else
 
					games.push_back(itr->path().leaf());
 
#endif
 
				}
 
			}
 
			return games;
 
		}
 

	
 
		void handleMessageSendRequest(const std::string &user, const std::string &legacyName, const std::string &message, const std::string &xhtml = "") {
 
		void handleMessageSendRequest(const std::string &user, const std::string &legacyName, const std::string &message, const std::string &xhtml = "", const std::string &id = "") {
 
			std::cout << "aaa\n";
 
			if (message.find("start") == 0) {
 
				std::string game = message.substr(6);
 
				std::vector<std::string> lst = getGames();
 
				if (std::find(lst.begin(), lst.end(), game) == lst.end()) {
 
					np->handleMessage(user, "zcode", "Unknown game");
 
					return;
 
				}
 
				np->handleMessage(user, "zcode", "Starting the game");
 

	
 
				dfrotz d;
 
				d.game = game;
 
				start_dfrotz(d, game);
 
				games[user] = d;
 
				fcntl(games[user].readpipe[0], F_SETFL, O_NONBLOCK);
 

	
 
				if (boost::filesystem::exists(user + "_" + games[user].game + ".save")) {
 

	
 
					std::string msg = "restore\n";
 
					write(games[user].writepipe[1], msg.c_str(), msg.size());
 

	
 
					msg = user + "_" + games[user].game + ".save\n";
 
					write(games[user].writepipe[1], msg.c_str(), msg.size());
 

	
backends/libcommuni/ircnetworkplugin.cpp
Show inline comments
 
@@ -123,49 +123,49 @@ void IRCNetworkPlugin::handleLogoutRequest(const std::string &user, const std::s
 
std::string IRCNetworkPlugin::getSessionName(const std::string &user, const std::string &legacyName) {
 
	std::string u = user;
 
	if (!CONFIG_BOOL(config, "service.server_mode") && m_servers.empty()) {
 
		u = user + legacyName.substr(legacyName.find("@") + 1);
 
		if (u.find("/") != std::string::npos) {
 
			u = u.substr(0, u.find("/"));
 
		}
 
	}
 
	return u;
 
}
 

	
 
std::string IRCNetworkPlugin::getTargetName(const std::string &legacyName) {
 
	std::string r = legacyName;
 
// 	if (!CONFIG_BOOL(config, "service.server_mode")) {
 
		if (legacyName.find("/") == std::string::npos) {
 
			r = legacyName.substr(0, r.find("@"));
 
		}
 
		else {
 
			r = legacyName.substr(legacyName.find("/") + 1);
 
		}
 
// 	}
 
	return r;
 
}
 

	
 
void IRCNetworkPlugin::handleMessageSendRequest(const std::string &user, const std::string &legacyName, const std::string &message, const std::string &/*xhtml*/) {
 
void IRCNetworkPlugin::handleMessageSendRequest(const std::string &user, const std::string &legacyName, const std::string &message, const std::string &/*xhtml*/, const std::string &/*id*/) {
 
	std::string session = getSessionName(user, legacyName);
 
	if (m_sessions[session] == NULL) {
 
		LOG4CXX_WARN(logger, user << ": Session name: " << session << ", No session for user");
 
		return;
 
	}
 

	
 
	std::string target = getTargetName(legacyName);
 

	
 
	LOG4CXX_INFO(logger, user << ": Session name: " << session << ", message to " << target);
 

	
 
	if (message.find("/me") == 0) {
 
		m_sessions[session]->sendCommand(IrcCommand::createCtcpAction(FROM_UTF8(target), FROM_UTF8(message.substr(4))));
 
	}
 
	else {
 
		m_sessions[session]->sendCommand(IrcCommand::createMessage(FROM_UTF8(target), FROM_UTF8(message)));
 
	}
 

	
 
	if (target.find("#") == 0) {
 
		handleMessage(user, legacyName, message, TO_UTF8(m_sessions[session]->nickName()));
 
	}
 
}
 

	
 
void IRCNetworkPlugin::handleRoomSubjectChangedRequest(const std::string &user, const std::string &room, const std::string &message) {
 
	std::string session = getSessionName(user, room);
backends/libcommuni/ircnetworkplugin.h
Show inline comments
 

	
 
#pragma once
 

	
 
#include "transport/config.h"
 
#include "transport/networkplugin.h"
 
#include "session.h"
 
#include <QtCore>
 
#include <QtNetwork>
 
#include "Swiften/EventLoop/Qt/QtEventLoop.h"
 
#include "ircnetworkplugin.h"
 

	
 

	
 
class IRCNetworkPlugin : public QObject, public NetworkPlugin {
 
	Q_OBJECT
 

	
 
	public:
 
		IRCNetworkPlugin(Config *config, Swift::QtEventLoop *loop, const std::string &host, int port);
 

	
 
		void handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password);
 

	
 
		void handleLogoutRequest(const std::string &user, const std::string &legacyName);
 

	
 
		void handleMessageSendRequest(const std::string &user, const std::string &legacyName, const std::string &message, const std::string &/*xhtml*/);
 
		void handleMessageSendRequest(const std::string &user, const std::string &legacyName, const std::string &message, const std::string &/*xhtml*/, const std::string &/*id*/);
 

	
 
		void handleJoinRoomRequest(const std::string &user, const std::string &room, const std::string &nickname, const std::string &password);
 

	
 
		void handleLeaveRoomRequest(const std::string &user, const std::string &room);
 

	
 
		void handleRoomSubjectChangedRequest(const std::string &user, const std::string &room, const std::string &message);
 

	
 
		void tryNextServer();
 

	
 
	public slots:
 
		void readData();
 
		void sendData(const std::string &string);
 

	
 
	private:
 
		MyIrcSession *createSession(const std::string &user, const std::string &hostname, const std::string &nickname, const std::string &password, const std::string &suffix = "");
 
		std::string getSessionName(const std::string &user, const std::string &legacyName);
 
		std::string getTargetName(const std::string &legacyName);
 

	
 
	private:
 
		Config *config;
 
		QTcpSocket *m_socket;
 
		std::map<std::string, MyIrcSession *> m_sessions;
 
		std::vector<std::string> m_servers;
 
		int m_currentServer;
backends/libpurple/main.cpp
Show inline comments
 
@@ -406,49 +406,49 @@ class SpectrumNetworkPlugin : public NetworkPlugin {
 
						st = PURPLE_STATUS_INVISIBLE;
 
						break;
 
					default:
 
						st = PURPLE_STATUS_AVAILABLE;
 
						break;
 
				}
 
				gchar *_markup = purple_markup_escape_text_wrapped(statusMessage.c_str(), -1);
 
				std::string markup(_markup);
 
				g_free(_markup);
 

	
 
				// we are already connected so we have to change status
 
				const PurpleStatusType *status_type = purple_account_get_status_type_with_primitive_wrapped(account, (PurpleStatusPrimitive) st);
 
				if (status_type != NULL) {
 
					// send presence to legacy network
 
					if (!markup.empty()) {
 
						purple_account_set_status_wrapped(account, purple_status_type_get_id_wrapped(status_type), TRUE, "message", markup.c_str(), NULL);
 
					}
 
					else {
 
						purple_account_set_status_wrapped(account, purple_status_type_get_id_wrapped(status_type), TRUE, NULL);
 
					}
 
				}
 
			}
 
		}
 

	
 
		void handleMessageSendRequest(const std::string &user, const std::string &legacyName, const std::string &message, const std::string &xhtml) {
 
		void handleMessageSendRequest(const std::string &user, const std::string &legacyName, const std::string &message, const std::string &xhtml, const std::string &id) {
 
			PurpleAccount *account = m_sessions[user];
 
			if (account) {
 
				PurpleConversation *conv = purple_find_conversation_with_account_wrapped(PURPLE_CONV_TYPE_CHAT, legacyName.c_str(), account);
 
				if (!conv) {
 
					conv = purple_find_conversation_with_account_wrapped(PURPLE_CONV_TYPE_IM, legacyName.c_str(), account);
 
					if (!conv) {
 
						conv = purple_conversation_new_wrapped(PURPLE_CONV_TYPE_IM, account, legacyName.c_str());
 
					}
 
				}
 
				if (xhtml.empty()) {
 
					gchar *_markup = purple_markup_escape_text_wrapped(message.c_str(), -1);
 
					if (purple_conversation_get_type_wrapped(conv) == PURPLE_CONV_TYPE_IM) {
 
						purple_conv_im_send_wrapped(PURPLE_CONV_IM_WRAPPED(conv), _markup);
 
					}
 
					else if (purple_conversation_get_type_wrapped(conv) == PURPLE_CONV_TYPE_CHAT) {
 
						purple_conv_chat_send_wrapped(PURPLE_CONV_CHAT_WRAPPED(conv), _markup);
 
					}
 
					g_free(_markup);
 
				}
 
				else {
 
					if (purple_conversation_get_type_wrapped(conv) == PURPLE_CONV_TYPE_IM) {
 
						purple_conv_im_send_wrapped(PURPLE_CONV_IM_WRAPPED(conv), xhtml.c_str());
 
					}
 
					else if (purple_conversation_get_type_wrapped(conv) == PURPLE_CONV_TYPE_CHAT) {
backends/libyahoo2/main.cpp
Show inline comments
 
@@ -124,49 +124,49 @@ class YahooPlugin : public NetworkPlugin {
 
		void _handleDataRead(boost::shared_ptr<Swift::SafeByteArray> data) {
 
			std::string d(data->begin(), data->end());
 
			handleDataRead(d);
 
		}
 

	
 
		void handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password) {
 
			YahooLocalAccount *account = new YahooLocalAccount(user, legacyName, password);
 
			m_users[user] = account;
 
			m_ids[account->id] = user;
 

	
 
			LOG4CXX_INFO(logger, user << ": Logging in the user as " << legacyName << " with id=" << account->id);
 
			account->login();
 
		}
 

	
 
		void handleLogoutRequest(const std::string &user, const std::string &legacyName) {
 
			YahooLocalAccount *account = m_users[user];
 
			if (account) {
 
				yahoo_logoff(account->id);
 
				m_ids.erase(account->id);
 
				m_users.erase(user);
 
				delete account;
 
			}
 
		}
 

	
 
		void handleMessageSendRequest(const std::string &user, const std::string &legacyName, const std::string &message, const std::string &xhtml = "") {
 
		void handleMessageSendRequest(const std::string &user, const std::string &legacyName, const std::string &message, const std::string &xhtml = "", const std::string &id = "") {
 
			YahooLocalAccount *account = m_users[user];
 
			if (account) {
 
				LOG4CXX_INFO(logger, "Sending message from " << user << " to " << legacyName << ": " << message << ".");
 
				yahoo_send_im(account->id, NULL, legacyName.c_str(), message.c_str(), 0, 0);
 
				_yahoo_write_ready(account);
 
			}
 
		}
 

	
 
		void handleBuddyUpdatedRequest(const std::string &user, const std::string &buddyName, const std::string &alias, const std::vector<std::string> &groups) {
 
			LOG4CXX_INFO(logger, user << ": Added buddy " << buddyName << ".");
 
			handleBuddyChanged(user, buddyName, alias, groups, pbnetwork::STATUS_ONLINE);
 
		}
 

	
 
		void _avatar_fetched(HTTPFetch *fetch, int account_id, unsigned int id, const std::string &img) {
 
			handleVCard(m_ids[account_id], id, "", "", "", img);
 
			delete fetch;
 
		}
 

	
 
		void handleVCardRequest(const std::string &user, const std::string &legacyName, unsigned int id) {
 
			YahooLocalAccount *account = m_users[user];
 
			if (!account) {
 
				return;
 
			}
 

	
backends/skype/main.cpp
Show inline comments
 
@@ -186,49 +186,49 @@ class SpectrumNetworkPlugin : public NetworkPlugin {
 
					break;
 
			}
 
			skype->send_command("SET USERSTATUS " + st);
 

	
 
			if (!statusMessage.empty()) {
 
				skype->send_command("SET PROFILE MOOD_TEXT " + statusMessage);
 
			}
 
		}
 

	
 
		void handleBuddyUpdatedRequest(const std::string &user, const std::string &buddyName, const std::string &alias, const std::vector<std::string> &groups) {
 
			Skype *skype = m_sessions[user];
 
			if (skype) {
 
				skype->send_command("SET USER " + buddyName + " BUDDYSTATUS 2 Please authorize me");
 
				skype->send_command("SET USER " + buddyName + " ISAUTHORIZED TRUE");
 
			}
 
		}
 

	
 
		void handleBuddyRemovedRequest(const std::string &user, const std::string &buddyName, const std::vector<std::string> &groups) {
 
			Skype *skype = m_sessions[user];
 
			if (skype) {
 
				skype->send_command("SET USER " + buddyName + " BUDDYSTATUS 1");
 
			}
 
		}
 

	
 
		void handleMessageSendRequest(const std::string &user, const std::string &legacyName, const std::string &message, const std::string &xhtml) {
 
		void handleMessageSendRequest(const std::string &user, const std::string &legacyName, const std::string &message, const std::string &xhtml = "", const std::string &id = "") {
 
			Skype *skype = m_sessions[user];
 
			if (skype) {
 
				skype->send_command("MESSAGE " + legacyName + " " + message);
 
			}
 
			
 
		}
 

	
 
		void handleVCardRequest(const std::string &user, const std::string &legacyName, unsigned int id) {
 
			Skype *skype = m_sessions[user];
 
			if (skype) {
 
				std::string name = legacyName;
 
				if (name.find("skype.") == 0) {
 
					name = name.substr(6);
 
				}
 
				std::string photo;
 
				gchar *filename = NULL;
 
				gchar *new_filename = NULL;
 
				gchar *image_data = NULL;
 
				gsize image_data_len = 0;
 
				gchar *ret;
 
				int fh;
 
				GError *error;
 
				const gchar *userfiles[] = {"user256", "user1024", "user4096", "user16384", "user32768", "user65536",
 
											"profile256", "profile1024", "profile4096", "profile16384", "profile32768", 
backends/smstools3/main.cpp
Show inline comments
 
@@ -172,49 +172,49 @@ class SMSNetworkPlugin : public NetworkPlugin {
 
			std::string d(data->begin(), data->end());
 
			handleDataRead(d);
 
		}
 

	
 
		void handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password) {
 
			UserInfo info;
 
			if (!storageBackend->getUser(user, info)) {
 
				handleDisconnected(user, 0, "Not registered user.");
 
				return;
 
			}
 
			std::list<BuddyInfo> roster;
 
			storageBackend->getBuddies(info.id, roster);
 

	
 
			// Send available presence to every number in the roster.
 
			BOOST_FOREACH(BuddyInfo &b, roster) {
 
				handleBuddyChanged(user, b.legacyName, b.alias, b.groups, pbnetwork::STATUS_ONLINE);
 
			}
 

	
 
			np->handleConnected(user);
 
		}
 

	
 
		void handleLogoutRequest(const std::string &user, const std::string &legacyName) {
 
		}
 

	
 
		void handleMessageSendRequest(const std::string &user, const std::string &legacyName, const std::string &message, const std::string &xhtml = "") {
 
		void handleMessageSendRequest(const std::string &user, const std::string &legacyName, const std::string &message, const std::string &xhtml = "", const std::string &id = "") {
 
			// Remove trailing +, because smstools doesn't use it in "From: " field for received messages.
 
			std::string n = legacyName;
 
			if (n.find("+") == 0) {
 
				n = n.substr(1);
 
			}
 

	
 
			// Create GSM Number - XMPP user pair to match the potential response and send it to the proper JID.
 
			BuddyInfo info;
 
			info.legacyName = n;
 
			info.alias = user;
 
			info.id = -1;
 
			info.subscription = "both";
 
			info.flags = 0;
 
			storageBackend->addBuddy(m_internalUser, info);
 

	
 
			LOG4CXX_INFO(logger, "Sending SMS from " << user << " to " << n << ".");
 
			sendSMS(n, message);
 
		}
 

	
 
		void handleJoinRoomRequest(const std::string &user, const std::string &room, const std::string &nickname, const std::string &password) {
 
		}
 

	
 
		void handleLeaveRoomRequest(const std::string &user, const std::string &room) {
 
		}
backends/swiften/main.cpp
Show inline comments
 
@@ -181,49 +181,49 @@ class SwiftenPlugin : public NetworkPlugin {
 
			m_users[user] = client;
 
			client->setAlwaysTrustCertificates();
 
			client->onConnected.connect(boost::bind(&SwiftenPlugin::handleSwiftConnected, this, user));
 
			client->onDisconnected.connect(boost::bind(&SwiftenPlugin::handleSwiftDisconnected, this, user, _1));
 
			client->onMessageReceived.connect(boost::bind(&SwiftenPlugin::handleSwiftMessageReceived, this, user, _1));
 
			client->getRoster()->onInitialRosterPopulated.connect(boost::bind(&SwiftenPlugin::handleSwiftRosterReceived, this, user));
 
			client->getPresenceOracle()->onPresenceChange.connect(boost::bind(&SwiftenPlugin::handleSwiftPresenceChanged, this, user, _1));
 
			Swift::ClientOptions opt;
 
			opt.allowPLAINWithoutTLS = true;
 
			client->connect(opt);
 
		}
 

	
 
		void handleLogoutRequest(const std::string &user, const std::string &legacyName) {
 
			boost::shared_ptr<Swift::Client> client = m_users[user];
 
			if (client) {
 
				client->onConnected.disconnect(boost::bind(&SwiftenPlugin::handleSwiftConnected, this, user));
 
// 				client->onDisconnected.disconnect(boost::bind(&SwiftenPlugin::handleSwiftDisconnected, this, user, _1));
 
				client->onMessageReceived.disconnect(boost::bind(&SwiftenPlugin::handleSwiftMessageReceived, this, user, _1));
 
				client->getRoster()->onInitialRosterPopulated.disconnect(boost::bind(&SwiftenPlugin::handleSwiftRosterReceived, this, user));
 
				client->getPresenceOracle()->onPresenceChange.disconnect(boost::bind(&SwiftenPlugin::handleSwiftPresenceChanged, this, user, _1));
 
				client->disconnect();
 
			}
 
		}
 

	
 
		void handleMessageSendRequest(const std::string &user, const std::string &legacyName, const std::string &msg, const std::string &xhtml = "") {
 
		void handleMessageSendRequest(const std::string &user, const std::string &legacyName, const std::string &msg, const std::string &xhtml = "", const std::string &id = "") {
 
			LOG4CXX_INFO(logger, "Sending message from " << user << " to " << legacyName << ".");
 
			boost::shared_ptr<Swift::Client> client = m_users[user];
 
			if (client) {
 
				boost::shared_ptr<Swift::Message> message(new Swift::Message());
 
				message->setTo(Swift::JID(legacyName));
 
				message->setFrom(client->getJID());
 
				message->setBody(msg);
 

	
 
				client->sendMessage(message);
 
			}
 
		}
 

	
 
		void handleVCardRequest(const std::string &user, const std::string &legacyName, unsigned int id) {
 
			boost::shared_ptr<Swift::Client> client = m_users[user];
 
			if (client) {
 
				LOG4CXX_INFO(logger, user << ": fetching VCard of " << legacyName << " id=" << id);
 
				Swift::GetVCardRequest::ref request = Swift::GetVCardRequest::create(Swift::JID(legacyName), client->getIQRouter());
 
				request->onResponse.connect(boost::bind(&SwiftenPlugin::handleSwiftVCardReceived, this, user, id, _1, _2));
 
				request->send();
 
			}
 
		}
 

	
 
		void handleBuddyUpdatedRequest(const std::string &user, const std::string &buddyName, const std::string &alias, const std::vector<std::string> &groups) {
 
			LOG4CXX_INFO(logger, user << ": Added/Updated buddy " << buddyName << ".");
backends/template/plugin.cpp
Show inline comments
 
@@ -24,39 +24,39 @@ Plugin::Plugin(Config *config, Swift::SimpleEventLoop *loop, const std::string &
 

	
 
	LOG4CXX_INFO(logger, "Starting the plugin.");
 
}
 

	
 
// NetworkPlugin uses this method to send the data to networkplugin server
 
void Plugin::sendData(const std::string &string) {
 
	m_conn->write(Swift::createSafeByteArray(string));
 
}
 

	
 
// This method has to call handleDataRead with all received data from network plugin server
 
void Plugin::_handleDataRead(boost::shared_ptr<Swift::SafeByteArray> data) {
 
	std::string d(data->begin(), data->end());
 
	handleDataRead(d);
 
}
 

	
 
void Plugin::handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password) {
 
	handleConnected(user);
 
	LOG4CXX_INFO(logger, user << ": Added buddy - Echo.");
 
	handleBuddyChanged(user, "echo", "Echo", std::vector<std::string>(), pbnetwork::STATUS_ONLINE);
 
}
 

	
 
void Plugin::handleLogoutRequest(const std::string &user, const std::string &legacyName) {
 
}
 

	
 
void Plugin::handleMessageSendRequest(const std::string &user, const std::string &legacyName, const std::string &message, const std::string &xhtml) {
 
void Plugin::handleMessageSendRequest(const std::string &user, const std::string &legacyName, const std::string &message, const std::string &xhtml, const std::string &id) {
 
	LOG4CXX_INFO(logger, "Sending message from " << user << " to " << legacyName << ".");
 
	if (legacyName == "echo") {
 
		handleMessage(user, legacyName, message);
 
	}
 
}
 

	
 
void Plugin::handleBuddyUpdatedRequest(const std::string &user, const std::string &buddyName, const std::string &alias, const std::vector<std::string> &groups) {
 
	LOG4CXX_INFO(logger, user << ": Added buddy " << buddyName << ".");
 
	handleBuddyChanged(user, buddyName, alias, groups, pbnetwork::STATUS_ONLINE);
 
}
 

	
 
void Plugin::handleBuddyRemovedRequest(const std::string &user, const std::string &buddyName, const std::vector<std::string> &groups) {
 

	
 
}
backends/template/plugin.h
Show inline comments
 
#pragma once
 

	
 
#include "Swiften/Swiften.h"
 

	
 
#include "transport/config.h"
 
#include "transport/networkplugin.h"
 

	
 
class Plugin : public Transport::NetworkPlugin {
 
	public:
 
		Plugin(Transport::Config *config, Swift::SimpleEventLoop *loop, const std::string &host, int port);
 

	
 
		// NetworkPlugin uses this method to send the data to networkplugin server
 
		void sendData(const std::string &string);
 

	
 
		void handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password);
 

	
 
		void handleLogoutRequest(const std::string &user, const std::string &legacyName);
 

	
 
		void handleMessageSendRequest(const std::string &user, const std::string &legacyName, const std::string &message, const std::string &xhtml = "");
 
		void handleMessageSendRequest(const std::string &user, const std::string &legacyName, const std::string &message, const std::string &xhtml = "", const std::string &id = "");
 

	
 
		void handleBuddyUpdatedRequest(const std::string &user, const std::string &buddyName, const std::string &alias, const std::vector<std::string> &groups);
 

	
 
		void handleBuddyRemovedRequest(const std::string &user, const std::string &buddyName, const std::vector<std::string> &groups);
 

	
 
	private:
 
		// This method has to call handleDataRead with all received data from network plugin server
 
		void _handleDataRead(boost::shared_ptr<Swift::SafeByteArray> data);
 

	
 
	private:
 
		Swift::BoostNetworkFactories *m_factories;
 
		Swift::BoostIOServiceThread m_boostIOServiceThread;
 
		boost::shared_ptr<Swift::Connection> m_conn;
 
		Transport::Config *config;
 
};
backends/twitter/TwitterPlugin.cpp
Show inline comments
 
@@ -173,49 +173,49 @@ void TwitterPlugin::handleJoinRoomRequest(const std::string &user, const std::st
 
		setTwitterMode(user, 2);
 
		handleParticipantChanged(user, adminNickName, room, 0, pbnetwork::STATUS_ONLINE);
 
		userdb[user].nickName = nickname;
 
		handleMessage(user, adminChatRoom, "Connected to Twitter room! Populating your followers list", adminNickName);
 
		tp->runAsThread(new FetchFriends(userdb[user].sessions, user,
 
										 boost::bind(&TwitterPlugin::populateRoster, this, _1, _2, _3, _4)));
 
	} else {
 
		setTwitterMode(user, 0);
 
		LOG4CXX_ERROR(logger, "Couldn't connect to chatroom - " << room <<"! Try twitter-chatroom as the chatroom to access Twitter account")
 
		handleMessage(user, adminLegacyName, "Couldn't connect to chatroom! Try twitter-chatroom as the chatroom to access Twitter account");
 
	}	
 
}
 

	
 
// User leaving a Chatroom
 
void TwitterPlugin::handleLeaveRoomRequest(const std::string &user, const std::string &room)
 
{
 
	if(room == adminChatRoom && onlineUsers.count(user)) {
 
		LOG4CXX_INFO(logger, "Leaving chatroom! Switching back to default mode 0")
 
		setTwitterMode(user, 0);
 
		handleBuddyChanged(user, adminLegacyName, adminAlias, std::vector<std::string>(), pbnetwork::STATUS_ONLINE);
 
	}
 
}
 

	
 
// Messages to be sent to Twitter 
 
void TwitterPlugin::handleMessageSendRequest(const std::string &user, const std::string &legacyName, const std::string &message, const std::string &xhtml) 
 
void TwitterPlugin::handleMessageSendRequest(const std::string &user, const std::string &legacyName, const std::string &message, const std::string &xhtml, const std::string &/*id*/) 
 
{
 

	
 
	LOG4CXX_INFO(logger, "Received " << user << " --> " << legacyName << " - " << message)
 
	
 
	if(legacyName == adminLegacyName || legacyName == adminChatRoom)  {
 
		std::string cmd = "", data = "";
 
	 
 
		/** Parsing the message - Assuming message format to be <cmd>[ ]*<data>**/	
 
		int i;
 
		for(i=0 ; i<message.size() && message[i] != ' '; i++) cmd += message[i];
 
		while(i<message.size() && message[i] == ' ') i++;
 
		data = message.substr(i);
 
		/***********************************************************************/
 
		
 
		if(cmd == "#pin") 
 
			tp->runAsThread(new PINExchangeProcess(np, userdb[user].sessions, user, data));
 
		else if(cmd == "#help") 
 
			tp->runAsThread(new HelpMessageRequest(user, boost::bind(&TwitterPlugin::helpMessageResponse, this, _1, _2)));
 
		else if(cmd[0] == '@') {
 
			std::string username = cmd.substr(1); 
 
			tp->runAsThread(new DirectMessageRequest(userdb[user].sessions, user, username, data,
 
												     boost::bind(&TwitterPlugin::directMessageResponse, this, _1, _2, _3, _4)));
 
		}
 
		else if(cmd == "#status") 
backends/twitter/TwitterPlugin.h
Show inline comments
 
@@ -53,49 +53,49 @@ class TwitterPlugin : public NetworkPlugin {
 
		boost::shared_ptr<Swift::Connection> m_conn;
 
		Swift::Timer::ref tweet_timer;
 
		Swift::Timer::ref message_timer;
 
		StorageBackend *storagebackend;
 

	
 
		TwitterPlugin(Config *config, Swift::SimpleEventLoop *loop, StorageBackend *storagebackend, const std::string &host, int port);
 
		~TwitterPlugin();
 

	
 
		// Send data to NetworkPlugin server
 
		void sendData(const std::string &string);
 

	
 
		// Receive date from the NetworkPlugin server and invoke the appropirate payload handler (implement in the NetworkPlugin class)
 
		void _handleDataRead(boost::shared_ptr<Swift::SafeByteArray> data);
 
	
 
		// User trying to login into his twitter account
 
		void handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password);
 
		
 
		// User logging out
 
		void handleLogoutRequest(const std::string &user, const std::string &legacyName);
 
		
 
		void handleJoinRoomRequest(const std::string &/*user*/, const std::string &/*room*/, const std::string &/*nickname*/, const std::string &/*pasword*/);
 

	
 
		void handleLeaveRoomRequest(const std::string &/*user*/, const std::string &/*room*/);
 

	
 
		void handleMessageSendRequest(const std::string &user, const std::string &legacyName, const std::string &message, const std::string &xhtml = "");
 
		void handleMessageSendRequest(const std::string &user, const std::string &legacyName, const std::string &message, const std::string &xhtml = "", const std::string &id = "");
 

	
 
		void handleBuddyUpdatedRequest(const std::string &user, const std::string &buddyName, const std::string &alias, const std::vector<std::string> &groups);
 

	
 
		void handleBuddyRemovedRequest(const std::string &user, const std::string &buddyName, const std::vector<std::string> &groups);
 
		
 
		void handleVCardRequest(const std::string &/*user*/, const std::string &/*legacyName*/, unsigned int /*id*/);
 
		
 
		void pollForTweets();
 

	
 
		void pollForDirectMessages();
 
		
 
		bool getUserOAuthKeyAndSecret(const std::string user, std::string &key, std::string &secret);
 
		
 
		bool checkSpectrum1User(const std::string user);
 
		
 
		bool storeUserOAuthKeyAndSecret(const std::string user, const std::string OAuthKey, const std::string OAuthSecret);
 
		
 
		void initUserSession(const std::string user, const std::string legacyName, const std::string password);
 
		
 
		void OAuthFlowComplete(const std::string user, twitCurl *obj);
 
		
 
		void pinExchangeComplete(const std::string user, const std::string OAuthAccessTokenKey, const std::string OAuthAccessTokenSecret);
 
		
 
		void updateLastTweetID(const std::string user, const std::string ID);
include/transport/config.h
Show inline comments
 
@@ -105,38 +105,39 @@ class Config {
 
		
 
		/// For variables in sections you can use "section.variable" key format.
 
		/// \param key config variable name
 
		const boost::program_options::variable_value &operator[] (const std::string &key) {
 
			if (m_variables.find(key) != m_variables.end()) {
 
				return m_variables[key];
 
			}
 
			if (m_backendConfig.find(key) != m_backendConfig.end()) {
 
				return m_backendConfig[key];
 
			}
 
			return m_unregistered[key];
 
		}
 

	
 
		SectionValuesCont getSectionValues(const std::string& sectionName);
 
 
 
		std::string getCommandLineArgs() const;
 

	
 
		/// Returns path to config file from which data were loaded.
 
		const std::string &getConfigFile() { return m_file; }
 

	
 
		/// This signal is emitted when config is loaded/reloaded.
 
		boost::signal<void ()> onConfigReloaded;
 

	
 
		void updateBackendConfig(const std::string &backendConfig);
 
		boost::signal<void ()> onBackendConfigUpdated;
 

	
 
		static Config *createFromArgs(int argc, char **argv, std::string &error, std::string &host, int &port);
 
	
 
	private:
 
		int m_argc;
 
		char **m_argv;
 
		Variables m_variables;
 
		Variables m_backendConfig;
 
		std::map<std::string, boost::program_options::variable_value> m_unregistered;
 
		std::string m_file;
 
		std::string m_jid;
 
};
 

	
 
}
include/transport/networkplugin.h
Show inline comments
 
@@ -92,48 +92,50 @@ class NetworkPlugin {
 
		/// \param status Current status of participant. Swift::StatusShow::None if participant left the room.
 
		/// \param statusMessage Current status message of participant.
 
		/// \param newname New name of participant if he changed the nickname. Otherwise empty.
 
		void handleParticipantChanged(const std::string &user, const std::string &nickname, const std::string &room, int flags,
 
			pbnetwork::StatusType = pbnetwork::STATUS_NONE, const std::string &statusMessage = "", const std::string &newname = "");
 

	
 
		/// Call this function when user disconnected the legacy network because of some legacy network error.
 
		/// \param user XMPP JID of user for which this event occurs. You can get it from NetworkPlugin::handleLoginRequest(). (eg. "user%gmail.com@xmpp.domain.tld")
 
		/// \param error Reserved for future use, currently keep it on 0.
 
		/// \param message XMPP message which is sent to XMPP user.
 
		void handleDisconnected(const std::string &user, int error = 0, const std::string &message = "");
 

	
 
		/// Call this function when user connected the legacy network and is logged in.
 
		/// \param user XMPP JID of user for which this event occurs. You can get it from NetworkPlugin::handleLoginRequest(). (eg. "user%gmail.com@xmpp.domain.tld")
 
		void handleConnected(const std::string &user);
 

	
 
		/// Call this function when new message is received from legacy network for user.
 
		/// \param user XMPP JID of user for which this event occurs. You can get it from NetworkPlugin::handleLoginRequest(). (eg. "user%gmail.com@xmpp.domain.tld")
 
		/// \param legacyName Name of legacy network buddy or name of room. (eg. "user2@gmail.com")
 
		/// \param message Plain text message.
 
		/// \param nickname Nickname of buddy in room. Empty if it's normal chat message.
 
		/// \param xhtml XHTML message.
 
		void handleMessage(const std::string &user, const std::string &legacyName, const std::string &message, const std::string &nickname = "", const std::string &xhtml = "", const std::string &timestamp = "", bool headline = false);
 

	
 
		void handleMessageAck(const std::string &user, const std::string &legacyName, const std::string &id);
 

	
 
		/// Call this function when subject in room changed.
 
		/// \param user XMPP JID of user for which this event occurs. You can get it from NetworkPlugin::handleLoginRequest(). (eg. "user%gmail.com@xmpp.domain.tld")
 
		/// \param legacyName Name of room. (eg. "#spectrum")
 
		/// \param message Subject message.
 
		/// \param nickname Nickname of user who changed subject.
 
		void handleSubject(const std::string &user, const std::string &legacyName, const std::string &message, const std::string &nickname = "");
 

	
 
		/// Call this function XMPP user's nickname changed.
 
		/// \param user XMPP JID of user for which this event occurs. You can get it from NetworkPlugin::handleLoginRequest(). (eg. "user%gmail.com@xmpp.domain.tld")
 
		/// \param room Room in which participant changed. (eg. #spectrum)
 
		/// \param nickname New nickname.
 
		void handleRoomNicknameChanged(const std::string &user, const std::string &room, const std::string &nickname);
 

	
 
		/// Call this function when requested VCard arrived.
 
		/// \param user XMPP JID of user for which this event occurs. You can get it from NetworkPlugin::handleLoginRequest(). (eg. "user%gmail.com@xmpp.domain.tld")
 
		/// \param id VCard ID.
 
		/// \param legacyName Name of legacy network buddy. (eg. "user2@gmail.com")
 
		/// \param fullName Name of legacy network buddy. (eg. "Monty Python")
 
		/// \param nickname Nickname.
 
		/// \param photo Raw photo.
 
		void handleVCard(const std::string &user, unsigned int id, const std::string &legacyName, const std::string &fullName, const std::string &nickname, const std::string &photo);
 

	
 
		/// Call this function when buddy started typing.
 
		/// \param user XMPP JID of user for which this event occurs. You can get it from NetworkPlugin::handleLoginRequest(). (eg. "user%gmail.com@xmpp.domain.tld")
 
@@ -178,49 +180,49 @@ class NetworkPlugin {
 
			NetworkPlugin,YourNetworkPlugin,LegacyNetwork;
 
			NetworkPlugin->YourNetworkPlugin [label="handleLoginRequest(...)", URL="\ref NetworkPlugin::handleLoginRequest()"];
 
			YourNetworkPlugin->LegacyNetwork [label="connect the legacy network"];
 
			--- [label="If password was valid and user is connected and logged in"];
 
			YourNetworkPlugin<-LegacyNetwork [label="connected"];
 
			YourNetworkPlugin->NetworkPlugin [label="handleConnected()", URL="\ref NetworkPlugin::handleConnected()"];
 
			--- [label="else"];
 
			YourNetworkPlugin<-LegacyNetwork [label="disconnected"];
 
			YourNetworkPlugin->NetworkPlugin [label="handleDisconnected()", URL="\ref NetworkPlugin::handleDisconnected()"];
 
			\endmsc
 
		*/
 
		virtual void handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password) = 0;
 

	
 
		/// Called when XMPP user wants to disconnect legacy network.
 
		/// You should disconnect him from legacy network.
 
		/// \param user XMPP JID of user for which this event occurs.
 
		/// \param legacyName Legacy network name of this user used for login.
 
		virtual void handleLogoutRequest(const std::string &user, const std::string &legacyName) = 0;
 

	
 
		/// Called when XMPP user sends message to legacy network.
 
		/// \param user XMPP JID of user for which this event occurs.
 
		/// \param legacyName Legacy network name of buddy or room.
 
		/// \param message Plain text message.
 
		/// \param xhtml XHTML message.
 
		virtual void handleMessageSendRequest(const std::string &user, const std::string &legacyName, const std::string &message, const std::string &xhtml = "") = 0;
 
		virtual void handleMessageSendRequest(const std::string &user, const std::string &legacyName, const std::string &message, const std::string &xhtml = "", const std::string &id = "") = 0;
 

	
 
		/// Called when XMPP user requests VCard of buddy.
 
		/// \param user XMPP JID of user for which this event occurs.
 
		/// \param legacyName Legacy network name of buddy whose VCard is requested.
 
		/// \param id ID which is associated with this request. You have to pass it to handleVCard function when you receive VCard.
 
		/**
 
			\msc
 
			NetworkPlugin,YourNetworkPlugin,LegacyNetwork;
 
			NetworkPlugin->YourNetworkPlugin [label="handleVCardRequest(...)", URL="\ref NetworkPlugin::handleVCardRequest()"];
 
			YourNetworkPlugin->LegacyNetwork [label="start VCard fetching"];
 
			YourNetworkPlugin<-LegacyNetwork [label="VCard fetched"];
 
			YourNetworkPlugin->NetworkPlugin [label="handleVCard()", URL="\ref NetworkPlugin::handleVCard()"];
 
			\endmsc
 
		*/
 
		virtual void handleVCardRequest(const std::string &/*user*/, const std::string &/*legacyName*/, unsigned int /*id*/) {}
 

	
 
		/// Called when XMPP user updates his own VCard.
 
		/// You should update the VCard in legacy network too.
 
		/// \param user XMPP JID of user for which this event occurs.
 
		/// \param photo Raw photo data.
 
		virtual void handleVCardUpdatedRequest(const std::string &/*user*/, const std::string &/*photo*/, const std::string &nickname) {}
 

	
 
		virtual void handleRoomSubjectChangedRequest(const std::string &/*user*/, const std::string &/*room*/, const std::string &/*message*/) {}
 

	
include/transport/networkpluginserver.h
Show inline comments
 
@@ -79,48 +79,49 @@ class NetworkPluginServer {
 
			return m_clients;
 
		}
 

	
 
		const std::vector<std::string> &getCrashedBackends() {
 
			return m_crashedBackends;
 
		}
 

	
 
		void collectBackend();
 

	
 
		bool moveToLongRunBackend(User *user);
 

	
 
		void handleMessageReceived(NetworkConversation *conv, boost::shared_ptr<Swift::Message> &message);
 

	
 
	public:
 
		void handleNewClientConnection(boost::shared_ptr<Swift::Connection> c);
 
		void handleSessionFinished(Backend *c);
 
		void handlePongReceived(Backend *c);
 
		void handleDataRead(Backend *c, boost::shared_ptr<Swift::SafeByteArray> data);
 

	
 
		void handleConnectedPayload(const std::string &payload);
 
		void handleDisconnectedPayload(const std::string &payload);
 
		void handleBuddyChangedPayload(const std::string &payload);
 
		void handleBuddyRemovedPayload(const std::string &payload);
 
		void handleConvMessagePayload(const std::string &payload, bool subject = false);
 
		void handleConvMessageAckPayload(const std::string &payload);
 
		void handleParticipantChangedPayload(const std::string &payload);
 
		void handleRoomChangedPayload(const std::string &payload);
 
		void handleVCardPayload(const std::string &payload);
 
		void handleChatStatePayload(const std::string &payload, Swift::ChatState::ChatStateType type);
 
		void handleAuthorizationPayload(const std::string &payload);
 
		void handleAttentionPayload(const std::string &payload);
 
		void handleStatsPayload(Backend *c, const std::string &payload);
 
		void handleFTStartPayload(const std::string &payload);
 
		void handleFTFinishPayload(const std::string &payload);
 
		void handleFTDataPayload(Backend *b, const std::string &payload);
 
		void handleQueryPayload(Backend *b, const std::string &payload);
 
		void handleBackendConfigPayload(const std::string &payload);
 
		void handleRoomListPayload(const std::string &payload);
 

	
 
		void handleUserCreated(User *user);
 
		void handleRoomJoined(User *user, const Swift::JID &who, const std::string &room, const std::string &nickname, const std::string &password);
 
		void handleRoomLeft(User *user, const std::string &room);
 
		void handleUserReadyToConnect(User *user);
 
		void handleUserPresenceChanged(User *user, Swift::Presence::ref presence);
 
		void handleUserDestroyed(User *user);
 

	
 
		void handleBuddyUpdated(Buddy *buddy, const Swift::RosterItemPayload &item);
 
		void handleBuddyRemoved(Buddy *buddy);
 
		void handleBuddyAdded(Buddy *buddy, const Swift::RosterItemPayload &item);
include/transport/protocol.proto
Show inline comments
 
@@ -50,48 +50,49 @@ message Login {
 
message Logout {
 
	required string user = 1;
 
	required string legacyName = 2;
 
}
 

	
 
message Buddy {
 
	required string userName = 1;
 
	required string buddyName = 2;
 
	optional string alias = 3;
 
	repeated string group = 4;
 
	optional StatusType status = 5;
 
	optional string statusMessage = 6;
 
	optional string iconHash = 7;
 
	optional bool blocked = 8;
 
}
 

	
 
message ConversationMessage {
 
	required string userName = 1;
 
	required string buddyName = 2;
 
	required string message = 3;
 
	optional string nickname = 4;
 
	optional string xhtml = 5;
 
	optional string timestamp = 6;
 
	optional bool headline = 7;
 
	optional string id = 8;
 
}
 

	
 
message Room {
 
	required string userName = 1;
 
	required string nickname = 2;
 
	required string room = 3;
 
	optional string password = 4;
 
}
 

	
 
message RoomList {
 
	repeated string room = 1;
 
	repeated string name = 2;
 
}
 

	
 
message Participant {
 
	required string userName = 1;
 
	required string room = 2;
 
	required string nickname = 3;
 
	required int32 flag = 4;
 
	required StatusType status = 5;
 
	optional string statusMessage = 6;
 
	optional string newname = 7;
 
}
 

	
 
@@ -146,29 +147,30 @@ message WrapperMessage {
 
		TYPE_PING					= 9;
 
		TYPE_PONG					= 10;
 
		TYPE_JOIN_ROOM				= 11;
 
		TYPE_LEAVE_ROOM				= 12;
 
		TYPE_PARTICIPANT_CHANGED	= 13;
 
		TYPE_ROOM_NICKNAME_CHANGED	= 14;
 
		TYPE_ROOM_SUBJECT_CHANGED	= 15;
 
		TYPE_VCARD					= 16;
 
		TYPE_STATUS_CHANGED			= 17;
 
		TYPE_BUDDY_TYPING			= 18;
 
		TYPE_BUDDY_STOPPED_TYPING	= 19;
 
		TYPE_BUDDY_TYPED			= 20;
 
		TYPE_AUTH_REQUEST			= 21;
 
		TYPE_ATTENTION				= 22;
 
		TYPE_STATS					= 23;
 
		TYPE_FT_START				= 24;
 
		TYPE_FT_FINISH				= 25;
 
		TYPE_FT_DATA				= 26;
 
		TYPE_FT_PAUSE				= 27;
 
		TYPE_FT_CONTINUE			= 28;
 
		TYPE_EXIT					= 29;
 
		TYPE_BACKEND_CONFIG			= 30;
 
		TYPE_QUERY					= 31;
 
		TYPE_ROOM_LIST				= 32;
 
		TYPE_CONV_MESSAGE_ACK		= 33;
 
	}
 
	required Type type = 1;
 
	optional bytes payload = 2;
 
}
 
;
plugin/cpp/networkplugin.cpp
Show inline comments
 
@@ -79,48 +79,63 @@ void NetworkPlugin::sendConfig(const PluginConfig &cfg) {
 

	
 
	WRAP(message, pbnetwork::WrapperMessage_Type_TYPE_BACKEND_CONFIG);
 

	
 
	send(message);
 
}
 

	
 
void NetworkPlugin::handleMessage(const std::string &user, const std::string &legacyName, const std::string &msg, const std::string &nickname, const std::string &xhtml, const std::string &timestamp, bool headline) {
 
	pbnetwork::ConversationMessage m;
 
	m.set_username(user);
 
	m.set_buddyname(legacyName);
 
	m.set_message(msg);
 
	m.set_nickname(nickname);
 
	m.set_xhtml(xhtml);
 
	m.set_timestamp(timestamp);
 
	m.set_headline(headline);
 

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

	
 
	WRAP(message, pbnetwork::WrapperMessage_Type_TYPE_CONV_MESSAGE);
 

	
 
	send(message);
 
}
 

	
 
void NetworkPlugin::handleMessageAck(const std::string &user, const std::string &legacyName, const std::string &id) {
 
	pbnetwork::ConversationMessage m;
 
	m.set_username(user);
 
	m.set_buddyname(legacyName);
 
	m.set_message("");
 
	m.set_id(id);
 

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

	
 
	WRAP(message, pbnetwork::WrapperMessage_Type_TYPE_CONV_MESSAGE_ACK);
 

	
 
	send(message);
 
}
 

	
 
void NetworkPlugin::handleAttention(const std::string &user, const std::string &buddyName, const std::string &msg) {
 
	pbnetwork::ConversationMessage m;
 
	m.set_username(user);
 
	m.set_buddyname(buddyName);
 
	m.set_message(msg);
 

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

	
 
	WRAP(message, pbnetwork::WrapperMessage_Type_TYPE_ATTENTION);
 

	
 
	send(message);
 
}
 

	
 
void NetworkPlugin::handleVCard(const std::string &user, unsigned int id, const std::string &legacyName, const std::string &fullName, const std::string &nickname, const std::string &photo) {
 
	pbnetwork::VCard vcard;
 
	vcard.set_username(user);
 
	vcard.set_buddyname(legacyName);
 
	vcard.set_id(id);
 
	vcard.set_fullname(fullName);
 
	vcard.set_nickname(nickname);
 
	vcard.set_photo(photo);
 

	
 
	std::string message;
 
@@ -370,49 +385,49 @@ void NetworkPlugin::handleLogoutPayload(const std::string &data) {
 
	if (payload.ParseFromString(data) == false) {
 
		// TODO: ERROR
 
		return;
 
	}
 
	handleLogoutRequest(payload.user(), payload.legacyname());
 
}
 

	
 
void NetworkPlugin::handleStatusChangedPayload(const std::string &data) {
 
	pbnetwork::Status payload;
 
	if (payload.ParseFromString(data) == false) {
 
		// TODO: ERROR
 
		return;
 
	}
 

	
 
	handleStatusChangeRequest(payload.username(), payload.status(), payload.statusmessage());
 
}
 

	
 
void NetworkPlugin::handleConvMessagePayload(const std::string &data) {
 
	pbnetwork::ConversationMessage payload;
 
	if (payload.ParseFromString(data) == false) {
 
		// TODO: ERROR
 
		return;
 
	}
 

	
 
	handleMessageSendRequest(payload.username(), payload.buddyname(), payload.message(), payload.xhtml());
 
	handleMessageSendRequest(payload.username(), payload.buddyname(), payload.message(), payload.xhtml(), payload.id());
 
}
 

	
 
void NetworkPlugin::handleRoomSubjectChangedPayload(const std::string &data) {
 
	pbnetwork::ConversationMessage payload;
 
	if (payload.ParseFromString(data) == false) {
 
		// TODO: ERROR
 
		return;
 
	}
 

	
 
	handleRoomSubjectChangedRequest(payload.username(), payload.buddyname(), payload.message());
 
}
 

	
 
void NetworkPlugin::handleAttentionPayload(const std::string &data) {
 
	pbnetwork::ConversationMessage payload;
 
	if (payload.ParseFromString(data) == false) {
 
		// TODO: ERROR
 
		return;
 
	}
 

	
 
	handleAttentionRequest(payload.username(), payload.buddyname(), payload.message());
 
}
 

	
 
void NetworkPlugin::handleFTStartPayload(const std::string &data) {
 
	pbnetwork::File payload;
src/adhocmanager.cpp
Show inline comments
 
@@ -48,57 +48,55 @@ AdHocManager::AdHocManager(Component *component, DiscoItemsResponder *discoItems
 

	
 
AdHocManager::~AdHocManager() {
 
	m_collectTimer->stop();
 
	stop();
 
}
 

	
 
void AdHocManager::start() {
 
	Swift::Responder<Swift::Command>::start();
 
}
 

	
 
void AdHocManager::stop() {
 
	Swift::Responder<Swift::Command>::stop();
 

	
 
	for (SessionsMap::iterator it = m_sessions.begin(); it != m_sessions.end(); it++) {
 
		std::vector<std::string> candidates;
 
		for (CommandsMap::iterator ct = it->second.begin(); ct != it->second.end(); ct++) {
 
			delete ct->second;
 
		}
 
	}
 

	
 
	m_sessions.clear();
 
}
 

	
 
void AdHocManager::handleUserCreated(User *user) {
 
	if (!m_storageBackend) {
 
		return;
 
	}
 

	
 
	for (std::map<std::string, AdHocCommandFactory *>::const_iterator it = m_factories.begin(); it != m_factories.end(); it++) {
 
		for (std::map<std::string, std::string>::const_iterator it2 = it->second->getUserSettings().begin(); it2 != it->second->getUserSettings().end(); it2++) {
 
			std::string value = CONFIG_STRING_DEFAULTED(m_component->getConfig(), it->second->getNode() + "." + it2->first, it2->second);
 
			int type = (int) TYPE_BOOLEAN;
 
			m_storageBackend->getUserSetting(user->getUserInfo().id, it2->first, type, value);
 
			if (m_storageBackend) {
 
				int type = (int) TYPE_BOOLEAN;
 
				m_storageBackend->getUserSetting(user->getUserInfo().id, it2->first, type, value);
 
			}
 
			user->addUserSetting(it2->first, value);
 
		}
 
	}
 
}
 

	
 
void AdHocManager::addAdHocCommand(AdHocCommandFactory *factory) {
 
	if (m_factories.find(factory->getNode()) != m_factories.end()) {
 
		LOG4CXX_ERROR(logger, "Command with node " << factory->getNode() << " is already registered. Ignoring this attempt.");
 
		return;
 
	}
 

	
 
	m_factories[factory->getNode()] = factory;
 
	m_discoItemsResponder->addAdHocCommand(factory->getNode(), factory->getName());
 
}
 

	
 
void AdHocManager::removeOldSessions() {
 
	unsigned long removedCommands = 0;
 
	time_t now = time(NULL);
 

	
 
	std::vector<std::string> toRemove;
 
	for (SessionsMap::iterator it = m_sessions.begin(); it != m_sessions.end(); it++) {
 
		std::vector<std::string> candidates;
 
		for (CommandsMap::iterator ct = it->second.begin(); ct != it->second.end(); ct++) {
 
			if (now - ct->second->getLastActivity() > 15*60) {
src/config.cpp
Show inline comments
 
@@ -291,55 +291,58 @@ Config::SectionValuesCont Config::getSectionValues(const std::string& sectionNam
 
		if (boost::istarts_with(varItem.first, sectionSearchString))
 
			sectionValues[varItem.first] = varItem.second;
 
	}
 

	
 
	return sectionValues;
 
}
 

	
 
std::string Config::getCommandLineArgs() const {
 
	std::ostringstream commandLineArgs;
 

	
 
	// Return the command-line arguments that were passed to us originally (but remove the initial .exe part)
 
	for (int i = 1; i < m_argc; ++i) 	{
 
		commandLineArgs << "\"" << m_argv[i] << "\" ";
 
	}
 

	
 
	return commandLineArgs.str();
 
}
 

	
 
void Config::updateBackendConfig(const std::string &backendConfig) {
 
	options_description opts("Backend options");
 
	opts.add_options()
 
		("registration.needPassword", value<bool>()->default_value(true), "")
 
		("registration.needRegistration", value<bool>()->default_value(false), "")
 
		("registration.extraField", value<std::vector<std::string> >()->multitoken(), "")
 
		("features.receipts", value<bool>()->default_value(false), "")
 
	;
 

	
 
	std::stringstream ifs(backendConfig);
 
	parsed_options parsed = parse_config_file(ifs, opts, true);
 

	
 
	store(parsed, m_backendConfig);
 
	notify(m_backendConfig);
 

	
 
	onBackendConfigUpdated();
 
}
 

	
 
Config *Config::createFromArgs(int argc, char **argv, std::string &error, std::string &host, int &port) {
 
	std::string jid;
 
	std::ostringstream os;
 
	std::string configFile;
 
	boost::program_options::variables_map vm;
 
	boost::program_options::options_description desc("Usage: spectrum <config_file.cfg>\nAllowed options");
 
	desc.add_options()
 
		("help", "help")
 
		("host,h", boost::program_options::value<std::string>(&host)->default_value(""), "Host to connect to")
 
		("port,p", boost::program_options::value<int>(&port)->default_value(10000), "Port to connect to")
 
		("no-daemonize,n", "Do not run spectrum as daemon")
 
		("no-debug,d", "Create coredumps on crash")
 
		("jid,j", boost::program_options::value<std::string>(&jid)->default_value(""), "Specify JID of transport manually")
 
		("config", boost::program_options::value<std::string>(&configFile)->default_value(""), "Config file")
 
		;
 

	
 
	os << desc;
 
	try
 
	{
 
		boost::program_options::positional_options_description p;
 
		p.add("config", -1);
 
		boost::program_options::store(boost::program_options::command_line_parser(argc, argv).
src/discoinforesponder.cpp
Show inline comments
 
@@ -18,90 +18,102 @@
 
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
 
 */
 

	
 
#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 "Swiften/Swiften.h"
 
#include "transport/config.h"
 
#include "transport/logging.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::updateBuddyFeatures, this));
 
	m_buddyInfo = NULL;
 
	m_transportInfo.addIdentity(DiscoInfo::Identity(CONFIG_STRING(m_config, "identity.name"),
 
													CONFIG_STRING(m_config, "identity.category"),
 
													CONFIG_STRING(m_config, "identity.type")));
 

	
 
	m_buddyInfo.addIdentity(DiscoInfo::Identity(CONFIG_STRING(m_config, "identity.name"), "client", "pc"));
 
	std::list<std::string> features;
 
	features.push_back("jabber:iq:register");
 
	features.push_back("jabber:iq:gateway");
 
	features.push_back("jabber:iq:private");
 
	features.push_back("http://jabber.org/protocol/disco#info");
 
	features.push_back("http://jabber.org/protocol/commands");
 
	setTransportFeatures(features);
 

	
 
	features.clear();
 
	updateBuddyFeatures();
 
}
 

	
 
DiscoInfoResponder::~DiscoInfoResponder() {
 
	delete m_buddyInfo;
 
}
 

	
 
void DiscoInfoResponder::updateBuddyFeatures() {
 
	std::list<std::string> features;
 
	features.push_back("http://jabber.org/protocol/disco#items");
 
	features.push_back("http://jabber.org/protocol/disco#info");
 
	features.push_back("http://jabber.org/protocol/chatstates");
 
	features.push_back("http://jabber.org/protocol/xhtml-im");
 
	if (CONFIG_BOOL_DEFAULTED(m_config, "features.receipts", false)) {
 
		features.push_back("urn:xmpp:receipts");
 
	}
 
	setBuddyFeatures(features);
 
}
 

	
 
DiscoInfoResponder::~DiscoInfoResponder() {
 
	
 
}
 

	
 
void DiscoInfoResponder::setTransportFeatures(std::list<std::string> &features) {
 
	for (std::list<std::string>::iterator it = features.begin(); it != features.end(); it++) {
 
		if (!m_transportInfo.hasFeature(*it)) {
 
			m_transportInfo.addFeature(*it);
 
		}
 
	}
 
}
 

	
 
void DiscoInfoResponder::setBuddyFeatures(std::list<std::string> &f) {
 
	delete m_buddyInfo;
 
	m_buddyInfo = new Swift::DiscoInfo;
 
	m_buddyInfo->addIdentity(DiscoInfo::Identity(CONFIG_STRING(m_config, "identity.name"), "client", "pc"));
 

	
 
	for (std::list<std::string>::iterator it = f.begin(); it != f.end(); it++) {
 
		if (!m_buddyInfo.hasFeature(*it)) {
 
			m_buddyInfo.addFeature(*it);
 
		if (!m_buddyInfo->hasFeature(*it)) {
 
			m_buddyInfo->addFeature(*it);
 
		}
 
	}
 

	
 
	CapsInfoGenerator caps("spectrum");
 
	m_capsInfo = caps.generateCapsInfo(m_buddyInfo);
 
	m_capsInfo = caps.generateCapsInfo(*m_buddyInfo);
 
	onBuddyCapsInfoChanged(m_capsInfo);
 
}
 

	
 
void DiscoInfoResponder::addRoom(const std::string &jid, const std::string &name) {
 
	std::string j = jid;
 
	boost::algorithm::to_lower(j);
 
	m_rooms[j] = name;
 
}
 

	
 
void DiscoInfoResponder::clearRooms() {
 
	m_rooms.clear();
 
}
 

	
 
void DiscoInfoResponder::addAdHocCommand(const std::string &node, const std::string &name) {
 
	m_commands[node] = node;
 
}
 

	
 
bool DiscoInfoResponder::handleGetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr<Swift::DiscoInfo> info) {
 
	// disco#info for transport
 
	if (to.getNode().empty()) {
 
		// Adhoc command
 
		if (m_commands.find(info->getNode()) != m_commands.end()) {
 
			boost::shared_ptr<DiscoInfo> res(new DiscoInfo());
 
			res->addFeature("http://jabber.org/protocol/commands");
 
@@ -115,32 +127,32 @@ bool DiscoInfoResponder::handleGetRequest(const Swift::JID& from, const Swift::J
 
			res->addIdentity(DiscoInfo::Identity("Commands", "automation", "command-list"));
 
			res->setNode(info->getNode());
 
			sendResponse(from, to, id, res);
 
		}
 
		else {
 
			if (!info->getNode().empty()) {
 
				sendError(from, id, ErrorPayload::ItemNotFound, ErrorPayload::Cancel);
 
				return true;
 
			}
 

	
 
			boost::shared_ptr<DiscoInfo> res(new DiscoInfo(m_transportInfo));
 
			res->setNode(info->getNode());
 
			sendResponse(from, id, res);
 
		}
 
	}
 
	// disco#info for room
 
	else if (m_rooms.find(to.toBare().toString()) != m_rooms.end()) {
 
		boost::shared_ptr<DiscoInfo> res(new DiscoInfo());
 
		res->addIdentity(DiscoInfo::Identity(m_rooms[to.toBare().toString()], "conference", "text"));
 
		res->setNode(info->getNode());
 
		sendResponse(from, to, id, res);
 
	}
 
	// disco#info for buddy
 
	else {
 
		boost::shared_ptr<DiscoInfo> res(new DiscoInfo(m_buddyInfo));
 
		boost::shared_ptr<DiscoInfo> res(new DiscoInfo(*m_buddyInfo));
 
		res->setNode(info->getNode());
 
		sendResponse(from, to, id, res);
 
	}
 
	return true;
 
}
 

	
 
}
src/discoinforesponder.h
Show inline comments
 
@@ -30,34 +30,35 @@ namespace Transport {
 

	
 
class Config;
 

	
 
class DiscoInfoResponder : public Swift::GetResponder<Swift::DiscoInfo> {
 
	public:
 
		DiscoInfoResponder(Swift::IQRouter *router, Config *config);
 
		~DiscoInfoResponder();
 

	
 
		void setTransportFeatures(std::list<std::string> &features);
 
		void setBuddyFeatures(std::list<std::string> &features);
 

	
 
		void addRoom(const std::string &jid, const std::string &name);
 
		void clearRooms();
 

	
 
		void addAdHocCommand(const std::string &node, const std::string &name);
 

	
 
		boost::signal<void (const Swift::CapsInfo &capsInfo)> onBuddyCapsInfoChanged;
 

	
 
		Swift::CapsInfo &getBuddyCapsInfo() {
 
				return m_capsInfo;
 
		}
 

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

	
 
		Swift::DiscoInfo m_transportInfo;
 
		Swift::DiscoInfo m_buddyInfo;
 
		Swift::DiscoInfo *m_buddyInfo;
 
		Config *m_config;
 
		Swift::CapsInfo m_capsInfo;
 
		std::map<std::string, std::string> m_rooms;
 
		std::map<std::string, std::string> m_commands;
 
};
 

	
 
}
src/networkpluginserver.cpp
Show inline comments
 
@@ -665,48 +665,75 @@ void NetworkPluginServer::handleConvMessagePayload(const std::string &data, bool
 
		msg->addPayload(delay);
 
	}
 

	
 
	
 
	NetworkConversation *conv = (NetworkConversation *) user->getConversationManager()->getConversation(payload.buddyname());
 

	
 
	// We can't create Conversation for payload with nickname, because this means the message is from room,
 
	// but this user is not in any room, so it's OK to just reject this message
 
	if (!conv && !payload.nickname().empty()) {
 
		return;
 
	}
 

	
 
	// Create new Conversation if it does not exist
 
	if (!conv) {
 
		conv = new NetworkConversation(user->getConversationManager(), payload.buddyname());
 
		user->getConversationManager()->addConversation(conv);
 
		conv->onMessageToSend.connect(boost::bind(&NetworkPluginServer::handleMessageReceived, this, _1, _2));
 
	}
 

	
 
	// Forward it
 
	conv->handleMessage(msg, payload.nickname());
 
	m_userManager->messageToXMPPSent();
 
}
 

	
 
void NetworkPluginServer::handleConvMessageAckPayload(const std::string &data) {
 
	pbnetwork::ConversationMessage payload;
 

	
 
	if (payload.ParseFromString(data) == false) {
 
		// TODO: ERROR
 
		return;
 
	}
 

	
 
	User *user = m_userManager->getUser(payload.username());
 
	if (!user)
 
		return;
 

	
 

	
 
	boost::shared_ptr<Swift::Message> msg(new Swift::Message());
 
	msg->addPayload(boost::make_shared<Swift::DeliveryReceipt>(payload.id()));
 

	
 
	NetworkConversation *conv = (NetworkConversation *) user->getConversationManager()->getConversation(payload.buddyname());
 

	
 
	// Receipts don't create conversation
 
	if (!conv) {
 
		return;
 
	}
 

	
 
	// Forward it
 
	conv->handleMessage(msg);
 
}
 

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

	
 
	User *user = m_userManager->getUser(payload.username());
 
	if (!user)
 
		return;
 

	
 
	boost::shared_ptr<Swift::Message> msg(new Swift::Message());
 
	msg->setBody(payload.message());
 
	msg->addPayload(boost::make_shared<Swift::AttentionPayload>());
 

	
 
	// Attentions trigger new Conversation creation
 
	NetworkConversation *conv = (NetworkConversation *) user->getConversationManager()->getConversation(payload.buddyname());
 
	if (!conv) {
 
		conv = new NetworkConversation(user->getConversationManager(), payload.buddyname());
 
		user->getConversationManager()->addConversation(conv);
 
		conv->onMessageToSend.connect(boost::bind(&NetworkPluginServer::handleMessageReceived, this, _1, _2));
 
	}
 

	
 
	conv->handleMessage(msg);
 
@@ -1002,48 +1029,51 @@ void NetworkPluginServer::handleDataRead(Backend *c, boost::shared_ptr<Swift::Sa
 
			case pbnetwork::WrapperMessage_Type_TYPE_STATS:
 
				handleStatsPayload(c, wrapper.payload());
 
				break;
 
			case pbnetwork::WrapperMessage_Type_TYPE_FT_START:
 
				handleFTStartPayload(wrapper.payload());
 
				break;
 
			case pbnetwork::WrapperMessage_Type_TYPE_FT_FINISH:
 
				handleFTFinishPayload(wrapper.payload());
 
				break;
 
			case pbnetwork::WrapperMessage_Type_TYPE_FT_DATA:
 
				handleFTDataPayload(c, wrapper.payload());
 
				break;
 
			case pbnetwork::WrapperMessage_Type_TYPE_BUDDY_REMOVED:
 
				handleBuddyRemovedPayload(wrapper.payload());
 
				break;
 
			case pbnetwork::WrapperMessage_Type_TYPE_QUERY:
 
				handleQueryPayload(c, wrapper.payload());
 
				break;
 
			case pbnetwork::WrapperMessage_Type_TYPE_BACKEND_CONFIG:
 
				handleBackendConfigPayload(wrapper.payload());
 
				break;
 
			case pbnetwork::WrapperMessage_Type_TYPE_ROOM_LIST:
 
				handleRoomListPayload(wrapper.payload());
 
				break;
 
			case pbnetwork::WrapperMessage_Type_TYPE_CONV_MESSAGE_ACK:
 
				handleConvMessageAckPayload(wrapper.payload());
 
				break;
 
			default:
 
				return;
 
		}
 
	}
 
}
 

	
 
void NetworkPluginServer::send(boost::shared_ptr<Swift::Connection> &c, const std::string &data) {
 
	// generate header - size of wrapper message
 
	uint32_t size = htonl(data.size());
 
	char *header = (char *) &size;
 

	
 
	// send header together with wrapper message
 
	c->write(Swift::createSafeByteArray(std::string(header, 4) + data));
 
}
 

	
 
void NetworkPluginServer::pingTimeout() {
 
	// TODO: move to separate timer, those 2 loops could be expensive
 
	// Some users are connected for weeks and they are blocking backend to be destroyed and its memory
 
	// to be freed. We are finding users who are inactive for more than "idle_reconnect_time" seconds and
 
	// reconnect them to long-running backend, where they can idle hapilly till the end of ages.
 
	time_t now = time(NULL);
 
	std::vector<User *> usersToMove;
 
	unsigned long diff = CONFIG_INT(m_config, "service.idle_reconnect_time");
 
	if (diff != 0) {
 
@@ -1385,48 +1415,52 @@ void NetworkPluginServer::handleMessageReceived(NetworkConversation *conv, boost
 
		std::string message;
 
		m.SerializeToString(&message);
 

	
 
		WRAP(message, pbnetwork::WrapperMessage_Type_TYPE_ROOM_SUBJECT_CHANGED);
 

	
 
		Backend *c = (Backend *) conv->getConversationManager()->getUser()->getData();
 
		send(c->connection, message);
 
		return;
 
	}
 
	
 

	
 
	std::string xhtml;
 
	boost::shared_ptr<Swift::XHTMLIMPayload> xhtmlPayload = msg->getPayload<Swift::XHTMLIMPayload>();
 
	if (xhtmlPayload) {
 
		xhtml = xhtmlPayload->getBody();
 
	}
 

	
 
	// Send normal message
 
	if (!msg->getBody().empty() || !xhtml.empty()) {
 
		pbnetwork::ConversationMessage m;
 
		m.set_username(conv->getConversationManager()->getUser()->getJID().toBare());
 
		m.set_buddyname(conv->getLegacyName());
 
		m.set_message(msg->getBody());
 
		m.set_xhtml(xhtml);
 
		boost::shared_ptr<Swift::DeliveryReceiptRequest> receiptPayload = msg->getPayload<Swift::DeliveryReceiptRequest>();
 
		if (receiptPayload && !msg->getID().empty()) {
 
			m.set_id(msg->getID());
 
		}
 

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

	
 
		WRAP(message, pbnetwork::WrapperMessage_Type_TYPE_CONV_MESSAGE);
 

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

	
 
void NetworkPluginServer::handleBuddyRemoved(Buddy *b) {
 
	User *user = b->getRosterManager()->getUser();
 

	
 
	pbnetwork::Buddy buddy;
 
	buddy.set_username(user->getJID().toBare());
 
	buddy.set_buddyname(b->getName());
 
	buddy.set_alias(b->getAlias());
 
	BOOST_FOREACH(const std::string &g, b->getGroups()) {
 
		buddy.add_group(g);
 
	}
src/tests/discoitemsresponder.cpp
Show inline comments
 
@@ -7,48 +7,49 @@
 
#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"
 

	
 
using namespace Transport;
 

	
 
class DiscoItemsResponderTest : public CPPUNIT_NS :: TestFixture, public BasicTest {
 
	CPPUNIT_TEST_SUITE(DiscoItemsResponderTest);
 
	CPPUNIT_TEST(roomList);
 
	CPPUNIT_TEST(roomInfo);
 
	CPPUNIT_TEST(clearRooms);
 
	CPPUNIT_TEST(receipts);
 
	CPPUNIT_TEST_SUITE_END();
 

	
 
	public:
 

	
 
		void setUp (void) {
 
			setMeUp();
 
		}
 

	
 
		void tearDown (void) {
 
			received.clear();
 
			tearMeDown();
 
		}
 

	
 
	void roomList() {
 
		itemsResponder->addRoom("#room@localhost", "#room");
 

	
 
		boost::shared_ptr<Swift::DiscoItems> payload(new Swift::DiscoItems());
 
		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());
 
		CPPUNIT_ASSERT(dynamic_cast<Swift::IQ *>(getStanza(received[0])));
 
@@ -73,27 +74,53 @@ class DiscoItemsResponderTest : public CPPUNIT_NS :: TestFixture, public BasicTe
 
		CPPUNIT_ASSERT_EQUAL(Swift::IQ::Result, dynamic_cast<Swift::IQ *>(getStanza(received[0]))->getType());
 
		CPPUNIT_ASSERT(getStanza(received[0])->getPayload<Swift::DiscoInfo>());
 
		CPPUNIT_ASSERT_EQUAL(std::string("#room"), getStanza(received[0])->getPayload<Swift::DiscoInfo>()->getIdentities()[0].getName());
 
		CPPUNIT_ASSERT_EQUAL(std::string("conference"), getStanza(received[0])->getPayload<Swift::DiscoInfo>()->getIdentities()[0].getCategory());
 
		CPPUNIT_ASSERT_EQUAL(std::string("text"), getStanza(received[0])->getPayload<Swift::DiscoInfo>()->getIdentities()[0].getType());
 
	}
 

	
 
	void clearRooms() {
 
		itemsResponder->addRoom("#room@localhost", "#room");
 
		itemsResponder->clearRooms();
 

	
 
		boost::shared_ptr<Swift::DiscoItems> payload(new Swift::DiscoItems());
 
		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());
 
		CPPUNIT_ASSERT(dynamic_cast<Swift::IQ *>(getStanza(received[0])));
 
		CPPUNIT_ASSERT_EQUAL(Swift::IQ::Result, dynamic_cast<Swift::IQ *>(getStanza(received[0]))->getType());
 
		CPPUNIT_ASSERT(getStanza(received[0])->getPayload<Swift::DiscoItems>());
 
		CPPUNIT_ASSERT(getStanza(received[0])->getPayload<Swift::DiscoItems>()->getItems().empty());
 
	}
 

	
 
	void receipts() {
 
		boost::shared_ptr<Swift::DiscoInfo> payload(new Swift::DiscoInfo());
 
		boost::shared_ptr<Swift::IQ> iq = Swift::IQ::createRequest(Swift::IQ::Get, Swift::JID("localhost"), "id", payload);
 
		iq->setFrom("user@localhost");
 
		iq->setTo("buddy@localhost");
 
		injectIQ(iq);
 
		loop->processEvents();
 

	
 
		CPPUNIT_ASSERT_EQUAL(1, (int) received.size());
 
		CPPUNIT_ASSERT(dynamic_cast<Swift::IQ *>(getStanza(received[0])));
 
		CPPUNIT_ASSERT(getStanza(received[0])->getPayload<Swift::DiscoInfo>());
 
		CPPUNIT_ASSERT(!getStanza(received[0])->getPayload<Swift::DiscoInfo>()->hasFeature("urn:xmpp:receipts"));
 
		received.clear();
 

	
 
		cfg->updateBackendConfig("[features]\nreceipts=1\n");
 

	
 
		injectIQ(iq);
 
		loop->processEvents();
 

	
 
		CPPUNIT_ASSERT_EQUAL(1, (int) received.size());
 
		CPPUNIT_ASSERT(dynamic_cast<Swift::IQ *>(getStanza(received[0])));
 
		CPPUNIT_ASSERT(getStanza(received[0])->getPayload<Swift::DiscoInfo>());
 
		CPPUNIT_ASSERT(getStanza(received[0])->getPayload<Swift::DiscoInfo>()->hasFeature("urn:xmpp:receipts"));
 
		received.clear();
 
	}
 

	
 
};
 

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