Changeset - aab37090125f
[Not reviewed]
CMakeLists.txt
Show inline comments
 
cmake_minimum_required(VERSION 2.6)
 
project(libtransport)
 

	
 
if(NOT LIB_INSTALL_DIR)
 
	set(LIB_INSTALL_DIR "lib")
 
endif()
 

	
 
set(CMAKE_MODULE_PATH "cmake_modules")
 

	
 
set(cppunit_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
 
find_package(cppunit)
 

	
 
if (WIN32)
ChangeLog
Show inline comments
 
Version 2.0.0-beta2 (2012-XX-XX):
 
Version 2.0.0-beta2 (2012-03-28):
 
	General:
 
	* Fixed bug when Roster Item Exchange and subscribe stanzas were sent
 
	  repeatedly.
 
	* Backends related logs now contain the backend PID.
 
	* Fixed username_mask setting.
 
	* Added new fields into statistics (backends_crashed, messages related
 
	  stats).
 
	* Chatstates are now not counted as incoming messages in stats.
 
	* Log4cxx is now optional dependency. Without Log4cxx, Spectrum 2 logs
 
	  to standard output.
 
	* Fixed crash when Log4cxx configuration file didn't exist.
 
	* Admin can now see "Admin" contact in server-mode.
 

	
 
	libpurple:
 
	* Added support for MUC for prpl-jabber protocol.
 
	* Added initial support for MUC for prpl-jabber protocol.
 

	
 
	LibCommuni IRC backend:
 
	* Fixed sending/receiving UTF8 messages.
 
	* Using the [registration] auto_register=1 config option, users don't
 
	  have to register manually when connecting IRC network.
 

	
 
	Skype:
 
	* Memory usage statistic now includes the Skype client.
 
	* Fixed logging issue when the logs were not stored in the proper instance
 
	  directory.
 
	* Skype backend includes also Skype client memory usage into the account.
 
	* Working buddies adding/removing.
 
	* Information about missed call is now forwarded to XMPP user.
 
	* Fixed bug when Skype client instance wasn't killed by backend.
 

	
 
Version 2.0.0-beta (2012-02-28):
 
	General:
 
	* Added PostreSQL support (thanks to Jadestorm).
 
	* Added XEP-0100 (Gateway interaction) support.
 
	* Send presences only "from" bare JID (fixed bug with buddies appearing
backends/libcommuni/ircnetworkplugin.cpp
Show inline comments
 
#include "ircnetworkplugin.h"
 
#include <IrcCommand>
 
#include <IrcMessage>
 

	
 
#define FROM_UTF8(WHAT) QString::fromUtf8((WHAT).c_str(), (WHAT).size())
 
#define TO_UTF8(WHAT) std::string((WHAT).toUtf8().data(), (WHAT).toUtf8().size())
 

	
 
IRCNetworkPlugin::IRCNetworkPlugin(Config *config, Swift::QtEventLoop *loop, const std::string &host, int port) {
 
	this->config = config;
 
	m_socket = new QTcpSocket();
 
	m_socket->connectToHost(QString::fromStdString(host), port);
 
	m_socket->connectToHost(FROM_UTF8(host), port);
 
	connect(m_socket, SIGNAL(readyRead()), this, SLOT(readData()));
 
}
 

	
 
void IRCNetworkPlugin::readData() {
 
	size_t availableBytes = m_socket->bytesAvailable();
 
	if (availableBytes == 0)
 
@@ -25,14 +28,14 @@ void IRCNetworkPlugin::sendData(const std::string &string) {
 

	
 
void IRCNetworkPlugin::handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password) {
 
	// Server is in server-mode, so user is JID of server when we want to connect
 
	if (CONFIG_BOOL(config, "service.server_mode")) {
 
		MyIrcSession *session = new MyIrcSession(user, this);
 
		std::string h = user.substr(0, user.find("@"));
 
		session->setNickName(QString::fromStdString(h.substr(0, h.find("%"))));
 
		session->setHost(QString::fromStdString(h.substr(h.find("%") + 1)));
 
		session->setNickName(FROM_UTF8(h.substr(0, h.find("%"))));
 
		session->setHost(FROM_UTF8(h.substr(h.find("%") + 1)));
 
		session->setPort(6667);
 
		session->open();
 
		std::cout << "CONNECTING IRC NETWORK " << h.substr(h.find("%") + 1) << "\n";
 
		m_sessions[user] = session;
 
	}
 
	else {
 
@@ -69,13 +72,13 @@ void IRCNetworkPlugin::handleMessageSendRequest(const std::string &user, const s
 
		}
 
		else {
 
			r = legacyName.substr(legacyName.find("/") + 1);
 
		}
 
	}
 
	std::cout << "MESSAGE " << u << " " << r << "\n";
 
	m_sessions[u]->sendCommand(IrcCommand::createMessage(QString::fromStdString(r), QString::fromStdString(message)));
 
	m_sessions[u]->sendCommand(IrcCommand::createMessage(FROM_UTF8(r), FROM_UTF8(message)));
 
	std::cout << "SENT\n";
 
}
 

	
 
void IRCNetworkPlugin::handleJoinRoomRequest(const std::string &user, const std::string &room, const std::string &nickname, const std::string &password) {
 
	std::cout << "JOIN\n";
 
	std::string r = room;
 
@@ -86,30 +89,30 @@ void IRCNetworkPlugin::handleJoinRoomRequest(const std::string &user, const std:
 
	}
 
	if (m_sessions[u] == NULL) {
 
		// in gateway mode we want to login this user to network according to legacyName
 
		if (room.find("@") != std::string::npos) {
 
			// suffix is %irc.freenode.net to let MyIrcSession return #room%irc.freenode.net
 
			MyIrcSession *session = new MyIrcSession(user, this, room.substr(room.find("@")));
 
			session->setNickName(QString::fromStdString(nickname));
 
			session->setHost(QString::fromStdString(room.substr(room.find("@") + 1)));
 
			session->setNickName(FROM_UTF8(nickname));
 
			session->setHost(FROM_UTF8(room.substr(room.find("@") + 1)));
 
			session->setPort(6667);
 
			session->open();
 
			std::cout << "CONNECTING IRC NETWORK " << room.substr(room.find("@") + 1) << "\n";
 
			std::cout << "SUFFIX " << room.substr(room.find("@")) << "\n";
 
			m_sessions[u] = session;
 
		}
 
		else {
 
			return;
 
		}
 
	}
 
	std::cout << "JOINING " << r << "\n";
 
	m_sessions[u]->addAutoJoinChannel(r);
 
	m_sessions[u]->sendCommand(IrcCommand::createJoin(QString::fromStdString(r), QString::fromStdString(password)));
 
	m_sessions[u]->sendCommand(IrcCommand::createJoin(FROM_UTF8(r), FROM_UTF8(password)));
 
	m_sessions[u]->rooms += 1;
 
	// update nickname, because we have nickname per session, no nickname per room.
 
	handleRoomNicknameChanged(user, r, m_sessions[u]->nickName().toStdString());
 
	handleRoomNicknameChanged(user, r, TO_UTF8(m_sessions[u]->nickName()));
 
}
 

	
 
void IRCNetworkPlugin::handleLeaveRoomRequest(const std::string &user, const std::string &room) {
 
	std::string r = room;
 
	std::string u = user;
 
	if (!CONFIG_BOOL(config, "service.server_mode")) {
 
@@ -117,13 +120,13 @@ void IRCNetworkPlugin::handleLeaveRoomRequest(const std::string &user, const std
 
		u = user + room.substr(room.find("@") + 1);
 
	}
 

	
 
	if (m_sessions[u] == NULL)
 
		return;
 

	
 
	m_sessions[u]->sendCommand(IrcCommand::createPart(QString::fromStdString(r)));
 
	m_sessions[u]->sendCommand(IrcCommand::createPart(FROM_UTF8(r)));
 
	m_sessions[u]->removeAutoJoinChannel(r);
 
	m_sessions[u]->rooms -= 1;
 

	
 
	if (m_sessions[u]->rooms <= 0) {
 
		m_sessions[u]->close();
 
		m_sessions[u]->deleteLater();
backends/libcommuni/session.cpp
Show inline comments
 
@@ -12,12 +12,15 @@
 
#include <QtCore>
 
#include <iostream>
 
#include "Swiften/Elements/StatusShow.h"
 
#include <IrcCommand>
 
#include <IrcMessage>
 

	
 
#define FROM_UTF8(WHAT) QString::fromUtf8((WHAT).c_str(), (WHAT).size())
 
#define TO_UTF8(WHAT) std::string((WHAT).toUtf8().data(), (WHAT).toUtf8().size())
 

	
 
#include "transport/logging.h"
 

	
 
DEFINE_LOGGER(logger, "IRCSession");
 

	
 
MyIrcSession::MyIrcSession(const std::string &user, NetworkPlugin *np, const std::string &suffix, QObject* parent) : IrcSession(parent)
 
{
 
@@ -35,19 +38,19 @@ void MyIrcSession::on_connected() {
 
	m_connected = true;
 
	if (suffix.empty()) {
 
		np->handleConnected(user);
 
	}
 

	
 
	for(std::list<std::string>::const_iterator it = m_autoJoin.begin(); it != m_autoJoin.end(); it++) {
 
		sendCommand(IrcCommand::createJoin(QString::fromStdString(*it)));
 
		sendCommand(IrcCommand::createJoin(FROM_UTF8(*it)));
 
	}
 

	
 
	if (getIdentify().find(" ") != std::string::npos) {
 
		std::string to = getIdentify().substr(0, getIdentify().find(" "));
 
		std::string what = getIdentify().substr(getIdentify().find(" ") + 1);
 
		sendCommand(IrcCommand::createMessage(QString::fromStdString(to), QString::fromStdString(what)));
 
		sendCommand(IrcCommand::createMessage(FROM_UTF8(to), FROM_UTF8(what)));
 
	}
 
}
 

	
 
void MyIrcSession::on_disconnected() {
 
	if (suffix.empty())
 
		np->handleDisconnected(user, 0, "");
 
@@ -64,56 +67,56 @@ bool MyIrcSession::correctNickname(std::string &nickname) {
 
	return flags;
 
}
 

	
 
void MyIrcSession::on_joined(IrcMessage *message) {
 
	IrcJoinMessage *m = (IrcJoinMessage *) message;
 
	bool flags = 0;
 
	std::string nickname = m->sender().name().toStdString();
 
	std::string nickname = TO_UTF8(m->sender().name());
 
	flags = correctNickname(nickname);
 
	np->handleParticipantChanged(user, nickname, m->channel().toStdString() + suffix, (int) flags, pbnetwork::STATUS_ONLINE);
 
	LOG4CXX_INFO(logger, user << ": Joined " << m->parameters()[0].toStdString());
 
	np->handleParticipantChanged(user, nickname, TO_UTF8(m->channel()), (int) flags, pbnetwork::STATUS_ONLINE);
 
	LOG4CXX_INFO(logger, user << ": Joined " << TO_UTF8(m->parameters()[0]));
 
}
 

	
 

	
 
void MyIrcSession::on_parted(IrcMessage *message) {
 
	IrcPartMessage *m = (IrcPartMessage *) message;
 
	bool flags = 0;
 
	std::string nickname = m->sender().name().toStdString();
 
	std::string nickname = TO_UTF8(m->sender().name());
 
	flags = correctNickname(nickname);
 
	LOG4CXX_INFO(logger, user << ": " << nickname << " parted " << m->channel().toStdString() + suffix);
 
	np->handleParticipantChanged(user, nickname, m->channel().toStdString() + suffix,(int) flags, pbnetwork::STATUS_NONE, m->reason().toStdString());
 
	LOG4CXX_INFO(logger, user << ": " << nickname << " parted " << TO_UTF8(m->channel()) + suffix);
 
	np->handleParticipantChanged(user, nickname, TO_UTF8(m->channel()) + suffix,(int) flags, pbnetwork::STATUS_NONE, TO_UTF8(m->reason()));
 
}
 

	
 
void MyIrcSession::on_quit(IrcMessage *message) {
 
	IrcQuitMessage *m = (IrcQuitMessage *) message;
 
	for(std::list<std::string>::const_iterator it = m_autoJoin.begin(); it != m_autoJoin.end(); it++) {
 
		bool flags = 0;
 
		std::string nickname = m->sender().name().toStdString();
 
		std::string nickname = TO_UTF8(m->sender().name());
 
		flags = correctNickname(nickname);
 
		LOG4CXX_INFO(logger, user << ": " << nickname << " quit " << (*it) + suffix);
 
		np->handleParticipantChanged(user, nickname, (*it) + suffix,(int) flags, pbnetwork::STATUS_NONE, m->reason().toStdString());
 
		np->handleParticipantChanged(user, nickname, (*it) + suffix,(int) flags, pbnetwork::STATUS_NONE, TO_UTF8(m->reason()));
 
	}
 
}
 

	
 
void MyIrcSession::on_nickChanged(IrcMessage *message) {
 
	IrcNickMessage *m = (IrcNickMessage *) message;
 

	
 
	for(std::list<std::string>::const_iterator it = m_autoJoin.begin(); it != m_autoJoin.end(); it++) {
 
		std::string nickname = m->sender().name().toStdString();
 
		std::string nickname = TO_UTF8(m->sender().name());
 
		bool flags = m_modes[(*it) + nickname];
 
		LOG4CXX_INFO(logger, user << ": " << nickname << " changed nickname to " << m->nick().toStdString());
 
		np->handleParticipantChanged(user, nickname, (*it) + suffix,(int) flags, pbnetwork::STATUS_ONLINE, "", m->nick().toStdString());
 
		LOG4CXX_INFO(logger, user << ": " << nickname << " changed nickname to " << TO_UTF8(m->nick()));
 
		np->handleParticipantChanged(user, nickname, (*it) + suffix,(int) flags, pbnetwork::STATUS_ONLINE, "", TO_UTF8(m->nick()));
 
	}
 
}
 

	
 
void MyIrcSession::on_modeChanged(IrcMessage *message) {
 
	IrcModeMessage *m = (IrcModeMessage *) message;
 

	
 
	// mode changed: "#testik" "HanzZ" "+o" "hanzz_k"
 
	std::string nickname = m->argument().toStdString();
 
	std::string mode = m->mode().toStdString();
 
	std::string nickname = TO_UTF8(m->argument());
 
	std::string mode = TO_UTF8(m->mode());
 
	if (nickname.empty())
 
		return;
 
	LOG4CXX_INFO(logger, user << ": " << nickname << " changed mode to " << mode);
 
	for(std::list<std::string>::const_iterator it = m_autoJoin.begin(); it != m_autoJoin.end(); it++) {
 
		if (mode == "+o") {
 
			m_modes[(*it) + nickname] = 1;
 
@@ -127,60 +130,60 @@ void MyIrcSession::on_modeChanged(IrcMessage *message) {
 
}
 

	
 
void MyIrcSession::on_topicChanged(IrcMessage *message) {
 
	IrcTopicMessage *m = (IrcTopicMessage *) message;
 

	
 
	bool flags = 0;
 
	std::string nickname = m->sender().name().toStdString();
 
	std::string nickname = TO_UTF8(m->sender().name());
 
	flags = correctNickname(nickname);
 

	
 
	LOG4CXX_INFO(logger, user << ": " << nickname << " topic changed to " << m->topic().toStdString());
 
	np->handleSubject(user, m->channel().toStdString() + suffix, m->topic().toStdString(), nickname);
 
	LOG4CXX_INFO(logger, user << ": " << nickname << " topic changed to " << TO_UTF8(m->topic()));
 
	np->handleSubject(user, TO_UTF8(m->channel()) + suffix, TO_UTF8(m->topic()), nickname);
 
}
 

	
 
void MyIrcSession::on_messageReceived(IrcMessage *message) {
 
	IrcPrivateMessage *m = (IrcPrivateMessage *) message;
 

	
 
	std::string target = m->target().toStdString();
 
	std::string target = TO_UTF8(m->target());
 
	LOG4CXX_INFO(logger, user << ": Message from " << target);
 
	if (target.find("#") == 0) {
 
		bool flags = 0;
 
		std::string nickname = m->sender().name().toStdString();
 
		std::string nickname = TO_UTF8(m->sender().name());
 
		flags = correctNickname(nickname);
 
		np->handleMessage(user, target + suffix, m->message().toStdString(), nickname);
 
		np->handleMessage(user, target + suffix, TO_UTF8(m->message()), nickname);
 
	}
 
	else {
 
		bool flags = 0;
 
		std::string nickname = m->sender().name().toStdString();
 
		std::string nickname = TO_UTF8(m->sender().name());
 
		flags = correctNickname(nickname);
 
		np->handleMessage(user, nickname, m->message().toStdString());
 
		np->handleMessage(user, nickname, TO_UTF8(m->message()));
 
	}
 
}
 

	
 
void MyIrcSession::on_numericMessageReceived(IrcMessage *message) {
 
	QString channel;
 
	QStringList members;
 

	
 
	IrcNumericMessage *m = (IrcNumericMessage *) message;
 
	switch (m->code()) {
 
		case 332:
 
			m_topicData = m->parameters().value(2).toStdString();
 
			m_topicData = TO_UTF8(m->parameters().value(2));
 
			break;
 
		case 333:
 
			 np->handleSubject(user, m->parameters().value(1).toStdString() + suffix, m_topicData, m->parameters().value(2).toStdString());
 
			 np->handleSubject(user, TO_UTF8(m->parameters().value(1)) + suffix, m_topicData, TO_UTF8(m->parameters().value(2)));
 
			break;
 
		case 353:
 
			channel = m->parameters().value(2);
 
			members = m->parameters().value(3).split(" ");
 

	
 
			for (int i = 0; i < members.size(); i++) {
 
				bool flags = 0;
 
				std::string nickname = members.at(i).toStdString();
 
				std::string nickname = TO_UTF8(members.at(i));
 
				flags = correctNickname(nickname);
 
				m_modes[channel.toStdString() + nickname] = flags;
 
				np->handleParticipantChanged(user, nickname, channel.toStdString() + suffix,(int) flags, pbnetwork::STATUS_ONLINE);
 
				m_modes[TO_UTF8(channel) + nickname] = flags;
 
				np->handleParticipantChanged(user, nickname, TO_UTF8(channel) + suffix,(int) flags, pbnetwork::STATUS_ONLINE);
 
			}
 
			break;
 
		case 432:
 
			if (m_connected) {
 
				np->handleDisconnected(user, pbnetwork::CONNECTION_ERROR_INVALID_USERNAME, "Erroneous Nickname");
 
			}
 
@@ -190,13 +193,13 @@ void MyIrcSession::on_numericMessageReceived(IrcMessage *message) {
 
	}
 

	
 
	//qDebug() << "numeric message received:" << receiver() << origin << code << params;
 
}
 

	
 
void MyIrcSession::onMessageReceived(IrcMessage *message) {
 
	LOG4CXX_INFO(logger, user << ": " << message->toString().toStdString());
 
	LOG4CXX_INFO(logger, user << ": " << TO_UTF8(message->toString()));
 
	switch (message->type()) {
 
		case IrcMessage::Join:
 
			on_joined(message);
 
			break;
 
		case IrcMessage::Part:
 
			on_parted(message);
backends/libcommuni/singleircnetworkplugin.cpp
Show inline comments
 
#include "singleircnetworkplugin.h"
 
#include "transport/logging.h"
 
#include <IrcCommand>
 
#include <IrcMessage>
 

	
 
#define FROM_UTF8(WHAT) QString::fromUtf8((WHAT).c_str(), (WHAT).size())
 
#define TO_UTF8(WHAT) std::string((WHAT).toUtf8().data(), (WHAT).toUtf8().size())
 

	
 
DEFINE_LOGGER(logger, "SingleIRCNetworkPlugin");
 

	
 
SingleIRCNetworkPlugin::SingleIRCNetworkPlugin(Config *config, Swift::QtEventLoop *loop, const std::string &host, int port) {
 
	this->config = config;
 
	m_server = config->getUnregistered().find("service.irc_server")->second;
 
	m_socket = new QTcpSocket();
 
	m_socket->connectToHost(QString::fromStdString(host), port);
 
	m_socket->connectToHost(FROM_UTF8(host), port);
 
	connect(m_socket, SIGNAL(readyRead()), this, SLOT(readData()));
 

	
 
	if (config->getUnregistered().find("service.irc_identify") != config->getUnregistered().end()) {
 
		m_identify = config->getUnregistered().find("service.irc_identify")->second;
 
	}
 
	else {
 
@@ -41,22 +44,24 @@ void SingleIRCNetworkPlugin::handleLoginRequest(const std::string &user, const s
 
		LOG4CXX_WARN(logger, user << ": Already logged in.");
 
		return;
 
	}
 
	LOG4CXX_INFO(logger, user << ": Connecting " << m_server << " as " << legacyName);
 

	
 
	MyIrcSession *session = new MyIrcSession(user, this);
 
	session->setUserName(QString::fromStdString(legacyName));
 
	session->setNickName(QString::fromStdString(legacyName));
 
	session->setRealName(QString::fromStdString(legacyName));
 
	session->setHost(QString::fromStdString(m_server));
 
	session->setUserName(FROM_UTF8(legacyName));
 
	session->setNickName(FROM_UTF8(legacyName));
 
	session->setRealName(FROM_UTF8(legacyName));
 
	session->setHost(FROM_UTF8(m_server));
 
	session->setPort(6667);
 

	
 
	std::string identify = m_identify;
 
	boost::replace_all(identify, "$password", password);
 
	boost::replace_all(identify, "$name", legacyName);
 
	session->setIdentify(identify);
 
	if (!password.empty()) {
 
		std::string identify = m_identify;
 
		boost::replace_all(identify, "$password", password);
 
		boost::replace_all(identify, "$name", legacyName);
 
		session->setIdentify(identify);
 
	}
 

	
 
	session->open();
 

	
 
	m_sessions[user] = session;
 
}
 

	
 
@@ -85,42 +90,42 @@ void SingleIRCNetworkPlugin::handleMessageSendRequest(const std::string &user, c
 
	}
 
	else {
 
		r = legacyName.substr(legacyName.find("/") + 1);
 
	}
 

	
 
	LOG4CXX_INFO(logger, user << ": Forwarding message to " << r);
 
	m_sessions[user]->sendCommand(IrcCommand::createMessage(QString::fromStdString(r), QString::fromStdString(message)));
 
	m_sessions[user]->sendCommand(IrcCommand::createMessage(FROM_UTF8(r), FROM_UTF8(message)));
 

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

	
 
void SingleIRCNetworkPlugin::handleJoinRoomRequest(const std::string &user, const std::string &room, const std::string &nickname, const std::string &password) {
 
	if (m_sessions[user] == NULL) {
 
		LOG4CXX_WARN(logger, user << ": Join room requested for unconnected user");
 
		return;
 
	}
 

	
 
	LOG4CXX_INFO(logger, user << ": Joining " << room);
 
	m_sessions[user]->addAutoJoinChannel(room);
 
	m_sessions[user]->sendCommand(IrcCommand::createJoin(QString::fromStdString(room), QString::fromStdString(password)));
 
	m_sessions[user]->sendCommand(IrcCommand::createJoin(FROM_UTF8(room), FROM_UTF8(password)));
 
	m_sessions[user]->rooms += 1;
 

	
 
	// update nickname, because we have nickname per session, no nickname per room.
 
	handleRoomNicknameChanged(user, room, m_sessions[user]->userName().toStdString());
 
	handleRoomNicknameChanged(user, room, TO_UTF8(m_sessions[user]->userName()));
 
}
 

	
 
void SingleIRCNetworkPlugin::handleLeaveRoomRequest(const std::string &user, const std::string &room) {
 
	std::string r = room;
 
	std::string u = user;
 

	
 
	if (m_sessions[u] == NULL) {
 
		LOG4CXX_WARN(logger, user << ": Leave room requested for unconnected user");
 
		return;
 
	}
 

	
 
	LOG4CXX_INFO(logger, user << ": Leaving " << room);
 
	m_sessions[u]->sendCommand(IrcCommand::createPart(QString::fromStdString(r)));
 
	m_sessions[u]->sendCommand(IrcCommand::createPart(FROM_UTF8(r)));
 
	m_sessions[u]->removeAutoJoinChannel(r);
 
	m_sessions[u]->rooms -= 1;
 
}
backends/skype/main.cpp
Show inline comments
 
@@ -363,13 +363,13 @@ bool Skype::createDBusProxy() {
 
		GError *error = NULL;
 
		m_proxy = dbus_g_proxy_new_for_name_owner (m_connection, "com.Skype.API", "/com/Skype", "com.Skype.API", &error);
 
		if (m_proxy == NULL && error != NULL) {
 
			LOG4CXX_INFO(logger,  m_username << ":" << error->message);
 

	
 
			if (m_counter == 15) {
 
				LOG4CXX_ERROR(logger, "Logging out, proxy couldn't be created");
 
				LOG4CXX_ERROR(logger, "Logging out, proxy couldn't be created: " << error->message);
 
				np->handleDisconnected(m_user, pbnetwork::CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE, error->message);
 
				logout();
 
				g_error_free(error);
 
				return FALSE;
 
			}
 
			g_error_free(error);
 
@@ -441,43 +441,51 @@ void Skype::login() {
 
	char *db = (char *) malloc(db_path.size() + 1);
 
	strcpy(db, db_path.c_str());
 
	LOG4CXX_INFO(logger,  m_username << ": Spawning new Skype instance dbpath=" << db);
 
	gchar* argv[6] = {"skype", "--disable-cleanlooks", "--pipelogin", "--dbpath", db, 0};
 

	
 
	int fd;
 
	g_spawn_async_with_pipes(NULL,
 
	GError *error = NULL;
 
	bool spawned = g_spawn_async_with_pipes(NULL,
 
		argv,
 
		NULL /*envp*/,
 
		G_SPAWN_SEARCH_PATH,
 
		NULL /*child_setup*/,
 
		NULL /*user_data*/,
 
		&m_pid /*child_pid*/,
 
		&fd,
 
		NULL,
 
		&fd_output,
 
		NULL /*error*/);
 
		&error);
 

	
 
	if (!spawned) {
 
		LOG4CXX_ERROR(logger, "Error spawning the Skype instance: " << error->message)
 
		np->handleDisconnected(m_user, pbnetwork::CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE, "Error spawning the Skype instance.");
 
		return;
 
	}
 

	
 
	std::string login_data = std::string(m_username + " " + m_password + "\n");
 
	LOG4CXX_INFO(logger,  m_username << ": Login data=" << login_data);
 
	LOG4CXX_INFO(logger,  m_username << ": Login data=" << m_username);
 
	write(fd, login_data.c_str(), login_data.size());
 
	close(fd);
 

	
 
	fcntl (fd_output, F_SETFL, O_NONBLOCK);
 

	
 
	free(db);
 

	
 
	//Initialise threading
 
	dbus_threads_init_default();
 

	
 
	if (m_connection == NULL)
 
	{
 
		LOG4CXX_INFO(logger, "Creating DBus connection.");
 
		LOG4CXX_INFO(logger, "Creating DBUS connection.");
 
		GError *error = NULL;
 
		m_connection = dbus_g_bus_get (DBUS_BUS_SESSION, &error);
 
		if (m_connection == NULL && error != NULL)
 
		{
 
			LOG4CXX_INFO(logger,  m_username << ": DBUS Error: " << error->message);
 
			LOG4CXX_INFO(logger,  m_username << ": Creating DBUS Connection error: " << error->message);
 
			g_error_free(error);
 
			return;
 
		}
 
	}
 

	
 
	sleep(1);
 
@@ -613,14 +621,18 @@ bool Skype::loadSkypeBuddies() {
 
void Skype::logout() {
 
	if (m_pid != 0) {
 
		send_command("SET USERSTATUS INVISIBLE");
 
		send_command("SET USERSTATUS OFFLINE");
 
		sleep(2);
 
		g_object_unref(m_proxy);
 
		LOG4CXX_INFO(logger,  m_username << ": Killing Skype instance");
 
		LOG4CXX_INFO(logger,  m_username << ": Terminating Skype instance (SIGTERM)");
 
		kill((int) m_pid, SIGTERM);
 
		// Give skype a chance
 
		sleep(2);
 
		LOG4CXX_INFO(logger,  m_username << ": Killing Skype instance (SIGKILL)");
 
		kill((int) m_pid, SIGKILL);
 
		m_pid = 0;
 
	}
 
}
 

	
 
std::string Skype::send_command(const std::string &message) {
 
	GError *error = NULL;
include/Swiften/Parser/PayloadParsers/MUCPayloadParser.cpp
Show inline comments
 
new file 100644
 
/*
 
 * Copyright (c) 2010 Kevin Smith
 
 * Licensed under the GNU General Public License v3.
 
 * See Documentation/Licenses/GPLv3.txt for more information.
 
 */
 

	
 
#include <Swiften/Parser/PayloadParsers/MUCPayloadParser.h>
 

	
 
#include <boost/lexical_cast.hpp>
 

	
 
#include <Swiften/Parser/PayloadParserFactoryCollection.h>
 
#include <Swiften/Parser/PayloadParserFactory.h>
 
#include <Swiften/Base/foreach.h>
 
#include <Swiften/Elements/MUCOccupant.h>
 
#include <Swiften/Parser/Tree/TreeReparser.h>
 

	
 
namespace Swift {
 

	
 
void MUCPayloadParser::handleTree(ParserElement::ref root) {
 
	foreach (ParserElement::ref child, root->getAllChildren()) {
 
		if (child->getName() == "password" && child->getNamespace() == root->getNamespace()) {
 
			getPayloadInternal()->setPassword(child->getText());
 
		}
 
	}
 
}
 

	
 
}
include/Swiften/Parser/PayloadParsers/MUCPayloadParser.h
Show inline comments
 
new file 100644
 
/*
 
 * Copyright (c) 2010 Kevin Smith
 
 * Licensed under the GNU General Public License v3.
 
 * See Documentation/Licenses/GPLv3.txt for more information.
 
 */
 

	
 
#pragma once
 

	
 
#include <boost/optional.hpp>
 

	
 
#include <Swiften/Elements/MUCPayload.h>
 
#include <Swiften/Parser/GenericPayloadTreeParser.h>
 
#include <Swiften/Parser/PayloadParsers/MUCItemParser.h>
 

	
 
namespace Swift {
 
	class PayloadParserFactoryCollection;
 
	class MUCPayloadParser : public GenericPayloadTreeParser<MUCPayload> {
 
		public:
 
			MUCPayloadParser(){}
 
			virtual void handleTree(ParserElement::ref root);
 
	};
 
}
include/transport/CMakeLists.txt
Show inline comments
 
if (PROTOBUF_FOUND)
 
    if (WIN32)
 
	set (PROTOBUF_PROTOC_EXECUTABLE protoc)
 
    endif()
 
    ADD_CUSTOM_COMMAND(
 
        OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/protocol.pb.cc ${CMAKE_CURRENT_BINARY_DIR}/protocol.pb.h
 
        COMMAND ${PROTOBUF_PROTOC_EXECUTABLE} --cpp_out  ${CMAKE_CURRENT_BINARY_DIR} --proto_path ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_BINARY_DIR}/protocol.proto
 
        OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/protocol.pb.cc ${CMAKE_CURRENT_SOURCE_DIR}/protocol.pb.h
 
        COMMAND ${PROTOBUF_PROTOC_EXECUTABLE} --cpp_out  ${CMAKE_CURRENT_SOURCE_DIR} --proto_path ${CMAKE_CURRENT_SOURCE_DIR} ${CMAKE_CURRENT_SOURCE_DIR}/protocol.proto
 
        COMMENT "Running C++ protocol buffer compiler on protocol.proto"
 
        DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/protocol.proto
 
        DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/protocol.proto
 
    )
 
    ADD_CUSTOM_TARGET(pb DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/protocol.pb.cc)
 
    ADD_CUSTOM_TARGET(pb DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/protocol.pb.cc)
 
endif()
 

	
 
FILE(GLOB HEADERS *.h protocol.h)
 

	
 
INSTALL(FILES ${HEADERS} DESTINATION include/transport COMPONENT headers)
 
\ No newline at end of file
plugin/cpp/CMakeLists.txt
Show inline comments
 
cmake_minimum_required(VERSION 2.6)
 
FILE(GLOB SRC *.cpp *.h)
 
FILE(GLOB HEADERS ../include/transport/*.h)
 
 
set(EXTRA_SOURCES ${CMAKE_CURRENT_BINARY_DIR}/../../src/memoryusage.cpp)
 
set(EXTRA_SOURCES ${EXTRA_SOURCES} ${CMAKE_CURRENT_BINARY_DIR}/../../src/logging.cpp)
 
set(EXTRA_SOURCES ${EXTRA_SOURCES} ${CMAKE_CURRENT_BINARY_DIR}/../../src/config.cpp)
 
set(EXTRA_SOURCES ${EXTRA_SOURCES} ${CMAKE_CURRENT_BINARY_DIR}/../../include/transport/protocol.pb.cc)
 
set(EXTRA_SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/../../src/memoryusage.cpp)
 
set(EXTRA_SOURCES ${EXTRA_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/../../src/logging.cpp)
 
set(EXTRA_SOURCES ${EXTRA_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/../../src/config.cpp)
 
set(EXTRA_SOURCES ${EXTRA_SOURCES} ${CMAKE_CURRENT_SOURCE_DIR}/../../include/transport/protocol.pb.cc)
 
 
if (NOT WIN32)
 
	ADD_LIBRARY(transport-plugin SHARED ${HEADERS} ${SRC} ${PROTOBUF_SRC} ${PROTOBUF_HDRS} ${EXTRA_SOURCES})
 
else()
 
	ADD_LIBRARY(transport-plugin STATIC ${HEADERS} ${SRC} ${EXTRA_SOURCES})
 
	include_directories("${CMAKE_SOURCE_DIR}/msvc-deps/protobuf/libprotobuf")
 
	ADD_DEPENDENCIES(transport-plugin libprotobuf)
 
endif()
 
ADD_DEPENDENCIES(transport-plugin pb)
 
SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/../../include/transport/protocol.pb.cc PROPERTIES GENERATED 1)
 
SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_SOURCE_DIR}/../../include/transport/protocol.pb.cc PROPERTIES GENERATED 1)
 
 
if (CMAKE_COMPILER_IS_GNUCXX)
 
	ADD_DEFINITIONS(-fPIC)
 
endif()
 
 
if (NOT WIN32)
 
@@ -28,10 +28,10 @@ else()
 
endif() 
 
 
SET_TARGET_PROPERTIES(transport-plugin PROPERTIES
 
      VERSION ${TRANSPORT_VERSION} SOVERSION ${TRANSPORT_VERSION}
 
)
 
 
INSTALL(TARGETS transport-plugin LIBRARY DESTINATION lib ARCHIVE DESTINATION lib COMPONENT libraries)
 
INSTALL(TARGETS transport-plugin LIBRARY DESTINATION ${LIB_INSTALL_DIR} ARCHIVE DESTINATION ${LIB_INSTALL_DIR} COMPONENT libraries)
 
 
#CONFIGURE_FILE(transport.pc.in "${CMAKE_CURRENT_BINARY_DIR}/transport.pc")
 
#INSTALL(FILES "${CMAKE_CURRENT_BINARY_DIR}/transport.pc" DESTINATION lib/pkgconfig)
 
#CONFIGURE_FILE(transport.pc.in "${CMAKE_CURRENT_SOURCE_DIR}/transport.pc")
 
#INSTALL(FILES "${CMAKE_CURRENT_SOURCE_DIR}/transport.pc" DESTINATION lib/pkgconfig)
spectrum/src/sample.cfg
Show inline comments
 
@@ -10,13 +10,14 @@ pidfile=./test.pid
 
#backend_port=10001
 
admin_jid=admin@localhost
 
admin_password=test
 
#cert=server.pfx #patch to PKCS#12 certificate
 
#cert_password=test #password to that certificate if any
 
users_per_backend=10
 
backend=../..//backends/libpurple/spectrum2_libpurple_backend
 
#backend=../..//backends/libpurple/spectrum2_libpurple_backend
 
backend=../../backends/template/spectrum2_template_backend
 
protocol=prpl-xmpp
 
#protocol=prpl-msn
 
#protocol=any
 
#protocol=prpl-icq
 
working_dir=./
 

	
spectrum/src/server.p12
Show inline comments
 
new file 100644
 
binary diff not shown
src/CMakeLists.txt
Show inline comments
 
@@ -48,10 +48,10 @@ else (WIN32)
 
endif(WIN32)
 

	
 
SET_TARGET_PROPERTIES(transport PROPERTIES
 
      VERSION ${TRANSPORT_VERSION} SOVERSION ${TRANSPORT_VERSION}
 
)
 

	
 
INSTALL(TARGETS transport LIBRARY DESTINATION lib ARCHIVE DESTINATION lib COMPONENT libraries)
 
INSTALL(TARGETS transport LIBRARY DESTINATION ${LIB_INSTALL_DIR} ARCHIVE DESTINATION ${LIB_INSTALL_DIR} COMPONENT libraries)
 

	
 
#CONFIGURE_FILE(transport.pc.in "${CMAKE_CURRENT_BINARY_DIR}/transport.pc")
 
#INSTALL(FILES "${CMAKE_CURRENT_BINARY_DIR}/transport.pc" DESTINATION lib/pkgconfig)
src/config.cpp
Show inline comments
 
@@ -90,12 +90,13 @@ bool Config::load(std::istream &ifs, boost::program_options::options_description
 
		("identity.type", value<std::string>()->default_value(""), "Type of transport ('icq','msn','gg','irc', ...)")
 
		("registration.enable_public_registration", value<bool>()->default_value(true), "True if users should be able to register.")
 
		("registration.language", value<std::string>()->default_value("en"), "Default language for registration form")
 
		("registration.instructions", value<std::string>()->default_value("Enter your legacy network username and password."), "Instructions showed to user in registration form")
 
		("registration.username_label", value<std::string>()->default_value("Legacy network username:"), "Label for username field")
 
		("registration.username_mask", value<std::string>()->default_value(""), "Username mask")
 
		("registration.auto_register", value<bool>()->default_value(false), "Register new user automatically when the presence arrives.")
 
		("registration.encoding", value<std::string>()->default_value("utf8"), "Default encoding in registration form")
 
		("registration.require_local_account", value<bool>()->default_value(false), "True if users have to have a local account to register to this transport from remote servers.")
 
		("registration.local_username_label", value<std::string>()->default_value("Local username:"), "Label for local usernme field")
 
		("registration.local_account_server", value<std::string>()->default_value("localhost"), "The server on which the local accounts will be checked for validity")
 
		("registration.local_account_server_timeout", value<int>()->default_value(10000), "Timeout when checking local user on local_account_server (msecs)")
 
		("database.type", value<std::string>()->default_value("none"), "Database type.")
src/networkpluginserver.cpp
Show inline comments
 
@@ -160,15 +160,20 @@ static unsigned long exec_(std::string path, const char *host, const char *port,
 

	
 
	// fork and exec
 
	pid_t pid = fork();
 
	if ( pid == 0 ) {
 
		setsid();
 
		// child process
 
		exit(execv(argv[0], argv));
 
		errno = 0;
 
		int ret = execv(argv[0], argv);
 
		if (ret == -1) {
 
			exit(errno);
 
		}
 
		exit(0);
 
	} else if ( pid < 0 ) {
 
		// fork failed
 
		LOG4CXX_ERROR(logger, "Fork failed");
 
	}
 
	free(p);
 

	
 
	return (unsigned long) pid;
 
#endif
 
}
 
@@ -255,18 +260,35 @@ NetworkPluginServer::NetworkPluginServer(Component *component, Config *config, U
 
	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));
 
	m_server->start();
 

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

	
 
	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(), m_config->getConfigFile().c_str());
 
	LOG4CXX_INFO(logger, "Backend should now connect to Spectrum2 instance. Spectrum2 won't accept any connection before backend connects");
 

	
 
#ifndef _WIN32
 
	// wait if the backend process will still be alive after 1 second
 
	sleep(1);
 
	pid_t result;
 
	int status;
 
	result = waitpid(-1, &status, WNOHANG);
 
	if (result != 0) {
 
		if (WIFEXITED(status)) {
 
			if (WEXITSTATUS(status) != 0) {
 
				LOG4CXX_ERROR(logger, "Backend can not be started, exit_code=" << WEXITSTATUS(status) << ", possible error: " << strerror(WEXITSTATUS(status)));
 
			}
 
		}
 
		else {
 
			LOG4CXX_ERROR(logger, "Backend can not be started");
 
		}
 
	}
 

	
 
	signal(SIGCHLD, SigCatcher);
 
#endif
 

	
 
	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(), m_config->getConfigFile().c_str());
 
	LOG4CXX_INFO(logger, "Backend should now connect to Spectrum2 instance. Spectrum2 won't accept any connection before backend connects");
 
}
 

	
 
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;
src/transport.cpp
Show inline comments
 
@@ -44,12 +44,13 @@
 
#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/Swiften.h"
 

	
 
@@ -104,12 +105,13 @@ Component::Component(Swift::EventLoop *loop, Swift::NetworkFactories *factories,
 
		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());
 
@@ -132,12 +134,13 @@ Component::Component(Swift::EventLoop *loop, Swift::NetworkFactories *factories,
 
		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());
src/usermanager.cpp
Show inline comments
 
@@ -211,12 +211,40 @@ void UserManager::handlePresence(Swift::Presence::ref presence) {
 
					registered = true;
 
				}
 
			}
 
			res.password = m_userRegistry->getUserPassword(userkey);
 
		}
 

	
 
		// We allow auto_register feature in gateway-mode. This allows IRC user to register
 
		// the transport just by joining the room.
 
		if (!m_component->inServerMode()) {
 
			if (!registered && CONFIG_BOOL(m_component->getConfig(), "registration.auto_register")) {
 
				res.password = "";
 
				res.jid = userkey;
 

	
 
				bool isMUC = presence->getPayload<Swift::MUCPayload>() != NULL || *presence->getTo().getNode().c_str() == '#';
 
				if (isMUC) {
 
					res.uin = presence->getTo().getResource();
 
				}
 
				else {
 
					res.uin = presence->getFrom().toString();
 
				}
 
				LOG4CXX_INFO(logger, "Auto-registering user " << userkey << " with uin=" << res.uin);
 

	
 
				if (m_storageBackend) {
 
					// store user and getUser again to get user ID.
 
					m_storageBackend->setUser(res);
 
					registered = m_storageBackend->getUser(userkey, res);
 
				}
 
				else {
 
					registered = false;
 
				}
 
			}
 
		}
 

	
 

	
 
		// Unregistered users are not able to login
 
		if (!registered) {
 
			LOG4CXX_WARN(logger, "Unregistered user " << userkey << " tried to login");
 
			return;
 
		}
 

	
 
@@ -279,13 +307,18 @@ void UserManager::handleMessageReceived(Swift::Message::ref message) {
 
	User *user = getUser(message->getFrom().toBare().toString());
 
	if (!user ){
 
		return;
 
	}
 

	
 
	user->getConversationManager()->handleMessageReceived(message);
 
	messageToBackendSent();
 

	
 
	// Do not count chatstate notification...
 
	boost::shared_ptr<Swift::ChatState> statePayload = message->getPayload<Swift::ChatState>();
 
	if (!statePayload) {
 
		messageToBackendSent();
 
	}
 
}
 

	
 
void UserManager::handleGeneralPresenceReceived(Swift::Presence::ref presence) {
 
	switch(presence->getType()) {
 
		case Swift::Presence::Subscribe:
 
		case Swift::Presence::Subscribed:
0 comments (0 inline, 0 general)