Changeset - eaa28f659925
[Not reviewed]
Merge
! ! !
Vitaly Takmazov - 14 years ago 2011-11-25 09:05:45
vitalyster@gmail.com
Merge remote-tracking branch 'hanzz/origin/master'
76 files changed with 1607 insertions and 892 deletions:
README
6
0 comments (0 inline, 0 general)
CMakeLists.txt
Show inline comments
 
@@ -41,14 +41,14 @@ endif()
 
find_package(Boost COMPONENTS program_options date_time system filesystem regex thread signals REQUIRED)
 
message( STATUS "Found Boost: ${Boost_LIBRARIES}, ${Boost_INCLUDE_DIR}")
 

	
 
set(Protobuf_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
 
find_package(Protobuf REQUIRED)
 

	
 
set(IRCClientQt_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
 
find_package(IRCClientQt)
 
set(Communi_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
 
find_package(Communi)
 

	
 
set(log4cxx_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
 
find_package(log4cxx)
 

	
 
set(event_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
 
find_package(event)
 
@@ -61,12 +61,31 @@ FIND_PACKAGE(Qt4 COMPONENTS QtCore QtNetwork)
 
# ADD_DEFINITIONS(${SWIFTEN_CFLAGS})
 
ADD_DEFINITIONS(-DSUPPORT_LEGACY_CAPS)
 
ADD_DEFINITIONS(-DBOOST_FILESYSTEM_VERSION=2)
 

	
 
message("  Supported features")
 
message("-----------------------")
 

	
 
if (SPECTRUM_VERSION)
 
	ADD_DEFINITIONS(-DSPECTRUM_VERSION="${SPECTRUM_VERSION}")
 
else (SPECTRUM_VERSION)
 
	if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/.git)
 
		execute_process(COMMAND git "--git-dir=${CMAKE_CURRENT_SOURCE_DIR}/.git" rev-parse --short HEAD
 
						OUTPUT_VARIABLE GIT_REVISION
 
						OUTPUT_STRIP_TRAILING_WHITESPACE
 
		)
 
		set(SPECTRUM_VERSION 2.0.0-beta-git-${GIT_REVISION})
 
		ADD_DEFINITIONS(-DSPECTRUM_VERSION="${SPECTRUM_VERSION}")
 
	else (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/.git)
 
		set(SPECTRUM_VERSION 2.0.0-alpha)
 
		ADD_DEFINITIONS(-DSPECTRUM_VERSION="${SPECTRUM_VERSION}")
 
	endif (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/.git)
 
endif (SPECTRUM_VERSION)
 

	
 
message("Version           : " ${SPECTRUM_VERSION})
 

	
 
if (SQLITE3_FOUND)
 
	ADD_DEFINITIONS(-DWITH_SQLITE)
 
	include_directories(${SQLITE3_INCLUDE_DIR})
 
	message("SQLite3           : yes")
 
else (SQLITE3_FOUND)
 
	set(SQLITE3_LIBRARIES "")
 
@@ -101,19 +120,19 @@ if (PROTOBUF_FOUND)
 
		message("  libev eventloop : yes")
 
	else()
 
		message("  libev eventloop : no (install libev-devel)")
 
	endif()
 

	
 
	if(IRC_FOUND)
 
		ADD_DEFINITIONS(-DIRC_SHARED)
 
		ADD_DEFINITIONS(-DCOMMUNI_SHARED)
 
		message("IRC plugin        : yes")
 
		include_directories(${QT_QTNETWORK_INCLUDE_DIR})
 
		include_directories(${IRC_INCLUDE_DIR})
 
		include(${QT_USE_FILE})
 
	else()
 
		message("IRC plugin        : no (install libircclient-qt and libprotobuf-dev)")
 
		message("IRC plugin        : no (install libCommuni and libprotobuf-dev)")
 
	endif()
 

	
 
	message("Frotz plugin      : yes")
 

	
 
else()
 
	message("Network plugins   : no (install libprotobuf-dev)")
 
@@ -167,16 +186,14 @@ include_directories(${SWIFTEN_INCLUDE_DIR})
 
include_directories(${Boost_INCLUDE_DIRS})
 
include_directories(${OPENSSL_INCLUDE_DIR})
 

	
 
ADD_SUBDIRECTORY(src)
 
ADD_SUBDIRECTORY(plugin)
 
ADD_SUBDIRECTORY(include)
 
#ADD_SUBDIRECTORY(examples)
 
ADD_SUBDIRECTORY(spectrum)
 
ADD_SUBDIRECTORY(backends)
 
#ADD_SUBDIRECTORY(tests)
 
if (NOT WIN32)
 
	ADD_SUBDIRECTORY(spectrum_manager)
 
endif()
 

	
 
if (CPPUNIT_FOUND)
 
	message("tests             : yes")
README
Show inline comments
 
Spectrum is an XMPP transport/gateway. It allows XMPP users to communicate with
 
their friends who are using one of the supported networks. It supports a wide
 
range of different networks such as ICQ, XMPP (Jabber, GTalk), AIM, MSN,
 
Facebook, Twitter, Gadu-Gadu, IRC and SIMPLE. Spectrum is written in C++
 
and uses the Swiften XMPP library and libpurple for “legacy networks”.
 
Spectrum is open source and released under the GNU GPL.
backends/CMakeLists.txt
Show inline comments
 
if (PROTOBUF_FOUND)
 
	if ( PURPLE_LIBRARY AND PURPLE_INCLUDE_DIR )
 
		ADD_SUBDIRECTORY(libpurple)
 
	endif()
 

	
 
	if (IRC_FOUND)
 
		ADD_SUBDIRECTORY(libircclient-qt)
 
		ADD_SUBDIRECTORY(libcommuni)
 
	endif()
 

	
 
if (NOT WIN32)
 
	ADD_SUBDIRECTORY(frotz)
 
endif()
 

	
backends/libcommuni/CMakeLists.txt
Show inline comments
 
new file 100644
 
cmake_minimum_required(VERSION 2.6)
 
FILE(GLOB SRC *.cpp)
 
FILE(GLOB HEADERS *.h)
 
QT4_WRAP_CPP(SRC ${HEADERS})
 
ADD_EXECUTABLE(spectrum2_libcommuni_backend ${SRC})
 
 
target_link_libraries(spectrum2_libcommuni_backend ${IRC_LIBRARY} ${QT_LIBRARIES} transport-plugin transport pthread)
 
 
INSTALL(TARGETS spectrum2_libcommuni_backend RUNTIME DESTINATION bin)
 
backends/libcommuni/ircnetworkplugin.cpp
Show inline comments
 
file renamed from backends/libircclient-qt/ircnetworkplugin.cpp to backends/libcommuni/ircnetworkplugin.cpp
 
#include "ircnetworkplugin.h"
 
#include <IrcCommand>
 
#include <IrcMessage>
 

	
 
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);
 
	connect(m_socket, SIGNAL(readyRead()), this, SLOT(readData()));
 
@@ -23,26 +25,28 @@ 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->setNick(QString::fromStdString(h.substr(0, h.find("%"))));
 
		session->connectToServer(QString::fromStdString(h.substr(h.find("%") + 1)), 6667);
 
		session->setNickName(QString::fromStdString(h.substr(0, h.find("%"))));
 
		session->setHost(QString::fromStdString(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 {
 
		handleConnected(user);
 
	}
 
}
 

	
 
void IRCNetworkPlugin::handleLogoutRequest(const std::string &user, const std::string &legacyName) {
 
	if (m_sessions[user] == NULL)
 
		return;
 
	m_sessions[user]->disconnectFromServer();
 
	m_sessions[user]->close();
 
	m_sessions[user]->deleteLater();
 
	m_sessions.erase(user);
 
}
 

	
 
void IRCNetworkPlugin::handleMessageSendRequest(const std::string &user, const std::string &legacyName, const std::string &message, const std::string &/*xhtml*/) {
 
	std::string u = user;
 
@@ -65,13 +69,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]->message(QString::fromStdString(r), QString::fromStdString(message));
 
	m_sessions[u]->sendCommand(IrcCommand::createMessage(QString::fromStdString(r), QString::fromStdString(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;
 
@@ -82,28 +86,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->setNick(QString::fromStdString(nickname));
 
			session->connectToServer(QString::fromStdString(room.substr(room.find("@") + 1)), 6667);
 
			session->setNickName(QString::fromStdString(nickname));
 
			session->setHost(QString::fromStdString(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(QString::fromStdString(r));
 
	m_sessions[u]->join(QString::fromStdString(r), QString::fromStdString(password));
 
	m_sessions[u]->addAutoJoinChannel(r);
 
	m_sessions[u]->sendCommand(IrcCommand::createJoin(QString::fromStdString(r), QString::fromStdString(password)));
 
	m_sessions[u]->rooms += 1;
 
	// update nickname, because we have nickname per session, no nickname per room.
 
	handleRoomNicknameChanged(user, r, m_sessions[u]->nick().toStdString());
 
	handleRoomNicknameChanged(user, r, m_sessions[u]->nickName().toStdString());
 
}
 

	
 
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")) {
 
@@ -111,16 +117,16 @@ 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]->part(QString::fromStdString(r));
 
	m_sessions[u]->removeAutoJoinChannel(QString::fromStdString(r));
 
	m_sessions[u]->sendCommand(IrcCommand::createPart(QString::fromStdString(r)));
 
	m_sessions[u]->removeAutoJoinChannel(r);
 
	m_sessions[u]->rooms -= 1;
 

	
 
	if (m_sessions[u]->rooms <= 0) {
 
		m_sessions[u]->disconnectFromServer();
 
		m_sessions[u]->close();
 
		m_sessions[u]->deleteLater();
 
		m_sessions.erase(u);
 
	}
 
}
backends/libcommuni/ircnetworkplugin.h
Show inline comments
 
file renamed from backends/libircclient-qt/ircnetworkplugin.h to backends/libcommuni/ircnetworkplugin.h
backends/libcommuni/main.cpp
Show inline comments
 
file renamed from backends/libircclient-qt/main.cpp to backends/libcommuni/main.cpp
 
@@ -12,17 +12,28 @@
 
#include "transport/networkplugin.h"
 
#include "session.h"
 
#include <QtCore>
 
#include <QtNetwork>
 
#include "Swiften/EventLoop/Qt/QtEventLoop.h"
 
#include "ircnetworkplugin.h"
 
#include "singleircnetworkplugin.h"
 

	
 
#include "log4cxx/logger.h"
 
#include "log4cxx/consoleappender.h"
 
#include "log4cxx/patternlayout.h"
 
#include "log4cxx/propertyconfigurator.h"
 
#include "log4cxx/helpers/properties.h"
 
#include "log4cxx/helpers/fileinputstream.h"
 
#include "log4cxx/helpers/transcoder.h"
 

	
 
using namespace boost::program_options;
 
using namespace Transport;
 

	
 
IRCNetworkPlugin * np = NULL;
 
using namespace log4cxx;
 

	
 
NetworkPlugin * np = NULL;
 

	
 
int main (int argc, char* argv[]) {
 
	std::string host;
 
	int port;
 

	
 

	
 
@@ -69,11 +80,42 @@ int main (int argc, char* argv[]) {
 
	if (!config.load(argv[5])) {
 
		std::cerr << "Can't open " << argv[1] << " configuration file.\n";
 
		return 1;
 
	}
 
	QCoreApplication app(argc, argv);
 

	
 
	if (CONFIG_STRING(&config, "logging.backend_config").empty()) {
 
		LoggerPtr root = log4cxx::Logger::getRootLogger();
 
#ifndef _MSC_VER
 
		root->addAppender(new ConsoleAppender(new PatternLayout("%d %-5p %c: %m%n")));
 
#else
 
		root->addAppender(new ConsoleAppender(new PatternLayout(L"%d %-5p %c: %m%n")));
 
#endif
 
	}
 
	else {
 
		log4cxx::helpers::Properties p;
 
		log4cxx::helpers::FileInputStream *istream = new log4cxx::helpers::FileInputStream(CONFIG_STRING(&config, "logging.backend_config"));
 
		p.load(istream);
 
		LogString pid, jid;
 
		log4cxx::helpers::Transcoder::decode(boost::lexical_cast<std::string>(getpid()), pid);
 
		log4cxx::helpers::Transcoder::decode(CONFIG_STRING(&config, "service.jid"), jid);
 
#ifdef _MSC_VER
 
		p.setProperty(L"pid", pid);
 
		p.setProperty(L"jid", jid);
 
#else
 
		p.setProperty("pid", pid);
 
		p.setProperty("jid", jid);
 
#endif
 
		log4cxx::PropertyConfigurator::configure(p);
 
	}
 

	
 
	Swift::QtEventLoop eventLoop;
 

	
 
	if (config.getUnregistered().find("service.irc_server") == config.getUnregistered().end()) {
 
		np = new IRCNetworkPlugin(&config, &eventLoop, host, port);
 
	}
 
	else {
 
		np = new SingleIRCNetworkPlugin(&config, &eventLoop, host, port);
 
	}
 

	
 
	return app.exec();
 
}
backends/libcommuni/session.cpp
Show inline comments
 
new file 100644
 
/*
 
 * Copyright (C) 2008-2009 J-P Nurmi jpnurmi@gmail.com
 
 *
 
 * This example is free, and not covered by LGPL license. There is no
 
 * restriction applied to their modification, redistribution, using and so on.
 
 * You can study them, modify them, use them in your own program - either
 
 * completely or partially. By using it you may give me some credits in your
 
 * program, but you don't have to.
 
 */
 

	
 
#include "session.h"
 
#include <QtCore>
 
#include <iostream>
 
#include "Swiften/Elements/StatusShow.h"
 
#include <IrcCommand>
 
#include <IrcMessage>
 

	
 
#include "log4cxx/logger.h"
 

	
 
using namespace log4cxx;
 

	
 
static LoggerPtr logger = log4cxx::Logger::getLogger("IRCSession");
 

	
 
MyIrcSession::MyIrcSession(const std::string &user, NetworkPlugin *np, const std::string &suffix, QObject* parent) : IrcSession(parent)
 
{
 
	this->np = np;
 
	this->user = user;
 
	this->suffix = suffix;
 
	rooms = 0;
 
	connect(this, SIGNAL(disconnected()), SLOT(on_disconnected()));
 
	connect(this, SIGNAL(connected()), SLOT(on_connected()));
 
	connect(this, SIGNAL(messageReceived(IrcMessage*)), this, SLOT(onMessageReceived(IrcMessage*)));
 
}
 

	
 
void MyIrcSession::on_connected() {
 
	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)));
 
	}
 

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

	
 
void MyIrcSession::on_disconnected() {
 
	if (suffix.empty())
 
		np->handleDisconnected(user, 0, "");
 
}
 

	
 
bool MyIrcSession::correctNickname(std::string &nickname) {
 
	bool flags = 0;
 
	switch(nickname.at(0)) {
 
		case '@': nickname = nickname.substr(1); flags = 1; break;
 
		case '+': nickname = nickname.substr(1); break;
 
		default: break;
 
	}
 
	return flags;
 
}
 

	
 
void MyIrcSession::on_joined(IrcMessage *message) {
 
	IrcJoinMessage *m = (IrcJoinMessage *) message;
 
	bool flags = 0;
 
	std::string nickname = m->sender().name().toStdString();
 
	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());
 
}
 

	
 

	
 
void MyIrcSession::on_parted(IrcMessage *message) {
 
	IrcPartMessage *m = (IrcPartMessage *) message;
 
	bool flags = 0;
 
	std::string nickname = m->sender().name().toStdString();
 
	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());
 
}
 

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

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

	
 
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();
 
	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;
 
		}
 
		else {
 
			m_modes[(*it) + nickname] = 0;
 
		}
 
		bool flags = m_modes[(*it) + nickname];
 
		np->handleParticipantChanged(user, nickname, (*it) + suffix,(int) flags, pbnetwork::STATUS_ONLINE, "");
 
	}
 
}
 

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

	
 
	bool flags = 0;
 
	std::string nickname = m->sender().name().toStdString();
 
	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);
 
}
 

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

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

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

	
 
			for (int i = 0; i < members.size(); i++) {
 
				bool flags = 0;
 
				std::string nickname = members.at(i).toStdString();
 
				flags = correctNickname(nickname);
 
				m_modes[channel.toStdString() + nickname] = flags;
 
				np->handleParticipantChanged(user, nickname, channel.toStdString() + suffix,(int) flags, pbnetwork::STATUS_ONLINE);
 
			}
 
			break;
 
	}
 

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

	
 
void MyIrcSession::onMessageReceived(IrcMessage *message) {
 
	LOG4CXX_INFO(logger, user << ": " << message->toString().toStdString());
 
	switch (message->type()) {
 
		case IrcMessage::Join:
 
			on_joined(message);
 
			break;
 
		case IrcMessage::Part:
 
			on_parted(message);
 
			break;
 
		case IrcMessage::Quit:
 
			on_quit(message);
 
			break;
 
		case IrcMessage::Nick:
 
			on_nickChanged(message);
 
			break;
 
		case IrcMessage::Mode:
 
			on_modeChanged(message);
 
			break;
 
		case IrcMessage::Topic:
 
			on_topicChanged(message);
 
			break;
 
		case IrcMessage::Private:
 
			on_messageReceived(message);
 
			break;
 
		case IrcMessage::Numeric:
 
			on_numericMessageReceived(message);
 
			break;
 
	}
 
}
backends/libcommuni/session.h
Show inline comments
 
new file 100644
 
/*
 
 * Copyright (C) 2008-2009 J-P Nurmi jpnurmi@gmail.com
 
 *
 
 * This example is free, and not covered by LGPL license. There is no
 
 * restriction applied to their modification, redistribution, using and so on.
 
 * You can study them, modify them, use them in your own program - either
 
 * completely or partially. By using it you may give me some credits in your
 
 * program, but you don't have to.
 
 */
 

	
 
#ifndef SESSION_H
 
#define SESSION_H
 

	
 
#include <IrcSession>
 
#include <transport/networkplugin.h>
 

	
 
using namespace Transport;
 

	
 
class MyIrcSession : public IrcSession
 
{
 
    Q_OBJECT
 

	
 
public:
 
	MyIrcSession(const std::string &user, NetworkPlugin *np, const std::string &suffix = "", QObject* parent = 0);
 
	std::map<std::string, bool> m_modes;
 
	std::string suffix;
 
	int rooms;
 

	
 
	void addAutoJoinChannel(const std::string &channel) {
 
		m_autoJoin.push_back(channel);
 
	}
 

	
 
	void removeAutoJoinChannel(const std::string &channel) {
 
		m_autoJoin.remove(channel);
 
	}
 

	
 
	void setIdentify(const std::string &identify) {
 
		m_identify = identify;
 
	}
 

	
 
	const std::string  &getIdentify() {
 
		return m_identify;
 
	}
 

	
 
	bool correctNickname(std::string &nickname);
 

	
 
	void on_joined(IrcMessage *message);
 
	void on_parted(IrcMessage *message);
 
	void on_quit(IrcMessage *message);
 
	void on_nickChanged(IrcMessage *message);
 
	void on_modeChanged(IrcMessage *message);
 
	void on_topicChanged(IrcMessage *message);
 
	void on_messageReceived(IrcMessage *message);
 
	void on_numericMessageReceived(IrcMessage *message);
 

	
 
protected Q_SLOTS:
 
	void on_connected();
 
	void on_disconnected();
 

	
 
	void onMessageReceived(IrcMessage* message);
 

	
 
protected:
 
	NetworkPlugin *np;
 
	std::string user;
 
	std::string m_identify;
 
	std::list<std::string> m_autoJoin;
 
	std::string m_topicData;
 
};
 

	
 
//class MyIrcBuffer : public Irc::Buffer
 
//{
 
//    Q_OBJECT
 

	
 
//public:
 
//	MyIrcBuffer(const QString& receiver, const std::string &user, NetworkPlugin *np, const std::string &suffix, Irc::Session* parent);
 
//	NetworkPlugin *np;
 
//	std::string user;
 
//	MyIrcSession *p;
 
//	std::string m_topicData;
 
//		std::string suffix;
 

	
 
//protected Q_SLOTS:
 
//    void on_receiverChanged(const QString& receiver);
 
//    void on_joined(const QString& origin);
 
//    void on_parted(const QString& origin, const QString& message);
 
//    void on_quit(const QString& origin, const QString& message);
 
//    void on_nickChanged(const QString& origin, const QString& nick);
 
//    void on_modeChanged(const QString& origin, const QString& mode, const QString& args);
 
//    void on_topicChanged(const QString& origin, const QString& topic);
 
//    void on_invited(const QString& origin, const QString& receiver, const QString& channel);
 
//    void on_kicked(const QString& origin, const QString& nick, const QString& message);
 
//    void on_messageReceived(const QString& origin, const QString& message, Irc::Buffer::MessageFlags flags);
 
//    void on_noticeReceived(const QString& origin, const QString& notice, Irc::Buffer::MessageFlags flags);
 
//    void on_ctcpRequestReceived(const QString& origin, const QString& request, Irc::Buffer::MessageFlags flags);
 
//    void on_ctcpReplyReceived(const QString& origin, const QString& reply, Irc::Buffer::MessageFlags flags);
 
//    void on_ctcpActionReceived(const QString& origin, const QString& action, Irc::Buffer::MessageFlags flags);
 
//    void on_numericMessageReceived(const QString& origin, uint code, const QStringList& params);
 
//    void on_unknownMessageReceived(const QString& origin, const QStringList& params);
 

	
 
//	bool correctNickname(std::string &nickname);
 
//};
 

	
 
#endif // SESSION_H
backends/libcommuni/singleircnetworkplugin.cpp
Show inline comments
 
new file 100644
 
#include "singleircnetworkplugin.h"
 
#include "log4cxx/logger.h"
 
#include <IrcCommand>
 
#include <IrcMessage>
 

	
 
using namespace log4cxx;
 

	
 
static LoggerPtr logger = log4cxx::Logger::getLogger("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);
 
	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 {
 
		m_identify = "NickServ identify $name $password";
 
	}
 

	
 
	LOG4CXX_INFO(logger, "SingleIRCNetworkPlugin for server " << m_server << " initialized.");
 
}
 

	
 
void SingleIRCNetworkPlugin::readData() {
 
	size_t availableBytes = m_socket->bytesAvailable();
 
	if (availableBytes == 0)
 
		return;
 

	
 
	std::string d = std::string(m_socket->readAll().data(), availableBytes);
 
	handleDataRead(d);
 
}
 

	
 
void SingleIRCNetworkPlugin::sendData(const std::string &string) {
 
	m_socket->write(string.c_str(), string.size());
 
}
 

	
 
void SingleIRCNetworkPlugin::handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password) {
 
	// legacy name is users nickname
 
	if (m_sessions[user] != NULL) {
 
		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->setPort(6667);
 

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

	
 
void SingleIRCNetworkPlugin::handleLogoutRequest(const std::string &user, const std::string &legacyName) {
 
	if (m_sessions[user] == NULL) {
 
		LOG4CXX_WARN(logger, user << ": Already disconnected.");
 
		return;
 
	}
 
	LOG4CXX_INFO(logger, user << ": Disconnecting.");
 

	
 
	m_sessions[user]->close();
 
	m_sessions[user]->deleteLater();
 
	m_sessions.erase(user);
 
}
 

	
 
void SingleIRCNetworkPlugin::handleMessageSendRequest(const std::string &user, const std::string &legacyName, const std::string &message, const std::string &/*xhtml*/) {
 
	if (m_sessions[user] == NULL) {
 
		LOG4CXX_WARN(logger, user << ": Message received for unconnected user");
 
		return;
 
	}
 

	
 
	// handle PMs
 
	std::string r = legacyName;
 
	if (legacyName.find("/") == std::string::npos) {
 
		r = legacyName.substr(0, r.find("@"));
 
	}
 
	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)));
 

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

	
 
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]->rooms += 1;
 

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

	
 
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]->removeAutoJoinChannel(r);
 
	m_sessions[u]->rooms -= 1;
 
}
backends/libcommuni/singleircnetworkplugin.h
Show inline comments
 
new file 100644
 

	
 
#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 SingleIRCNetworkPlugin : public QObject, public NetworkPlugin {
 
	Q_OBJECT
 

	
 
	public:
 
		SingleIRCNetworkPlugin(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 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);
 

	
 
		std::map<std::string, MyIrcSession *> m_sessions;
 

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

	
 
	private:
 
		Config *config;
 
		QTcpSocket *m_socket;
 
		std::string m_server;
 
		std::string m_identify;
 
};
backends/libircclient-qt/CMakeLists.txt
Show inline comments
 
deleted file
backends/libircclient-qt/session.cpp
Show inline comments
 
deleted file
backends/libircclient-qt/session.h
Show inline comments
 
deleted file
backends/libpurple/main.cpp
Show inline comments
 
@@ -66,12 +66,26 @@ static void transportDataReceived(gpointer data, gint source, PurpleInputConditi
 

	
 
class SpectrumNetworkPlugin;
 

	
 
GKeyFile *keyfile;
 
SpectrumNetworkPlugin *np;
 

	
 
std::string replaceAll(
 
  std::string result,
 
  const std::string& replaceWhat,
 
  const std::string& replaceWithWhat)
 
{
 
  while(1)
 
  {
 
	const int pos = result.find(replaceWhat);
 
	if (pos==-1) break;
 
	result.replace(pos,replaceWhat.size(),replaceWithWhat);
 
  }
 
  return result;
 
}
 

	
 
static std::string KEYFILE_STRING(const std::string &cat, const std::string &key, const std::string &def = "") {
 
	gchar *str = g_key_file_get_string(keyfile, cat.c_str(), key.c_str(), 0);
 
	if (!str) {
 
		return def;
 
	}
 
	std::string ret(str);
 
@@ -80,12 +94,17 @@ static std::string KEYFILE_STRING(const std::string &cat, const std::string &key
 
	if (ret.find("#") != std::string::npos) {
 
		ret = ret.substr(0, ret.find("#"));
 
		while(*(ret.end() - 1) == ' ') {
 
			ret.erase(ret.end() - 1);
 
		}
 
	}
 

	
 
	if (ret.find("$jid") != std::string::npos) {
 
		std::string jid = KEYFILE_STRING("service", "jid");
 
		ret = replaceAll(ret, "$jid", jid);
 
	}
 
	return ret;
 
}
 

	
 
#define KEYFILE_BOOL(CAT, KEY) g_key_file_get_boolean(keyfile, CAT, KEY, 0)
 

	
 
static gboolean nodaemon = FALSE;
 
@@ -520,12 +539,16 @@ class SpectrumNetworkPlugin : public NetworkPlugin {
 
		void setDefaultAccountOptions(PurpleAccount *account) {
 
			int i = 0;
 
			gchar **keys = g_key_file_get_keys (keyfile, "purple", NULL, NULL);
 
			while (keys && keys[i] != NULL) {
 
				std::string key = keys[i];
 

	
 
				if (key == "fb_api_key" || key == "fb_api_secret") {
 
					purple_account_set_bool(account, "auth_fb", TRUE);
 
				}
 

	
 
				PurplePlugin *plugin = purple_find_prpl(purple_account_get_protocol_id(account));
 
				PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(plugin);
 
				bool found = false;
 
				for (GList *l = prpl_info->protocol_options; l != NULL; l = l->next) {
 
					PurpleAccountOption *option = (PurpleAccountOption *) l->data;
 
					PurplePrefType type = purple_account_option_get_type(option);
 
@@ -567,17 +590,19 @@ class SpectrumNetworkPlugin : public NetworkPlugin {
 
			
 
			std::string name;
 
			std::string protocol;
 
			getProtocolAndName(legacyName, name, protocol);
 

	
 
			if (password.empty()) {
 
				LOG4CXX_INFO(logger,  name.c_str() << ": Empty password");
 
				np->handleDisconnected(user, 0, "Empty password.");
 
				return;
 
			}
 

	
 
			if (!purple_find_prpl(protocol.c_str())) {
 
				LOG4CXX_INFO(logger,  name.c_str() << ": Invalid protocol '" << protocol << "'");
 
				np->handleDisconnected(user, 0, "Invalid protocol " + protocol);
 
				return;
 
			}
 

	
 
			LOG4CXX_INFO(logger,  "Creating account with name '" << name.c_str() << "' and protocol '" << protocol << "'");
 
			if (purple_accounts_find(name.c_str(), protocol.c_str()) != NULL){
 
@@ -1202,12 +1227,17 @@ static gboolean disconnectMe(void *data) {
 
	if (account) {
 
		np->handleLogoutRequest(np->m_accounts[account], purple_account_get_username(account));
 
	}
 
	return FALSE;
 
}
 

	
 
static gboolean pingTimeout(void *data) {
 
	np->checkPing();
 
	return TRUE;
 
}
 

	
 
static void connection_report_disconnect(PurpleConnection *gc, PurpleConnectionError reason, const char *text){
 
	PurpleAccount *account = purple_connection_get_account(gc);
 
	np->handleDisconnected(np->m_accounts[account], (int) reason, text ? text : "");
 
	Dis *d = new Dis;
 
	d->name = purple_account_get_username(account);
 
	d->protocol = purple_account_get_protocol_id(account);
 
@@ -1547,17 +1577,84 @@ static void transport_core_ui_init(void)
 
	purple_conversations_set_ui_ops(&conversation_ui_ops);
 
// #ifndef WIN32
 
// 	purple_dnsquery_set_ui_ops(getDNSUiOps());
 
// #endif
 
}
 

	
 
/***** Core Ui Ops *****/
 
static void
 
spectrum_glib_log_handler(const gchar *domain,
 
						  GLogLevelFlags flags,
 
						  const gchar *message,
 
						  gpointer user_data)
 
{
 
	const char *level;
 
	char *new_msg = NULL;
 
	char *new_domain = NULL;
 

	
 
	if ((flags & G_LOG_LEVEL_ERROR) == G_LOG_LEVEL_ERROR)
 
		level = "ERROR";
 
	else if ((flags & G_LOG_LEVEL_CRITICAL) == G_LOG_LEVEL_CRITICAL)
 
		level = "CRITICAL";
 
	else if ((flags & G_LOG_LEVEL_WARNING) == G_LOG_LEVEL_WARNING)
 
		level = "WARNING";
 
	else if ((flags & G_LOG_LEVEL_MESSAGE) == G_LOG_LEVEL_MESSAGE)
 
		level = "MESSAGE";
 
	else if ((flags & G_LOG_LEVEL_INFO) == G_LOG_LEVEL_INFO)
 
		level = "INFO";
 
	else if ((flags & G_LOG_LEVEL_DEBUG) == G_LOG_LEVEL_DEBUG)
 
		level = "DEBUG";
 
	else {
 
		LOG4CXX_ERROR(logger, "Unknown glib logging level in " << (guint)flags);
 
		level = "UNKNOWN"; /* This will never happen. */
 
	}
 

	
 
	if (message != NULL)
 
		new_msg = purple_utf8_try_convert(message);
 

	
 
	if (domain != NULL)
 
		new_domain = purple_utf8_try_convert(domain);
 

	
 
	if (new_msg != NULL) {
 
		std::string area("glib");
 
		area.push_back('/');
 
		area.append(level);
 

	
 
		std::string message(new_domain ? new_domain : "g_log");
 
		message.push_back(' ');
 
		message.append(new_msg);
 

	
 
		LOG4CXX_ERROR(logger, message);
 
		g_free(new_msg);
 
	}
 

	
 
	g_free(new_domain);
 
}
 

	
 
static void
 
debug_init(void)
 
{
 
#define REGISTER_G_LOG_HANDLER(name) \
 
	g_log_set_handler((name), \
 
		(GLogLevelFlags)(G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL \
 
										  | G_LOG_FLAG_RECURSION), \
 
					  spectrum_glib_log_handler, NULL)
 

	
 
	REGISTER_G_LOG_HANDLER(NULL);
 
	REGISTER_G_LOG_HANDLER("GLib");
 
	REGISTER_G_LOG_HANDLER("GModule");
 
	REGISTER_G_LOG_HANDLER("GLib-GObject");
 
	REGISTER_G_LOG_HANDLER("GThread");
 

	
 
#undef REGISTER_G_LOD_HANDLER
 
}
 

	
 
static PurpleCoreUiOps coreUiOps =
 
{
 
	NULL,
 
// 	debug_init,
 
	NULL,
 
	debug_init,
 
	transport_core_ui_init,
 
	NULL,
 
	spectrum_ui_get_info,
 
	NULL,
 
	NULL,
 
	NULL
 
@@ -1849,13 +1946,13 @@ int main(int argc, char **argv) {
 
		else {
 
			log4cxx::helpers::Properties p;
 
			log4cxx::helpers::FileInputStream *istream = new log4cxx::helpers::FileInputStream(KEYFILE_STRING("logging", "backend_config"));
 
			p.load(istream);
 
			LogString pid, jid;
 
			log4cxx::helpers::Transcoder::decode(stringOf(getpid()), pid);
 
			log4cxx::helpers::Transcoder::decode(KEYFILE_STRING("service", "service.jid"), jid);
 
			log4cxx::helpers::Transcoder::decode(KEYFILE_STRING("service", "jid"), jid);
 
#ifdef _MSC_VER
 
			p.setProperty(L"pid", pid);
 
			p.setProperty(L"jid", jid);
 
#else
 
			p.setProperty("pid", pid);
 
			p.setProperty("jid", jid);
 
@@ -1865,12 +1962,13 @@ int main(int argc, char **argv) {
 

	
 
		initPurple();
 

	
 
		m_sock = create_socket(host, port);
 

	
 
		purple_input_add(m_sock, PURPLE_INPUT_READ, &transportDataReceived, NULL);
 
		purple_timeout_add_seconds(30, pingTimeout, NULL);
 

	
 
		np = new SpectrumNetworkPlugin(host, port);
 
		bool libev = KEYFILE_STRING("service", "eventloop") == "libev";
 

	
 
		GMainLoop *m_loop;
 
#ifdef WITH_LIBEVENT
cmake_modules/CommuniConfig.cmake
Show inline comments
 
new file 100644
 
FIND_LIBRARY(IRC_LIBRARY NAMES Communi)
 
FIND_PATH(IRC_INCLUDE_DIR NAMES "ircglobal.h" PATH_SUFFIXES Communi qt4/Communi )
 

	
 
# message( STATUS ${IRC_LIBRARY})
 
if( IRC_LIBRARY AND IRC_INCLUDE_DIR )
 
    message( STATUS "Found libCommuni ${IRC_LIBRARY}, ${IRC_INCLUDE_DIR}")
 
    set( IRC_FOUND 1 )
 
else()
 
    message( STATUS "Could NOT find libCommuni" )
 
endif()
cmake_modules/IRCClientQtConfig.cmake
Show inline comments
 
deleted file
examples/CMakeLists.txt
Show inline comments
 
deleted file
examples/external_network_plugin/CMakeLists.txt
Show inline comments
 
deleted file
examples/external_network_plugin/main.cpp
Show inline comments
 
deleted file
examples/external_network_plugin/pbnetwork.proto
Show inline comments
 
deleted file
examples/external_network_plugin/plugin.py
Show inline comments
 
deleted file
examples/server_connect/CMakeLists.txt
Show inline comments
 
deleted file
examples/server_connect/main.cpp
Show inline comments
 
deleted file
examples/server_connect/sample.cfg
Show inline comments
 
deleted file
examples/usermanager/CMakeLists.txt
Show inline comments
 
deleted file
examples/usermanager/main.cpp
Show inline comments
 
deleted file
examples/usermanager/sample.cfg
Show inline comments
 
deleted file
include/Swiften/Elements/StatsPayload.cpp
Show inline comments
 
new file 100644
 
/*
 
 * Copyright (c) 2011 Jan Kaluza
 
 * Licensed under the Simplified BSD license.
 
 * See Documentation/Licenses/BSD-simplified.txt for more information.
 
 */
 

	
 
#include <Swiften/Elements/StatsPayload.h>
 

	
 
namespace Swift {
 

	
 
StatsPayload::StatsPayload() {
 
}
 

	
 
}
include/Swiften/Elements/StatsPayload.h
Show inline comments
 
new file 100644
 
/*
 
 * Copyright (c) 2011 Jan Kaluza
 
 * Licensed under the Simplified BSD license.
 
 * See Documentation/Licenses/BSD-simplified.txt for more information.
 
 */
 

	
 
#pragma once
 

	
 
#include <vector>
 

	
 
#include <string>
 
#include <Swiften/Elements/Payload.h>
 

	
 
namespace Swift {
 
	class StatsPayload : public Payload {
 
		public:
 
			class Item {
 
				public:
 
					Item(const std::string &name = "", const std::string &units = "", const std::string &value = "") :
 
						name(name), units(units), value(value) { }
 

	
 
					void setName(const std::string &name) {
 
						this->name = name;
 
					}
 

	
 
					const std::string &getName() const {
 
						return name;
 
					}
 

	
 
					void setUnits(const std::string &units) {
 
						this->units = units;
 
					}
 

	
 
					const std::string &getUnits() const {
 
						return units;
 
					}
 

	
 
					void setValue(const std::string &value) {
 
						this->value = value;
 
					}
 

	
 
					const std::string &getValue() const {
 
						return value;
 
					}
 

	
 
				private:
 
					std::string name;
 
					std::string units;
 
					std::string value;
 
			};
 

	
 
			typedef std::vector<StatsPayload::Item> StatsPayloadItems;
 

	
 
			StatsPayload();
 

	
 
			void addItem(const StatsPayload::Item &item) {
 
				items.push_back(item);
 
			}
 

	
 
			const StatsPayloadItems &getItems() const {
 
				return items;
 
			}
 

	
 
		private:
 
			StatsPayloadItems items;
 
	};
 
}
include/Swiften/Parser/PayloadParsers/StatsParser.cpp
Show inline comments
 
new file 100644
 
/*
 
 * Copyright (c) 2011 Jan Kaluza
 
 * Licensed under the Simplified BSD license.
 
 * See Documentation/Licenses/BSD-simplified.txt for more information.
 
 */
 

	
 
#include <Swiften/Parser/PayloadParsers/StatsParser.h>
 
#include <Swiften/Parser/SerializingParser.h>
 

	
 
namespace Swift {
 

	
 
StatsParser::StatsParser() : level_(TopLevel), inItem_(false) {
 
}
 

	
 
void StatsParser::handleStartElement(const std::string& element, const std::string& /*ns*/, const AttributeMap& attributes) {
 
	if (level_ == PayloadLevel) {
 
		if (element == "stat") {
 
			inItem_ = true;
 

	
 
			currentItem_ = StatsPayload::Item();
 

	
 
			currentItem_.setName(attributes.getAttribute("name"));
 
			currentItem_.setValue(attributes.getAttribute("value"));
 
			currentItem_.setUnits(attributes.getAttribute("units"));
 
		}
 
	}
 
	++level_;
 
}
 

	
 
void StatsParser::handleEndElement(const std::string& element, const std::string& /*ns*/) {
 
	--level_;
 
	if (level_ == PayloadLevel) {
 
		if (inItem_) {
 
			getPayloadInternal()->addItem(currentItem_);
 
			inItem_ = false;
 
		}
 
	}
 
}
 

	
 
void StatsParser::handleCharacterData(const std::string& data) {
 
}
 

	
 
}
include/Swiften/Parser/PayloadParsers/StatsParser.h
Show inline comments
 
new file 100644
 
/*
 
 * Copyright (c) 2011 Jan Kaluza
 
 * Licensed under the Simplified BSD license.
 
 * See Documentation/Licenses/BSD-simplified.txt for more information.
 
 */
 

	
 
#pragma once
 

	
 
#include <Swiften/Elements/StatsPayload.h>
 
#include <Swiften/Parser/GenericPayloadParser.h>
 

	
 
namespace Swift {
 
	class SerializingParser;
 

	
 
	class StatsParser : public GenericPayloadParser<StatsPayload> {
 
		public:
 
			StatsParser();
 

	
 
			virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes);
 
			virtual void handleEndElement(const std::string& element, const std::string&);
 
			virtual void handleCharacterData(const std::string& data);
 

	
 
		private:
 
			enum Level { 
 
				TopLevel = 0, 
 
				PayloadLevel = 1,
 
				ItemLevel = 2
 
			};
 
			int level_;
 
			bool inItem_;
 
			StatsPayload::Item currentItem_;
 
	};
 
}
include/Swiften/Serializer/PayloadSerializers/StatsSerializer.cpp
Show inline comments
 
new file 100644
 
/*
 
 * Copyright (c) 2011 Jan Kaluza
 
 * Licensed under the Simplified BSD license.
 
 * See Documentation/Licenses/BSD-simplified.txt for more information.
 
 */
 

	
 
#include <Swiften/Serializer/PayloadSerializers/StatsSerializer.h>
 

	
 
#include <boost/shared_ptr.hpp>
 

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

	
 
namespace Swift {
 

	
 
StatsSerializer::StatsSerializer() : GenericPayloadSerializer<StatsPayload>() {
 
}
 

	
 
std::string StatsSerializer::serializePayload(boost::shared_ptr<StatsPayload> stats)  const {
 
	XMLElement queryElement("query", "http://jabber.org/protocol/stats");
 
	foreach(const StatsPayload::Item& item, stats->getItems()) {
 
		boost::shared_ptr<XMLElement> statElement(new XMLElement("stat"));
 
		statElement->setAttribute("name", item.getName());
 
		if (!item.getUnits().empty()) {
 
			statElement->setAttribute("units", item.getUnits());
 
		}
 
		if (!item.getValue().empty()) {
 
			statElement->setAttribute("value", item.getValue());
 
		}
 

	
 
		queryElement.addNode(statElement);
 
	}
 

	
 
	return queryElement.serialize();
 
}
 

	
 
}
include/Swiften/Serializer/PayloadSerializers/StatsSerializer.h
Show inline comments
 
new file 100644
 
/*
 
 * Copyright (c) 2011 Jan Kaluza
 
 * Licensed under the Simplified BSD license.
 
 * See Documentation/Licenses/BSD-simplified.txt for more information.
 
 */
 

	
 
#pragma once
 

	
 
#include <Swiften/Serializer/GenericPayloadSerializer.h>
 
#include <Swiften/Elements/StatsPayload.h>
 

	
 
namespace Swift {
 
	class StatsSerializer : public GenericPayloadSerializer<StatsPayload> {
 
		public:
 
			StatsSerializer();
 

	
 
			virtual std::string serializePayload(boost::shared_ptr<StatsPayload>)  const;
 
	};
 
}
include/transport/config.h
Show inline comments
 
@@ -31,12 +31,13 @@
 

	
 
#define CONFIG_STRING(PTR, KEY) (*PTR)[KEY].as<std::string>()
 
#define CONFIG_INT(PTR, KEY) (*PTR)[KEY].as<int>()
 
#define CONFIG_BOOL(PTR, KEY) (*PTR)[KEY].as<bool>()
 
#define CONFIG_LIST(PTR, KEY) (*PTR)[KEY].as<std::list<std::string> >()
 
#define CONFIG_VECTOR(PTR, KEY) (*PTR)[KEY].as<std::vector<std::string> >()
 
#define CONFIG_HAS_KEY(PTR, KEY) (*PTR).hasKey(KEY)
 

	
 
namespace Transport {
 

	
 
/// Represents variable:value pairs.
 
typedef boost::program_options::variables_map Variables;
 

	
 
@@ -57,27 +58,31 @@ class Config {
 
		/// Loads data from config file.
 
		
 
		/// You can pass your extra options which will be recognized by
 
		/// the parser using opts parameter.
 
		/// \param configfile path to config file
 
		/// \param opts extra options which will be recognized by a parser
 
		bool load(const std::string &configfile, boost::program_options::options_description &opts);
 
		bool load(const std::string &configfile, boost::program_options::options_description &opts, const std::string &jid = "");
 

	
 
		bool load(std::istream &ifs, boost::program_options::options_description &opts);
 
		bool load(std::istream &ifs, boost::program_options::options_description &opts, const std::string &jid = "");
 

	
 
		bool load(std::istream &ifs);
 

	
 
		/// Loads data from config file.
 
		
 
		/// This function loads only config variables needed by libtransport.
 
		/// \see load(const std::string &, boost::program_options::options_description &)
 
		/// \param configfile path to config file
 
		bool load(const std::string &configfile);
 
		bool load(const std::string &configfile, const std::string &jid = "");
 

	
 
		bool reload();
 

	
 
		bool hasKey(const std::string &key) {
 
			return m_variables.find(key) != m_variables.end();
 
		}
 

	
 
		/// Returns value of variable defined by key.
 
		
 
		/// 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) {
 
			return m_variables[key];
include/transport/conversation.h
Show inline comments
 
@@ -71,12 +71,20 @@ class Conversation {
 

	
 
		/// \param nickname XMPP user nickname in MUC rooms.
 
		void setNickname(const std::string &nickname) {
 
			m_nickname = nickname;
 
		}
 

	
 
		const std::string &getNickname() {
 
			return m_nickname;
 
		}
 

	
 
		void setJID(const Swift::JID &jid) {
 
			m_jid = jid;
 
		}
 

	
 
		/// Sends message to Legacy network.
 

	
 
		/// \param message Message.
 
		virtual void sendMessage(boost::shared_ptr<Swift::Message> &message) = 0;
 

	
 
		/// Returns ConversationManager associated with this Conversation.
 
@@ -109,9 +117,10 @@ class Conversation {
 
	private:
 
		ConversationManager *m_conversationManager;
 
		std::string m_legacyName;
 
		std::string m_nickname;
 
		std::string m_room;
 
		bool m_muc;
 
		Swift::JID m_jid;
 
};
 

	
 
}
include/transport/conversationmanager.h
Show inline comments
 
@@ -70,12 +70,14 @@ class ConversationManager {
 

	
 
		/// Removes Conversation from the manager.
 

	
 
		/// \param conv Conversation.
 
		void removeConversation(Conversation *conv);
 

	
 
		void resetResources();
 

	
 
	private:
 
		void handleMessageReceived(Swift::Message::ref message);
 

	
 
		Component *m_component;
 
		User *m_user;
 

	
include/transport/networkplugin.h
Show inline comments
 
@@ -212,12 +212,13 @@ class NetworkPlugin {
 
		virtual void handleFTContinueRequest(unsigned long ftID) {}
 

	
 
		virtual void handleExitRequest() { exit(1); }
 
		void handleDataRead(std::string &data);
 
		virtual void sendData(const std::string &string) {}
 

	
 
		void checkPing();
 

	
 
	private:
 
		void handleLoginPayload(const std::string &payload);
 
		void handleLogoutPayload(const std::string &payload);
 
		void handleStatusChangedPayload(const std::string &payload);
 
		void handleConvMessagePayload(const std::string &payload);
include/transport/networkpluginserver.h
Show inline comments
 
@@ -93,13 +93,13 @@ class NetworkPluginServer {
 
		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 handleUserCreated(User *user);
 
		void handleRoomJoined(User *user, const std::string &room, const std::string &nickname, const std::string &password);
 
		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);
include/transport/protocol.proto
Show inline comments
 
package pbnetwork;
 

	
 
enum ConnectionError {
 
	CONNECTION_ERROR_NETWORK_ERROR = 0;
 
	CONNECTION_ERROR_INVALID_USERNAME = 1;
 
	CONNECTION_ERROR_AUTHENTICATION_FAILED = 2;
 
	CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE = 3;
 
	CONNECTION_ERROR_NO_SSL_SUPPORT = 4;
 
	CONNECTION_ERROR_ENCRYPTION_ERROR = 5;
 
	CONNECTION_ERROR_NAME_IN_USE = 6;
 
	CONNECTION_ERROR_INVALID_SETTINGS = 7;
 
	CONNECTION_ERROR_CERT_NOT_PROVIDED = 8;
 
	CONNECTION_ERROR_CERT_UNTRUSTED = 9;
 
	CONNECTION_ERROR_CERT_EXPIRED = 10;
 
	CONNECTION_ERROR_CERT_NOT_ACTIVATED = 11;
 
	CONNECTION_ERROR_CERT_HOSTNAME_MISMATCH = 12;
 
	CONNECTION_ERROR_CERT_FINGERPRINT_MISMATCH = 13;
 
	CONNECTION_ERROR_CERT_SELF_SIGNED = 14;
 
	CONNECTION_ERROR_CERT_OTHER_ERROR = 15;
 
	CONNECTION_ERROR_OTHER_ERROR = 16;
 
}
 

	
 
enum StatusType {
 
	STATUS_ONLINE		= 0;
 
	STATUS_AWAY			= 1;
 
	STATUS_FFC			= 2;
 
	STATUS_XA			= 3;
 
	STATUS_DND			= 4;
include/transport/rostermanager.h
Show inline comments
 
@@ -46,12 +46,13 @@ class AddressedRosterRequest : public Swift::GenericRequest<Swift::RosterPayload
 
		}
 
};
 

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

	
 
		/// Destructor.
 
@@ -77,12 +78,16 @@ class RosterManager {
 
		Swift::RosterPayload::ref generateRosterPayload();
 

	
 
		/// Returns user associated with this roster.
 
		/// \return User
 
		User *getUser() { return m_user; }
 

	
 
		const BuddiesMap &getBuddies() {
 
			return m_buddies;
 
		}
 

	
 
		bool isRemoteRosterSupported() {
 
			return m_supportRemoteRoster;
 
		}
 

	
 
		/// Called when new Buddy is added to this roster.
 
		/// \param buddy newly added Buddy
 
@@ -122,9 +127,10 @@ class RosterManager {
 
		RosterStorage *m_rosterStorage;
 
		User *m_user;
 
		Swift::Timer::ref m_setBuddyTimer;
 
		Swift::Timer::ref m_RIETimer;
 
		std::list <Swift::SetRosterRequest::ref> m_requests;
 
		bool m_supportRemoteRoster;
 
		AddressedRosterRequest::ref m_remoteRosterRequest;
 
};
 

	
 
}
include/transport/statsresponder.h
Show inline comments
 
new file 100644
 
/**
 
 * libtransport -- C++ library for easy XMPP Transports development
 
 *
 
 * Copyright (C) 2011, Jan Kaluza <hanzz.k@gmail.com>
 
 *
 
 * This program is free software; you can redistribute it and/or modify
 
 * it under the terms of the GNU General Public License as published by
 
 * the Free Software Foundation; either version 2 of the License, or
 
 * (at your option) any later version.
 
 *
 
 * This program is distributed in the hope that it will be useful,
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
 * GNU General Public License for more details.
 
 *
 
 * You should have received a copy of the GNU General Public License
 
 * along with this program; if not, write to the Free Software
 
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
 
 */
 

	
 
#pragma once
 

	
 
#include <vector>
 
#include "Swiften/Swiften.h"
 
#include "Swiften/Queries/SetResponder.h"
 
#include "Swiften/Elements/StatsPayload.h"
 

	
 
namespace Transport {
 

	
 
class Component;
 
class UserManager;
 
class NetworkPluginServer;
 
class StorageBackend;
 

	
 
class StatsResponder : public Swift::Responder<Swift::StatsPayload> {
 
	public:
 
		StatsResponder(Component *component, UserManager *userManager, NetworkPluginServer *server, StorageBackend *storageBackend);
 
		~StatsResponder();
 

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

	
 
		unsigned long usedMemory();
 

	
 
		Component *m_component;
 
		UserManager *m_userManager;
 
		NetworkPluginServer *m_server;
 
		StorageBackend *m_storageBackend;
 
		time_t m_start;
 
};
 

	
 
}
include/transport/user.h
Show inline comments
 
@@ -108,13 +108,13 @@ class User : public Swift::EntityCapsProvider {
 
		bool isConnected() {
 
			return m_connected;
 
		}
 

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

	
 
	private:
 
		void onConnectingTimeout();
 

	
 
@@ -132,9 +132,10 @@ class User : public Swift::EntityCapsProvider {
 
		bool m_ignoreDisconnect;
 
		Swift::Timer::ref m_reconnectTimer;
 
		boost::shared_ptr<Swift::Connection> connection;
 
		time_t m_lastActivity;
 
		std::map<Swift::JID, Swift::DiscoInfo::ref> m_legacyCaps;
 
		std::vector<boost::shared_ptr<Swift::OutgoingFileTransfer> > m_filetransfers;
 
		int m_resources;
 
};
 

	
 
}
include/transport/util.h
Show inline comments
 
@@ -21,16 +21,21 @@
 
#pragma once
 

	
 
#include <stdio.h>
 
#include <stdlib.h>
 
#include <vector>
 
#include <string>
 
#include "Swiften/StringCodecs/Base64.h"
 

	
 
namespace Transport {
 

	
 
namespace Util {
 

	
 
void removeEverythingOlderThan(const std::vector<std::string> &dirs, time_t t);
 

	
 
std::string encryptPassword(const std::string &password, const std::string &key);
 

	
 
std::string decryptPassword(std::string &encrypted, const std::string &key);
 

	
 
}
 

	
 
}
plugin/src/networkplugin.cpp
Show inline comments
 
@@ -550,12 +550,19 @@ void NetworkPlugin::handleDataRead(std::string &data) {
 
void NetworkPlugin::send(const std::string &data) {
 
	char header[4];
 
	*((int*)(header)) = htonl(data.size());
 
	sendData(std::string(header, 4) + data);
 
}
 

	
 
void NetworkPlugin::checkPing() {
 
	if (m_pingReceived == false) {
 
		handleExitRequest();
 
	}
 
	m_pingReceived = false;
 
}
 

	
 
void NetworkPlugin::sendPong() {
 
	m_pingReceived = true;
 
	std::string message;
 
	pbnetwork::WrapperMessage wrap;
 
	wrap.set_type(pbnetwork::WrapperMessage_Type_TYPE_PONG);
 
	wrap.SerializeToString(&message);
spectrum/src/CMakeLists.txt
Show inline comments
 
@@ -10,13 +10,13 @@ target_link_libraries(spectrum2 transport ${Boost_LIBRARIES} ${SWIFTEN_LIBRARY}
 
 
INSTALL(TARGETS spectrum2 RUNTIME DESTINATION bin)
 
 
INSTALL(FILES
 
	sample2.cfg
 
	RENAME spectrum.cfg.example
 
	DESTINATION /etc/spectrum2
 
	DESTINATION /etc/spectrum2/transports
 
	)
 
 
INSTALL(FILES
 
	backend-logging.cfg
 
	DESTINATION /etc/spectrum2
 
	)
spectrum/src/main.cpp
Show inline comments
 
@@ -5,15 +5,17 @@
 
#include "transport/logger.h"
 
#include "transport/sqlite3backend.h"
 
#include "transport/mysqlbackend.h"
 
#include "transport/userregistration.h"
 
#include "transport/networkpluginserver.h"
 
#include "transport/admininterface.h"
 
#include "transport/statsresponder.h"
 
#include "transport/util.h"
 
#include "Swiften/EventLoop/SimpleEventLoop.h"
 
#include <boost/filesystem.hpp>
 
#include <boost/algorithm/string.hpp>
 
#ifndef WIN32
 
#include "sys/signal.h"
 
#include <pwd.h>
 
#include <grp.h>
 
#include <sys/resource.h>
 
#include "libgen.h"
 
@@ -119,12 +121,13 @@ int main(int argc, char **argv)
 
{
 
	Config config;
 

	
 
	boost::program_options::variables_map vm;
 
	bool no_daemon = false;
 
	std::string config_file;
 
	std::string jid;
 
	
 

	
 
#ifndef WIN32
 
	if (signal(SIGINT, spectrum_sigint_handler) == SIG_ERR) {
 
		std::cout << "SIGINT handler can't be set\n";
 
		return -1;
 
@@ -132,27 +135,33 @@ int main(int argc, char **argv)
 

	
 
	if (signal(SIGTERM, spectrum_sigterm_handler) == SIG_ERR) {
 
		std::cout << "SIGTERM handler can't be set\n";
 
		return -1;
 
	}
 
#endif
 
	boost::program_options::options_description desc("Usage: spectrum [OPTIONS] <config_file.cfg>\nAllowed options");
 
	boost::program_options::options_description desc(std::string("Spectrum version: ") + SPECTRUM_VERSION + "\nUsage: spectrum [OPTIONS] <config_file.cfg>\nAllowed options");
 
	desc.add_options()
 
		("help,h", "help")
 
		("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>(&config_file)->default_value(""), "Config file")
 
		("version,v", "Shows Spectrum version")
 
		;
 
	try
 
	{
 
		boost::program_options::positional_options_description p;
 
		p.add("config", -1);
 
		boost::program_options::store(boost::program_options::command_line_parser(argc, argv).
 
          options(desc).positional(p).run(), vm);
 
		boost::program_options::notify(vm);
 

	
 
		
 
		if (vm.count("version")) {
 
			std::cout << SPECTRUM_VERSION << "\n";
 
			return 0;
 
		}
 

	
 
		if(vm.count("help"))
 
		{
 
			std::cout << desc << "\n";
 
			return 1;
 
		}
 
@@ -174,37 +183,52 @@ int main(int argc, char **argv)
 
	catch (...)
 
	{
 
		std::cout << desc << "\n";
 
		return 1;
 
	}
 

	
 
	if (!config.load(vm["config"].as<std::string>())) {
 
	if (!config.load(vm["config"].as<std::string>(), jid)) {
 
		std::cerr << "Can't load configuration file.\n";
 
		return 1;
 
	}
 

	
 
#ifndef WIN32
 
	if (!no_daemon) {
 
	// create directories
 
	try {
 
			boost::filesystem::create_directories(CONFIG_STRING(&config, "service.working_dir"));
 
		boost::filesystem::create_directories(
 
			boost::filesystem::path(CONFIG_STRING(&config, "service.pidfile")).parent_path().string()
 
		);
 
	}
 
	catch (...) {
 
			std::cerr << "Can't create service.working_dir directory " << CONFIG_STRING(&config, "service.working_dir") << ".\n";
 
		std::cerr << "Can't create service.pidfile directory " << boost::filesystem::path(CONFIG_STRING(&config, "service.pidfile")).parent_path().string() << ".\n";
 
		return 1;
 
	}
 
	// create directories
 
	try {
 
			boost::filesystem::create_directories(
 
				boost::filesystem::path(CONFIG_STRING(&config, "service.pidfile")).parent_path().string()
 
			);
 
		boost::filesystem::create_directories(CONFIG_STRING(&config, "service.working_dir"));
 
	}
 
	catch (...) {
 
			std::cerr << "Can't create service.pidfile directory " << boost::filesystem::path(CONFIG_STRING(&config, "service.pidfile")).parent_path().string() << ".\n";
 
		std::cerr << "Can't create service.working_dir directory " << CONFIG_STRING(&config, "service.working_dir") << ".\n";
 
		return 1;
 
	}
 

	
 
	if (!CONFIG_STRING(&config, "service.group").empty() ||!CONFIG_STRING(&config, "service.user").empty() ) {
 
		struct group *gr;
 
		if ((gr = getgrnam(CONFIG_STRING(&config, "service.group").c_str())) == NULL) {
 
			std::cerr << "Invalid service.group name " << CONFIG_STRING(&config, "service.group") << "\n";
 
			return 1;
 
		}
 
		struct passwd *pw;
 
		if ((pw = getpwnam(CONFIG_STRING(&config, "service.user").c_str())) == NULL) {
 
			std::cerr << "Invalid service.user name " << CONFIG_STRING(&config, "service.user") << "\n";
 
			return 1;
 
		}
 
		chown(CONFIG_STRING(&config, "service.working_dir").c_str(), pw->pw_uid, gr->gr_gid);
 
	}
 

	
 
#ifndef WIN32
 
	if (!no_daemon) {
 
		// daemonize
 
		daemonize(CONFIG_STRING(&config, "service.working_dir").c_str(), CONFIG_STRING(&config, "service.pidfile").c_str());
 
// 		removeOldIcons(CONFIG_STRING(&config, "service.working_dir") + "/icons");
 
    }
 
#endif
 

	
 
@@ -228,47 +252,92 @@ int main(int argc, char **argv)
 
		p.setProperty(L"pid", pid);
 
		p.setProperty(L"jid", jid);
 
#else
 
		p.setProperty("pid", pid);
 
		p.setProperty("jid", jid);
 
#endif
 

	
 
		std::string dir;
 
		BOOST_FOREACH(const log4cxx::LogString &prop, p.propertyNames()) {
 
			if (boost::ends_with(prop, ".File")) {
 
				dir = p.get(prop);
 
				boost::replace_all(dir, "${jid}", jid);
 
				break;
 
			}
 
		}
 

	
 
		if (!dir.empty()) {
 
			// create directories
 
			try {
 
				boost::filesystem::create_directories(
 
					boost::filesystem::path(dir).parent_path().string()
 
				);
 
			}
 
			catch (...) {
 
				std::cerr << "Can't create logging directory directory " << boost::filesystem::path(dir).parent_path().string() << ".\n";
 
				return 1;
 
			}
 

	
 
#ifndef WIN32
 
			if (!CONFIG_STRING(&config, "service.group").empty() && !CONFIG_STRING(&config, "service.user").empty()) {
 
				struct group *gr;
 
				if ((gr = getgrnam(CONFIG_STRING(&config, "service.group").c_str())) == NULL) {
 
					std::cerr << "Invalid service.group name " << CONFIG_STRING(&config, "service.group") << "\n";
 
					return 1;
 
				}
 
				struct passwd *pw;
 
				if ((pw = getpwnam(CONFIG_STRING(&config, "service.user").c_str())) == NULL) {
 
					std::cerr << "Invalid service.user name " << CONFIG_STRING(&config, "service.user") << "\n";
 
					return 1;
 
				}
 
				chown(dir.c_str(), pw->pw_uid, gr->gr_gid);
 
			}
 

	
 
#endif
 
		}
 

	
 
		log4cxx::PropertyConfigurator::configure(p);
 
	}
 

	
 
#ifndef WIN32
 
	if (!CONFIG_STRING(&config, "service.group").empty() ||!CONFIG_STRING(&config, "service.user").empty() ) {
 
		struct rlimit limit;
 
		getrlimit(RLIMIT_CORE, &limit);
 

	
 
		if (!CONFIG_STRING(&config, "service.group").empty()) {
 
			struct group *gr;
 
			if ((gr = getgrnam(CONFIG_STRING(&config, "service.group").c_str())) == NULL) {
 
				LOG4CXX_ERROR(logger, "Invalid service.group name " << CONFIG_STRING(&config, "service.group"));
 
				std::cerr << "Invalid service.group name " << CONFIG_STRING(&config, "service.group") << "\n";
 
				return 1;
 
			}
 

	
 
			if (((setgid(gr->gr_gid)) != 0) || (initgroups(CONFIG_STRING(&config, "service.user").c_str(), gr->gr_gid) != 0)) {
 
				LOG4CXX_ERROR(logger, "Failed to set service.group name " << CONFIG_STRING(&config, "service.group") << " - " << gr->gr_gid << ":" << strerror(errno));
 
				std::cerr << "Failed to set service.group name " << CONFIG_STRING(&config, "service.group") << " - " << gr->gr_gid << ":" << strerror(errno) << "\n";
 
				return 1;
 
			}
 
		}
 

	
 
		if (!CONFIG_STRING(&config, "service.user").empty()) {
 
			struct passwd *pw;
 
			if ((pw = getpwnam(CONFIG_STRING(&config, "service.user").c_str())) == NULL) {
 
				LOG4CXX_ERROR(logger, "Invalid service.user name " << CONFIG_STRING(&config, "service.user"));
 
				std::cerr << "Invalid service.user name " << CONFIG_STRING(&config, "service.user") << "\n";
 
				return 1;
 
			}
 

	
 
			if ((setuid(pw->pw_uid)) != 0) {
 
				LOG4CXX_ERROR(logger, "Failed to set service.user name " << CONFIG_STRING(&config, "service.user") << " - " << pw->pw_uid << ":" << strerror(errno));
 
				std::cerr << "Failed to set service.user name " << CONFIG_STRING(&config, "service.user") << " - " << pw->pw_uid << ":" << strerror(errno) << "\n";
 
				return 1;
 
			}
 
		}
 
		setrlimit(RLIMIT_CORE, &limit);
 
	}
 

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

	
 
	Swift::SimpleEventLoop eventLoop;
 

	
 
	Swift::BoostNetworkFactories *factories = new Swift::BoostNetworkFactories(&eventLoop);
 
	UserRegistry userRegistry(&config, factories);
 
@@ -310,12 +379,14 @@ int main(int argc, char **argv)
 

	
 
	FileTransferManager ftManager(&transport, &userManager);
 

	
 
	NetworkPluginServer plugin(&transport, &config, &userManager, &ftManager);
 

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

	
 
	eventLoop_ = &eventLoop;
 

	
 
	eventLoop.run();
 

	
 
	if (userRegistration) {
spectrum/src/sample.cfg
Show inline comments
 
@@ -2,26 +2,28 @@
 
jid = localhost
 
password = secret
 
server = 127.0.0.1
 
port = 5222
 
server_mode = 1
 
backend_host=localhost
 
pidfile=./test.pid
 
# < this option doesn't work yet
 
backend_port=10001
 
admin_username=admin
 
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=/home/hanzz/code/libtransport/backends/libpurple/spectrum2_libpurple_backend
 
#backend=/home/hanzz/code/libtransport/backends/libpurple/spectrum2_libpurple_backend
 
#backend=/usr/bin/mono /home/hanzz/code/networkplugin-csharp/msnp-sharp-backend/bin/Debug/msnp-sharp-backend.exe
 
#backend=/home/hanzz/code/libtransport/backends/frotz/spectrum2_frotz_backend
 
#backend=/home/hanzz/code/libtransport/backends/libircclient-qt/spectrum2_libircclient-qt_backend
 
backend=/home/hanzz/code/libtransport/backends/libircclient-qt/spectrum2_libircclient-qt_backend
 
#protocol=prpl-msn
 
protocol=any
 
#protocol=prpl-icq
 
irc_server=irc.freenode.org
 

	
 
[backend]
 
#default_avatar=catmelonhead.jpg
 
#no_vcard_fetch=true
 

	
 
[logging]
spectrum/src/sample2.cfg
Show inline comments
 
@@ -33,14 +33,14 @@ backend_port=10001
 
#cert_password= 
 

	
 
# Number of users per one legacy network backend.
 
users_per_backend=10
 

	
 
# Full path to backend binary.
 
backend=/usr/bin/spectrum_libpurple_backend
 
#backend=/usr/bin/spectrum_libircclient-qt_backend
 
backend=/usr/bin/spectrum2_libpurple_backend
 
#backend=/usr/bin/spectrum2_libircclient-qt_backend
 

	
 
# Libpurple protocol-id for spectrum_libpurple_backend
 
protocol=prpl-jabber
 
#protocol=prpl-msn
 
#protocol=prpl-icq
 

	
 
@@ -62,21 +62,22 @@ type=xmpp
 

	
 
[logging]
 
# log4cxx/log4j logging configuration file in ini format used for main spectrum2 instance.
 
config = /etc/spectrum2/logging.cfg
 

	
 
# log4cxx/log4j logging configuration file in ini format used for backends.
 
backend_config = /etc/spectrum2/backend-logging.cfg # log4cxx/log4j logging configuration file for backends
 
backend_config = /etc/spectrum2/backend-logging.cfg
 

	
 
[database]
 
# Database backend type
 
# "sqlite3", "mysql" or "none" without database backend
 
type = none
 

	
 
# For SQLite3: Full path to database
 
# For MySQL: name of database
 
# database = /var/lib/spectrum2/$jid/database.sql
 
database = jabber_transport
 

	
 
# Server.
 
server = localhost
 

	
 
# Port.
spectrum_manager/src/CMakeLists.txt
Show inline comments
 
cmake_minimum_required(VERSION 2.6)
 
FILE(GLOB SRC *.cpp)
 
 
ADD_EXECUTABLE(spectrum2_manager ${SRC})
 
ADD_EXECUTABLE(spectrum2_manager ${SRC} ../../src/config.cpp)
 
 
target_link_libraries(spectrum2_manager transport)
 
target_link_libraries(spectrum2_manager ${SWIFTEN_LIBRARY})
 
 
INSTALL(TARGETS spectrum2_manager RUNTIME DESTINATION bin)
 
 
INSTALL(FILES
 
	spectrum_manager.cfg
 
	DESTINATION /etc/spectrum2
spectrum_manager/src/main.cpp
Show inline comments
 
#include "managerconfig.h"
 
#include "transport/transport.h"
 
#include "transport/usermanager.h"
 
#include "transport/logger.h"
 
#include "transport/sqlite3backend.h"
 
#include "transport/userregistration.h"
 
#include "transport/networkpluginserver.h"
 
#include "transport/config.h"
 
#include "Swiften/Swiften.h"
 
#include "Swiften/EventLoop/SimpleEventLoop.h"
 
 
#include <boost/foreach.hpp>
 
#include <iostream>
 
#include <fstream>
 
#include <iterator>
 
@@ -83,18 +79,23 @@ static std::string searchForBinary(const std::string &binary) {
 
		}
 
	}
 
	return "";
 
}
 
 
// Executes new backend
 
static unsigned long exec_(std::string path, std::string config) {
 
static unsigned long exec_(std::string path, std::string config, std::string jid = "") {
 
	// fork and exec
 
	pid_t pid = fork();
 
	if ( pid == 0 ) {
 
		// child process
 
		if (jid.empty()) {
 
			exit(execl(path.c_str(), path.c_str(), config.c_str(), NULL));
 
		}
 
		else {
 
			exit(execl(path.c_str(), path.c_str(), "-j", jid.c_str(), config.c_str(), NULL));
 
		}
 
	} else if ( pid < 0 ) {
 
		// fork failed
 
	}
 
	else {
 
		waitpid(pid, 0, 0);
 
	}
 
@@ -144,25 +145,40 @@ static void start_all_instances(ManagerConfig *config) {
 
		directory_iterator end_itr;
 
		for (directory_iterator itr(p); itr != end_itr; ++itr) {
 
			if (is_regular(itr->path()) && extension(itr->path()) == ".cfg") {
 
				Config cfg;
 
				if (cfg.load(itr->path().string()) == false) {
 
					std::cerr << "Can't load config file " << itr->path().string() << ". Skipping...\n";
 
					continue;
 
				}
 
 
				
 
				std::vector<std::string> vhosts;
 
				if (CONFIG_HAS_KEY(&cfg, "vhosts.vhost"))
 
					vhosts = CONFIG_VECTOR(&cfg, "vhosts.vhost");
 
				vhosts.push_back(CONFIG_STRING(&cfg, "service.jid"));
 
 
				BOOST_FOREACH(std::string &vhost, vhosts) {
 
					Config vhostCfg;
 
					if (vhostCfg.load(itr->path().string(), vhost) == false) {
 
						std::cerr << "Can't load config file " << itr->path().string() << ". Skipping...\n";
 
						continue;
 
					}
 
 
				int pid = isRunning(CONFIG_STRING(&cfg, "service.pidfile"));
 
					int pid = isRunning(CONFIG_STRING(&vhostCfg, "service.pidfile"));
 
					if (pid == 0) {
 
						std::cout << "Starting " << itr->path() << ": OK\n";
 
					exec_(spectrum2_binary, itr->path().string());
 
						exec_(spectrum2_binary, itr->path().string(), vhost);
 
					}
 
					else {
 
						std::cout << "Starting " << itr->path() << ": Already started (PID=" << pid << ")\n";
 
					}
 
				}
 
			}
 
		}
 
	}
 
	catch (const filesystem_error& ex) {
 
		std::cerr << "boost filesystem error\n";
 
		exit(5);
 
	}
 
}
 
 
@@ -185,23 +201,36 @@ static void stop_all_instances(ManagerConfig *config) {
 
			if (is_regular(itr->path()) && extension(itr->path()) == ".cfg") {
 
				Config cfg;
 
				if (cfg.load(itr->path().string()) == false) {
 
					std::cerr << "Can't load config file " << itr->path().string() << ". Skipping...\n";
 
				}
 
 
				int pid = isRunning(CONFIG_STRING(&cfg, "service.pidfile"));
 
				std::vector<std::string> vhosts;
 
				if (CONFIG_HAS_KEY(&cfg, "vhosts.vhost"))
 
					vhosts = CONFIG_VECTOR(&cfg, "vhosts.vhost");
 
				vhosts.push_back(CONFIG_STRING(&cfg, "service.jid"));
 
 
				BOOST_FOREACH(std::string &vhost, vhosts) {
 
					Config vhostCfg;
 
					if (vhostCfg.load(itr->path().string(), vhost) == false) {
 
						std::cerr << "Can't load config file " << itr->path().string() << ". Skipping...\n";
 
						continue;
 
					}
 
 
					int pid = isRunning(CONFIG_STRING(&vhostCfg, "service.pidfile"));
 
					if (pid) {
 
						std::cout << "Stopping " << itr->path() << ": OK\n";
 
						kill(pid, SIGTERM);
 
					}
 
					else {
 
						std::cout << "Stopping " << itr->path() << ": Not running\n";
 
					}
 
				}
 
			}
 
		}
 
	}
 
	catch (const filesystem_error& ex) {
 
		std::cerr << "boost filesystem error\n";
 
		exit(5);
 
	}
 
}
 
src/CMakeLists.txt
Show inline comments
 
@@ -32,15 +32,15 @@ endif(PROTOBUF_FOUND)
 

	
 
if (CMAKE_COMPILER_IS_GNUCXX)
 
	ADD_DEFINITIONS(-fPIC)
 
endif()
 

	
 
if (WIN32)
 
	TARGET_LINK_LIBRARIES(transport ${Boost_LIBRARIES} ${SQLITE3_LIBRARIES} ${MYSQL_LIBRARIES} ${SWIFTEN_LIBRARY} ${PROTOBUF_LIBRARIES} ${LOG4CXX_LIBRARIES})
 
	TARGET_LINK_LIBRARIES(transport ${SQLITE3_LIBRARIES} ${MYSQL_LIBRARIES} ${SWIFTEN_LIBRARY} ${PROTOBUF_LIBRARIES} ${LOG4CXX_LIBRARIES})
 
else (WIN32)
 
	TARGET_LINK_LIBRARIES(transport ${Boost_LIBRARIES} ${SQLITE3_LIBRARIES} ${MYSQL_LIBRARIES} ${SWIFTEN_LIBRARY} ${PROTOBUF_LIBRARIES} ${LOG4CXX_LIBRARIES} ${POPT_LIBRARY})
 
	TARGET_LINK_LIBRARIES(transport ${SQLITE3_LIBRARIES} ${MYSQL_LIBRARIES} ${SWIFTEN_LIBRARY} ${PROTOBUF_LIBRARIES} ${LOG4CXX_LIBRARIES} ${POPT_LIBRARY})
 
endif(WIN32)
 

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

	
src/admininterface.cpp
Show inline comments
 
@@ -63,12 +63,17 @@ void AdminInterface::handleMessageReceived(Swift::Message::ref message) {
 

	
 
	if (message->getFrom().toBare().toString() != CONFIG_STRING(m_component->getConfig(), "service.admin_jid")) {
 
		LOG4CXX_WARN(logger, "Message not from admin user, but from " << message->getFrom().toBare().toString());
 
		return;
 
	}
 

	
 
	// Ignore empty messages
 
	if (message->getBody().empty()) {
 
		return;
 
	}
 

	
 
	LOG4CXX_INFO(logger, "Message from admin received");
 
	message->setTo(message->getFrom());
 
	message->setFrom(m_component->getJID());
 

	
 
	if (message->getBody() == "status") {
 
		int users = m_userManager->getUserCount();
src/config.cpp
Show inline comments
 
@@ -28,86 +28,147 @@
 
#endif
 

	
 
using namespace boost::program_options;
 

	
 
namespace Transport {
 

	
 
bool Config::load(const std::string &configfile, boost::program_options::options_description &opts) {
 
bool Config::load(const std::string &configfile, boost::program_options::options_description &opts, const std::string &jid) {
 
	std::ifstream ifs(configfile.c_str());
 
	if (!ifs.is_open())
 
		return false;
 

	
 
	m_file = configfile;
 
	bool ret = load(ifs, opts);
 
	bool ret = load(ifs, opts, jid);
 
	ifs.close();
 

	
 
	char path[PATH_MAX] = "";
 
	if (m_file.find_first_of("/") != 0) {
 
		getcwd(path, PATH_MAX);
 
		m_file = std::string(path) + "/" + m_file;
 
	}
 

	
 
	return ret;
 
}
 

	
 
bool Config::load(std::istream &ifs, boost::program_options::options_description &opts) {
 
bool Config::load(std::istream &ifs, boost::program_options::options_description &opts, const std::string &_jid) {
 
	m_unregistered.clear();
 
	opts.add_options()
 
		("service.jid", value<std::string>()->default_value(""), "Transport Jabber ID")
 
		("service.server", value<std::string>()->default_value(""), "Server to connect to")
 
		("service.password", value<std::string>()->default_value(""), "Password used to auth the server")
 
		("service.port", value<int>()->default_value(0), "Port the server is listening on")
 
		("service.user", value<std::string>()->default_value(""), "The name of user Spectrum runs as.")
 
		("service.group", value<std::string>()->default_value(""), "The name of group Spectrum runs as.")
 
		("service.backend", value<std::string>()->default_value("libpurple_backend"), "Backend")
 
		("service.protocol", value<std::string>()->default_value(""), "Protocol")
 
		("service.pidfile", value<std::string>()->default_value("/var/run/spectrum2/spectrum2.pid"), "Full path to pid file")
 
		("service.working_dir", value<std::string>()->default_value("/var/lib/spectrum2"), "Working dir")
 
		("service.pidfile", value<std::string>()->default_value("/var/run/spectrum2/$jid.pid"), "Full path to pid file")
 
		("service.working_dir", value<std::string>()->default_value("/var/lib/spectrum2/$jid"), "Working dir")
 
		("service.allowed_servers", value<std::string>()->default_value(""), "Only users from these servers can connect")
 
		("service.server_mode", value<bool>()->default_value(false), "True if Spectrum should behave as server")
 
		("service.users_per_backend", value<int>()->default_value(100), "Number of users per one legacy network backend")
 
		("service.backend_host", value<std::string>()->default_value("localhost"), "Host to bind backend server to")
 
		("service.backend_port", value<std::string>()->default_value("10000"), "Port to bind backend server to")
 
		("service.backend_port", value<std::string>()->default_value("0"), "Port to bind backend server to")
 
		("service.cert", value<std::string>()->default_value(""), "PKCS#12 Certificate.")
 
		("service.cert_password", value<std::string>()->default_value(""), "PKCS#12 Certificate password.")
 
		("service.admin_jid", value<std::string>()->default_value(""), "Administrator jid.")
 
		("service.admin_password", value<std::string>()->default_value(""), "Administrator password.")
 
		("service.reuse_old_backends", value<bool>()->default_value(true), "True if Spectrum should use old backends which were full in the past.")
 
		("service.idle_reconnect_time", value<int>()->default_value(0), "Time in seconds after which idle users are reconnected to let their backend die.")
 
		("service.memory_collector_time", value<int>()->default_value(0), "Time in seconds after which backend with most memory is set to die.")
 
		("service.more_resources", value<bool>()->default_value(false), "Allow more resources to be connected in server mode at the same time.")
 
		("service.enable_privacy_lists", value<bool>()->default_value(true), "")
 
		("vhosts.vhost", value<std::vector<std::string> >()->multitoken(), "")
 
		("identity.name", value<std::string>()->default_value("Spectrum 2 Transport"), "Name showed in service discovery.")
 
		("identity.category", value<std::string>()->default_value("gateway"), "Disco#info identity category. 'gateway' by default.")
 
		("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(""), "Instructions showed to user in registration form")
 
		("registration.username_field", value<std::string>()->default_value(""), "Label for username field")
 
		("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.encoding", value<std::string>()->default_value("en"), "Default encoding in registration form")
 
		("registration.encoding", value<std::string>()->default_value("utf8"), "Default encoding in registration form")
 
		("database.type", value<std::string>()->default_value("none"), "Database type.")
 
		("database.database", value<std::string>()->default_value(""), "Database used to store data")
 
		("database.server", value<std::string>()->default_value("localhost"), "Database server.")
 
		("database.user", value<std::string>()->default_value(""), "Database user.")
 
		("database.password", value<std::string>()->default_value(""), "Database Password.")
 
		("database.port", value<int>()->default_value(0), "Database port.")
 
		("database.prefix", value<std::string>()->default_value(""), "Prefix of tables in database")
 
		("database.encryption_key", value<std::string>()->default_value(""), "Encryption key.")
 
		("logging.config", value<std::string>()->default_value(""), "Path to log4cxx config file which is used for Spectrum 2 instance")
 
		("logging.backend_config", value<std::string>()->default_value(""), "Path to log4cxx config file which is used for backends")
 
		("backend.default_avatar", value<std::string>()->default_value(""), "Full path to default avatar")
 
		("backend.avatars_directory", value<std::string>()->default_value(""), "Path to directory with avatars")
 
		("backend.no_vcard_fetch", value<bool>()->default_value(false), "True if VCards for buddies should not be fetched. Only avatars will be forwarded.")
 
	;
 

	
 
	parsed_options parsed = parse_config_file(ifs, opts, true);
 

	
 
	BOOST_FOREACH(option opt, parsed.options) {
 
	bool found_working = false;
 
	bool found_pidfile = false;
 
	bool found_backend_port = false;
 
	std::string jid = "";
 
	BOOST_FOREACH(option &opt, parsed.options) {
 
		if (opt.string_key == "service.jid") {
 
			if (_jid.empty()) {
 
				jid = opt.value[0];
 
			}
 
			else {
 
				opt.value[0] = _jid;
 
				jid = _jid;
 
			}
 
		}
 
		else if (opt.string_key == "service.backend_port") {
 
			found_backend_port = true;
 
			if (opt.value[0] == "0") {
 
				unsigned long r = 0;
 
				BOOST_FOREACH(char c, _jid) {
 
					r += (int) c;
 
				}
 
				srand(time(NULL) + r);
 
				int randomPort = 30000 + rand() % 10000;
 
				opt.value[0] = boost::lexical_cast<std::string>(randomPort);
 
			}
 
		}
 
		else if (opt.string_key == "service.working_dir") {
 
			found_working = true;
 
		}
 
		else if (opt.string_key == "service.pidfile") {
 
			found_pidfile = true;
 
		}
 
	}
 

	
 
	if (!found_working) {
 
		std::vector<std::string> value;
 
		value.push_back("/var/lib/spectrum2/$jid");
 
		parsed.options.push_back(boost::program_options::basic_option<char>("service.working_dir", value));
 
	}
 
	if (!found_pidfile) {
 
		std::vector<std::string> value;
 
		value.push_back("/var/run/spectrum2/$jid.pid");
 
		parsed.options.push_back(boost::program_options::basic_option<char>("service.pidfile", value));
 
	}
 
	if (!found_backend_port) {
 
		unsigned long r = 0;
 
		BOOST_FOREACH(char c, _jid) {
 
			r += (int) c;
 
		}
 
		srand(time(NULL) + r);
 
		int randomPort = 30000 + rand() % 10000;
 
		std::vector<std::string> value;
 
		value.push_back(boost::lexical_cast<std::string>(randomPort));
 
		parsed.options.push_back(boost::program_options::basic_option<char>("service.backend_port", value));
 
	}
 

	
 
	BOOST_FOREACH(option &opt, parsed.options) {
 
		if (opt.unregistered) {
 
			m_unregistered[opt.string_key] = opt.value[0];
 
		}
 
		else if (opt.value[0].find("$jid") != std::string::npos) {
 
			boost::replace_all(opt.value[0], "$jid", jid);
 
		}
 
	}
 

	
 
	store(parsed, m_variables);
 
	notify(m_variables);
 

	
 
	onConfigReloaded();
 
@@ -117,15 +178,15 @@ bool Config::load(std::istream &ifs, boost::program_options::options_description
 

	
 
bool Config::load(std::istream &ifs) {
 
	options_description opts("Transport options");
 
	return load(ifs, opts);
 
}
 

	
 
bool Config::load(const std::string &configfile) {
 
bool Config::load(const std::string &configfile, const std::string &jid) {
 
	options_description opts("Transport options");
 
	return load(configfile, opts);
 
	return load(configfile, opts, jid);
 
}
 

	
 
bool Config::reload() {
 
	if (m_file.empty()) {
 
		return false;
 
	}
src/conversation.cpp
Show inline comments
 
@@ -34,12 +34,13 @@ namespace Transport {
 
// static LoggerPtr logger = Logger::getLogger("Conversation");
 

	
 
Conversation::Conversation(ConversationManager *conversationManager, const std::string &legacyName, bool isMUC) : m_conversationManager(conversationManager) {
 
	m_legacyName = legacyName;
 
	m_conversationManager->addConversation(this);
 
	m_muc = isMUC;
 
	m_jid = m_conversationManager->getUser()->getJID().toBare();
 
}
 

	
 
Conversation::~Conversation() {
 
}
 

	
 
void Conversation::setRoom(const std::string &room) {
 
@@ -51,42 +52,47 @@ void Conversation::handleMessage(boost::shared_ptr<Swift::Message> &message, con
 
	if (m_muc) {
 
		message->setType(Swift::Message::Groupchat);
 
	}
 
	else {
 
		message->setType(Swift::Message::Chat);
 
	}
 
	if (message->getType() != Swift::Message::Groupchat) {
 

	
 
		message->setTo(m_conversationManager->getUser()->getJID().toBare());
 
	std::string n = nickname;
 
	if (n.empty() && !m_room.empty() && !m_muc) {
 
		n = m_nickname;
 
	}
 

	
 
	if (message->getType() != Swift::Message::Groupchat) {
 
		message->setTo(m_jid);
 
		// normal message
 
		if (nickname.empty()) {
 
		if (n.empty()) {
 
			Buddy *buddy = m_conversationManager->getUser()->getRosterManager()->getBuddy(m_legacyName);
 
			if (buddy) {
 
				message->setFrom(buddy->getJID());
 
			}
 
			else {
 
				message->setFrom(Swift::JID(Swift::JID::getEscapedNode(m_legacyName), m_conversationManager->getComponent()->getJID().toBare()));
 
			}
 
		}
 
		// PM message
 
		else {
 
			if (m_room.empty()) {
 
				message->setFrom(Swift::JID(nickname, m_conversationManager->getComponent()->getJID().toBare(), "user"));
 
				message->setFrom(Swift::JID(n, m_conversationManager->getComponent()->getJID().toBare(), "user"));
 
			}
 
			else {
 
				message->setFrom(Swift::JID(m_room, m_conversationManager->getComponent()->getJID().toBare(), nickname));
 
				message->setFrom(Swift::JID(m_room, m_conversationManager->getComponent()->getJID().toBare(), n));
 
			}
 
		}
 
		m_conversationManager->getComponent()->getStanzaChannel()->sendMessage(message);
 
	}
 
	else {
 
		std::string legacyName = m_legacyName;
 
		if (legacyName.find_last_of("@") != std::string::npos) {
 
			legacyName.replace(legacyName.find_last_of("@"), 1, "%"); // OK
 
		}
 
		message->setTo(m_conversationManager->getUser()->getJID().toString());
 
		message->setTo(m_jid);
 
		message->setFrom(Swift::JID(legacyName, m_conversationManager->getComponent()->getJID().toBare(), nickname));
 
		m_conversationManager->getComponent()->getStanzaChannel()->sendMessage(message);
 
	}
 
}
 

	
 
void Conversation::handleParticipantChanged(const std::string &nick, int flag, int status, const std::string &statusMessage, const std::string &newname) {
 
@@ -96,13 +102,13 @@ void Conversation::handleParticipantChanged(const std::string &nick, int flag, i
 
	if (m_muc) {
 
		if (legacyName.find_last_of("@") != std::string::npos) {
 
			legacyName.replace(legacyName.find_last_of("@"), 1, "%"); // OK
 
		}
 
	}
 
	presence->setFrom(Swift::JID(legacyName, m_conversationManager->getComponent()->getJID().toBare(), nickname));
 
	presence->setTo(m_conversationManager->getUser()->getJID().toString());
 
	presence->setTo(m_jid);
 
	presence->setType(Swift::Presence::Available);
 

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

	
 
	Swift::StatusShow s((Swift::StatusShow::Type) status);
src/conversationmanager.cpp
Show inline comments
 
@@ -59,12 +59,21 @@ void ConversationManager::removeConversation(Conversation *conv) {
 
			(*it).second->setRoom("");
 
		}
 
	}
 
	m_convs.erase(conv->getLegacyName());
 
}
 

	
 
void ConversationManager::resetResources() {
 
	for (std::map<std::string, Conversation *>::const_iterator it = m_convs.begin(); it != m_convs.end(); it++) {
 
		if ((*it).second->isMUC()) {
 
			continue;
 
		}
 
		(*it).second->setJID(m_user->getJID().toBare());
 
	}
 
}
 

	
 
void ConversationManager::handleMessageReceived(Swift::Message::ref message) {
 
// 	std::string name = message->getTo().getUnescapedNode();
 
// 	if (name.find_last_of("%") != std::string::npos) { // OK when commented
 
// 		name.replace(name.find_last_of("%"), 1, "@"); // OK when commented
 
// 	}
 
	std::string name = Buddy::JIDToLegacyName(message->getTo());
 
@@ -81,13 +90,16 @@ void ConversationManager::handleMessageReceived(Swift::Message::ref message) {
 
	else if (m_convs[name]->isMUC() && message->getType() != Swift::Message::Groupchat) {
 
		std::string room_name = name;
 
		name = message->getTo().getResource();
 
		if (!m_convs[name]) {
 
			m_convs[name] = m_component->getFactory()->createConversation(this, name);
 
			m_convs[name]->setRoom(room_name);
 
			m_convs[name]->setNickname(name);
 
		}
 
	}
 

	
 
	// update resource and send the message
 
	m_convs[name]->setJID(message->getFrom());
 
	m_convs[name]->sendMessage(message);
 
}
 

	
 
}
src/mysqlbackend.cpp
Show inline comments
 
@@ -18,12 +18,13 @@
 
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
 
 */
 

	
 
#ifdef WITH_MYSQL
 

	
 
#include "transport/mysqlbackend.h"
 
#include "transport/util.h"
 
#include <boost/bind.hpp>
 
#include "log4cxx/logger.h"
 

	
 
using namespace log4cxx;
 

	
 
#define MYSQL_DB_VERSION 2
 
@@ -406,13 +407,17 @@ bool MySQLBackend::exec(const std::string &query) {
 
		return false;
 
	}
 
	return true;
 
}
 

	
 
void MySQLBackend::setUser(const UserInfo &user) {
 
	*m_setUser << user.jid << user.uin << user.password << user.language << user.encoding << user.vip << user.password;
 
	std::string encrypted = user.password;
 
	if (!CONFIG_STRING(m_config, "database.encryption_key").empty()) {
 
		encrypted = Util::encryptPassword(encrypted, CONFIG_STRING(m_config, "database.encryption_key"));
 
	}
 
	*m_setUser << user.jid << user.uin << encrypted << user.language << user.encoding << user.vip << user.password;
 
	EXEC(m_setUser, setUser(user));
 
}
 

	
 
bool MySQLBackend::getUser(const std::string &barejid, UserInfo &user) {
 
	*m_getUser << barejid;
 
	EXEC(m_getUser, getUser(barejid, user));
 
@@ -420,12 +425,16 @@ bool MySQLBackend::getUser(const std::string &barejid, UserInfo &user) {
 
		return false;
 

	
 
	int ret = false;
 
	while (m_getUser->fetch() == 0) {
 
		ret = true;
 
		*m_getUser >> user.id >> user.jid >> user.uin >> user.password >> user.encoding >> user.language >> user.vip;
 

	
 
		if (!CONFIG_STRING(m_config, "database.encryption_key").empty()) {
 
			user.password = Util::decryptPassword(user.password, CONFIG_STRING(m_config, "database.encryption_key"));
 
		}
 
	}
 

	
 
	return ret;
 
}
 

	
 
void MySQLBackend::setUserOnline(long id, bool online) {
src/networkpluginserver.cpp
Show inline comments
 
@@ -254,12 +254,23 @@ NetworkPluginServer::NetworkPluginServer(Component *component, Config *config, U
 
#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());
 
}
 

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

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

	
 
	m_pingTimer->stop();
 
	m_server->stop();
 
	m_server.reset();
 
	delete m_component->m_factory;
 
	delete m_vcardResponder;
 
	delete m_rosterResponder;
 
@@ -921,13 +932,13 @@ void NetworkPluginServer::handleUserCreated(User *user) {
 
	user->setData(c);
 
	c->users.push_back(user);
 

	
 
// 	UserInfo userInfo = user->getUserInfo();
 
	user->onReadyToConnect.connect(boost::bind(&NetworkPluginServer::handleUserReadyToConnect, this, user));
 
	user->onPresenceChanged.connect(boost::bind(&NetworkPluginServer::handleUserPresenceChanged, this, user, _1));
 
	user->onRoomJoined.connect(boost::bind(&NetworkPluginServer::handleRoomJoined, this, user, _1, _2, _3));
 
	user->onRoomJoined.connect(boost::bind(&NetworkPluginServer::handleRoomJoined, this, user, _1, _2, _3, _4));
 
	user->onRoomLeft.connect(boost::bind(&NetworkPluginServer::handleRoomLeft, this, user, _1));
 
}
 

	
 
void NetworkPluginServer::handleUserReadyToConnect(User *user) {
 
	UserInfo userInfo = user->getUserInfo();
 

	
 
@@ -977,13 +988,13 @@ void NetworkPluginServer::handleUserPresenceChanged(User *user, Swift::Presence:
 
	if (!c) {
 
		return;
 
	}
 
	send(c->connection, message);
 
}
 

	
 
void NetworkPluginServer::handleRoomJoined(User *user, const std::string &r, const std::string &nickname, const std::string &password) {
 
void NetworkPluginServer::handleRoomJoined(User *user, const Swift::JID &who, const std::string &r, const std::string &nickname, const std::string &password) {
 
	UserInfo userInfo = user->getUserInfo();
 

	
 
	pbnetwork::Room room;
 
	room.set_username(user->getJID().toBare());
 
	room.set_nickname(nickname);
 
	room.set_room(r);
 
@@ -1000,12 +1011,13 @@ void NetworkPluginServer::handleRoomJoined(User *user, const std::string &r, con
 
	}
 
	send(c->connection, message);
 

	
 
	NetworkConversation *conv = new NetworkConversation(user->getConversationManager(), r, true);
 
	conv->onMessageToSend.connect(boost::bind(&NetworkPluginServer::handleMessageReceived, this, _1, _2));
 
	conv->setNickname(nickname);
 
	conv->setJID(who);
 
}
 

	
 
void NetworkPluginServer::handleRoomLeft(User *user, const std::string &r) {
 
	UserInfo userInfo = user->getUserInfo();
 

	
 
	pbnetwork::Room room;
 
@@ -1033,13 +1045,12 @@ void NetworkPluginServer::handleRoomLeft(User *user, const std::string &r) {
 
	user->getConversationManager()->removeConversation(conv);
 

	
 
	delete conv;
 
}
 

	
 
void NetworkPluginServer::handleUserDestroyed(User *user) {
 
	std::cout << "HANDLE_DESTROYED\n";
 
	m_waitingUsers.remove(user);
 
	UserInfo userInfo = user->getUserInfo();
 

	
 
	pbnetwork::Logout logout;
 
	logout.set_user(user->getJID().toBare());
 
	logout.set_legacyname(userInfo.uin);
src/rostermanager.cpp
Show inline comments
 
@@ -49,27 +49,32 @@ RosterManager::RosterManager(User *user, Component *component){
 
	m_RIETimer = m_component->getNetworkFactories()->getTimerFactory()->createTimer(5000);
 
	m_RIETimer->onTick.connect(boost::bind(&RosterManager::sendRIE, this));
 

	
 
	m_supportRemoteRoster = false;
 

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

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

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

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

	
 
	for (std::map<std::string, Buddy *, std::less<std::string>, boost::pool_allocator< std::pair<std::string, Buddy *> > >::iterator it = m_buddies.begin(); it != m_buddies.end(); it++) {
 
		Buddy *buddy = (*it).second;
 
		if (!buddy) {
 
			continue;
 
		}
 
		delete buddy;
 
@@ -133,27 +138,22 @@ void RosterManager::handleBuddyChanged(Buddy *buddy) {
 
	if (m_rosterStorage) {
 
		m_rosterStorage->storeBuddy(buddy);
 
	}
 
}
 

	
 
void RosterManager::setBuddyCallback(Buddy *buddy) {
 
	m_setBuddyTimer->onTick.disconnect(boost::bind(&RosterManager::setBuddyCallback, this, buddy));
 

	
 
	LOG4CXX_INFO(logger, "Associating buddy " << buddy->getName() << " with " << m_user->getJID().toString());
 
	m_buddies[buddy->getName()] = buddy;
 
	onBuddySet(buddy);
 

	
 
	// In server mode the only way is to send jabber:iq:roster push.
 
	// In component mode we send RIE or Subscribe presences, based on features.
 
	if (m_component->inServerMode()) {
 
		sendBuddyRosterPush(buddy);
 
	}
 
	else {
 
		if (m_setBuddyTimer->onTick.empty()) {
 
			m_setBuddyTimer->stop();
 

	
 
		if (m_supportRemoteRoster) {
 
			sendBuddyRosterPush(buddy);
 
		}
 
		else {
 
			// Send RIE only if there's resource which supports it.
 
			Swift::JID jidWithRIE = m_user->getJIDWithFeature("http://jabber.org/protocol/rosterx");
 
@@ -162,13 +162,12 @@ void RosterManager::setBuddyCallback(Buddy *buddy) {
 
			}
 
			else {
 
				sendBuddySubscribePresence(buddy);
 
			}
 
		}
 
	}
 
	}
 

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

	
 
void RosterManager::unsetBuddy(Buddy *buddy) {
 
@@ -195,12 +194,13 @@ void RosterManager::handleBuddyRosterPushResponse(Swift::ErrorPayload::ref error
 

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

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

	
src/statsresponder.cpp
Show inline comments
 
new file 100644
 
/**
 
 * XMPP - libpurple transport
 
 *
 
 * Copyright (C) 2009, Jan Kaluza <hanzz@soc.pidgin.im>
 
 *
 
 * This program is free software; you can redistribute it and/or modify
 
 * it under the terms of the GNU General Public License as published by
 
 * the Free Software Foundation; either version 2 of the License, or
 
 * (at your option) any later version.
 
 *
 
 * This program is distributed in the hope that it will be useful,
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
 * GNU General Public License for more details.
 
 *
 
 * You should have received a copy of the GNU General Public License
 
 * along with this program; if not, write to the Free Software
 
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
 
 */
 

	
 
#include "transport/statsresponder.h"
 

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

	
 
using namespace log4cxx;
 

	
 
using namespace Swift;
 
using namespace boost;
 

	
 
namespace Transport {
 

	
 
static LoggerPtr logger = Logger::getLogger("StatsResponder");
 

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

	
 
StatsResponder::~StatsResponder() {
 
	
 
}
 

	
 
unsigned long StatsResponder::usedMemory() {
 
	double shared = 0;
 
	double rss = 0;
 
#ifndef WIN32
 
	process_mem_usage(shared, rss);
 
#endif
 
	rss -= shared;
 

	
 
	const std::list <NetworkPluginServer::Backend *> &backends = m_server->getBackends();
 
	BOOST_FOREACH(NetworkPluginServer::Backend * backend, backends) {
 
		rss += backend->res - backend->shared;
 
	}
 

	
 
	return (unsigned long) rss;
 
}
 

	
 
bool StatsResponder::handleGetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr<StatsPayload> stats) {
 
	boost::shared_ptr<StatsPayload> response(new StatsPayload());
 

	
 
	if (stats->getItems().empty()) {
 
		response->addItem(StatsPayload::Item("uptime"));
 
		response->addItem(StatsPayload::Item("users/online"));
 
		response->addItem(StatsPayload::Item("contacts/online"));
 
		response->addItem(StatsPayload::Item("contacts/total"));
 
		response->addItem(StatsPayload::Item("backends"));
 
		response->addItem(StatsPayload::Item("memory-usage"));
 
	}
 
	else {
 
		unsigned long contactsOnline = 0;
 
		unsigned long contactsTotal = 0;
 

	
 
		Swift::StatusShow s;
 
		std::string statusMessage;
 
		for (std::map<std::string, User *>::const_iterator it = m_userManager->getUsers().begin(); it != m_userManager->getUsers().end(); it++) {
 
			if (!(*it).second) {
 
				continue;
 
			}
 
			const RosterManager::BuddiesMap &buddies = (*it).second->getRosterManager()->getBuddies();
 
			contactsTotal += buddies.size();
 
			for(RosterManager::BuddiesMap::const_iterator bt = buddies.begin(); bt != buddies.end(); bt++) {
 
				if (!(*bt).second) {
 
					continue;
 
				}
 
				if (!(*bt).second->getStatus(s, statusMessage))
 
					continue;
 
				if (s.getType() != Swift::StatusShow::None) {
 
					contactsOnline++;
 
				}
 
			}
 
		}
 

	
 
		BOOST_FOREACH(const StatsPayload::Item &item, stats->getItems()) {
 
			if (item.getName() == "uptime") {
 
				response->addItem(StatsPayload::Item("uptime", "seconds", boost::lexical_cast<std::string>(time(0) - m_start)));
 
			}
 
			else if (item.getName() == "users/online") {
 
				response->addItem(StatsPayload::Item("users/online", "users", boost::lexical_cast<std::string>(m_userManager->getUserCount())));
 
			}
 
			else if (item.getName() == "backends") {
 
				response->addItem(StatsPayload::Item("backends", "backends", boost::lexical_cast<std::string>(m_server->getBackendCount())));
 
			}
 
			else if (item.getName() == "memory-usage") {
 
				response->addItem(StatsPayload::Item("memory-usage", "KB", boost::lexical_cast<std::string>(usedMemory())));
 
			}
 
			else if (item.getName() == "contacts/online") {
 
				response->addItem(StatsPayload::Item("contacts/online", "contacts", boost::lexical_cast<std::string>(contactsOnline)));
 
			}
 
			else if (item.getName() == "contacts/total") {
 
				response->addItem(StatsPayload::Item("contacts/total", "contacts", boost::lexical_cast<std::string>(contactsTotal)));
 
			}
 
		}
 
	}
 

	
 
	sendResponse(from, id, response);
 

	
 
	return true;
 
}
 

	
 
bool StatsResponder::handleSetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr<StatsPayload> stats) {
 
	return false;
 
}
 

	
 
}
src/tests/rostermanager.cpp
Show inline comments
 
@@ -21,12 +21,13 @@
 
using namespace Transport;
 

	
 
class RosterManagerTest : public CPPUNIT_NS :: TestFixture, public BasicTest {
 
	CPPUNIT_TEST_SUITE(RosterManagerTest);
 
	CPPUNIT_TEST(setBuddy);
 
	CPPUNIT_TEST(sendCurrentPresences);
 
	CPPUNIT_TEST(sendCurrentPresence);
 
	CPPUNIT_TEST_SUITE_END();
 

	
 
	public:
 
		void setUp (void) {
 
			setMeUp();
 
			userManager->onUserCreated.connect(boost::bind(&RosterManagerTest::handleUserCreated, this, _1));
 
@@ -129,19 +130,38 @@ class RosterManagerTest : public CPPUNIT_NS :: TestFixture, public BasicTest {
 
		received.clear();
 

	
 
		User *user = userManager->getUser("user@localhost");
 
		user->getRosterManager()->sendCurrentPresences("user@localhost/resource");
 

	
 
		CPPUNIT_ASSERT_EQUAL(2, (int) received.size());
 
// 		CPPUNIT_ASSERT(dynamic_cast<Swift::Presence *>(getStanza(received[2])));
 
// 		CPPUNIT_ASSERT_EQUAL(Swift::StatusShow::Away, dynamic_cast<Swift::Presence *>(getStanza(received[2]))->getShow());
 
// 		CPPUNIT_ASSERT_EQUAL(std::string("status1"), dynamic_cast<Swift::Presence *>(getStanza(received[2]))->getStatus());
 
// 
 
// 		CPPUNIT_ASSERT(dynamic_cast<Swift::Presence *>(getStanza(received[3])));
 
// 		CPPUNIT_ASSERT_EQUAL(Swift::StatusShow::Away, dynamic_cast<Swift::Presence *>(getStanza(received[3]))->getShow());
 
// 		CPPUNIT_ASSERT_EQUAL(std::string("status2"), dynamic_cast<Swift::Presence *>(getStanza(received[3]))->getStatus());
 

	
 
		for (int i = 0; i < 2; i++) {
 
			CPPUNIT_ASSERT(dynamic_cast<Swift::Presence *>(getStanza(received[i])));
 
			CPPUNIT_ASSERT_EQUAL(Swift::StatusShow::Away, dynamic_cast<Swift::Presence *>(getStanza(received[i]))->getShow());
 
			CPPUNIT_ASSERT_EQUAL(std::string("user@localhost/resource"), dynamic_cast<Swift::Presence *>(getStanza(received[i]))->getTo().toString());
 
		}
 
	}
 

	
 
	void sendCurrentPresence() {
 
		setBuddy();
 
		received.clear();
 

	
 
		User *user = userManager->getUser("user@localhost");
 
		user->getRosterManager()->sendCurrentPresence("buddy1@localhost", "user@localhost/resource");
 

	
 
		CPPUNIT_ASSERT_EQUAL(1, (int) received.size());
 
		CPPUNIT_ASSERT(dynamic_cast<Swift::Presence *>(getStanza(received[0])));
 
		CPPUNIT_ASSERT_EQUAL(Swift::StatusShow::Away, dynamic_cast<Swift::Presence *>(getStanza(received[0]))->getShow());
 
		CPPUNIT_ASSERT_EQUAL(std::string("user@localhost/resource"), dynamic_cast<Swift::Presence *>(getStanza(received[0]))->getTo().toString());
 

	
 
		received.clear();
 
		user->getRosterManager()->sendCurrentPresence("buddy_unknown@localhost", "user@localhost/resource");
 
		CPPUNIT_ASSERT_EQUAL(1, (int) received.size());
 
		CPPUNIT_ASSERT(dynamic_cast<Swift::Presence *>(getStanza(received[0])));
 
		CPPUNIT_ASSERT_EQUAL(Swift::Presence::Unavailable, dynamic_cast<Swift::Presence *>(getStanza(received[0]))->getType());
 
		CPPUNIT_ASSERT_EQUAL(std::string("user@localhost/resource"), dynamic_cast<Swift::Presence *>(getStanza(received[0]))->getTo().toString());
 
	}
 

	
 
	void disconnectUser() {
 
		userManager->disconnectUser("user@localhost");
 
		dynamic_cast<Swift::DummyTimerFactory *>(factories->getTimerFactory())->setTime(10);
 
		loop->processEvents();
src/tests/util.cpp
Show inline comments
 
new file 100644
 
#include "transport/userregistry.h"
 
#include "transport/config.h"
 
#include "transport/storagebackend.h"
 
#include "transport/user.h"
 
#include "transport/transport.h"
 
#include "transport/conversation.h"
 
#include "transport/usermanager.h"
 
#include "transport/localbuddy.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"
 

	
 
#include "transport/util.h"
 

	
 
using namespace Transport;
 

	
 
class UtilTest : public CPPUNIT_NS :: TestFixture{
 
	CPPUNIT_TEST_SUITE(UtilTest);
 
	CPPUNIT_TEST(encryptDecryptPassword);
 
	CPPUNIT_TEST_SUITE_END();
 

	
 
	public:
 
		void setUp (void) {
 
		}
 

	
 
		void tearDown (void) {
 

	
 
		}
 

	
 
	void encryptDecryptPassword() {
 
		std::string encrypted = Util::encryptPassword("password", "key");
 
		CPPUNIT_ASSERT_EQUAL(std::string("password"), Util::decryptPassword(encrypted, "key"));
 
	}
 

	
 
};
 

	
 
CPPUNIT_TEST_SUITE_REGISTRATION (UtilTest);
src/transport.cpp
Show inline comments
 
@@ -31,12 +31,14 @@
 
#include "Swiften/TLS/PKCS12Certificate.h"
 
#include "Swiften/TLS/OpenSSL/OpenSSLServerContextFactory.h"
 
#include "Swiften/Parser/PayloadParsers/AttentionParser.h"
 
#include "Swiften/Serializer/PayloadSerializers/AttentionSerializer.h"
 
#include "Swiften/Parser/PayloadParsers/XHTMLIMParser.h"
 
#include "Swiften/Serializer/PayloadSerializers/XHTMLIMSerializer.h"
 
#include "Swiften/Parser/PayloadParsers/StatsParser.h"
 
#include "Swiften/Serializer/PayloadSerializers/StatsSerializer.h"
 
#include "transport/BlockParser.h"
 
#include "transport/BlockSerializer.h"
 
#include "Swiften/Parser/PayloadParsers/InvisibleParser.h"
 
#include "Swiften/Serializer/PayloadSerializers/InvisibleSerializer.h"
 
#include "log4cxx/logger.h"
 
#include "log4cxx/consoleappender.h"
 
@@ -87,17 +89,19 @@ Component::Component(Swift::EventLoop *loop, Swift::NetworkFactories *factories,
 

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

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

	
 
		m_server->onDataRead.connect(boost::bind(&Component::handleDataRead, this, _1));
 
		m_server->onDataWritten.connect(boost::bind(&Component::handleDataWritten, this, _1));
 
	}
 
	else {
 
		LOG4CXX_INFO(logger, "Creating component in gateway mode");
 
@@ -110,17 +114,19 @@ Component::Component(Swift::EventLoop *loop, Swift::NetworkFactories *factories,
 

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

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

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

	
 
	m_capsMemoryStorage = new CapsMemoryStorage();
src/user.cpp
Show inline comments
 
@@ -40,23 +40,24 @@ using namespace boost;
 

	
 
namespace Transport {
 

	
 
static LoggerPtr logger = Logger::getLogger("User");
 

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

	
 
	m_component = component;
 
	m_presenceOracle = component->m_presenceOracle;
 
	m_entityCapsManager = component->m_entityCapsManager;
 
	m_userManager = userManager;
 
	m_userInfo = userInfo;
 
	m_connected = false;
 
	m_readyForConnect = false;
 
	m_ignoreDisconnect = false;
 
	m_resources = 0;
 

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

	
 
	m_rosterManager = new RosterManager(this, m_component);
 
	m_conversationManager = new ConversationManager(this, m_component);
 
@@ -93,12 +94,16 @@ Swift::JID User::getJIDWithFeature(const std::string &feature) {
 
			if (m_legacyCaps.find(presence->getFrom()) != m_legacyCaps.end()) {
 
				discoInfo = m_legacyCaps[presence->getFrom()];
 
			}
 
			else {
 
				continue;
 
			}
 

	
 
			if (!discoInfo) {
 
				continue;
 
			}
 
#else
 
			continue;
 
#endif
 
		}
 

	
 
		if (discoInfo->hasFeature(feature)) {
 
@@ -126,47 +131,58 @@ Swift::DiscoInfo::ref User::getCaps(const Swift::JID &jid) const {
 

	
 
void User::sendCurrentPresence() {
 
	if (m_component->inServerMode()) {
 
		return;
 
	}
 

	
 
	std::vector<Swift::Presence::ref> presences = m_presenceOracle->getAllPresence(m_jid);
 
	foreach(Swift::Presence::ref presence, presences) {
 
		if (presence->getType() == Swift::Presence::Unavailable) {
 
			continue;
 
		}
 

	
 
		if (m_connected) {
 
			Swift::Presence::ref highest = m_presenceOracle->getHighestPriorityPresence(m_jid.toBare());
 
			if (highest) {
 
				Swift::Presence::ref response = Swift::Presence::create(highest);
 
			response->setTo(m_jid);
 
				response->setTo(presence->getFrom());
 
				response->setFrom(m_component->getJID());
 
				m_component->getStanzaChannel()->sendPresence(response);
 
			}
 
			else {
 
				Swift::Presence::ref response = Swift::Presence::create();
 
			response->setTo(m_jid.toBare());
 
				response->setTo(presence->getFrom());
 
				response->setFrom(m_component->getJID());
 
				response->setType(Swift::Presence::Unavailable);
 
				m_component->getStanzaChannel()->sendPresence(response);
 
			}
 
		}
 
		else {
 
			Swift::Presence::ref response = Swift::Presence::create();
 
		response->setTo(m_jid.toBare());
 
			response->setTo(presence->getFrom());
 
			response->setFrom(m_component->getJID());
 
			response->setType(Swift::Presence::Unavailable);
 
			response->setStatus("Connecting");
 
			m_component->getStanzaChannel()->sendPresence(response);
 
		}
 
	}
 
}
 

	
 
void User::setConnected(bool connected) {
 
	m_connected = connected;
 
	setIgnoreDisconnect(false);
 
	updateLastActivity();
 

	
 
	sendCurrentPresence();
 
}
 

	
 
void User::handlePresence(Swift::Presence::ref presence) {
 
	int currentResourcesCount = m_presenceOracle->getAllPresence(m_jid).size();
 

	
 
	m_conversationManager->resetResources();
 

	
 
	if (!m_connected) {
 
		// we are not connected to legacy network, so we should do it when disco#info arrive :)
 
		if (m_readyForConnect == false) {
 
			
 
			// Forward status message to legacy network, but only if it's sent from active resource
 
// 					if (m_activeResource == presence->getFrom().getResource().getUTF8String()) {
 
@@ -207,18 +223,41 @@ void User::handlePresence(Swift::Presence::ref presence) {
 
			LOG4CXX_INFO(logger, m_jid.toString() << ": Going to join room " << presence->getTo().getNode() << " as " << presence->getTo().getResource());
 
			std::string room = Buddy::JIDToLegacyName(presence->getTo());
 
			std::string password = "";
 
			if (presence->getPayload<Swift::MUCPayload>() != NULL) {
 
				password = presence->getPayload<Swift::MUCPayload>()->getPassword() ? *presence->getPayload<Swift::MUCPayload>()->getPassword() : "";
 
			}
 
			onRoomJoined(room, presence->getTo().getResource(), password);
 
			onRoomJoined(presence->getFrom(), room, presence->getTo().getResource(), password);
 
		}
 
		return;
 
	}
 

	
 

	
 
	// User wants to disconnect this resource
 
	if (!m_component->inServerMode()) {
 
		if (presence->getType() == Swift::Presence::Unavailable) {
 
				// Send unavailable presences for online contacts
 
				m_rosterManager->sendUnavailablePresences(presence->getFrom());
 

	
 
				// Send unavailable presence for transport contact itself
 
				Swift::Presence::ref response = Swift::Presence::create();
 
				response->setTo(presence->getFrom());
 
				response->setFrom(m_component->getJID());
 
				response->setType(Swift::Presence::Unavailable);
 
				m_component->getStanzaChannel()->sendPresence(response);
 
		}
 
		else {
 
			sendCurrentPresence();
 
			// This resource is new, so we have to send buddies presences
 
			if (currentResourcesCount != m_resources) {
 
				m_rosterManager->sendCurrentPresences(presence->getFrom());
 
			}
 
		}
 
	}
 

	
 
	m_resources = currentResourcesCount;
 

	
 

	
 
	// Change legacy network presence
 
	if (m_readyForConnect) {
 
		Swift::Presence::ref highest = m_presenceOracle->getHighestPriorityPresence(m_jid.toBare());
 
		if (highest) {
src/usermanager.cpp
Show inline comments
 
@@ -146,13 +146,13 @@ void UserManager::handlePresence(Swift::Presence::ref presence) {
 
	std::string userkey = presence->getFrom().toBare().toString();
 

	
 
	User *user = getUser(userkey);
 
	// Create user class if it's not there
 
	if (!user) {
 
		// Admin user is not legacy network user, so do not create User class instance for him
 
		if (CONFIG_STRING(m_component->getConfig(), "service.admin_username") == presence->getFrom().getNode()) {
 
		if (m_component->inServerMode() && CONFIG_STRING(m_component->getConfig(), "service.admin_jid") == presence->getFrom().toBare().toString()) {
 
			return;
 
		}
 

	
 
		// No user and unavailable presence -> answer with unavailable
 
		if (presence->getType() == Swift::Presence::Unavailable) {
 
			Swift::Presence::ref response = Swift::Presence::create();
 
@@ -316,12 +316,17 @@ void UserManager::handleSubscription(Swift::Presence::ref presence) {
 
// 		response->setTo(presence->getFrom());
 
// 		response->setType(Swift::Presence::Subscribe);
 
// 		m_component->getStanzaChannel()->sendPresence(response);
 
		return;
 
	}
 

	
 
	// Don't let RosterManager to handle presences for us
 
	if (presence->getTo().getNode().empty()) {
 
		return;
 
	}
 

	
 
	User *user = getUser(presence->getFrom().toBare().toString());
 

	
 
 	if (user) {
 
 		user->handleSubscription(presence);
 
 	}
 
 	else if (presence->getType() == Swift::Presence::Unsubscribe) {
src/userregistration.cpp
Show inline comments
 
@@ -178,13 +178,13 @@ bool UserRegistration::handleGetRequest(const Swift::JID& from, const Swift::JID
 
	boost::shared_ptr<InBandRegistrationPayload> reg(new InBandRegistrationPayload());
 

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

	
 
	std::string instructions = CONFIG_STRING(m_config, "registration.instructions");
 
	std::string usernameField = CONFIG_STRING(m_config, "registration.username_field");
 
	std::string usernameField = CONFIG_STRING(m_config, "registration.username_label");
 

	
 
	// normal jabber:iq:register
 
	reg->setInstructions(instructions);
 
	reg->setRegistered(registered);
 
	reg->setUsername(res.uin);
 
	if (CONFIG_STRING(m_config, "service.protocol") != "twitter" && CONFIG_STRING(m_config, "service.protocol") != "bonjour")
 
@@ -216,26 +216,27 @@ bool UserRegistration::handleGetRequest(const Swift::JID& from, const Swift::JID
 
		form->addField(password);
 
	}
 

	
 
	ListSingleFormField::ref language = ListSingleFormField::create();
 
	language->setName("language");
 
	language->setLabel((("Language")));
 
	language->addOption(Swift::FormField::Option(CONFIG_STRING(m_config, "registration.language"), CONFIG_STRING(m_config, "registration.language")));
 
	if (registered)
 
		language->setValue(res.language);
 
	else
 
		language->setValue(CONFIG_STRING(m_config, "registration.language"));
 
	form->addField(language);
 

	
 
	TextSingleFormField::ref encoding = TextSingleFormField::create();
 
	encoding->setName("encoding");
 
	encoding->setLabel((("Encoding")));
 
	if (registered)
 
		encoding->setValue(res.encoding);
 
	else
 
		encoding->setValue(CONFIG_STRING(m_config, "registration.encoding"));
 
	form->addField(encoding);
 
//	TextSingleFormField::ref encoding = TextSingleFormField::create();
 
//	encoding->setName("encoding");
 
//	encoding->setLabel((("Encoding")));
 
//	if (registered)
 
//		encoding->setValue(res.encoding);
 
//	else
 
//		encoding->setValue(CONFIG_STRING(m_config, "registration.encoding"));
 
//	form->addField(encoding);
 

	
 
	if (registered) {
 
		BooleanFormField::ref boolean = BooleanFormField::create();
 
		boolean->setName("unregister");
 
		boolean->setLabel((("Remove your registration")));
 
		boolean->setValue(0);
 
@@ -325,16 +326,13 @@ bool UserRegistration::handleSetRequest(const Swift::JID& from, const Swift::JID
 
	if (!payload->getUsername() || !payload->getPassword()) {
 
		sendError(from, id, ErrorPayload::NotAcceptable, ErrorPayload::Modify);
 
		return true;
 
	}
 

	
 
	// Register or change password
 
	if (payload->getUsername()->empty() ||
 
		(payload->getPassword()->empty() && CONFIG_STRING(m_config, "service.protocol") != "twitter" && CONFIG_STRING(m_config, "service.protocol") != "bonjour")
 
	)
 
	{
 
	if (payload->getUsername()->empty()) {
 
		sendError(from, id, ErrorPayload::NotAcceptable, ErrorPayload::Modify);
 
		return true;
 
	}
 

	
 
	// TODO: Move this check to backend somehow
 
	if (CONFIG_STRING(m_config, "service.protocol") == "prpl-jabber") {
src/util.cpp
Show inline comments
 
@@ -72,9 +72,37 @@ void removeEverythingOlderThan(const std::vector<std::string> &dirs, time_t t) {
 
		catch (const filesystem_error& ex) {
 
			
 
		}
 
	}
 
}
 

	
 
std::string encryptPassword(const std::string &password, const std::string &key) {
 
	std::string encrypted;
 
	encrypted.resize(password.size());
 
	for (int i = 0; i < password.size(); i++) {
 
		char c = password[i];
 
		char keychar = key[i % key.size()];
 
		c += keychar;
 
		encrypted[i] = c;
 
	}
 

	
 
	encrypted = Swift::Base64::encode(Swift::createByteArray(encrypted));
 
	return encrypted;
 
}
 

	
 
std::string decryptPassword(std::string &encrypted, const std::string &key) {
 
	encrypted = Swift::byteArrayToString(Swift::Base64::decode(encrypted));
 
	std::string password;
 
	password.resize(encrypted.size());
 
	for (int i = 0; i < encrypted.size(); i++) {
 
		char c = encrypted[i];
 
		char keychar = key[i % key.size()];
 
		c -= keychar;
 
		password[i] = c;
 
	}
 

	
 
	return password;
 
}
 

	
 
}
 

	
 
}
tests/CMakeLists.txt
Show inline comments
 
deleted file
tests/login/CMakeLists.txt
Show inline comments
 
deleted file
tests/login/main.cpp
Show inline comments
 
deleted file
tests/login_bad_name/CMakeLists.txt
Show inline comments
 
deleted file
tests/login_bad_name/main.cpp
Show inline comments
 
deleted file
tests/login_bad_name2/.nolibircclient-qt
Show inline comments
 
deleted file
tests/login_bad_name2/CMakeLists.txt
Show inline comments
 
deleted file
tests/login_bad_name2/main.cpp
Show inline comments
 
deleted file
tests/runtests.py
Show inline comments
 
deleted file
0 comments (0 inline, 0 general)