Changeset - 285502c6ef00
[Not reviewed]
Merge
! ! !
Vitaly Takmazov - 14 years ago 2012-03-02 20:13:26
vitalyster@gmail.com
Merge branch 'master' of https://github.com/hanzz/libtransport
76 files changed:
Changeset was too big and was cut off... Show full diff anyway
0 comments (0 inline, 0 general)
CMakeLists.txt
Show inline comments
 
cmake_minimum_required(VERSION 2.6)
 
project(libtransport)
 

	
 
set(CMAKE_MODULE_PATH "cmake_modules")
 

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

	
 
set(sqlite3_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
 
find_package(sqlite3)
 

	
 
set(mysql_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
 
find_package(mysql)
 

	
 
set(purple_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
 
find_package(purple)
 

	
 
set(glib_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
 
find_package(glib)
 

	
 
if (NOT WIN32)
 
	set(popt_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
 
	find_package(popt)
 
endif()
 

	
 
set(event_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
 
find_package(event)
 

	
 
set(Swiften_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
 
find_package(Swiften REQUIRED)
 

	
 
set(openssl_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
 
find_package(openssl REQUIRED)
 

	
 
set(Boost_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
 
if (WIN32)
 
set(Boost_USE_STATIC_LIBS        ON)
 
set(Boost_USE_MULTITHREADED      ON)
 
set(Boost_USE_STATIC_RUNTIME    OFF)
 
endif()
 
find_package(Boost COMPONENTS program_options date_time system filesystem regex thread signals REQUIRED)
 
find_package(Boost COMPONENTS program_options date_time system filesystem regex  signals REQUIRED)
 
message( STATUS "Found Boost: ${Boost_LIBRARIES}, ${Boost_INCLUDE_DIR}")
 

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

	
 
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)
 

	
 
set(pqxx_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
 
find_package(pqxx)
 

	
 
set(dbus_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
 
find_package(dbus)
 

	
 
find_package(Doxygen)
 

	
 
INCLUDE(FindQt4)
 
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 "")
 
	message("SQLite3           : no")
 
endif (SQLITE3_FOUND)
 

	
 
if (MYSQL_FOUND)
 
	ADD_DEFINITIONS(-DWITH_MYSQL)
 
	include_directories(${MYSQL_INCLUDE_DIR})
 
	message("MySQL             : yes")
 
else (MYSQL_FOUND)
 
	set(MYSQL_LIBRARIES "")
 
	message("MySQL             : no (install mysql-devel)")
 
endif (MYSQL_FOUND)
 

	
 
if (PQXX_FOUND)
 
	ADD_DEFINITIONS(-DWITH_PQXX)
 
	include_directories(${PQXX_INCLUDE_DIR})
 
	message("PostgreSQL        : yes")
 
else (PQXX_FOUND)
 
	set(PQXX_LIBRARY "")
 
	set(PQ_LIBRARY "")
 
	message("PostgreSQL        : no (install libpqxx-devel)")
 
endif (PQXX_FOUND)
 

	
 
if (PROTOBUF_FOUND)
 
	ADD_DEFINITIONS(-DWITH_PROTOBUF)
 
	include_directories(${PROTOBUF_INCLUDE_DIRS})
 
	message("Network plugins   : yes")
 

	
 
	if(PURPLE_LIBRARY AND PURPLE_INCLUDE_DIR)
 
		message("Libpurple plugin  : yes")
 
		include_directories(${PURPLE_INCLUDE_DIR})
 
		include_directories(${GLIB2_INCLUDE_DIR})
 
	else()
 
		message("Libpurple plugin  : no (install libpurple)")
 
	endif()
 

	
 
	if (HAVE_EVENT)
 
		ADD_DEFINITIONS(-DWITH_LIBEVENT)
 
		include_directories(${EVENT_INCLUDE_DIRS})
 
		message("  libev eventloop : yes")
 
	else()
 
		message("  libev eventloop : no (install libev-devel)")
 
	endif()
 

	
 
	if(IRC_FOUND)
 
		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 libCommuni and libprotobuf-dev)")
 
	endif()
 

	
 
	message("Frotz plugin      : yes")
 
	message("SMSTools3 plugin  : yes")
 

	
 
	if(${LIBDBUSGLIB_FOUND})
 
		message("Skype plugin      : yes")
 
		include_directories(${LIBDBUSGLIB_INCLUDE_DIRS})
 
	else()
 
		message("Skype plugin      : no (install dbus-glib-devel)")
 
	endif()
 

	
 
else()
 
	message("Network plugins   : no (install libprotobuf-dev)")
 
	message("Libpurple plugin  : no (install libpurple and libprotobuf-dev)")
 
	message("IRC plugin        : no (install libircclient-qt and libprotobuf-dev)")
 
	message("Frotz plugin      : no (install libprotobuf-dev)")
 
	message("SMSTools3 plugin  : no (install libprotobuf-dev)")
 
endif()
 

	
 
if (LOG4CXX_FOUND)
 
	message("Logging           : yes")
 
	include_directories(${LOG4CXX_INCLUDE_DIR})
 
else()
 
	message(FATAL_ERROR "Logging           : no (install log4cxx-devel)")
 
endif()
 

	
 
if (WIN32)
 
ADD_DEFINITIONS(-D_WIN32_WINNT=0x501)
 
ADD_DEFINITIONS(-DWIN32_LEAN_AND_MEAN)
 
endif()
 

	
 
if(CMAKE_BUILD_TYPE MATCHES Debug)
 
if (CMAKE_COMPILER_IS_GNUCXX)
 
	ADD_DEFINITIONS(-O3)
 
	ADD_DEFINITIONS(-ggdb)
 
	ADD_DEFINITIONS(-Wall)
 
	ADD_DEFINITIONS(-W)
 
	ADD_DEFINITIONS(-Wcast-align)
 
	ADD_DEFINITIONS(-Wextra -Wno-sign-compare -Wno-unused-parameter)
 
	ADD_DEFINITIONS(-Winit-self)
 
	ADD_DEFINITIONS(-Wmissing-declarations)
 
	ADD_DEFINITIONS(-Wpointer-arith)
 
	ADD_DEFINITIONS(-Wreorder)
 
	ADD_DEFINITIONS(-Woverloaded-virtual)
 
	ADD_DEFINITIONS(-Wsign-promo)
 
	ADD_DEFINITIONS(-Wundef -Wunused)
 
endif()
 
	ADD_DEFINITIONS(-DDEBUG)
 
	message("Debug             : yes")
 
else(CMAKE_BUILD_TYPE MATCHES Debug)
 
	message("Debug             : no (run \"cmake . -DCMAKE_BUILD_TYPE=Debug\")")
 
endif(CMAKE_BUILD_TYPE MATCHES Debug)
 

	
 

	
 
SET(TRANSPORT_VERSION 2.0)
 
SET(PROJECT_VERSION 2.0)
 
include_directories(include)
 

	
 

	
 
include_directories(${EVENT_INCLUDE_DIRS})
 
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(spectrum)
 
ADD_SUBDIRECTORY(backends)
 
if (NOT WIN32)
 
	ADD_SUBDIRECTORY(spectrum_manager)
 
endif()
 

	
 
if (CPPUNIT_FOUND)
 
	message("tests             : yes")
 
	include_directories(${CPPUNIT_INCLUDE_DIR})
 
else()
 
	message("tests             : no (install CPPUnit)")
 
endif()
 

	
 
if(DOXYGEN_FOUND)
 
	message("Docs              : yes")
 
	ADD_SUBDIRECTORY(docs)
 
else(DOXYGEN_FOUND)
 
	message("Docs              : no (install doxygen)")
 
endif(DOXYGEN_FOUND)
 

	
 
message("----------------------")
ChangeLog
Show inline comments
 
Version 2.0.0-beta (2012-02-28):
 
	General:
 
	* Added PostreSQL support (thanks to Jadestorm).
 
	* Added XEP-0100 (Gateway interaction) support.
 
	* Send presences only "from" bare JID (fixed bug with buddies appearing
 
	  twice in the roster and potential unregistering issues).
 
	* Fixed potential MySQL/SQLite3 deadlocks.
 
	* Fixed disconnecting in server-mode when client does not send unavailable
 
	  presence before disconnection.
 
	* Fixed crash in server-mode when client send its custom jabber:iq:storage
 
	  payload.
 
	* Fixed registration from Pidgin.
 
	* Unsubscribe presence sent to some buddy doesn't disconnect the account.
 
	* Remote Roster requests are not sent to resources, but to bare JID.
 
	* Added automatic reconnection in case of non-fatal error.
 
	* Added more error messages.
 

	
 
	Skype:
 
	* Initial support for Skype added, read more on
 
	  http://spectrum.im/projects/spectrum/wiki/Spectrum_2_Admin_-_Skype_backend
 

	
 
	SMSTools3:
 
	* Initial support for SMSTools3, read more on
 
	http://spectrum.im/projects/spectrum/wiki/Spectrum_2_Admin_-_SMSTools3_backend
 

	
 
version 2.0.0 alpha (2011-12-06):
 
	General:
 
	* First Spectrum 2.0.0 alpha release, check more on
 
	  http://spectrum.im/projects/spectrum/wiki/Spectrum_200_alpha
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(libcommuni)
 
	endif()
 

	
 
	ADD_SUBDIRECTORY(smstools3)
 

	
 
	ADD_SUBDIRECTORY(template)
 

	
 
if (NOT WIN32)
 
	ADD_SUBDIRECTORY(frotz)
 
	if (${LIBDBUSGLIB_FOUND})
 
		ADD_SUBDIRECTORY(skype)
 
	endif()
 
endif()
 

	
 
endif()
backends/frotz/CMakeLists.txt
Show inline comments
 
cmake_minimum_required(VERSION 2.6)
 
 
ADD_SUBDIRECTORY(dfrotz)
 
 
FILE(GLOB SRC *.c *.cpp)
 
 
ADD_EXECUTABLE(spectrum2_frotz_backend ${SRC})
 
 
target_link_libraries(spectrum2_frotz_backend transport pthread transport-plugin ${Boost_LIBRARIES} ${SWIFTEN_LIBRARY} ${LOG4CXX_LIBRARIES})
 
target_link_libraries(spectrum2_frotz_backend transport pthread ${Boost_LIBRARIES} ${SWIFTEN_LIBRARY} ${LOG4CXX_LIBRARIES})
 
 
INSTALL(TARGETS spectrum2_frotz_backend RUNTIME DESTINATION bin)
 
backends/libcommuni/CMakeLists.txt
Show inline comments
 
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)
 
target_link_libraries(spectrum2_libcommuni_backend ${IRC_LIBRARY} ${QT_LIBRARIES} transport pthread)
 
 
INSTALL(TARGETS spectrum2_libcommuni_backend RUNTIME DESTINATION bin)
 
backends/libcommuni/session.cpp
Show inline comments
 
/*
 
 * 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;
 
	m_connected = false;
 
	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() {
 
	m_connected = true;
 
	if (suffix.empty()) {
 
		np->handleConnected(user);
 
	}
 

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

	
 
	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, "");
 
	m_connected = false;
 
}
 

	
 
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) {
 
	QString channel;
 
	QStringList members;
 

	
 
	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(" ");
 
			channel = m->parameters().value(2);
 
			members = m->parameters().value(3).split(" ");
 

	
 
			for (int i = 0; i < members.size(); i++) {
 
				bool flags = 0;
 
				std::string nickname = members.at(i).toStdString();
 
				flags = correctNickname(nickname);
 
				m_modes[channel.toStdString() + nickname] = flags;
 
				np->handleParticipantChanged(user, nickname, channel.toStdString() + suffix,(int) flags, pbnetwork::STATUS_ONLINE);
 
			}
 
			break;
 
		case 432:
 
			if (m_connected) {
 
				np->handleDisconnected(user, pbnetwork::CONNECTION_ERROR_INVALID_USERNAME, "Erroneous Nickname");
 
			}
 
			break;
 
		default:
 
			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;
 
		default:break;
 
	}
 
}
backends/libcommuni/session.h
Show inline comments
 
/*
 
 * 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;
 
	bool m_connected;
 
};
 

	
 
//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/libpurple/main.cpp
Show inline comments
 
@@ -348,360 +348,372 @@ spectrum_markup_linkify(const char *text)
 
				flag = 0;
 
			else {
 
				flag = 1;
 
				gurl_buf = g_string_new("");
 
			}
 

	
 
			t = c;
 
			while (flag) {
 
				/* iterate backwards grabbing the local part of an email address */
 
				g = g_utf8_get_char(t);
 
				if (badchar(*t) || (g >= 127) || (*t == '(') ||
 
					((*t == ';') && ((t > (text+2) && (!g_ascii_strncasecmp(t - 3, "&lt;", 4) ||
 
				                                       !g_ascii_strncasecmp(t - 3, "&gt;", 4))) ||
 
				                     (t > (text+4) && (!g_ascii_strncasecmp(t - 5, "&quot;", 6)))))) {
 
					/* local part will already be part of ret, strip it out */
 
					ret = g_string_truncate(ret, ret->len - (c - t));
 
					ret = g_string_append_unichar(ret, g);
 
					break;
 
				} else {
 
					g_string_prepend_unichar(gurl_buf, g);
 
					t = g_utf8_find_prev_char(text, t);
 
					if (t < text) {
 
						ret = g_string_assign(ret, "");
 
						break;
 
					}
 
				}
 
			}
 

	
 
			t = g_utf8_find_next_char(c, NULL);
 

	
 
			while (flag) {
 
				/* iterate forwards grabbing the domain part of an email address */
 
				g = g_utf8_get_char(t);
 
				if (badchar(*t) || (g >= 127) || (*t == ')') || badentity(t)) {
 
					char *d;
 

	
 
					url_buf = g_string_free(gurl_buf, FALSE);
 

	
 
					/* strip off trailing periods */
 
					if (strlen(url_buf) > 0) {
 
						for (d = url_buf + strlen(url_buf) - 1; *d == '.'; d--, t--)
 
							*d = '\0';
 
					}
 

	
 
					tmpurlbuf = purple_unescape_html(url_buf);
 
					if (purple_email_is_valid(tmpurlbuf)) {
 
						g_string_append_printf(ret, "<A HREF=\"mailto:%s\">%s</A>",
 
								url_buf, url_buf);
 
					} else {
 
						g_string_append(ret, url_buf);
 
					}
 
					g_free(url_buf);
 
					g_free(tmpurlbuf);
 
					c = t;
 

	
 
					break;
 
				} else {
 
					g_string_append_unichar(gurl_buf, g);
 
					t = g_utf8_find_next_char(t, NULL);
 
				}
 
			}
 
		}
 

	
 
		if(*c == ')' && !inside_html) {
 
			inside_paren--;
 
			ret = g_string_append_c(ret, *c);
 
			c++;
 
		}
 

	
 
		if (*c == 0)
 
			break;
 

	
 
		ret = g_string_append_c(ret, *c);
 
		c++;
 

	
 
	}
 
	return g_string_free(ret, FALSE);
 
}
 

	
 
struct authRequest {
 
	PurpleAccountRequestAuthorizationCb authorize_cb;
 
	PurpleAccountRequestAuthorizationCb deny_cb;
 
	void *user_data;
 
	std::string who;
 
	PurpleAccount *account;
 
	std::string mainJID;	// JID of user connected with this request
 
};
 

	
 
static void * requestInput(const char *title, const char *primary,const char *secondary, const char *default_value, gboolean multiline, gboolean masked, gchar *hint,const char *ok_text, GCallback ok_cb,const char *cancel_text, GCallback cancel_cb, PurpleAccount *account, const char *who,PurpleConversation *conv, void *user_data) {
 
	if (primary) {
 
		std::string primaryString(primary);
 
		if (primaryString == "Authorization Request Message:") {
 
			LOG4CXX_INFO(logger, "Authorization Request Message: calling ok_cb(...)");
 
			((PurpleRequestInputCb) ok_cb)(user_data, "Please authorize me.");
 
			return NULL;
 
		}
 
		else if (primaryString == "Authorization Request Message:") {
 
			LOG4CXX_INFO(logger, "Authorization Request Message: calling ok_cb(...)");
 
			((PurpleRequestInputCb) ok_cb)(user_data, "Please authorize me.");
 
			return NULL;
 
		}
 
		else if (primaryString == "Authorization Denied Message:") {
 
			LOG4CXX_INFO(logger, "Authorization Deined Message: calling ok_cb(...)");
 
			((PurpleRequestInputCb) ok_cb)(user_data, "Authorization denied.");
 
			return NULL;
 
		}
 
		else {
 
			LOG4CXX_WARN(logger, "Unhandled request input. primary=" << primaryString);
 
		}
 
	}
 
	else if (title) {
 
		std::string titleString(title);
 
		if (titleString == "Xfire Invitation Message") {
 
			LOG4CXX_INFO(logger, "Authorization Request Message: calling ok_cb(...)");
 
			((PurpleRequestInputCb) ok_cb)(user_data, "Please authorize me.");
 
			return NULL;
 
		}
 
		else {
 
			LOG4CXX_WARN(logger, "Unhandled request input. title=" << titleString);
 
		}
 
	}
 
	else {
 
		LOG4CXX_WARN(logger, "Request input without primary string");
 
	}
 
	return NULL;
 
}
 

	
 
static void *requestAction(const char *title, const char *primary, const char *secondary, int default_action, PurpleAccount *account, const char *who,PurpleConversation *conv, void *user_data, size_t action_count, va_list actions){
 
	std::string t(title ? title : "NULL");
 
	if (t == "SSL Certificate Verification") {
 
		LOG4CXX_INFO(logger,  "accepting SSL certificate");
 
		va_arg(actions, char *);
 
		((PurpleRequestActionCb) va_arg(actions, GCallback)) (user_data, 2);
 
	}
 
	else {
 
		if (title) {
 
			std::string headerString(title);
 
			LOG4CXX_INFO(logger,  "header string: " << headerString);
 
			if (headerString == "SSL Certificate Verification") {
 
				va_arg(actions, char *);
 
				((PurpleRequestActionCb) va_arg(actions, GCallback)) (user_data, 2);
 
			}
 
		}
 
	}
 
	return NULL;
 
}
 

	
 
static std::string getAlias(PurpleBuddy *m_buddy) {
 
	std::string alias;
 
	PurpleContact *contact = PURPLE_CONTACT(PURPLE_BLIST_NODE(m_buddy)->parent);
 
	if (contact && contact->alias) {
 
		alias = contact->alias;
 
	}
 
	else if (purple_buddy_get_alias(m_buddy)) {
 
		alias = (std::string) purple_buddy_get_alias(m_buddy);
 
	}
 
	else {
 
		alias = (std::string) purple_buddy_get_server_alias(m_buddy);
 
	}
 
	return alias;
 
}
 

	
 
class SpectrumNetworkPlugin : public NetworkPlugin {
 
	public:
 
		SpectrumNetworkPlugin(const std::string &host, int port) : NetworkPlugin() {
 

	
 
		}
 

	
 
		void handleExitRequest() {
 
			LOG4CXX_INFO(logger, "Exiting...");
 
			exit(1);
 
		}
 

	
 
		void getProtocolAndName(const std::string &legacyName, std::string &name, std::string &protocol) {
 
			name = legacyName;
 
			protocol = KEYFILE_STRING("service", "protocol");
 
			if (protocol == "any") {
 
				protocol = name.substr(0, name.find("."));
 
				name = name.substr(name.find(".") + 1);
 
			}
 
		}
 

	
 
		void setDefaultAvatar(PurpleAccount *account, const std::string &legacyName) {
 
			char* contents;
 
			gsize length;
 
			gboolean ret = false;
 
			if (!KEYFILE_STRING("backend", "avatars_directory").empty()) {
 
				std::string f = KEYFILE_STRING("backend", "avatars_directory") + "/" + legacyName;
 
				ret = g_file_get_contents (f.c_str(), &contents, &length, NULL);
 
			}
 

	
 
			if (!KEYFILE_STRING("backend", "default_avatar").empty() && !ret) {
 
				ret = g_file_get_contents (KEYFILE_STRING("backend", "default_avatar").c_str(),
 
											&contents, &length, NULL);
 
			}
 

	
 
			if (ret) {
 
				purple_buddy_icons_set_account_icon(account, (guchar *) contents, length);
 
			}
 
		}
 

	
 
		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);
 
					std::string key2(purple_account_option_get_setting(option));
 
					if (key != key2) {
 
						continue;
 
					}
 
					
 
					found = true;
 
					switch (type) {
 
						case PURPLE_PREF_BOOLEAN:
 
							purple_account_set_bool(account, key.c_str(), fromString<bool>(KEYFILE_STRING("purple", key)));
 
							break;
 

	
 
						case PURPLE_PREF_INT:
 
							purple_account_set_int(account, key.c_str(), fromString<int>(KEYFILE_STRING("purple", key)));
 
							break;
 

	
 
						case PURPLE_PREF_STRING:
 
						case PURPLE_PREF_STRING_LIST:
 
							purple_account_set_string(account, key.c_str(), KEYFILE_STRING("purple", key).c_str());
 
							break;
 
						default:
 
							continue;
 
					}
 
					break;
 
				}
 

	
 
				if (!found) {
 
					purple_account_set_string(account, key.c_str(), KEYFILE_STRING("purple", key).c_str());
 
				}
 
				i++;
 
			}
 
			g_strfreev (keys);
 
		}
 

	
 
		void handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password) {
 
			PurpleAccount *account = NULL;
 
			
 
			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){
 

	
 
			if (purple_accounts_find(name.c_str(), protocol.c_str()) != NULL) {
 
				LOG4CXX_INFO(logger, "Using previously created account with name '" << name.c_str() << "' and protocol '" << protocol << "'");
 
				account = purple_accounts_find(name.c_str(), protocol.c_str());
 
			}
 
			else {
 
				LOG4CXX_INFO(logger, "Creating account with name '" << name.c_str() << "' and protocol '" << protocol << "'");
 
				account = purple_account_new(name.c_str(), protocol.c_str());
 
				purple_accounts_add(account);
 
			}
 

	
 
			m_sessions[user] = account;
 
			m_accounts[account] = user;
 

	
 
			// Default avatar
 
			setDefaultAvatar(account, legacyName);
 

	
 
			purple_account_set_password(account, password.c_str());
 
			purple_account_set_bool(account, "custom_smileys", FALSE);
 
			purple_account_set_bool(account, "direct_connect", FALSE);
 

	
 
			setDefaultAccountOptions(account);
 

	
 
			purple_account_set_enabled(account, "spectrum", TRUE);
 
			if (KEYFILE_BOOL("service", "enable_privacy_lists")) {
 
				purple_account_set_privacy_type(account, PURPLE_PRIVACY_DENY_USERS);
 
			}
 

	
 
			const PurpleStatusType *status_type = purple_account_get_status_type_with_primitive(account, PURPLE_STATUS_AVAILABLE);
 
			if (status_type != NULL) {
 
				purple_account_set_status(account, purple_status_type_get_id(status_type), TRUE, NULL);
 
			}
 
		}
 

	
 
		void handleLogoutRequest(const std::string &user, const std::string &legacyName) {
 
			PurpleAccount *account = m_sessions[user];
 
			if (account) {
 
// 				VALGRIND_DO_LEAK_CHECK;
 
				m_sessions.erase(user);
 
				purple_account_disconnect(account);
 
				purple_account_set_enabled(account, "spectrum", FALSE);
 

	
 
				g_free(account->ui_data);
 
				account->ui_data = NULL;
 
				m_accounts.erase(account);
 

	
 
				purple_accounts_delete(account);
 
// 
 
// 				// Remove conversations.
 
// 				// This has to be called before m_account->ui_data = NULL;, because it uses
 
// 				// ui_data to call SpectrumMessageHandler::purpleConversationDestroyed() callback.
 
// 				GList *iter;
 
// 				for (iter = purple_get_conversations(); iter; ) {
 
// 					PurpleConversation *conv = (PurpleConversation*) iter->data;
 
// 					iter = iter->next;
 
// 					if (purple_conversation_get_account(conv) == account)
 
// 						purple_conversation_destroy(conv);
 
// 				}
 
// 
 
// 				g_free(account->ui_data);
 
// 				account->ui_data = NULL;
 
// 				m_accounts.erase(account);
 
// 
 
// 				purple_notify_close_with_handle(account);
 
// 				purple_request_close_with_handle(account);
 
// 
 
// 				purple_accounts_remove(account);
 
// 
 
// 				GSList *buddies = purple_find_buddies(account, NULL);
 
// 				while(buddies) {
 
// 					PurpleBuddy *b = (PurpleBuddy *) buddies->data;
 
// 					purple_blist_remove_buddy(b);
 
// 					buddies = g_slist_delete_link(buddies, buddies);
 
// 				}
 
// 
 
// 				/* Remove any open conversation for this account */
 
// 				for (GList *it = purple_get_conversations(); it; ) {
 
// 					PurpleConversation *conv = (PurpleConversation *) it->data;
 
// 					it = it->next;
 
// 					if (purple_conversation_get_account(conv) == account)
 
// 						purple_conversation_destroy(conv);
 
// 				}
 
// 
 
// 				/* Remove this account's pounces */
 
// 					// purple_pounce_destroy_all_by_account(account);
 
// 
 
// 				/* This will cause the deletion of an old buddy icon. */
 
// 				purple_buddy_icons_set_account_icon(account, NULL, 0);
 
// 
 
// 				purple_account_destroy(account);
 
				// force returning of memory chunks allocated by libxml2 to kernel
 
#ifndef WIN32
 
				malloc_trim(0);
 
#endif
 
// 				VALGRIND_DO_LEAK_CHECK;
 
			}
 
		}
 

	
 
		void handleStatusChangeRequest(const std::string &user, int status, const std::string &statusMessage) {
 
			PurpleAccount *account = m_sessions[user];
 
			if (account) {
 
				int st;
 
				switch(status) {
 
@@ -810,367 +822,404 @@ class SpectrumNetworkPlugin : public NetworkPlugin {
 

	
 
		void handleBuddyRemovedRequest(const std::string &user, const std::string &buddyName, const std::vector<std::string> &groups) {
 
			PurpleAccount *account = m_sessions[user];
 
			if (account) {
 
				if (m_authRequests.find(user + buddyName) != m_authRequests.end()) {
 
					m_authRequests[user + buddyName]->deny_cb(m_authRequests[user + buddyName]->user_data);
 
					m_authRequests.erase(user + buddyName);
 
				}
 
				PurpleBuddy *buddy = purple_find_buddy(account, buddyName.c_str());
 
				if (buddy) {
 
					purple_account_remove_buddy(account, buddy, purple_buddy_get_group(buddy));
 
					purple_blist_remove_buddy(buddy);
 
				}
 
			}
 
		}
 

	
 
		void handleBuddyUpdatedRequest(const std::string &user, const std::string &buddyName, const std::string &alias, const std::vector<std::string> &groups_) {
 
			PurpleAccount *account = m_sessions[user];
 
			if (account) {
 
				std::string groups = groups_.empty() ? "" : groups_[0];
 

	
 
				if (m_authRequests.find(user + buddyName) != m_authRequests.end()) {
 
					m_authRequests[user + buddyName]->authorize_cb(m_authRequests[user + buddyName]->user_data);
 
					m_authRequests.erase(user + buddyName);
 
				}
 

	
 
				PurpleBuddy *buddy = purple_find_buddy(account, buddyName.c_str());
 
				if (buddy) {
 
					if (getAlias(buddy) != alias) {
 
						purple_blist_alias_buddy(buddy, alias.c_str());
 
						purple_blist_server_alias_buddy(buddy, alias.c_str());
 
						serv_alias_buddy(buddy);
 
					}
 

	
 
					PurpleGroup *group = purple_find_group(groups.c_str());
 
					if (!group) {
 
						group = purple_group_new(groups.c_str());
 
					}
 
					purple_blist_add_contact(purple_buddy_get_contact(buddy), group ,NULL);
 
				}
 
				else {
 
					PurpleBuddy *buddy = purple_buddy_new(account, buddyName.c_str(), alias.c_str());
 

	
 
					// Add newly created buddy to legacy network roster.
 
					PurpleGroup *group = purple_find_group(groups.c_str());
 
					if (!group) {
 
						group = purple_group_new(groups.c_str());
 
					}
 
					purple_blist_add_buddy(buddy, NULL, group ,NULL);
 
					purple_account_add_buddy(account, buddy);
 
				}
 
			}
 
		}
 

	
 
		void handleBuddyBlockToggled(const std::string &user, const std::string &buddyName, bool blocked) {
 
			if (KEYFILE_BOOL("service", "enable_privacy_lists")) {
 
				PurpleAccount *account = m_sessions[user];
 
				if (account) {
 
					if (blocked) {
 
						purple_privacy_deny(account, buddyName.c_str(), FALSE, FALSE);
 
					}
 
					else {
 
						purple_privacy_allow(account, buddyName.c_str(), FALSE, FALSE);
 
					}
 
				}
 
			}
 
		}
 

	
 
		void handleTypingRequest(const std::string &user, const std::string &buddyName) {
 
			PurpleAccount *account = m_sessions[user];
 
			if (account) {
 
				serv_send_typing(purple_account_get_connection(account), buddyName.c_str(), PURPLE_TYPING);
 
			}
 
		}
 

	
 
		void handleTypedRequest(const std::string &user, const std::string &buddyName) {
 
			PurpleAccount *account = m_sessions[user];
 
			if (account) {
 
				serv_send_typing(purple_account_get_connection(account), buddyName.c_str(), PURPLE_TYPED);
 
			}
 
		}
 

	
 
		void handleStoppedTypingRequest(const std::string &user, const std::string &buddyName) {
 
			PurpleAccount *account = m_sessions[user];
 
			if (account) {
 
				serv_send_typing(purple_account_get_connection(account), buddyName.c_str(), PURPLE_NOT_TYPING);
 
			}
 
		}
 

	
 
		void handleAttentionRequest(const std::string &user, const std::string &buddyName, const std::string &message) {
 
			PurpleAccount *account = m_sessions[user];
 
			if (account) {
 
				purple_prpl_send_attention(purple_account_get_connection(account), buddyName.c_str(), 0);
 
			}
 
		}
 

	
 
		void handleJoinRoomRequest(const std::string &user, const std::string &room, const std::string &nickname, const std::string &pasword) {
 
			PurpleAccount *account = m_sessions[user];
 
			if (!account) {
 
				return;
 
			}
 

	
 
			PurpleConnection *gc = purple_account_get_connection(account);
 
			GHashTable *comps = NULL;
 

	
 
			// Check if the PurpleChat is not stored in buddy list
 
			PurpleChat *chat = purple_blist_find_chat(account, room.c_str());
 
			if (chat) {
 
				comps = purple_chat_get_components(chat);
 
			}
 
			else if (PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info_defaults != NULL) {
 
				comps = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl)->chat_info_defaults(gc, room.c_str());
 
			}
 

	
 
			LOG4CXX_INFO(logger, user << ": Joining the room " << room);
 
			if (comps) {
 
				serv_join_chat(gc, comps);
 
				g_hash_table_destroy(comps);
 
			}
 
		}
 

	
 
		void handleLeaveRoomRequest(const std::string &user, const std::string &room) {
 
			PurpleAccount *account = m_sessions[user];
 
			if (!account) {
 
				return;
 
			}
 

	
 
			PurpleConversation *conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, room.c_str(), account);
 
			purple_conversation_destroy(conv);
 
		}
 

	
 
		void handleFTStartRequest(const std::string &user, const std::string &buddyName, const std::string &fileName, unsigned long size, unsigned long ftID) {
 
			PurpleXfer *xfer = m_unhandledXfers[user + fileName + buddyName];
 
			if (xfer) {
 
				m_unhandledXfers.erase(user + fileName + buddyName);
 
				FTData *ftData = (FTData *) xfer->ui_data;
 
				
 
				ftData->id = ftID;
 
				m_xfers[ftID] = xfer;
 
				purple_xfer_request_accepted(xfer, fileName.c_str());
 
				purple_xfer_ui_ready(xfer);
 
			}
 
		}
 

	
 
		void handleFTFinishRequest(const std::string &user, const std::string &buddyName, const std::string &fileName, unsigned long size, unsigned long ftID) {
 
			PurpleXfer *xfer = m_unhandledXfers[user + fileName + buddyName];
 
			if (xfer) {
 
				m_unhandledXfers.erase(user + fileName + buddyName);
 
				purple_xfer_request_denied(xfer);
 
			}
 
		}
 

	
 
		void handleFTPauseRequest(unsigned long ftID) {
 
			PurpleXfer *xfer = m_xfers[ftID];
 
			if (!xfer)
 
				return;
 
			FTData *ftData = (FTData *) xfer->ui_data;
 
			ftData->paused = true;
 
		}
 

	
 
		void handleFTContinueRequest(unsigned long ftID) {
 
			PurpleXfer *xfer = m_xfers[ftID];
 
			if (!xfer)
 
				return;
 
			FTData *ftData = (FTData *) xfer->ui_data;
 
			ftData->paused = false;
 
			purple_xfer_ui_ready(xfer);
 
		}
 

	
 
		void sendData(const std::string &string) {
 
			write(m_sock, string.c_str(), string.size());
 
			if (writeInput == 0)
 
				writeInput = purple_input_add(m_sock, PURPLE_INPUT_WRITE, &transportDataReceived, NULL);
 
		}
 

	
 
		void readyForData() {
 
			if (m_waitingXfers.empty())
 
				return;
 
			std::vector<PurpleXfer *> tmp;
 
			tmp.swap(m_waitingXfers);
 

	
 
			for (std::vector<PurpleXfer *>::const_iterator it = tmp.begin(); it != tmp.end(); it++) {
 
				FTData *ftData = (FTData *) (*it)->ui_data;
 
				if (ftData->timer == 0) {
 
					ftData->timer = purple_timeout_add(1, ft_ui_ready, *it);
 
				}
 
// 				purple_xfer_ui_ready(xfer);
 
			}
 
		}
 

	
 
		std::map<std::string, PurpleAccount *> m_sessions;
 
		std::map<PurpleAccount *, std::string> m_accounts;
 
		std::map<std::string, unsigned int> m_vcards;
 
		std::map<std::string, authRequest *> m_authRequests;
 
		std::map<unsigned long, PurpleXfer *> m_xfers;
 
		std::map<std::string, PurpleXfer *> m_unhandledXfers;
 
		std::vector<PurpleXfer *> m_waitingXfers;
 
};
 

	
 
static bool getStatus(PurpleBuddy *m_buddy, pbnetwork::StatusType &status, std::string &statusMessage) {
 
	PurplePresence *pres = purple_buddy_get_presence(m_buddy);
 
	if (pres == NULL)
 
		return false;
 
	PurpleStatus *stat = purple_presence_get_active_status(pres);
 
	if (stat == NULL)
 
		return false;
 
	int st = purple_status_type_get_primitive(purple_status_get_type(stat));
 

	
 
	switch(st) {
 
		case PURPLE_STATUS_AVAILABLE: {
 
			status = pbnetwork::STATUS_ONLINE;
 
			break;
 
		}
 
		case PURPLE_STATUS_AWAY: {
 
			status = pbnetwork::STATUS_AWAY;
 
			break;
 
		}
 
		case PURPLE_STATUS_UNAVAILABLE: {
 
			status = pbnetwork::STATUS_DND;
 
			break;
 
		}
 
		case PURPLE_STATUS_EXTENDED_AWAY: {
 
			status = pbnetwork::STATUS_XA;
 
			break;
 
		}
 
		case PURPLE_STATUS_OFFLINE: {
 
			status = pbnetwork::STATUS_NONE;
 
			break;
 
		}
 
		default:
 
			status = pbnetwork::STATUS_ONLINE;
 
			break;
 
	}
 

	
 
	const char *message = purple_status_get_attr_string(stat, "message");
 

	
 
	if (message != NULL) {
 
		char *stripped = purple_markup_strip_html(message);
 
		statusMessage = std::string(stripped);
 
		g_free(stripped);
 
	}
 
	else
 
		statusMessage = "";
 
	return true;
 
}
 

	
 
static std::string getIconHash(PurpleBuddy *m_buddy) {
 
	char *avatarHash = NULL;
 
	PurpleBuddyIcon *icon = purple_buddy_icons_find(purple_buddy_get_account(m_buddy), purple_buddy_get_name(m_buddy));
 
	if (icon) {
 
		avatarHash = purple_buddy_icon_get_full_path(icon);
 
		purple_buddy_icon_unref(icon);
 
	}
 

	
 
	if (avatarHash) {
 
		// Check if it's patched libpurple which saves icons to directories
 
		char *hash = strrchr(avatarHash,'/');
 
		std::string h;
 
		if (hash) {
 
			char *dot;
 
			hash++;
 
			dot = strchr(hash, '.');
 
			if (dot)
 
				*dot = '\0';
 

	
 
			std::string ret(hash);
 
			g_free(avatarHash);
 
			return ret;
 
		}
 
		else {
 
			std::string ret(avatarHash);
 
			g_free(avatarHash);
 
			return ret;
 
		}
 
	}
 

	
 
	return "";
 
}
 

	
 
static std::vector<std::string> getGroups(PurpleBuddy *m_buddy) {
 
	std::vector<std::string> groups;
 
	if (purple_buddy_get_name(m_buddy)) {
 
		GSList *buddies = purple_find_buddies(purple_buddy_get_account(m_buddy), purple_buddy_get_name(m_buddy));
 
		while(buddies) {
 
			PurpleGroup *g = purple_buddy_get_group((PurpleBuddy *) buddies->data);
 
			buddies = g_slist_delete_link(buddies, buddies);
 

	
 
			if(g && purple_group_get_name(g)) {
 
				groups.push_back(purple_group_get_name(g));
 
			}
 
		}
 
	}
 

	
 
	if (groups.empty()) {
 
		groups.push_back("Buddies");
 
	}
 

	
 
	return groups;
 
}
 

	
 
static void buddyListNewNode(PurpleBlistNode *node) {
 
	if (!PURPLE_BLIST_NODE_IS_BUDDY(node))
 
		return;
 
	PurpleBuddy *buddy = (PurpleBuddy *) node;
 
	PurpleAccount *account = purple_buddy_get_account(buddy);
 

	
 
	LOG4CXX_INFO(logger, "Buddy updated " << np->m_accounts[account] << " " << purple_buddy_get_name(buddy) << " " << getAlias(buddy));
 

	
 
	// Status
 
	pbnetwork::StatusType status = pbnetwork::STATUS_NONE;
 
	std::string message;
 
	getStatus(buddy, status, message);
 

	
 
	// Tooltip
 
	PurplePlugin *prpl = purple_find_prpl(purple_account_get_protocol_id(account));
 
	PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
 

	
 
	bool blocked = false;
 
	if (KEYFILE_BOOL("service", "enable_privacy_lists")) {
 
		if (prpl_info && prpl_info->tooltip_text) {
 
			PurpleNotifyUserInfo *user_info = purple_notify_user_info_new();
 
			prpl_info->tooltip_text(buddy, user_info, true);
 
			GList *entries = purple_notify_user_info_get_entries(user_info);
 

	
 
			while (entries) {
 
				PurpleNotifyUserInfoEntry *entry = (PurpleNotifyUserInfoEntry *)(entries->data);
 
				if (purple_notify_user_info_entry_get_label(entry) && purple_notify_user_info_entry_get_value(entry)) {
 
					std::string label = purple_notify_user_info_entry_get_label(entry);
 
					if (label == "Blocked" ) {
 
						if (std::string(purple_notify_user_info_entry_get_value(entry)) == "Yes") {
 
							blocked = true;
 
							break;
 
						}
 
					}
 
				}
 
				entries = entries->next;
 
			}
 
			purple_notify_user_info_destroy(user_info);
 
		}
 

	
 
		if (!blocked) {
 
			blocked = purple_privacy_check(account, purple_buddy_get_name(buddy)) == false;
 
		}
 
		else {
 
			bool purpleBlocked = purple_privacy_check(account, purple_buddy_get_name(buddy)) == false;
 
			if (blocked != purpleBlocked) {
 
				purple_privacy_deny(account, purple_buddy_get_name(buddy), FALSE, FALSE);
 
			}
 
		}
 
	}
 

	
 
	np->handleBuddyChanged(np->m_accounts[account], purple_buddy_get_name(buddy), getAlias(buddy), getGroups(buddy), status, message, getIconHash(buddy),
 
		blocked
 
	);
 
}
 

	
 
static void buddyListUpdate(PurpleBuddyList *list, PurpleBlistNode *node) {
 
	if (!PURPLE_BLIST_NODE_IS_BUDDY(node))
 
		return;
 
	buddyListNewNode(node);
 
}
 

	
 
static void buddyPrivacyChanged(PurpleBlistNode *node, void *data) {
 
	if (!PURPLE_BLIST_NODE_IS_BUDDY(node))
 
		return;
 
	buddyListUpdate(NULL, node);
 
}
 

	
 
static void NodeRemoved(PurpleBlistNode *node, void *data) {
 
	if (!PURPLE_BLIST_NODE_IS_BUDDY(node))
 
		return;
 
// 	PurpleBuddy *buddy = (PurpleBuddy *) node;
 
}
 

	
 
static PurpleBlistUiOps blistUiOps =
 
{
 
	NULL,
 
	buddyListNewNode,
 
	NULL,
 
	buddyListUpdate,
 
	NULL, //NodeRemoved,
 
	NULL,
 
	NULL,
 
	NULL, // buddyListAddBuddy,
 
	NULL,
 
	NULL,
 
	NULL, //buddyListSaveNode,
 
	NULL, //buddyListRemoveNode,
 
	NULL, //buddyListSaveAccount,
 
	NULL
 
};
 

	
 
static void conv_write_im(PurpleConversation *conv, const char *who, const char *msg, PurpleMessageFlags flags, time_t mtime) {
 
	// Don't forwards our own messages.
 
	if (flags & PURPLE_MESSAGE_SEND || flags & PURPLE_MESSAGE_SYSTEM)
 
		return;
 
	PurpleAccount *account = purple_conversation_get_account(conv);
 

	
 
// 	char *striped = purple_markup_strip_html(message);
 
// 	std::string msg = striped;
 
// 	g_free(striped);
 

	
 
	std::string w = purple_normalize(account, who);
 
	size_t pos = w.find("/");
backends/skype/CMakeLists.txt
Show inline comments
 
new file 100644
 
cmake_minimum_required(VERSION 2.6)
 
FILE(GLOB SRC *.cpp)
 
 
ADD_EXECUTABLE(spectrum2_skype_backend ${SRC})
 
 
target_link_libraries(spectrum2_skype_backend ${GLIB2_LIBRARIES} ${EVENT_LIBRARIES} transport pthread ${LIBDBUSGLIB_LIBRARIES})
 
 
INSTALL(TARGETS spectrum2_skype_backend RUNTIME DESTINATION bin)
 
backends/skype/main.cpp
Show inline comments
 
new file 100644
 
#include "glib.h"
 
#include <iostream>
 

	
 
#include "transport/config.h"
 
#include "transport/transport.h"
 
#include "transport/usermanager.h"
 
#include "transport/logger.h"
 
#include "transport/sqlite3backend.h"
 
#include "transport/userregistration.h"
 
#include "transport/user.h"
 
#include "transport/storagebackend.h"
 
#include "transport/rostermanager.h"
 
#include "transport/conversation.h"
 
#include "transport/networkplugin.h"
 
#include <boost/filesystem.hpp>
 
#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 "sys/wait.h"
 
#include "sys/signal.h"
 
// #include "valgrind/memcheck.h"
 
#include "malloc.h"
 
#include <dbus-1.0/dbus/dbus-glib-lowlevel.h>
 

	
 

	
 
using namespace log4cxx;
 

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

	
 
using namespace Transport;
 

	
 
class SpectrumNetworkPlugin;
 

	
 

	
 
SpectrumNetworkPlugin *np;
 

	
 
static gboolean nodaemon = FALSE;
 
static gchar *logfile = NULL;
 
static gchar *lock_file = NULL;
 
static gchar *host = NULL;
 
static int port = 10000;
 
static gboolean ver = FALSE;
 
static gboolean list_purple_settings = FALSE;
 

	
 
int m_sock;
 
static int writeInput;
 

	
 
static GOptionEntry options_entries[] = {
 
	{ "nodaemon", 'n', 0, G_OPTION_ARG_NONE, &nodaemon, "Disable background daemon mode", NULL },
 
	{ "logfile", 'l', 0, G_OPTION_ARG_STRING, &logfile, "Set file to log", NULL },
 
	{ "pidfile", 'p', 0, G_OPTION_ARG_STRING, &lock_file, "File where to write transport PID", NULL },
 
	{ "version", 'v', 0, G_OPTION_ARG_NONE, &ver, "Shows Spectrum version", NULL },
 
	{ "list-purple-settings", 's', 0, G_OPTION_ARG_NONE, &list_purple_settings, "Lists purple settings which can be used in config file", NULL },
 
	{ "host", 'h', 0, G_OPTION_ARG_STRING, &host, "Host to connect to", NULL },
 
	{ "port", 'p', 0, G_OPTION_ARG_INT, &port, "Port to connect to", NULL },
 
	{ NULL, 0, 0, G_OPTION_ARG_NONE, NULL, "", NULL }
 
};
 

	
 
DBusHandlerResult skype_notify_handler(DBusConnection *connection, DBusMessage *message, gpointer user_data);
 

	
 
static pbnetwork::StatusType getStatus(const std::string &st) {
 
	pbnetwork::StatusType status = pbnetwork::STATUS_ONLINE;
 
	if (st == "SKYPEOUT" || st == "OFFLINE") {
 
		status = pbnetwork::STATUS_NONE;
 
	}
 
	else if (st == "DND") {
 
		status = pbnetwork::STATUS_DND;
 
	}
 
	else if (st == "NA") {
 
		status = pbnetwork::STATUS_XA;
 
	}
 
	else if (st == "AWAY") {
 
		status = pbnetwork::STATUS_AWAY;
 
	}
 
	return status;
 
}
 

	
 
class Skype {
 
	public:
 
		Skype(const std::string &user, const std::string &username, const std::string &password);
 
		~Skype() { logout(); }
 
		void login();
 
		void logout();
 
		std::string send_command(const std::string &message);
 

	
 
		const std::string &getUser() {
 
			return m_user;
 
		}
 

	
 
		const std::string &getUsername() {
 
			return m_username;
 
		}
 

	
 
		bool createDBusProxy();
 
		bool loadSkypeBuddies();
 

	
 
	private:
 
		std::string m_username;
 
		std::string m_password;
 
		GPid m_pid;
 
		DBusGConnection *m_connection;
 
		DBusGProxy *m_proxy;
 
		std::string m_user;
 
		int m_timer;
 
		int m_counter;
 
		int fd_output;
 
};
 

	
 
class SpectrumNetworkPlugin : public NetworkPlugin {
 
	public:
 
		SpectrumNetworkPlugin(Config *config, const std::string &host, int port) : NetworkPlugin() {
 
			this->config = config;
 
			LOG4CXX_INFO(logger, "Starting the backend.");
 
		}
 

	
 
		~SpectrumNetworkPlugin() {
 
			for (std::map<Skype *, std::string>::iterator it = m_accounts.begin(); it != m_accounts.end(); it++) {
 
				delete (*it).first;
 
			}
 
		}
 

	
 
		void handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password) {
 
			std::string name = legacyName;
 
			name = name.substr(name.find(".") + 1);
 
			LOG4CXX_INFO(logger,  "Creating account with name '" << name << "'");
 

	
 
			Skype *skype = new Skype(user, name, password);
 
			m_sessions[user] = skype;
 
			m_accounts[skype] = user;
 

	
 
			skype->login();
 
		}
 

	
 
		void handleLogoutRequest(const std::string &user, const std::string &legacyName) {
 
			Skype *skype = m_sessions[user];
 
			if (skype) {
 
				skype->logout();
 
				exit(1);
 
			}
 
		}
 

	
 
		void handleStatusChangeRequest(const std::string &user, int status, const std::string &statusMessage) {
 
			Skype *skype = m_sessions[user];
 
			if (!skype)
 
				return;
 

	
 
			std::string st;
 
			switch(status) {
 
				case Swift::StatusShow::Away: {
 
					st = "AWAY";
 
					break;
 
				}
 
				case Swift::StatusShow::DND: {
 
					st = "DND";
 
					break;
 
				}
 
				case Swift::StatusShow::XA: {
 
					st = "NA";
 
					break;
 
				}
 
				case Swift::StatusShow::None: {
 
					break;
 
				}
 
				case pbnetwork::STATUS_INVISIBLE:
 
					st = "INVISIBLE";
 
					break;
 
				default:
 
					st = "ONLINE";
 
					break;
 
			}
 
			skype->send_command("SET USERSTATUS " + st);
 

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

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

	
 
		void handleVCardRequest(const std::string &user, const std::string &legacyName, unsigned int id) {
 
			Skype *skype = m_sessions[user];
 
			if (skype) {
 
				std::string name = legacyName;
 
				if (name.find("skype.") == 0) {
 
					name = name.substr(6);
 
				}
 
				std::string photo;
 
				gchar *filename = NULL;
 
				gchar *new_filename = NULL;
 
				gchar *image_data = NULL;
 
				gsize image_data_len = 0;
 
				gchar *ret;
 
				int fh;
 
				GError *error;
 
				const gchar *userfiles[] = {"user256", "user1024", "user4096", "user16384", "user32768", "user65536",
 
											"profile256", "profile1024", "profile4096", "profile16384", "profile32768", 
 
											NULL};
 
				char *username = g_strdup_printf("\x03\x10%s", name.c_str());
 
				for (fh = 0; userfiles[fh]; fh++) {
 
					filename = g_strconcat("/tmp/skype/", skype->getUsername().c_str(), "/", skype->getUsername().c_str(), "/", userfiles[fh], ".dbb", NULL);
 
					std::cout << "getting filename:" << filename << "\n";
 
					if (g_file_get_contents(filename, &image_data, &image_data_len, NULL))
 
					{
 
						std::cout << "got\n";
 
						char *start = (char *)memmem(image_data, image_data_len, username, strlen(username)+1);
 
						if (start != NULL)
 
						{
 
							char *next = image_data;
 
							char *last = next;
 
							//find last index of l33l
 
							while ((next = (char *)memmem(next+4, start-next-4, "l33l", 4)))
 
							{
 
								last = next;
 
							}
 
							start = last;
 
							if (start != NULL)
 
							{
 
								char *img_start;
 
								//find end of l33l block
 
								char *end = (char *)memmem(start+4, image_data+image_data_len-start-4, "l33l", 4);
 
								if (!end) end = image_data+image_data_len;
 
								
 
								//look for start of JPEG block
 
								img_start = (char *)memmem(start, end-start, "\xFF\xD8", 2);
 
								if (img_start)
 
								{
 
									//look for end of JPEG block
 
									char *img_end = (char *)memmem(img_start, end-img_start, "\xFF\xD9", 2);
 
									if (img_end)
 
									{
 
										image_data_len = img_end - img_start + 2;
 
										photo = std::string(img_start, image_data_len);
 
									}
 
								}
 
							}
 
						}
 
						g_free(image_data);
 
					}
 
					g_free(filename);
 
				}
 
				g_free(username);
 
				
 
				std::string alias = "";
 
				std::cout << skype->getUsername() << " " << name << "\n";
 
				if (skype->getUsername() == name) {
 
					alias = skype->send_command("GET PROFILE FULLNAME");
 
					alias = alias.substr(17);
 
				}
 
				handleVCard(user, id, legacyName, "", alias, photo);
 
			}
 
		}
 

	
 
		void sendData(const std::string &string) {
 
			write(m_sock, string.c_str(), string.size());
 
// 			if (writeInput == 0)
 
// 				writeInput = purple_input_add(m_sock, PURPLE_INPUT_WRITE, &transportDataReceived, NULL);
 
		}
 

	
 
		void handleVCardUpdatedRequest(const std::string &user, const std::string &p, const std::string &nickname) {
 
		}
 

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

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

	
 
		}
 

	
 
		void handleBuddyBlockToggled(const std::string &user, const std::string &buddyName, bool blocked) {
 

	
 
		}
 

	
 
		void handleTypingRequest(const std::string &user, const std::string &buddyName) {
 

	
 
		}
 

	
 
		void handleTypedRequest(const std::string &user, const std::string &buddyName) {
 

	
 
		}
 

	
 
		void handleStoppedTypingRequest(const std::string &user, const std::string &buddyName) {
 

	
 
		}
 

	
 
		void handleAttentionRequest(const std::string &user, const std::string &buddyName, const std::string &message) {
 

	
 
		}
 

	
 
		std::map<std::string, Skype *> m_sessions;
 
		std::map<Skype *, std::string> m_accounts;
 
		std::map<std::string, unsigned int> m_vcards;
 
		Config *config;
 
		
 
};
 

	
 

	
 
Skype::Skype(const std::string &user, const std::string &username, const std::string &password) {
 
	m_username = username;
 
	m_user = user;
 
	m_password = password;
 
	m_pid = 0;
 
	m_connection = 0;
 
	m_proxy = 0;
 
	m_timer = -1;
 
	m_counter = 0;
 
}
 

	
 

	
 
static gboolean load_skype_buddies(gpointer data) {
 
	Skype *skype = (Skype *) data;
 
	return skype->loadSkypeBuddies();
 
}
 

	
 
bool Skype::createDBusProxy() {
 
	if (m_proxy == NULL) {
 
		LOG4CXX_INFO(logger, "Creating DBus proxy for com.Skype.Api.");
 
		m_counter++;
 

	
 
		GError *error = NULL;
 
		m_proxy = dbus_g_proxy_new_for_name_owner (m_connection, "com.Skype.API", "/com/Skype", "com.Skype.API", &error);
 
		if (m_proxy == NULL && error != NULL) {
 
			LOG4CXX_INFO(logger,  m_username << ":" << error->message);
 

	
 
			if (m_counter == 15) {
 
				np->handleDisconnected(m_user, 0, error->message);
 
				logout();
 
				g_error_free(error);
 
				return FALSE;
 
			}
 
			g_error_free(error);
 
		}
 

	
 
		if (m_proxy) {
 
			LOG4CXX_INFO(logger, "Proxy created.");
 
			DBusObjectPathVTable vtable;
 
			vtable.message_function = &skype_notify_handler;
 
			dbus_connection_register_object_path(dbus_g_connection_get_connection(m_connection), "/com/Skype/Client", &vtable, this);
 

	
 
			m_counter = 0;
 
			m_timer = g_timeout_add_seconds(1, load_skype_buddies, this);
 
			return FALSE;
 
		}
 
		return TRUE;
 
	}
 
	return FALSE;
 
}
 

	
 
static gboolean create_dbus_proxy(gpointer data) {
 
	Skype *skype = (Skype *) data;
 
	return skype->createDBusProxy();
 
}
 

	
 
void Skype::login() {
 
	boost::filesystem::path	path(std::string("/tmp/skype/") + m_username);
 
	if (!boost::filesystem::exists(path)) {
 
		boost::filesystem::create_directories(path);
 
		boost::filesystem::path	path2(std::string("/tmp/skype/") + m_username + "/" + m_username );
 
		boost::filesystem::create_directories(path2);
 
	}
 

	
 
	std::string shared_xml = "<?xml version=\"1.0\"?>\n"
 
							"<config version=\"1.0\" serial=\"28\" timestamp=\"" + boost::lexical_cast<std::string>(time(NULL)) + ".0\">\n"
 
							"<UI>\n"
 
								"<Installed>2</Installed>\n"
 
								"<Language>en</Language>\n"
 
							"</UI>\n"
 
							"</config>\n";
 
	g_file_set_contents(std::string(std::string("/tmp/skype/") + m_username + "/shared.xml").c_str(), shared_xml.c_str(), -1, NULL);
 

	
 
	std::string config_xml = "<?xml version=\"1.0\"?>\n"
 
							"<config version=\"1.0\" serial=\"7\" timestamp=\"" + boost::lexical_cast<std::string>(time(NULL)) + ".0\">\n"
 
								"<Lib>\n"
 
									"<Account>\n"
 
									"<IdleTimeForAway>30000000</IdleTimeForAway>\n"
 
									"<IdleTimeForNA>300000000</IdleTimeForNA>\n"
 
									"<LastUsed>" + boost::lexical_cast<std::string>(time(NULL)) + "</LastUsed>\n"
 
									"</Account>\n"
 
								"</Lib>\n"
 
								"<UI>\n"
 
									"<API>\n"
 
									"<Authorizations>Spectrum</Authorizations>\n"
 
									"<BlockedPrograms></BlockedPrograms>\n"
 
									"</API>\n"
 
								"</UI>\n"
 
							"</config>\n";
 
	g_file_set_contents(std::string(std::string("/tmp/skype/") + m_username + "/" + m_username +"/config.xml").c_str(), config_xml.c_str(), -1, NULL);
 

	
 
	std::string db_path = std::string("/tmp/skype/") + m_username;
 
	char *db = (char *) malloc(db_path.size() + 1);
 
	strcpy(db, db_path.c_str());
 
	LOG4CXX_INFO(logger,  m_username << ": Spawning new Skype instance dbpath=" << db);
 
	gchar* argv[6] = {"skype", "--disable-cleanlooks", "--pipelogin", "--dbpath", db, 0};
 

	
 
	int fd;
 
	g_spawn_async_with_pipes(NULL,
 
		argv,
 
		NULL /*envp*/,
 
		G_SPAWN_SEARCH_PATH,
 
		NULL /*child_setup*/,
 
		NULL /*user_data*/,
 
		&m_pid /*child_pid*/,
 
		&fd,
 
		NULL,
 
		&fd_output,
 
		NULL /*error*/);
 
	std::string login_data = std::string(m_username + " " + m_password + "\n");
 
	LOG4CXX_INFO(logger,  m_username << ": Login data=" << login_data);
 
	write(fd, login_data.c_str(), login_data.size());
 
	close(fd);
 

	
 
	fcntl (fd_output, F_SETFL, O_NONBLOCK);
 

	
 
	free(db);
 

	
 
	//Initialise threading
 
	dbus_threads_init_default();
 

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

	
 
	m_timer = g_timeout_add_seconds(1, create_dbus_proxy, this);
 
}
 

	
 
bool Skype::loadSkypeBuddies() {
 
//	std::string re = "CONNSTATUS OFFLINE";
 
//	while (re == "CONNSTATUS OFFLINE" || re.empty()) {
 
//		sleep(1);
 

	
 
	gchar buffer[1024];
 
	int bytes_read = read(fd_output, buffer, 1023);
 
	if (bytes_read > 0) {
 
		buffer[bytes_read] = 0;
 
		np->handleDisconnected(m_user, 0, buffer);
 
		close(fd_output);
 
		logout();
 
		return FALSE;
 
	}
 

	
 
	std::string re = send_command("NAME Spectrum");
 
	if (m_counter++ > 15) {
 
		np->handleDisconnected(m_user, 0, "");
 
		close(fd_output);
 
		logout();
 
		return FALSE;
 
	}
 

	
 
	if (re.empty() || re == "CONNSTATUS OFFLINE") {
 
		return TRUE;
 
	}
 

	
 
	close(fd_output);
 

	
 
	if (send_command("PROTOCOL 7") != "PROTOCOL 7") {
 
		np->handleDisconnected(m_user, 0, "Skype is not ready");
 
		logout();
 
		return FALSE;
 
	}
 

	
 
	np->handleConnected(m_user);
 

	
 
	std::map<std::string, std::string> group_map;
 
	std::string groups = send_command("SEARCH GROUPS CUSTOM");
 
	groups = groups.substr(groups.find(' ') + 1);
 
	std::vector<std::string> grps;
 
	boost::split(grps, groups, boost::is_any_of(","));
 
	BOOST_FOREACH(std::string grp, grps) {
 
		std::vector<std::string> data;
 
		std::string name = send_command("GET GROUP " + grp + " DISPLAYNAME");
 
		boost::split(data, name, boost::is_any_of(" "));
 
		name = name.substr(name.find("DISPLAYNAME") + 12);
 

	
 
		std::string users = send_command("GET GROUP " + data[1] + " USERS");
 
		users = name.substr(name.find("USERS") + 6);
 
		boost::split(data, users, boost::is_any_of(","));
 
		BOOST_FOREACH(std::string u, data) {
 
			group_map[u] = grp;
 
		}
 
	}
 

	
 
	std::string friends = send_command("GET AUTH_CONTACTS_PROFILES");
 

	
 
	char **full_friends_list = g_strsplit((strchr(friends.c_str(), ' ')+1), ";", 0);
 
	if (full_friends_list && full_friends_list[0])
 
	{
 
		//in the format of: username;full name;phone;office phone;mobile phone;
 
		//                  online status;friendly name;voicemail;mood
 
		// (comma-seperated lines, usernames can have comma's)
 

	
 
		for (int i=0; full_friends_list[i] && full_friends_list[i+1] && *full_friends_list[i] != '\0'; i+=8)
 
		{
 
			std::string buddy = full_friends_list[i];
 

	
 
			if (buddy[0] == ',') {
 
				buddy.erase(buddy.begin());
 
			}
 

	
 
			if (buddy.rfind(",") != std::string::npos) {
 
				buddy = buddy.substr(buddy.rfind(","));
 
			}
 

	
 
			if (buddy[0] == ',') {
 
				buddy.erase(buddy.begin());
 
			}
 

	
 
			LOG4CXX_INFO(logger, "Got buddy " << buddy);
 
			std::string st = full_friends_list[i + 5];
 

	
 
			pbnetwork::StatusType status = getStatus(st);
 

	
 
			std::string alias = full_friends_list[i + 6];
 

	
 
			std::string mood_text = "";
 
			if (full_friends_list[i + 8] && *full_friends_list[i + 8] != '\0' && *full_friends_list[i + 8] != ',') {
 
				mood_text = full_friends_list[i + 8];
 
			}
 

	
 
			std::vector<std::string> groups;
 
			if (group_map.find(buddy) != group_map.end()) {
 
				groups.push_back(group_map[buddy]);
 
			}
 
			np->handleBuddyChanged(m_user, buddy, alias, groups, status, mood_text);
 
		}
 
	}
 
	g_strfreev(full_friends_list);
 

	
 
	send_command("SET AUTOAWAY OFF");
 
	send_command("SET USERSTATUS ONLINE");
 
	return FALSE;
 
}
 

	
 
void Skype::logout() {
 
	if (m_pid != 0) {
 
		send_command("SET USERSTATUS INVISIBLE");
 
		send_command("SET USERSTATUS OFFLINE");
 
		sleep(2);
 
		g_object_unref(m_proxy);
 
		LOG4CXX_INFO(logger,  m_username << ": Killing Skype instance");
 
		kill((int) m_pid, SIGTERM);
 
		m_pid = 0;
 
	}
 
}
 

	
 
std::string Skype::send_command(const std::string &message) {
 
	GError *error = NULL;
 
	gchar *str = NULL;
 
// 			int message_num;
 
// 			gchar error_return[30];
 

	
 
	if (!dbus_g_proxy_call (m_proxy, "Invoke", &error, G_TYPE_STRING, message.c_str(), G_TYPE_INVALID,
 
						G_TYPE_STRING, &str, G_TYPE_INVALID))
 
	{
 
			if (error && error->message)
 
			{
 
			LOG4CXX_INFO(logger,  m_username << ": DBUS Error: " << error->message);
 
			g_error_free(error);
 
		} else {
 
			LOG4CXX_INFO(logger,  m_username << ": DBUS no response");
 
		}
 

	
 
	}
 
	if (str != NULL)
 
	{
 
		LOG4CXX_INFO(logger,  m_username << ": DBUS:" << str);
 
	}
 
	return str ? std::string(str) : std::string();
 
}
 

	
 
static void handle_skype_message(std::string &message, Skype *sk) {
 
	std::vector<std::string> cmd;
 
	boost::split(cmd, message, boost::is_any_of(" "));
 

	
 
	if (cmd[0] == "USER") {
 
		if (cmd[1] == sk->getUsername()) {
 
			return;
 
		}
 

	
 
		if (cmd[2] == "ONLINESTATUS") {
 
			if (cmd[3] == "SKYPEOUT" || cmd[3] == "UNKNOWN") {
 
				return;
 
			}
 
			else {
 
				pbnetwork::StatusType status = getStatus(cmd[3]);
 
				std::string mood_text = sk->send_command("GET USER " + cmd[1] + " MOOD_TEXT");
 
				mood_text = mood_text.substr(mood_text.find("MOOD_TEXT") + 10);
 

	
 
				std::string alias = sk->send_command("GET USER " + cmd[1] + " FULLNAME");
 
				alias = alias.substr(alias.find("FULLNAME") + 9);
 

	
 
				std::vector<std::string> groups;
 
				np->handleBuddyChanged(sk->getUser(), cmd[1], alias, groups, status, mood_text);
 
			}
 
		}
 
		else if (cmd[2] == "MOOD_TEXT") {
 
			std::string st = sk->send_command("GET USER " + cmd[1] + " ONLINESTATUS");
 
			st = st.substr(st.find("ONLINESTATUS") + 13);
 
			pbnetwork::StatusType status = getStatus(st);
 

	
 
			std::string mood_text = message.substr(message.find("MOOD_TEXT") + 10);
 

	
 
			std::vector<std::string> groups;
 
			np->handleBuddyChanged(sk->getUser(), cmd[1], "", groups, status, mood_text);
 
		}
 
		else if (cmd[2] == "BUDDYSTATUS" && cmd[3] == "3") {
 
			std::string st = sk->send_command("GET USER " + cmd[1] + " ONLINESTATUS");
 
			st = st.substr(st.find("ONLINESTATUS") + 13);
 
			pbnetwork::StatusType status = getStatus(st);
 

	
 
			std::string mood_text = message.substr(message.find("MOOD_TEXT") + 10);
 

	
 
			std::vector<std::string> groups;
 
			np->handleBuddyChanged(sk->getUser(), cmd[1], "", groups, status, mood_text);
 
		}
 
		else if (cmd[2] == "FULLNAME") {
 
			std::string st = sk->send_command("GET USER " + cmd[1] + " ONLINESTATUS");
 
			st = st.substr(st.find("ONLINESTATUS") + 13);
 
			pbnetwork::StatusType status = getStatus(st);
 

	
 
			std::string mood_text = sk->send_command("GET USER " + cmd[1] + " MOOD_TEXT");
 
			mood_text = mood_text.substr(mood_text.find("MOOD_TEXT") + 10);
 

	
 
			std::string alias = message.substr(message.find("FULLNAME") + 9);
 

	
 
			std::vector<std::string> groups;
 
			np->handleBuddyChanged(sk->getUser(), cmd[1], alias, groups, status, mood_text);
 
		}
 
	}
 
	else if (cmd[0] == "CHATMESSAGE") {
 
		if (cmd[3] == "RECEIVED") {
 
			std::string body = sk->send_command("GET CHATMESSAGE " + cmd[1] + " BODY");
 
			body = body.substr(body.find("BODY") + 5);
 

	
 
			std::string chatname = sk->send_command("GET CHATMESSAGE " + cmd[1] + " CHATNAME");
 
			size_t start = chatname.find("$") + 1;
 
			size_t len = chatname.find(";") - start;
 
			std::string from = chatname.substr(start, len);
 

	
 
			std::string from_handle = sk->send_command("GET CHATMESSAGE " + cmd[1] + " FROM_HANDLE");
 
			from_handle = from_handle.substr(from_handle.find("FROM_HANDLE") + 12);
 

	
 
// 			if (from_handle != sk->getUsername()) {
 
				from = from_handle;
 
// 			}
 
			if (from_handle == sk->getUsername())
 
				return;
 

	
 
			np->handleMessage(sk->getUser(), from, body);
 
		}
 
	}
 
}
 

	
 
DBusHandlerResult skype_notify_handler(DBusConnection *connection, DBusMessage *message, gpointer user_data) {
 
	DBusMessageIter iterator;
 
	gchar *message_temp;
 
	DBusMessage *temp_message;
 
	
 
	temp_message = dbus_message_ref(message);
 
	dbus_message_iter_init(temp_message, &iterator);
 
	if (dbus_message_iter_get_arg_type(&iterator) != DBUS_TYPE_STRING)
 
	{
 
		dbus_message_unref(message);
 
		return (DBusHandlerResult) FALSE;
 
	}
 
	
 
	do {
 
		dbus_message_iter_get_basic(&iterator, &message_temp);
 
		std::string m(message_temp);
 
		LOG4CXX_INFO(logger,"DBUS message: " << m);
 
		handle_skype_message(m, (Skype *) user_data);
 
	} while(dbus_message_iter_has_next(&iterator) && dbus_message_iter_next(&iterator));
 
	
 
	dbus_message_unref(message);
 
	
 
	return DBUS_HANDLER_RESULT_HANDLED;
 
}
 

	
 
static void spectrum_sigchld_handler(int sig)
 
{
 
	int status;
 
	pid_t pid;
 

	
 
	do {
 
		pid = waitpid(-1, &status, WNOHANG);
 
	} while (pid != 0 && pid != (pid_t)-1);
 

	
 
	if ((pid == (pid_t) - 1) && (errno != ECHILD)) {
 
		char errmsg[BUFSIZ];
 
		snprintf(errmsg, BUFSIZ, "Warning: waitpid() returned %d", pid);
 
		perror(errmsg);
 
	}
 
}
 

	
 
static int create_socket(char *host, int portno) {
 
	struct sockaddr_in serv_addr;
 
	
 
	int m_sock = socket(AF_INET, SOCK_STREAM, 0);
 
	memset((char *) &serv_addr, 0, sizeof(serv_addr));
 
	serv_addr.sin_family = AF_INET;
 
	serv_addr.sin_port = htons(portno);
 

	
 
	hostent *hos;  // Resolve name
 
	if ((hos = gethostbyname(host)) == NULL) {
 
		// strerror() will not work for gethostbyname() and hstrerror() 
 
		// is supposedly obsolete
 
		exit(1);
 
	}
 
	serv_addr.sin_addr.s_addr = *((unsigned long *) hos->h_addr_list[0]);
 

	
 
	if (connect(m_sock, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
 
		close(m_sock);
 
		m_sock = 0;
 
	}
 

	
 
	int flags = fcntl(m_sock, F_GETFL);
 
	flags |= O_NONBLOCK;
 
	fcntl(m_sock, F_SETFL, flags);
 
	return m_sock;
 
}
 

	
 

	
 
static gboolean transportDataReceived(GIOChannel *source, GIOCondition condition, gpointer data) {
 
	char buffer[65535];
 
	char *ptr = buffer;
 
	ssize_t n = read(m_sock, ptr, sizeof(buffer));
 
	if (n <= 0) {
 
		LOG4CXX_INFO(logger, "Diconnecting from spectrum2 server");
 
		exit(errno);
 
	}
 
	std::string d = std::string(buffer, n);
 
	np->handleDataRead(d);
 
	return TRUE;
 
}
 

	
 
static void io_destroy(gpointer data) {
 
	exit(1);
 
}
 

	
 
static void log_glib_error(const gchar *string) {
 
	LOG4CXX_ERROR(logger, "GLIB ERROR:" << string);
 
}
 

	
 
int main(int argc, char **argv) {
 
	GError *error = NULL;
 
	GOptionContext *context;
 
	context = g_option_context_new("config_file_name or profile name");
 
	g_option_context_add_main_entries(context, options_entries, "");
 
	if (!g_option_context_parse (context, &argc, &argv, &error)) {
 
		std::cout << "option parsing failed: " << error->message << "\n";
 
		return -1;
 
	}
 

	
 
	if (ver) {
 
// 		std::cout << VERSION << "\n";
 
		std::cout << "verze\n";
 
		g_option_context_free(context);
 
		return 0;
 
	}
 

	
 
	if (argc != 2) {
 
#ifdef WIN32
 
		std::cout << "Usage: spectrum.exe <configuration_file.cfg>\n";
 
#else
 

	
 
#if GLIB_CHECK_VERSION(2,14,0)
 
	std::cout << g_option_context_get_help(context, FALSE, NULL);
 
#else
 
	std::cout << "Usage: spectrum <configuration_file.cfg>\n";
 
	std::cout << "See \"man spectrum\" for more info.\n";
 
#endif
 
		
 
#endif
 
	}
 
	else {
 
#ifndef WIN32
 
		signal(SIGPIPE, SIG_IGN);
 

	
 
		if (signal(SIGCHLD, spectrum_sigchld_handler) == SIG_ERR) {
 
			std::cout << "SIGCHLD handler can't be set\n";
 
			g_option_context_free(context);
 
			return -1;
 
		}
 
// 
 
// 		if (signal(SIGINT, spectrum_sigint_handler) == SIG_ERR) {
 
// 			std::cout << "SIGINT handler can't be set\n";
 
// 			g_option_context_free(context);
 
// 			return -1;
 
// 		}
 
// 
 
// 		if (signal(SIGTERM, spectrum_sigterm_handler) == SIG_ERR) {
 
// 			std::cout << "SIGTERM handler can't be set\n";
 
// 			g_option_context_free(context);
 
// 			return -1;
 
// 		}
 
// 
 
// 		struct sigaction sa;
 
// 		memset(&sa, 0, sizeof(sa)); 
 
// 		sa.sa_handler = spectrum_sighup_handler;
 
// 		if (sigaction(SIGHUP, &sa, NULL)) {
 
// 			std::cout << "SIGHUP handler can't be set\n";
 
// 			g_option_context_free(context);
 
// 			return -1;
 
//		}
 
#endif
 
		Config config;
 
		if (!config.load(argv[1])) {
 
			std::cout << "Can't open " << argv[1] << " configuration file.\n";
 
			return 1;
 
		}
 

	
 
		if (CONFIG_STRING(&config, "logging.backend_config").empty()) {
 
			LoggerPtr root = log4cxx::Logger::getRootLogger();
 
			root->addAppender(new ConsoleAppender(new PatternLayout("%d %-5p %c: %m%n")));
 
		}
 
		else {
 
			log4cxx::helpers::Properties p;
 
			log4cxx::helpers::FileInputStream *istream = new log4cxx::helpers::FileInputStream(CONFIG_STRING(&config, "logging.backend_config"));
 

	
 
			p.load(istream);
 
			p.setProperty("pid", boost::lexical_cast<std::string>(getpid()));
 
			log4cxx::PropertyConfigurator::configure(p);
 
		}
 

	
 
// 		initPurple(config);
 

	
 
		g_type_init();
 

	
 
		m_sock = create_socket(host, port);
 

	
 
		g_set_printerr_handler(log_glib_error);
 

	
 
	GIOChannel *channel;
 
	GIOCondition cond = (GIOCondition) G_IO_IN;
 
	channel = g_io_channel_unix_new(m_sock);
 
	g_io_add_watch_full(channel, G_PRIORITY_DEFAULT, cond, transportDataReceived, NULL, io_destroy);
 

	
 
		np = new SpectrumNetworkPlugin(&config, host, port);
 

	
 
		GMainLoop *m_loop;
 
		m_loop = g_main_loop_new(NULL, FALSE);
 

	
 
		if (m_loop) {
 
			g_main_loop_run(m_loop);
 
		}
 
	}
 

	
 
	g_option_context_free(context);
 
}
backends/smstools3/CMakeLists.txt
Show inline comments
 
new file 100644
 
cmake_minimum_required(VERSION 2.6)
 
 
FILE(GLOB SRC *.c *.cpp)
 
 
ADD_EXECUTABLE(spectrum2_smstools3_backend ${SRC})
 
 
target_link_libraries(spectrum2_smstools3_backend transport pthread ${Boost_LIBRARIES} ${SWIFTEN_LIBRARY} ${LOG4CXX_LIBRARIES})
 
 
INSTALL(TARGETS spectrum2_smstools3_backend RUNTIME DESTINATION bin)
 
backends/smstools3/main.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 "transport/config.h"
 
#include "transport/networkplugin.h"
 
#include "transport/sqlite3backend.h"
 
#include "transport/mysqlbackend.h"
 
#include "transport/pqxxbackend.h"
 
#include "transport/storagebackend.h"
 
#include "Swiften/Swiften.h"
 
#include <boost/filesystem.hpp>
 
#include "unistd.h"
 
#include "signal.h"
 
#include "sys/wait.h"
 
#include "sys/signal.h"
 
#include <fstream>
 
#include <streambuf>
 

	
 
Swift::SimpleEventLoop *loop_;
 

	
 
#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"
 
#include <boost/filesystem.hpp>
 
#include <boost/algorithm/string.hpp>
 

	
 
using namespace boost::filesystem;
 

	
 
using namespace boost::program_options;
 
using namespace Transport;
 

	
 
using namespace log4cxx;
 

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

	
 
#define INTERNAL_USER "/sms@backend@internal@user"
 

	
 
class SMSNetworkPlugin;
 
SMSNetworkPlugin * np = NULL;
 
StorageBackend *storageBackend;
 

	
 
class SMSNetworkPlugin : public NetworkPlugin {
 
	public:
 
		Swift::BoostNetworkFactories *m_factories;
 
		Swift::BoostIOServiceThread m_boostIOServiceThread;
 
		boost::shared_ptr<Swift::Connection> m_conn;
 
		Swift::Timer::ref m_timer;
 
		int m_internalUser;
 

	
 
		SMSNetworkPlugin(Config *config, Swift::SimpleEventLoop *loop, const std::string &host, int port) : NetworkPlugin() {
 
			this->config = config;
 
			m_factories = new Swift::BoostNetworkFactories(loop);
 
			m_conn = m_factories->getConnectionFactory()->createConnection();
 
			m_conn->onDataRead.connect(boost::bind(&SMSNetworkPlugin::_handleDataRead, this, _1));
 
			m_conn->connect(Swift::HostAddressPort(Swift::HostAddress(host), port));
 
// 			m_conn->onConnectFinished.connect(boost::bind(&FrotzNetworkPlugin::_handleConnected, this, _1));
 
// 			m_conn->onDisconnected.connect(boost::bind(&FrotzNetworkPlugin::handleDisconnected, this));
 

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

	
 
			m_timer = m_factories->getTimerFactory()->createTimer(5000);
 
			m_timer->onTick.connect(boost::bind(&SMSNetworkPlugin::handleSMSDir, this));
 
			m_timer->start();
 

	
 
			// We're reusing our database model here. Buddies of user with JID INTERNAL_USER are there
 
			// to match received GSM messages from number N with the XMPP users who sent message to number N.
 
			// BuddyName = GSM number
 
			// Alias = XMPP user JID to which the messages from this number is sent to.
 
			// TODO: This should be per Modem!!!
 
			UserInfo info;
 
			info.jid = INTERNAL_USER;
 
			info.password = "";
 
			storageBackend->setUser(info);
 
			storageBackend->getUser(INTERNAL_USER, info);
 
			m_internalUser = info.id;
 
		}
 

	
 

	
 
		void handleSMS(const std::string &sms) {
 
			LOG4CXX_INFO(logger, "Handling SMS " << sms << ".")
 
			std::ifstream t(sms.c_str());
 
			std::string str;
 

	
 
			t.seekg(0, std::ios::end);
 
			str.reserve(t.tellg());
 
			t.seekg(0, std::ios::beg);
 

	
 
			str.assign((std::istreambuf_iterator<char>(t)), std::istreambuf_iterator<char>());
 

	
 
			std::string from = "";
 
			std::string msg = "";
 
			while(str.find("\n") != std::string::npos) {
 
				std::string line = str.substr(0, str.find("\n"));
 
				if (line.find("From: ") == 0) {
 
					from = line.substr(strlen("From: "));
 
				}
 
				else if (line.empty()) {
 
					msg = str.substr(1);
 
					break;
 
				}
 
				str = str.substr(str.find("\n") + 1);
 
			}
 

	
 
			std::list<BuddyInfo> roster;
 
			storageBackend->getBuddies(m_internalUser, roster);
 

	
 
			std::string to;
 
			BOOST_FOREACH(BuddyInfo &b, roster) {
 
				if (b.legacyName == from) {
 
					to = b.alias;
 
				}
 
			}
 

	
 
			if (to.empty()) {
 
				LOG4CXX_WARN(logger, "Received SMS from " << from << ", but this number is not associated with any XMPP user.");
 
			}
 

	
 
			LOG4CXX_INFO(logger, "Forwarding SMS from " << from << " to " << to << ".");
 
			handleMessage(to, from, msg);
 
		}
 

	
 
		void handleSMSDir() {
 
			std::string dir = "/var/spool/sms/incoming/";
 
			if (config->getUnregistered().find("backend.incoming_dir") != config->getUnregistered().end()) {
 
				dir = config->getUnregistered().find("backend.incoming_dir")->second;
 
			}
 
			LOG4CXX_INFO(logger, "Checking directory " << dir << " for incoming SMS.");
 

	
 
			path p(dir);
 
			directory_iterator end_itr;
 
			for (directory_iterator itr(p); itr != end_itr; ++itr) {
 

	
 
				try {
 
					if (is_regular(itr->path())) {
 
						handleSMS(itr->path().string());
 
						remove(itr->path());
 
					}
 
				}
 
				catch (const filesystem_error& ex) {
 
					LOG4CXX_ERROR(logger, "Error when removing the SMS: " << ex.what() << ".");
 
				}
 
			}
 
			m_timer->start();
 
		}
 

	
 
		void sendSMS(const std::string &to, const std::string &msg) {
 
			// TODO: Probably 
 
			std::string data = "To: " + to + "\n";
 
			data += "\n";
 
			data += msg;
 

	
 
			// generate random string here...
 
			std::string bucket = "abcdefghijklmnopqrstuvwxyz";
 
			std::string uuid;
 
			for (int i = 0; i < 10; i++) {
 
				uuid += bucket[rand() % bucket.size()];
 
			}
 
			std::ofstream myfile;
 
			myfile.open (std::string("/var/spool/sms/outgoing/spectrum." + uuid).c_str());
 
			myfile << data;
 
			myfile.close();
 
		}
 

	
 
		void sendData(const std::string &string) {
 
			m_conn->write(Swift::createSafeByteArray(string));
 
		}
 

	
 
		void _handleDataRead(boost::shared_ptr<Swift::SafeByteArray> data) {
 
			std::string d(data->begin(), data->end());
 
			handleDataRead(d);
 
		}
 

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

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

	
 
			np->handleConnected(user);
 
		}
 

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

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

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

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

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

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

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

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

	
 
		}
 

	
 

	
 
	private:
 
		
 
		Config *config;
 
};
 

	
 
static void spectrum_sigchld_handler(int sig)
 
{
 
	int status;
 
	pid_t pid;
 

	
 
	do {
 
		pid = waitpid(-1, &status, WNOHANG);
 
	} while (pid != 0 && pid != (pid_t)-1);
 

	
 
	if ((pid == (pid_t) - 1) && (errno != ECHILD)) {
 
		char errmsg[BUFSIZ];
 
		snprintf(errmsg, BUFSIZ, "Warning: waitpid() returned %d", pid);
 
		perror(errmsg);
 
	}
 
}
 

	
 

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

	
 
	if (signal(SIGCHLD, spectrum_sigchld_handler) == SIG_ERR) {
 
		std::cout << "SIGCHLD handler can't be set\n";
 
		return -1;
 
	}
 

	
 
	boost::program_options::options_description desc("Usage: spectrum [OPTIONS] <config_file.cfg>\nAllowed options");
 
	desc.add_options()
 
		("host,h", value<std::string>(&host), "host")
 
		("port,p", value<int>(&port), "port")
 
		;
 
	try
 
	{
 
		boost::program_options::variables_map vm;
 
		boost::program_options::store(boost::program_options::parse_command_line(argc, argv, desc), vm);
 
		boost::program_options::notify(vm);
 
	}
 
	catch (std::runtime_error& e)
 
	{
 
		std::cout << desc << "\n";
 
		exit(1);
 
	}
 
	catch (...)
 
	{
 
		std::cout << desc << "\n";
 
		exit(1);
 
	}
 

	
 

	
 
	if (argc < 5) {
 
		return 1;
 
	}
 

	
 
// 	QStringList channels;
 
// 	for (int i = 3; i < argc; ++i)
 
// 	{
 
// 		channels.append(argv[i]);
 
// 	}
 
// 
 
// 	MyIrcSession session;
 
// 	session.setNick(argv[2]);
 
// 	session.setAutoJoinChannels(channels);
 
// 	session.connectToServer(argv[1], 6667);
 

	
 
	Config config;
 
	if (!config.load(argv[5])) {
 
		std::cerr << "Can't open " << argv[1] << " configuration file.\n";
 
		return 1;
 
	}
 

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

	
 
#ifdef WITH_SQLITE
 
	if (CONFIG_STRING(&config, "database.type") == "sqlite3") {
 
		storageBackend = new SQLite3Backend(&config);
 
		if (!storageBackend->connect()) {
 
			std::cerr << "Can't connect to database. Check the log to find out the reason.\n";
 
			return -1;
 
		}
 
	}
 
#else
 
	if (CONFIG_STRING(&config, "database.type") == "sqlite3") {
 
		std::cerr << "Spectrum2 is not compiled with mysql backend.\n";
 
		return -2;
 
	}
 
#endif
 

	
 
#ifdef WITH_MYSQL
 
	if (CONFIG_STRING(&config, "database.type") == "mysql") {
 
		storageBackend = new MySQLBackend(&config);
 
		if (!storageBackend->connect()) {
 
			std::cerr << "Can't connect to database. Check the log to find out the reason.\n";
 
			return -1;
 
		}
 
	}
 
#else
 
	if (CONFIG_STRING(&config, "database.type") == "mysql") {
 
		std::cerr << "Spectrum2 is not compiled with mysql backend.\n";
 
		return -2;
 
	}
 
#endif
 

	
 
#ifdef WITH_PQXX
 
	if (CONFIG_STRING(&config, "database.type") == "pqxx") {
 
		storageBackend = new PQXXBackend(&config);
 
		if (!storageBackend->connect()) {
 
			std::cerr << "Can't connect to database. Check the log to find out the reason.\n";
 
			return -1;
 
		}
 
	}
 
#else
 
	if (CONFIG_STRING(&config, "database.type") == "pqxx") {
 
		std::cerr << "Spectrum2 is not compiled with pqxx backend.\n";
 
		return -2;
 
	}
 
#endif
 

	
 
	if (CONFIG_STRING(&config, "database.type") != "mysql" && CONFIG_STRING(&config, "database.type") != "sqlite3"
 
		&& CONFIG_STRING(&config, "database.type") != "pqxx" && CONFIG_STRING(&config, "database.type") != "none") {
 
		std::cerr << "Unknown storage backend " << CONFIG_STRING(&config, "database.type") << "\n";
 
		return -2;
 
	}
 

	
 
	Swift::SimpleEventLoop eventLoop;
 
	loop_ = &eventLoop;
 
	np = new SMSNetworkPlugin(&config, &eventLoop, host, port);
 
	loop_->run();
 

	
 
	return 0;
 
}
backends/template/CMakeLists.txt
Show inline comments
 
new file 100644
 
cmake_minimum_required(VERSION 2.6)
 
 
FILE(GLOB SRC *.c *.cpp)
 
 
ADD_EXECUTABLE(spectrum2_template_backend ${SRC})
 
 
target_link_libraries(spectrum2_template_backend transport pthread ${Boost_LIBRARIES} ${SWIFTEN_LIBRARY} ${LOG4CXX_LIBRARIES})
 
 
#INSTALL(TARGETS spectrum2_template_backend RUNTIME DESTINATION bin)
 
backends/template/README
Show inline comments
 
new file 100644
 
This is just template for creating new generic spectrum2 backends. It does not do anything!
 
\ No newline at end of file
backends/template/main.cpp
Show inline comments
 
new file 100644
 
// Transport includes
 
#include "transport/config.h"
 
#include "transport/networkplugin.h"
 

	
 
// Swiften
 
#include "Swiften/Swiften.h"
 

	
 
// for signal handler
 
#include "unistd.h"
 
#include "signal.h"
 
#include "sys/wait.h"
 
#include "sys/signal.h"
 

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

	
 
// Boost
 
#include <boost/algorithm/string.hpp>
 
using namespace boost::filesystem;
 
using namespace boost::program_options;
 
using namespace Transport;
 

	
 
// log4cxx main logger
 
using namespace log4cxx;
 
static LoggerPtr logger = log4cxx::Logger::getLogger("Backend Template");
 

	
 
// eventloop
 
Swift::SimpleEventLoop *loop_;
 

	
 
// Plugin
 
class TemplatePlugin;
 
TemplatePlugin * np = NULL;
 

	
 
class TemplatePlugin : public NetworkPlugin {
 
	public:
 
		Swift::BoostNetworkFactories *m_factories;
 
		Swift::BoostIOServiceThread m_boostIOServiceThread;
 
		boost::shared_ptr<Swift::Connection> m_conn;
 

	
 
		TemplatePlugin(Config *config, Swift::SimpleEventLoop *loop, const std::string &host, int port) : NetworkPlugin() {
 
			this->config = config;
 
			m_factories = new Swift::BoostNetworkFactories(loop);
 
			m_conn = m_factories->getConnectionFactory()->createConnection();
 
			m_conn->onDataRead.connect(boost::bind(&TemplatePlugin::_handleDataRead, this, _1));
 
			m_conn->connect(Swift::HostAddressPort(Swift::HostAddress(host), port));
 

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

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

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

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

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

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

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

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

	
 
		}
 

	
 
	private:
 
		Config *config;
 
};
 

	
 
static void spectrum_sigchld_handler(int sig)
 
{
 
	int status;
 
	pid_t pid;
 

	
 
	do {
 
		pid = waitpid(-1, &status, WNOHANG);
 
	} while (pid != 0 && pid != (pid_t)-1);
 

	
 
	if ((pid == (pid_t) - 1) && (errno != ECHILD)) {
 
		char errmsg[BUFSIZ];
 
		snprintf(errmsg, BUFSIZ, "Warning: waitpid() returned %d", pid);
 
		perror(errmsg);
 
	}
 
}
 

	
 

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

	
 
	if (signal(SIGCHLD, spectrum_sigchld_handler) == SIG_ERR) {
 
		std::cout << "SIGCHLD handler can't be set\n";
 
		return -1;
 
	}
 

	
 
	boost::program_options::options_description desc("Usage: spectrum [OPTIONS] <config_file.cfg>\nAllowed options");
 
	desc.add_options()
 
		("host,h", value<std::string>(&host), "host")
 
		("port,p", value<int>(&port), "port")
 
		;
 
	try
 
	{
 
		boost::program_options::variables_map vm;
 
		boost::program_options::store(boost::program_options::parse_command_line(argc, argv, desc), vm);
 
		boost::program_options::notify(vm);
 
	}
 
	catch (std::runtime_error& e)
 
	{
 
		std::cout << desc << "\n";
 
		exit(1);
 
	}
 
	catch (...)
 
	{
 
		std::cout << desc << "\n";
 
		exit(1);
 
	}
 

	
 

	
 
	if (argc < 5) {
 
		return 1;
 
	}
 

	
 
	Config config;
 
	if (!config.load(argv[5])) {
 
		std::cerr << "Can't open " << argv[1] << " configuration file.\n";
 
		return 1;
 
	}
 

	
 
	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::SimpleEventLoop eventLoop;
 
	loop_ = &eventLoop;
 
	np = new TemplatePlugin(&config, &eventLoop, host, port);
 
	loop_->run();
 

	
 
	return 0;
 
}
cmake_modules/dbusConfig.cmake
Show inline comments
 
new file 100644
 
# - Try to find LIBDBUS GLIB Bindings
 
# Find LIBDBUSGLIB headers, libraries and the answer to all questions.
 
#
 
#  LIBDBUSGLIB_FOUND               True if libdbus-glib got found
 
#  LIBDBUSGLIB_INCLUDE_DIRS        Location of libdbus-glib headers 
 
#  LIBDBUSGLIB_LIBRARIES           List of libraries to use libdbus-glib 
 
#
 
# Copyright (c) 2008 Bjoern Ricks <bjoern.ricks@googlemail.com>
 
#
 
#  Redistribution and use is allowed according to the terms of the New
 
#  BSD license.
 
#  For details see the accompanying COPYING-CMAKE-SCRIPTS file.
 
#
 

	
 
INCLUDE( FindPkgConfig )
 

	
 
IF ( LibDbusGlib_FIND_REQUIRED )
 
	SET( _pkgconfig_REQUIRED "REQUIRED" )
 
ELSE( LibDbusGlib_FIND_REQUIRED )
 
	SET( _pkgconfig_REQUIRED "" )	
 
ENDIF ( LibDbusGlib_FIND_REQUIRED )
 

	
 
IF ( LIBDBUSGLIB_MIN_VERSION )
 
	PKG_SEARCH_MODULE( LIBDBUSGLIB ${_pkgconfig_REQUIRED} dbus-glib-1>=${LIBDBUSGLIB_MIN_VERSION} )
 
ELSE ( LIBDBUSGLIB_MIN_VERSION )
 
	PKG_SEARCH_MODULE( LIBDBUSGLIB ${_pkgconfig_REQUIRED} dbus-glib-1 )
 
ENDIF ( LIBDBUSGLIB_MIN_VERSION )
 

	
 

	
 
IF( NOT LIBDBUSGLIB_FOUND AND NOT PKG_CONFIG_FOUND )
 
	FIND_PATH( LIBDBUSGLIB_INCLUDE_DIRS dbus/dbus-glib.h PATH_SUFFIXES dbus-1.0 dbus )
 
	FIND_LIBRARY( LIBDBUSGLIB_LIBRARIES dbus-glib dbus-glib-1)
 

	
 
	# Report results
 
	IF ( LIBDBUSGLIB_LIBRARIES AND LIBDBUSGLIB_INCLUDE_DIRS )	
 
		SET( LIBDBUSGLIB_FOUND 1 )
 
		IF ( NOT LIBDBUSGLIB_FIND_QUIETLY )
 
			MESSAGE( STATUS "Found libdbus-glib: ${LIBDBUSGLIB_LIBRARIES} ${LIBDBUSGLIB_INCLUDE_DIRS}" )
 
		ENDIF ( NOT LIBDBUSGLIB_FIND_QUIETLY )
 
	ELSE ( LIBDBUSGLIB_LIBRARIES AND LIBDBUSGLIB_INCLUDE_DIRS )	
 
		IF ( LIBDBUSGLIB_FIND_REQUIRED )
 
			MESSAGE( SEND_ERROR "Could NOT find libdbus-glib" )
 
		ELSE ( LIBDBUSGLIB_FIND_REQUIRED )
 
			IF ( NOT LIBDBUSGLIB_FIND_QUIETLY )
 
				MESSAGE( STATUS "Could NOT find libdbus-glib" )	
 
			ENDIF ( NOT LIBDBUSGLIB_FIND_QUIETLY )
 
		ENDIF ( LIBDBUSGLIB_FIND_REQUIRED )
 
	ENDIF ( LIBDBUSGLIB_LIBRARIES AND LIBDBUSGLIB_INCLUDE_DIRS )
 
else()
 
	MESSAGE( STATUS "Found libdbus-glib: ${LIBDBUSGLIB_LIBRARIES} ${LIBDBUSGLIB_INCLUDE_DIRS}" )
 
ENDIF()
 

	
 
MARK_AS_ADVANCED( LIBDBUSGLIB_LIBRARIES LIBDBUSGLIB_INCLUDE_DIRS )
 
\ No newline at end of file
cmake_modules/pqxxConfig.cmake
Show inline comments
 
new file 100644
 
FIND_PATH(PQXX_INCLUDE_DIR pqxx/pqxx PATHS)
 
MARK_AS_ADVANCED(PQXX_INCLUDE_DIR)
 

	
 
FIND_LIBRARY(PQXX_LIBRARY pqxx )
 
MARK_AS_ADVANCED(PQXX_LIBRARY)
 

	
 
FIND_LIBRARY(PQ_LIBRARY pq )
 
MARK_AS_ADVANCED(PQ_LIBRARY)
 

	
 
if(PQXX_LIBRARY AND PQ_LIBRARY AND PQXX_INCLUDE_DIR)
 
	set( PQXX_FOUND 1 )
 
	message( STATUS "Found pqxx: ${PQXX_LIBRARY}, ${PQ_LIBRARY}, ${PQXX_INCLUDE_DIR}")
 
else()
 
	message(STATUS "Could NOT find pqxx and pq library")
 
endif()
 

	
include/Swiften/Elements/GatewayPayload.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/GatewayPayload.h>
 

	
 
namespace Swift {
 

	
 
GatewayPayload::GatewayPayload(const JID &jid, const std::string &desc, const std::string &prompt) :
 
	jid(jid), desc(desc), prompt(prompt) {
 
		
 
	}
 

	
 
}
include/Swiften/Elements/GatewayPayload.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>
 
#include <Swiften/JID/JID.h>
 

	
 
namespace Swift {
 
	class GatewayPayload : public Payload {
 
		public:
 
			GatewayPayload(const JID &jid = JID(), const std::string &desc = "", const std::string &prompt = "");
 

	
 
			void setJID(const JID &jid) {
 
				this->jid = jid;
 
			}
 

	
 
			const JID &getJID() const {
 
				return jid;
 
			}
 

	
 
			void setDesc(const std::string &desc) {
 
				this->desc = desc;
 
			}
 

	
 
			const std::string &getDesc() const {
 
				return desc;
 
			}
 

	
 
			void setPrompt(const std::string &prompt) {
 
				this->prompt = prompt;
 
			}
 

	
 
			const std::string &getPrompt() const {
 
				return prompt;
 
			}
 

	
 
		private:
 
			JID jid;
 
			std::string desc;
 
			std::string prompt;
 
	};
 
}
include/Swiften/Elements/PubSubItem.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/PubSubItem.h>
 

	
 
namespace Swift {
 

	
 
PubSubItem::PubSubItem() {
 
}
 

	
 
}
include/Swiften/Elements/PubSubItem.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 PubSubItem : public Payload {
 
		public:
 
			PubSubItem();
 

	
 
			void addPayload(boost::shared_ptr<Payload> payload) {
 
				payloads.push_back(payload);
 
			}
 

	
 
			const std::vector<boost::shared_ptr<Payload> > getPayloads() const {
 
				return payloads;
 
			}
 
			
 
			template<typename T>
 
			const std::vector<boost::shared_ptr<T> > getPayloads() const {
 
				std::vector<boost::shared_ptr<T> > matched_payloads;
 
				for (std::vector<boost::shared_ptr<Payload> >::const_iterator i = payloads.begin(); i != payloads.end(); ++i) {
 
					boost::shared_ptr<T> result = boost::dynamic_pointer_cast<T>(*i);
 
					if (result) {
 
						matched_payloads.push_back(result);
 
					}
 
				}
 
				
 
				return matched_payloads;
 
				
 
			}
 

	
 
			template<typename T>
 
			const boost::shared_ptr<T> getPayload() const {
 
				boost::shared_ptr<T> result;
 
				for (std::vector<boost::shared_ptr<Payload> >::const_iterator i = payloads.begin(); i != payloads.end(); ++i) {
 
					result = boost::dynamic_pointer_cast<T>(*i);
 
					if (result) {
 
						return result;
 
					}
 
				}
 
				
 
				return result;
 
			}
 

	
 
			const std::string& getId() const { return id; }
 

	
 
			void setId(const std::string& id) { 
 
				this->id = id;
 
			}
 

	
 
		private:
 
			std::vector<boost::shared_ptr<Payload> > payloads;
 
			std::string id;
 
	};
 
}
include/Swiften/Elements/PubSubPayload.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/PubSubPayload.h>
 

	
 
namespace Swift {
 

	
 
PubSubPayload::PubSubPayload() {
 
}
 

	
 
}
include/Swiften/Elements/PubSubPayload.h
Show inline comments
 
new file 100644
 
/*
 
 * Copyright (c) 2012 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 PubSubPayload : public Payload {
 
		public:
 
			PubSubPayload();
 

	
 
			void addPayload(boost::shared_ptr<Payload> payload) {
 
				payloads.push_back(payload);
 
			}
 

	
 
			const std::vector<boost::shared_ptr<Payload> > getPayloads() const {
 
				return payloads;
 
			}
 

	
 
			template<typename T>
 
			const std::vector<boost::shared_ptr<T> > getPayloads() const {
 
				std::vector<boost::shared_ptr<T> > matched_payloads;
 
				for (std::vector<boost::shared_ptr<Payload> >::const_iterator i = payloads.begin(); i != payloads.end(); ++i) {
 
					boost::shared_ptr<T> result = boost::dynamic_pointer_cast<T>(*i);
 
					if (result) {
 
						matched_payloads.push_back(result);
 
					}
 
				}
 
				
 
				return matched_payloads;
 
				
 
			}
 

	
 
			template<typename T>
 
			const boost::shared_ptr<T> getPayload() const {
 
				boost::shared_ptr<T> result;
 
				for (std::vector<boost::shared_ptr<Payload> >::const_iterator i = payloads.begin(); i != payloads.end(); ++i) {
 
					result = boost::dynamic_pointer_cast<T>(*i);
 
					if (result) {
 
						return result;
 
					}
 
				}
 
				
 
				return result;
 
			}
 

	
 
		private:
 
			std::vector<boost::shared_ptr<Payload> > payloads;
 
	};
 
}
include/Swiften/Elements/PubSubPublishPayload.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/PubSubPublishPayload.h>
 

	
 
namespace Swift {
 

	
 
PubSubPublishPayload::PubSubPublishPayload(const std::string &node) :
 
	node(node) {
 
		
 
	}
 

	
 
}
include/Swiften/Elements/PubSubPublishPayload.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>
 
#include <Swiften/Elements/PubSubItem.h>
 
#include <Swiften/JID/JID.h>
 

	
 
namespace Swift {
 
	class PubSubPublishPayload : public Payload {
 
		public:
 
			enum Type { None, Pending, Subscribed, Unconfigured };
 

	
 
			PubSubPublishPayload(const std::string &node = "");
 

	
 
			void setNode(const std::string &node) {
 
				this->node = node;
 
			}
 

	
 
			const std::string &getNode() const {
 
				return node;
 
			}
 

	
 
			void addItem(const boost::shared_ptr<Payload> &item) {
 
				items.push_back(item);
 
			}
 

	
 
			const std::vector<boost::shared_ptr<Payload> > &getItems() const {
 
				return items;
 
			}
 

	
 
		private:
 
			std::string node;
 
			std::vector<boost::shared_ptr<Payload> > items;
 
	};
 
}
include/Swiften/Elements/PubSubSubscribePayload.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/PubSubSubscribePayload.h>
 

	
 
namespace Swift {
 

	
 
PubSubSubscribePayload::PubSubSubscribePayload(const JID &jid, const std::string &node) :
 
	jid(jid), node(node) {
 
		
 
	}
 

	
 
}
include/Swiften/Elements/PubSubSubscribePayload.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>
 
#include <Swiften/JID/JID.h>
 

	
 
namespace Swift {
 
	class PubSubSubscribePayload : public Payload {
 
		public:
 
			PubSubSubscribePayload(const JID &jid = JID(), const std::string &node = "");
 

	
 
			void setJID(const JID &jid) {
 
				this->jid = jid;
 
			}
 

	
 
			const JID &getJID() const {
 
				return jid;
 
			}
 

	
 
			void setNode(const std::string &node) {
 
				this->node = node;
 
			}
 

	
 
			const std::string &getNode() const {
 
				return node;
 
			}
 

	
 
		private:
 
			JID jid;
 
			std::string node;
 
	};
 
}
include/Swiften/Elements/PubSubSubscriptionPayload.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/PubSubSubscriptionPayload.h>
 

	
 
namespace Swift {
 

	
 
PubSubSubscriptionPayload::PubSubSubscriptionPayload(const JID &jid, const std::string &node) :
 
	jid(jid), node(node), type(None) {
 
		
 
	}
 

	
 
}
include/Swiften/Elements/PubSubSubscriptionPayload.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>
 
#include <Swiften/JID/JID.h>
 

	
 
namespace Swift {
 
	class PubSubSubscriptionPayload : public Payload {
 
		public:
 
			enum Type { None, Pending, Subscribed, Unconfigured };
 

	
 
			PubSubSubscriptionPayload(const JID &jid = JID(), const std::string &node = "");
 

	
 
			void setJID(const JID &jid) {
 
				this->jid = jid;
 
			}
 

	
 
			const JID &getJID() const {
 
				return jid;
 
			}
 

	
 
			void setNode(const std::string &node) {
 
				this->node = node;
 
			}
 

	
 
			const std::string &getNode() const {
 
				return node;
 
			}
 

	
 
			void setId(const std::string &id) {
 
				this->id = id;
 
			}
 

	
 
			const std::string &getId() const {
 
				return id;
 
			}
 

	
 
			void setType(const Type &type) {
 
				this->type = type;
 
			}
 

	
 
			const Type &getType() const {
 
				return type;
 
			}
 

	
 
		private:
 
			JID jid;
 
			std::string node;
 
			std::string id;
 
			Type type;
 
	};
 
}
include/Swiften/FileTransfer/CombinedOutgoingFileTransferManager.cpp
Show inline comments
 
/*
 
 * Copyright (c) 2011 Tobias Markmann
 
 * Licensed under the simplified BSD license.
 
 * See Documentation/Licenses/BSD-simplified.txt for more information.
 
 */
 

	
 
#include "CombinedOutgoingFileTransferManager.h"
 

	
 
#include <boost/smart_ptr/make_shared.hpp>
 

	
 
#include <Swiften/JID/JID.h>
 
#include "Swiften/Disco/EntityCapsProvider.h"
 
#include <Swiften/Jingle/JingleSessionManager.h>
 
#include <Swiften/Jingle/JingleSessionImpl.h>
 
#include <Swiften/Jingle/JingleContentID.h>
 
#include <Swiften/FileTransfer/OutgoingJingleFileTransfer.h>
 
#include <Swiften/FileTransfer/MyOutgoingSIFileTransfer.h>
 
#include <Swiften/FileTransfer/SOCKS5BytestreamServer.h>
 
#include <Swiften/Base/IDGenerator.h>
 
#include <Swiften/Elements/Presence.h>
 
#include <Swiften/Presence/PresenceOracle.h>
 
#include <Swiften/Base/foreach.h>
 

	
 

	
 
namespace Swift {
 

	
 
CombinedOutgoingFileTransferManager::CombinedOutgoingFileTransferManager(JingleSessionManager* jingleSessionManager, IQRouter* router, EntityCapsProvider* capsProvider, RemoteJingleTransportCandidateSelectorFactory* remoteFactory, LocalJingleTransportCandidateGeneratorFactory* localFactory, SOCKS5BytestreamRegistry* bytestreamRegistry, SOCKS5BytestreamProxy* bytestreamProxy, PresenceOracle *presOracle, SOCKS5BytestreamServer *bytestreamServer) : jsManager(jingleSessionManager), iqRouter(router), capsProvider(capsProvider), remoteFactory(remoteFactory), localFactory(localFactory), bytestreamRegistry(bytestreamRegistry), bytestreamProxy(bytestreamProxy), presenceOracle(presOracle), bytestreamServer(bytestreamServer) {
 
CombinedOutgoingFileTransferManager::CombinedOutgoingFileTransferManager(JingleSessionManager* jingleSessionManager, IQRouter* router, EntityCapsProvider* capsProvider, RemoteJingleTransportCandidateSelectorFactory* remoteFactory, LocalJingleTransportCandidateGeneratorFactory* localFactory, SOCKS5BytestreamRegistry* bytestreamRegistry, SOCKS5BytestreamProxy* bytestreamProxy, Transport::PresenceOracle *presOracle, SOCKS5BytestreamServer *bytestreamServer) : jsManager(jingleSessionManager), iqRouter(router), capsProvider(capsProvider), remoteFactory(remoteFactory), localFactory(localFactory), bytestreamRegistry(bytestreamRegistry), bytestreamProxy(bytestreamProxy), presenceOracle(presOracle), bytestreamServer(bytestreamServer) {
 
	idGenerator = new IDGenerator();
 
}
 

	
 
CombinedOutgoingFileTransferManager::~CombinedOutgoingFileTransferManager() {
 
	delete idGenerator;
 
}
 

	
 
boost::shared_ptr<OutgoingFileTransfer> CombinedOutgoingFileTransferManager::createOutgoingFileTransfer(const JID& from, const JID& receipient, boost::shared_ptr<ReadBytestream> readBytestream, const StreamInitiationFileInfo& fileInfo) {
 
	// check if receipient support Jingle FT
 
	boost::optional<JID> fullJID = highestPriorityJIDSupportingJingle(receipient);
 
	if (!fullJID.is_initialized()) {
 
		fullJID = highestPriorityJIDSupportingSI(receipient);
 
	}
 
	else {
 
		JingleSessionImpl::ref jingleSession = boost::make_shared<JingleSessionImpl>(from, receipient, idGenerator->generateID(), iqRouter);
 

	
 
		//jsManager->getSession(receipient, idGenerator->generateID());
 
		assert(jingleSession);
 
		jsManager->registerOutgoingSession(from, jingleSession);
 
		boost::shared_ptr<OutgoingJingleFileTransfer> jingleFT =  boost::shared_ptr<OutgoingJingleFileTransfer>(new OutgoingJingleFileTransfer(jingleSession, remoteFactory, localFactory, iqRouter, idGenerator, from, receipient, readBytestream, fileInfo, bytestreamRegistry, bytestreamProxy));
 
		return jingleFT;
 
	}
 

	
 
	if (!fullJID.is_initialized()) {
 
		return boost::shared_ptr<OutgoingFileTransfer>();
 
	}
 
	
 
	// otherwise try SI
 
	boost::shared_ptr<MyOutgoingSIFileTransfer> jingleFT =  boost::shared_ptr<MyOutgoingSIFileTransfer>(new MyOutgoingSIFileTransfer(idGenerator->generateID(), from, fullJID.get(), fileInfo.getName(), fileInfo.getSize(), fileInfo.getDescription(), readBytestream, iqRouter, bytestreamServer, bytestreamRegistry));
 
	// else fail
 
	
 
	return jingleFT;
 
}
 

	
 
boost::optional<JID> CombinedOutgoingFileTransferManager::highestPriorityJIDSupportingJingle(const JID& bareJID) {
 
	JID fullReceipientJID;
 
	int priority = INT_MIN;
 
	
 
	//getAllPresence(bareJID) gives you all presences for the bare JID (i.e. all resources) Remko Tronçon @ 11:11
 
	std::vector<Presence::ref> presences = presenceOracle->getAllPresence(bareJID);
 

	
 
	//iterate over them
 
	foreach(Presence::ref pres, presences) {
 
		if (pres->getPriority() > priority) {
 
			// look up caps from the jid
 
			DiscoInfo::ref info = capsProvider->getCaps(pres->getFrom());
 
			if (info && info->hasFeature(DiscoInfo::JingleFeature) && info->hasFeature(DiscoInfo::JingleFTFeature) &&
 
				info->hasFeature(DiscoInfo::JingleTransportsIBBFeature)) {
 
			
 
				priority = pres->getPriority();
 
				fullReceipientJID = pres->getFrom();
 
			}
 
		}
 
	}
 
	
 
	return fullReceipientJID.isValid() ? boost::optional<JID>(fullReceipientJID) : boost::optional<JID>();
 
}
 

	
 
boost::optional<JID> CombinedOutgoingFileTransferManager::highestPriorityJIDSupportingSI(const JID& bareJID) {
 
	JID fullReceipientJID;
 
	int priority = INT_MIN;
 
	
 
	//getAllPresence(bareJID) gives you all presences for the bare JID (i.e. all resources) Remko Tronçon @ 11:11
 
	std::vector<Presence::ref> presences = presenceOracle->getAllPresence(bareJID);
 

	
 
	//iterate over them
 
	foreach(Presence::ref pres, presences) {
 
		if (pres->getPriority() > priority) {
 
			// look up caps from the jid
 
			DiscoInfo::ref info = capsProvider->getCaps(pres->getFrom());
 
			if (info && info->hasFeature("http://jabber.org/protocol/si/profile/file-transfer")) {
 
			
 
				priority = pres->getPriority();
 
				fullReceipientJID = pres->getFrom();
 
			}
 
		}
 
	}
 
	
 
	return fullReceipientJID.isValid() ? boost::optional<JID>(fullReceipientJID) : boost::optional<JID>();
 
}
 

	
 
}
include/Swiften/FileTransfer/CombinedOutgoingFileTransferManager.h
Show inline comments
 
/*
 
 * Copyright (c) 2011 Tobias Markmann
 
 * Licensed under the simplified BSD license.
 
 * See Documentation/Licenses/BSD-simplified.txt for more information.
 
 */
 

	
 
#pragma once
 

	
 
#include <boost/shared_ptr.hpp>
 
#include <boost/optional.hpp>
 

	
 
#include <Swiften/JID/JID.h>
 

	
 
#include "transport/presenceoracle.h"
 

	
 
namespace Swift {
 

	
 
class JingleSessionManager;
 
class IQRouter;
 
class EntityCapsProvider;
 
class RemoteJingleTransportCandidateSelectorFactory;
 
class LocalJingleTransportCandidateGeneratorFactory;
 
class OutgoingFileTransfer;
 
class JID;
 
class IDGenerator;
 
class ReadBytestream;
 
class StreamInitiationFileInfo;
 
class SOCKS5BytestreamRegistry;
 
class SOCKS5BytestreamProxy;
 
class SOCKS5BytestreamServer;
 
class PresenceOracle;
 

	
 
class CombinedOutgoingFileTransferManager {
 
public:
 
	CombinedOutgoingFileTransferManager(JingleSessionManager* jingleSessionManager, IQRouter* router, EntityCapsProvider* capsProvider, RemoteJingleTransportCandidateSelectorFactory* remoteFactory, LocalJingleTransportCandidateGeneratorFactory* localFactory, SOCKS5BytestreamRegistry* bytestreamRegistry, SOCKS5BytestreamProxy* bytestreamProxy, PresenceOracle* presOracle, SOCKS5BytestreamServer *server);
 
	CombinedOutgoingFileTransferManager(JingleSessionManager* jingleSessionManager, IQRouter* router, EntityCapsProvider* capsProvider, RemoteJingleTransportCandidateSelectorFactory* remoteFactory, LocalJingleTransportCandidateGeneratorFactory* localFactory, SOCKS5BytestreamRegistry* bytestreamRegistry, SOCKS5BytestreamProxy* bytestreamProxy, Transport::PresenceOracle* presOracle, SOCKS5BytestreamServer *server);
 
	~CombinedOutgoingFileTransferManager();
 
	
 
	boost::shared_ptr<OutgoingFileTransfer> createOutgoingFileTransfer(const JID& from, const JID& to, boost::shared_ptr<ReadBytestream>, const StreamInitiationFileInfo&);
 

	
 
private:
 
	boost::optional<JID> highestPriorityJIDSupportingJingle(const JID& bareJID);
 
	boost::optional<JID> highestPriorityJIDSupportingSI(const JID& bareJID);
 
	JingleSessionManager* jsManager;
 
	IQRouter* iqRouter;
 
	EntityCapsProvider* capsProvider;
 
	RemoteJingleTransportCandidateSelectorFactory* remoteFactory;
 
	LocalJingleTransportCandidateGeneratorFactory* localFactory;
 
	IDGenerator *idGenerator;
 
	SOCKS5BytestreamRegistry* bytestreamRegistry;
 
	SOCKS5BytestreamProxy* bytestreamProxy;
 
	PresenceOracle* presenceOracle;
 
	Transport::PresenceOracle* presenceOracle;
 
	SOCKS5BytestreamServer *bytestreamServer;
 
};
 

	
 
}
include/Swiften/Network/DummyNetworkFactories.cpp
Show inline comments
 
/*
 
 * Copyright (c) 2010 Remko Tronçon
 
 * Licensed under the GNU General Public License v3.
 
 * See Documentation/Licenses/GPLv3.txt for more information.
 
 */
 

	
 
#include <Swiften/Network/DummyNetworkFactories.h>
 
#include <Swiften/Network/DummyTimerFactory.h>
 
#include <Swiften/Network/DummyConnectionFactory.h>
 
#include <Swiften/Network/PlatformDomainNameResolver.h>
 
#include <Swiften/Network/DummyConnectionServerFactory.h>
 

	
 
namespace Swift {
 

	
 
DummyNetworkFactories::DummyNetworkFactories(EventLoop* eventLoop) {
 
	timerFactory = new DummyTimerFactory();
 
	connectionFactory = new DummyConnectionFactory(eventLoop);
 
	domainNameResolver = new PlatformDomainNameResolver(eventLoop);
 
	connectionServerFactory = new DummyConnectionServerFactory(eventLoop);
 
	m_platformXMLParserFactory =  new PlatformXMLParserFactory();
 
	this->eventLoop = eventLoop;
 
}
 

	
 
DummyNetworkFactories::~DummyNetworkFactories() {
 
	delete connectionServerFactory;
 
	delete domainNameResolver;
 
	delete connectionFactory;
 
	delete timerFactory;
 
	delete m_platformXMLParserFactory;
 
}
 

	
 
}
include/Swiften/Network/DummyNetworkFactories.h
Show inline comments
 
/*
 
 * Copyright (c) 2010 Remko Tronçon
 
 * Licensed under the GNU General Public License v3.
 
 * See Documentation/Licenses/GPLv3.txt for more information.
 
 */
 

	
 
#pragma once
 

	
 
#include <Swiften/Network/NetworkFactories.h>
 
#include <Swiften/Parser/PlatformXMLParserFactory.h>
 

	
 
namespace Swift {
 
	class EventLoop;
 

	
 
	class DummyNetworkFactories : public NetworkFactories {
 
		public:
 
			DummyNetworkFactories(EventLoop *eventLoop);
 
			~DummyNetworkFactories();
 

	
 
			virtual TimerFactory* getTimerFactory() const {
 
				return timerFactory;
 
			}
 

	
 
			virtual ConnectionFactory* getConnectionFactory() const {
 
				return connectionFactory;
 
			}
 

	
 
			DomainNameResolver* getDomainNameResolver() const {
 
				return domainNameResolver;
 
			}
 

	
 
			ConnectionServerFactory* getConnectionServerFactory() const {
 
				return connectionServerFactory;
 
			}
 

	
 
			virtual Swift::NATTraverser* getNATTraverser() const {
 
				return 0;
 
			}
 

	
 
			Swift::XMLParserFactory* getXMLParserFactory() const {
 
				return m_platformXMLParserFactory;
 
			}
 

	
 
			EventLoop *getEventLoop() const {
 
				return eventLoop;
 
			}
 

	
 
            Swift::TLSContextFactory* getTLSContextFactory() const {
 
                return 0;
 
            }
 

	
 
            Swift::ProxyProvider* getProxyProvider() const {
 
                return 0;
 
            }
 

	
 
		private:
 
			PlatformXMLParserFactory *m_platformXMLParserFactory;
 
			TimerFactory* timerFactory;
 
			ConnectionFactory* connectionFactory;
 
			DomainNameResolver* domainNameResolver;
 
			ConnectionServerFactory* connectionServerFactory;
 
			EventLoop *eventLoop;
 
	};
 
}
include/Swiften/Parser/PayloadParsers/GatewayPayloadParser.cpp
Show inline comments
 
new file 100644
 
/*
 
 * Copyright (c) 2012 Jan Kaluza
 
 * Licensed under the Simplified BSD license.
 
 * See Documentation/Licenses/BSD-simplified.txt for more information.
 
 */
 

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

	
 
#include <boost/lexical_cast.hpp>
 

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

	
 
namespace Swift {
 

	
 
void GatewayPayloadParser::handleTree(ParserElement::ref root) {
 
	foreach (ParserElement::ref child, root->getAllChildren()) {
 
		if (child->getName() == "desc") {
 
			getPayloadInternal()->setDesc(child->getText());
 
		}
 
		else if (child->getName() == "prompt") {
 
			getPayloadInternal()->setPrompt(child->getText());
 
		}
 
		else if (child->getName() == "jid") {
 
			getPayloadInternal()->setJID(child->getText());
 
		}
 
	}
 
}
 

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

	
 
#pragma once
 

	
 
#include <boost/optional.hpp>
 

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

	
 
namespace Swift {
 
	class GatewayPayloadParser : public GenericPayloadTreeParser<GatewayPayload> {
 
		public:
 
			GatewayPayloadParser() {}
 
			virtual void handleTree(ParserElement::ref root);
 
	};
 
}
include/Swiften/Parser/PayloadParsers/PubSubItemParser.cpp
Show inline comments
 
new file 100644
 
/*
 
 * Copyright (c) 2012 Jan Kaluza
 
 * Licensed under the Simplified BSD license.
 
 * See Documentation/Licenses/BSD-simplified.txt for more information.
 
 */
 

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

	
 
#include <boost/lexical_cast.hpp>
 

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

	
 
namespace Swift {
 

	
 
void PubSubItemParser::handleTree(ParserElement::ref root) {
 
	std::string id = root->getAttributes().getAttribute("id");
 
	if (!id.empty()) {
 
		getPayloadInternal()->setId(id);
 
	}
 

	
 
	foreach (ParserElement::ref child, root->getAllChildren()) {
 
		getPayloadInternal()->addPayload(TreeReparser::parseTree(child, factories));
 
	}
 
}
 

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

	
 
#pragma once
 

	
 
#include <boost/optional.hpp>
 

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

	
 
namespace Swift {
 
	class PayloadParserFactoryCollection;
 
	class PubSubItemParser : public GenericPayloadTreeParser<PubSubItem> {
 
		public:
 
			PubSubItemParser(PayloadParserFactoryCollection* collection) : factories(collection) {}
 
			virtual void handleTree(ParserElement::ref root);
 
		private:
 
			PayloadParserFactoryCollection* factories;
 
	};
 
}
include/Swiften/Parser/PayloadParsers/PubSubPayloadParser.cpp
Show inline comments
 
new file 100644
 
/*
 
 * Copyright (c) 2012 Jan Kaluza
 
 * Licensed under the Simplified BSD license.
 
 * See Documentation/Licenses/BSD-simplified.txt for more information.
 
 */
 

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

	
 
#include <boost/lexical_cast.hpp>
 

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

	
 
namespace Swift {
 

	
 
void PubSubPayloadParser::handleTree(ParserElement::ref root) {
 
	foreach (ParserElement::ref child, root->getAllChildren()) {
 
		getPayloadInternal()->addPayload(TreeReparser::parseTree(child, factories));
 
	}
 
}
 

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

	
 
#pragma once
 

	
 
#include <boost/optional.hpp>
 

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

	
 
namespace Swift {
 
	class PayloadParserFactoryCollection;
 
	class PubSubPayloadParser : public GenericPayloadTreeParser<PubSubPayload> {
 
		public:
 
			PubSubPayloadParser(PayloadParserFactoryCollection* collection) : factories(collection) {}
 
			virtual void handleTree(ParserElement::ref root);
 
		private:
 
			PayloadParserFactoryCollection* factories;
 
	};
 
}
include/Swiften/Parser/PayloadParsers/PubSubPublishPayloadParser.cpp
Show inline comments
 
new file 100644
 
/*
 
 * Copyright (c) 2012 Jan Kaluza
 
 * Licensed under the Simplified BSD license.
 
 * See Documentation/Licenses/BSD-simplified.txt for more information.
 
 */
 

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

	
 
#include <boost/lexical_cast.hpp>
 

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

	
 
namespace Swift {
 

	
 
void PubSubPublishPayloadParser::handleTree(ParserElement::ref root) {
 
	std::string node = root->getAttributes().getAttribute("node");
 
	if (!node.empty()) {
 
		getPayloadInternal()->setNode(node);
 
	}
 

	
 
	foreach (ParserElement::ref child, root->getAllChildren()) {
 
		getPayloadInternal()->addItem(TreeReparser::parseTree(child, factories));
 
	}
 
}
 

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

	
 
#pragma once
 

	
 
#include <boost/optional.hpp>
 

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

	
 
namespace Swift {
 
	class PayloadParserFactoryCollection;
 
	class PubSubPublishPayloadParser : public GenericPayloadTreeParser<PubSubPublishPayload> {
 
		public:
 
			PubSubPublishPayloadParser(PayloadParserFactoryCollection* collection) : factories(collection) {}
 
			virtual void handleTree(ParserElement::ref root);
 
		private:
 
			PayloadParserFactoryCollection* factories;
 
	};
 
}
include/Swiften/Parser/PayloadParsers/PubSubSubscribePayloadParser.cpp
Show inline comments
 
new file 100644
 
/*
 
 * Copyright (c) 2012 Jan Kaluza
 
 * Licensed under the Simplified BSD license.
 
 * See Documentation/Licenses/BSD-simplified.txt for more information.
 
 */
 

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

	
 
#include <boost/lexical_cast.hpp>
 

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

	
 
namespace Swift {
 

	
 
void PubSubSubscribePayloadParser::handleTree(ParserElement::ref root) {
 
	std::string node = root->getAttributes().getAttribute("node");
 
	if (!node.empty()) {
 
		getPayloadInternal()->setNode(node);
 
	}
 

	
 
	std::string jid = root->getAttributes().getAttribute("jid");
 
	if (!jid.empty()) {
 
		getPayloadInternal()->setJID(jid);
 
	}
 

	
 
}
 

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

	
 
#pragma once
 

	
 
#include <boost/optional.hpp>
 

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

	
 
namespace Swift {
 
	class PayloadParserFactoryCollection;
 
	class PubSubSubscribePayloadParser : public GenericPayloadTreeParser<PubSubSubscribePayload> {
 
		public:
 
			PubSubSubscribePayloadParser(PayloadParserFactoryCollection* collection) : factories(collection) {}
 
			virtual void handleTree(ParserElement::ref root);
 
		private:
 
			PayloadParserFactoryCollection* factories;
 
	};
 
}
include/Swiften/Parser/PayloadParsers/PubSubSubscriptionPayloadParser.cpp
Show inline comments
 
new file 100644
 
/*
 
 * Copyright (c) 2012 Jan Kaluza
 
 * Licensed under the Simplified BSD license.
 
 * See Documentation/Licenses/BSD-simplified.txt for more information.
 
 */
 

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

	
 
#include <boost/lexical_cast.hpp>
 

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

	
 
namespace Swift {
 

	
 
void PubSubSubscriptionPayloadParser::handleTree(ParserElement::ref root) {
 
	std::string node = root->getAttributes().getAttribute("node");
 
	if (!node.empty()) {
 
		getPayloadInternal()->setNode(node);
 
	}
 

	
 
	std::string jid = root->getAttributes().getAttribute("jid");
 
	if (!jid.empty()) {
 
		getPayloadInternal()->setJID(jid);
 
	}
 

	
 
	std::string id = root->getAttributes().getAttribute("subid");
 
	if (!id.empty()) {
 
		getPayloadInternal()->setId(id);
 
	}
 

	
 
	std::string type = root->getAttributes().getAttribute("subscription");
 
	if (type == "none") {
 
		getPayloadInternal()->setType(PubSubSubscriptionPayload::None);
 
	}
 
	else if (type == "subscribed") {
 
		getPayloadInternal()->setType(PubSubSubscriptionPayload::Subscribed);
 
	}
 
	else if (type == "pending") {
 
		getPayloadInternal()->setType(PubSubSubscriptionPayload::Pending);
 
	}
 
	else if (type == "unconfigured") {
 
		getPayloadInternal()->setType(PubSubSubscriptionPayload::Unconfigured);
 
	}
 

	
 
}
 

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

	
 
#pragma once
 

	
 
#include <boost/optional.hpp>
 

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

	
 
namespace Swift {
 
	class PayloadParserFactoryCollection;
 
	class PubSubSubscriptionPayloadParser : public GenericPayloadTreeParser<PubSubSubscriptionPayload> {
 
		public:
 
			PubSubSubscriptionPayloadParser(PayloadParserFactoryCollection* collection) : factories(collection) {}
 
			virtual void handleTree(ParserElement::ref root);
 
		private:
 
			PayloadParserFactoryCollection* factories;
 
	};
 
}
include/Swiften/Serializer/PayloadSerializers/GatewayPayloadSerializer.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/GatewayPayloadSerializer.h>
 
#include <Swiften/Base/foreach.h>
 
#include <Swiften/Serializer/XML/XMLRawTextNode.h>
 
#include <Swiften/Serializer/XML/XMLTextNode.h>
 
#include <Swiften/Serializer/XML/XMLElement.h>
 
#include <Swiften/Serializer/PayloadSerializerCollection.h>
 

	
 
namespace Swift {
 

	
 
GatewayPayloadSerializer::GatewayPayloadSerializer()
 
	: GenericPayloadSerializer<GatewayPayload>() {
 
}
 

	
 
std::string GatewayPayloadSerializer::serializePayload(boost::shared_ptr<GatewayPayload> payload)  const {
 
	XMLElement query("query", "jabber:iq:gateway");
 

	
 
	if (payload->getJID().isValid()) {
 
		boost::shared_ptr<XMLElement> jid(new XMLElement("jid", "", payload->getJID().toBare().toString()));
 
		query.addNode(jid);
 
	}
 

	
 
	if (!payload->getDesc().empty()) {
 
		boost::shared_ptr<XMLElement> desc(new XMLElement("desc", "", payload->getDesc()));
 
		query.addNode(desc);
 
	}
 

	
 
	if (!payload->getPrompt().empty()) {
 
		boost::shared_ptr<XMLElement> prompt(new XMLElement("prompt", "", payload->getPrompt()));
 
		query.addNode(prompt);
 
	}
 

	
 
	return query.serialize();
 
}
 

	
 
}
include/Swiften/Serializer/PayloadSerializers/GatewayPayloadSerializer.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/GatewayPayload.h>
 

	
 
namespace Swift {
 
	class GatewayPayloadSerializer : public GenericPayloadSerializer<GatewayPayload> {
 
		public:
 
			GatewayPayloadSerializer();
 

	
 
			virtual std::string serializePayload(boost::shared_ptr<GatewayPayload> item)  const;
 
	};
 
}
include/Swiften/Serializer/PayloadSerializers/PubSubItemSerializer.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/PubSubItemSerializer.h>
 
#include <Swiften/Base/foreach.h>
 
#include <Swiften/Serializer/XML/XMLRawTextNode.h>
 
#include <Swiften/Serializer/XML/XMLTextNode.h>
 
#include <Swiften/Serializer/XML/XMLElement.h>
 
#include <Swiften/Serializer/PayloadSerializerCollection.h>
 

	
 
namespace Swift {
 

	
 
PubSubItemSerializer::PubSubItemSerializer(PayloadSerializerCollection *serializers) : 
 
	GenericPayloadSerializer<PubSubItem>(), serializers(serializers) {
 
}
 

	
 
std::string PubSubItemSerializer::serializePayload(boost::shared_ptr<PubSubItem> payload)  const {
 
	XMLElement item("item");
 
	if (!payload->getId().empty()) {
 
		item.setAttribute("id", payload->getId());
 
	}
 

	
 
	if (!payload->getPayloads().empty()) {		
 
		foreach(boost::shared_ptr<Payload> subPayload, payload->getPayloads()) {
 
			PayloadSerializer* serializer = serializers->getPayloadSerializer(subPayload);
 
			if (serializer) {
 
				item.addNode(boost::shared_ptr<XMLRawTextNode>(new XMLRawTextNode(serializer->serialize(subPayload))));
 
			}
 
		}
 
	}
 

	
 
	return item.serialize();
 
}
 

	
 
}
include/Swiften/Serializer/PayloadSerializers/PubSubItemSerializer.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/PubSubItem.h>
 

	
 
namespace Swift {
 
	class PayloadSerializerCollection;
 
	class PubSubItemSerializer : public GenericPayloadSerializer<PubSubItem> {
 
		public:
 
			PubSubItemSerializer(PayloadSerializerCollection *serializers);
 

	
 
			virtual std::string serializePayload(boost::shared_ptr<PubSubItem> item)  const;
 
		private:
 
			PayloadSerializerCollection *serializers;
 
	};
 
}
include/Swiften/Serializer/PayloadSerializers/PubSubPayloadSerializer.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/PubSubPayloadSerializer.h>
 
#include <Swiften/Base/foreach.h>
 
#include <Swiften/Serializer/XML/XMLRawTextNode.h>
 
#include <Swiften/Serializer/XML/XMLTextNode.h>
 
#include <Swiften/Serializer/XML/XMLElement.h>
 
#include <Swiften/Serializer/PayloadSerializerCollection.h>
 

	
 
namespace Swift {
 

	
 
PubSubPayloadSerializer::PubSubPayloadSerializer(PayloadSerializerCollection *serializers)
 
	: GenericPayloadSerializer<PubSubPayload>(),
 
	serializers(serializers) {
 
}
 

	
 
std::string PubSubPayloadSerializer::serializePayload(boost::shared_ptr<PubSubPayload> payload)  const {
 
	XMLElement pubsub("pubsub", "http://jabber.org/protocol/pubsub");
 

	
 
	if (!payload->getPayloads().empty()) {		
 
		foreach(boost::shared_ptr<Payload> subPayload, payload->getPayloads()) {
 
			PayloadSerializer* serializer = serializers->getPayloadSerializer(subPayload);
 
			if (serializer) {
 
				pubsub.addNode(boost::shared_ptr<XMLRawTextNode>(new XMLRawTextNode(serializer->serialize(subPayload))));
 
			}
 
		}
 
	}
 

	
 
	return pubsub.serialize();
 
}
 

	
 
}
include/Swiften/Serializer/PayloadSerializers/PubSubPayloadSerializer.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/PubSubPayload.h>
 

	
 
namespace Swift {
 
	class PayloadSerializerCollection;
 

	
 
	class PubSubPayloadSerializer : public GenericPayloadSerializer<PubSubPayload> {
 
		public:
 
			PubSubPayloadSerializer(PayloadSerializerCollection *serializers);
 

	
 
			virtual std::string serializePayload(boost::shared_ptr<PubSubPayload> item)  const;
 
		private:
 
			PayloadSerializerCollection *serializers;
 
	};
 
}
include/Swiften/Serializer/PayloadSerializers/PubSubPublishPayloadSerializer.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/PubSubPublishPayloadSerializer.h>
 
#include <Swiften/Base/foreach.h>
 
#include <Swiften/Serializer/XML/XMLRawTextNode.h>
 
#include <Swiften/Serializer/XML/XMLTextNode.h>
 
#include <Swiften/Serializer/XML/XMLElement.h>
 
#include <Swiften/Serializer/PayloadSerializerCollection.h>
 

	
 
namespace Swift {
 

	
 
PubSubPublishPayloadSerializer::PubSubPublishPayloadSerializer(PayloadSerializerCollection *serializers)
 
	: GenericPayloadSerializer<PubSubPublishPayload>(),
 
	serializers(serializers) {
 
}
 

	
 
std::string PubSubPublishPayloadSerializer::serializePayload(boost::shared_ptr<PubSubPublishPayload> payload)  const {
 
	XMLElement publish("publish");
 

	
 
	if (!payload->getNode().empty()) {
 
		publish.setAttribute("node", payload->getNode());
 
	}
 

	
 
	if (!payload->getItems().empty()) {		
 
		foreach(boost::shared_ptr<Payload> subPayload, payload->getItems()) {
 
			PayloadSerializer* serializer = serializers->getPayloadSerializer(subPayload);
 
			if (serializer) {
 
				publish.addNode(boost::shared_ptr<XMLRawTextNode>(new XMLRawTextNode(serializer->serialize(subPayload))));
 
			}
 
		}
 
	}
 

	
 
	return publish.serialize();
 
}
 

	
 
}
include/Swiften/Serializer/PayloadSerializers/PubSubPublishPayloadSerializer.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/PubSubPublishPayload.h>
 

	
 
namespace Swift {
 
	class PayloadSerializerCollection;
 

	
 
	class PubSubPublishPayloadSerializer : public GenericPayloadSerializer<PubSubPublishPayload> {
 
		public:
 
			PubSubPublishPayloadSerializer(PayloadSerializerCollection *serializers);
 

	
 
			virtual std::string serializePayload(boost::shared_ptr<PubSubPublishPayload> item)  const;
 
		private:
 
			PayloadSerializerCollection *serializers;
 
	};
 
}
include/Swiften/Serializer/PayloadSerializers/PubSubSubscribePayloadSerializer.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/PubSubSubscribePayloadSerializer.h>
 
#include <Swiften/Base/foreach.h>
 
#include <Swiften/Serializer/XML/XMLRawTextNode.h>
 
#include <Swiften/Serializer/XML/XMLTextNode.h>
 
#include <Swiften/Serializer/XML/XMLElement.h>
 
#include <Swiften/Serializer/PayloadSerializerCollection.h>
 

	
 
namespace Swift {
 

	
 
PubSubSubscribePayloadSerializer::PubSubSubscribePayloadSerializer()
 
	: GenericPayloadSerializer<PubSubSubscribePayload>() {
 
}
 

	
 
std::string PubSubSubscribePayloadSerializer::serializePayload(boost::shared_ptr<PubSubSubscribePayload> payload)  const {
 
	XMLElement subscribe("subscribe");
 

	
 
	if (!payload->getJID().isValid()) {
 
		subscribe.setAttribute("jid", payload->getJID().toBare().toString());
 
	}
 

	
 
	if (!payload->getNode().empty()) {
 
		subscribe.setAttribute("node", payload->getNode());
 
	}
 

	
 
	return subscribe.serialize();
 
}
 

	
 
}
include/Swiften/Serializer/PayloadSerializers/PubSubSubscribePayloadSerializer.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/PubSubSubscribePayload.h>
 

	
 
namespace Swift {
 
	class PubSubSubscribePayloadSerializer : public GenericPayloadSerializer<PubSubSubscribePayload> {
 
		public:
 
			PubSubSubscribePayloadSerializer();
 

	
 
			virtual std::string serializePayload(boost::shared_ptr<PubSubSubscribePayload> item)  const;
 
	};
 
}
include/Swiften/Serializer/PayloadSerializers/PubSubSubscriptionPayloadSerializer.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/PubSubSubscriptionPayloadSerializer.h>
 
#include <Swiften/Base/foreach.h>
 
#include <Swiften/Serializer/XML/XMLRawTextNode.h>
 
#include <Swiften/Serializer/XML/XMLTextNode.h>
 
#include <Swiften/Serializer/XML/XMLElement.h>
 
#include <Swiften/Serializer/PayloadSerializerCollection.h>
 

	
 
namespace Swift {
 

	
 
PubSubSubscriptionPayloadSerializer::PubSubSubscriptionPayloadSerializer()
 
	: GenericPayloadSerializer<PubSubSubscriptionPayload>() {
 
}
 

	
 
std::string PubSubSubscriptionPayloadSerializer::serializePayload(boost::shared_ptr<PubSubSubscriptionPayload> payload)  const {
 
	XMLElement subscription("subscription");
 

	
 
	if (!payload->getJID().isValid()) {
 
		subscription.setAttribute("jid", payload->getJID().toBare().toString());
 
	}
 

	
 
	if (!payload->getNode().empty()) {
 
		subscription.setAttribute("node", payload->getNode());
 
	}
 

	
 
	switch (payload->getType()) {
 
		case PubSubSubscriptionPayload::None:
 
			subscription.setAttribute("subscription", "none");
 
			break;
 
		case PubSubSubscriptionPayload::Subscribed:
 
			subscription.setAttribute("subscription", "subscribed");
 
			break;
 
		case PubSubSubscriptionPayload::Unconfigured:
 
			subscription.setAttribute("subscription", "unconfigured");
 
			break;
 
		case PubSubSubscriptionPayload::Pending:
 
			subscription.setAttribute("subscription", "pending");
 
			break;
 
	}
 

	
 
	return subscription.serialize();
 
}
 

	
 
}
include/Swiften/Serializer/PayloadSerializers/PubSubSubscriptionPayloadSerializer.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/PubSubSubscriptionPayload.h>
 

	
 
namespace Swift {
 
	class PubSubSubscriptionPayloadSerializer : public GenericPayloadSerializer<PubSubSubscriptionPayload> {
 
		public:
 
			PubSubSubscriptionPayloadSerializer();
 

	
 
			virtual std::string serializePayload(boost::shared_ptr<PubSubSubscriptionPayload> item)  const;
 
	};
 
}
include/Swiften/Server/ServerStanzaChannel.cpp
Show inline comments
 
/*
 
 * Copyright (c) 2010 Remko Tronçon
 
 * Licensed under the GNU General Public License v3.
 
 * See Documentation/Licenses/GPLv3.txt for more information.
 
 */
 

	
 
#include "Swiften/Server/ServerStanzaChannel.h"
 
#include "Swiften/Base/Error.h"
 
#include <iostream>
 

	
 
#include <boost/bind.hpp>
 

	
 
namespace Swift {
 

	
 
namespace {
 
// 	struct PriorityLessThan {
 
// 		bool operator()(const ServerSession* s1, const ServerSession* s2) const {
 
// 			return s1->getPriority() < s2->getPriority();
 
// 		}
 
// 	};
 

	
 
	struct HasJID {
 
		HasJID(const JID& jid) : jid(jid) {}
 
		bool operator()(const boost::shared_ptr<ServerFromClientSession> session) const {
 
			return session->getRemoteJID().equals(jid, JID::WithResource);
 
		}
 
		JID jid;
 
	};
 
}
 

	
 
void ServerStanzaChannel::addSession(boost::shared_ptr<ServerFromClientSession> session) {
 
	sessions[session->getRemoteJID().toBare().toString()].push_back(session);
 
	session->onSessionFinished.connect(boost::bind(&ServerStanzaChannel::handleSessionFinished, this, _1, session));
 
	session->onElementReceived.connect(boost::bind(&ServerStanzaChannel::handleElement, this, _1, session));
 
	session->onDataRead.connect(boost::bind(&ServerStanzaChannel::handleDataRead, this, _1, session));
 
}
 

	
 
void ServerStanzaChannel::removeSession(boost::shared_ptr<ServerFromClientSession> session) {
 
	session->onSessionFinished.disconnect(boost::bind(&ServerStanzaChannel::handleSessionFinished, this, _1, session));
 
	session->onElementReceived.disconnect(boost::bind(&ServerStanzaChannel::handleElement, this, _1, session));
 
	session->onDataRead.disconnect(boost::bind(&ServerStanzaChannel::handleDataRead, this, _1, session));
 
	std::list<boost::shared_ptr<ServerFromClientSession> > &lst = sessions[session->getRemoteJID().toBare().toString()];
 
	lst.erase(std::remove(lst.begin(), lst.end(), session), lst.end());
 
}
 

	
 
void ServerStanzaChannel::sendIQ(boost::shared_ptr<IQ> iq) {
 
	send(iq);
 
}
 

	
 
void ServerStanzaChannel::sendMessage(boost::shared_ptr<Message> message) {
 
	send(message);
 
}
 

	
 
void ServerStanzaChannel::sendPresence(boost::shared_ptr<Presence> presence) {
 
	send(presence);
 
}
 

	
 
void ServerStanzaChannel::handleDataRead(const SafeByteArray &data, const boost::shared_ptr<ServerFromClientSession> &session) {
 
	if (safeByteArrayToString(data).find("</stream:stream>") != std::string::npos) {
 
		Swift::Presence::ref presence = Swift::Presence::create();
 
		presence->setFrom(session->getRemoteJID());
 
		presence->setType(Swift::Presence::Unavailable);
 
		onPresenceReceived(presence);
 
	}
 
}
 

	
 
void ServerStanzaChannel::finishSession(const JID& to, boost::shared_ptr<Element> element, bool last) {
 
	std::vector<boost::shared_ptr<ServerFromClientSession> > candidateSessions;
 
	for (std::list<boost::shared_ptr<ServerFromClientSession> >::const_iterator i = sessions[to.toBare().toString()].begin(); i != sessions[to.toBare().toString()].end(); ++i) {
 
		candidateSessions.push_back(*i);
 
	}
 

	
 
	for (std::vector<boost::shared_ptr<ServerFromClientSession> >::const_iterator i = candidateSessions.begin(); i != candidateSessions.end(); ++i) {
 
		removeSession(*i);
 
		if (element) {
 
			(*i)->sendElement(element);
 
		}
 

	
 
		if (last && (*i)->getRemoteJID().isValid()) {
 
			Swift::Presence::ref presence = Swift::Presence::create();
 
			presence->setFrom((*i)->getRemoteJID());
 
			presence->setType(Swift::Presence::Unavailable);
 
			onPresenceReceived(presence);
 
		}
 

	
 
		(*i)->finishSession();
 
// 		std::cout << "FINISH SESSION " << sessions[to.toBare().toString()].size() << "\n";
 
		if (last) {
 
			break;
 
		}
 
	}
 
}
 

	
 
std::string ServerStanzaChannel::getNewIQID() {
 
	return idGenerator.generateID();
 
}
 

	
 
void ServerStanzaChannel::send(boost::shared_ptr<Stanza> stanza) {
 
	JID to = stanza->getTo();
 
	assert(to.isValid());
 

	
 
	// For a full JID, first try to route to a session with the full JID
 
	if (!to.isBare()) {
 
		std::list<boost::shared_ptr<ServerFromClientSession> >::const_iterator i = std::find_if(sessions[stanza->getTo().toBare().toString()].begin(), sessions[stanza->getTo().toBare().toString()].end(), HasJID(to));
 
		if (i != sessions[stanza->getTo().toBare().toString()].end()) {
 
			(*i)->sendElement(stanza);
 
			return;
 
		}
 
	}
 

	
 
	// Look for candidate sessions
 
	to = to.toBare();
 
	std::vector<boost::shared_ptr<ServerFromClientSession> > candidateSessions;
 
	for (std::list<boost::shared_ptr<ServerFromClientSession> >::const_iterator i = sessions[stanza->getTo().toBare().toString()].begin(); i != sessions[stanza->getTo().toBare().toString()].end(); ++i) {
 
		if ((*i)->getRemoteJID().equals(to, JID::WithoutResource)) {
 
			candidateSessions.push_back(*i);
 
			(*i)->sendElement(stanza);
 
		}
 
	}
 
	if (candidateSessions.empty()) {
 
		return;
 
	}
 

	
 
	// Find the session with the highest priority
 
// 	std::vector<ServerSession*>::const_iterator i = std::max_element(sessions.begin(), sessions.end(), PriorityLessThan());
 
// 	(*i)->sendStanza(stanza);
 
	return;
 
}
 

	
 
void ServerStanzaChannel::handleSessionFinished(const boost::optional<Session::SessionError>&, const boost::shared_ptr<ServerFromClientSession>& session) {
 
	removeSession(session);
 

	
 
// 	if (!session->initiatedFinish()) {
 
		Swift::Presence::ref presence = Swift::Presence::create();
 
		presence->setFrom(session->getRemoteJID());
 
		presence->setType(Swift::Presence::Unavailable);
 
		onPresenceReceived(presence);
 
// 	}
 
}
 

	
 
void ServerStanzaChannel::handleElement(boost::shared_ptr<Element> element, const boost::shared_ptr<ServerFromClientSession>& session) {
 
	boost::shared_ptr<Stanza> stanza = boost::dynamic_pointer_cast<Stanza>(element);
 
	if (!stanza) {
 
		return;
 
	}
 

	
 
	stanza->setFrom(session->getRemoteJID());
 

	
 
	if (!stanza->getFrom().isValid())
 
		return;
 
	
 

	
 
	boost::shared_ptr<Message> message = boost::dynamic_pointer_cast<Message>(stanza);
 
	if (message) {
 
		onMessageReceived(message);
 
		return;
 
	}
 

	
 
	boost::shared_ptr<Presence> presence = boost::dynamic_pointer_cast<Presence>(stanza);
 
	if (presence) {
 
		onPresenceReceived(presence);
 
		return;
include/Swiften/Server/ServerStanzaChannel.h
Show inline comments
 
/*
 
 * Copyright (c) 2010 Remko Tronçon
 
 * Licensed under the GNU General Public License v3.
 
 * See Documentation/Licenses/GPLv3.txt for more information.
 
 */
 

	
 
#pragma once
 

	
 
#include <boost/shared_ptr.hpp>
 

	
 
#include "Swiften/Base/IDGenerator.h"
 
#include "Swiften/Server/ServerFromClientSession.h"
 
#include "Swiften/Client/StanzaChannel.h"
 
#include "Swiften/Elements/Message.h"
 
#include "Swiften/Elements/IQ.h"
 
#include "Swiften/Elements/Presence.h"
 

	
 
namespace Swift {
 
	class Error;
 
	class ServerStanzaChannel : public StanzaChannel {
 
		public:
 
			void addSession(boost::shared_ptr<ServerFromClientSession> session);
 
			void removeSession(boost::shared_ptr<ServerFromClientSession> session);
 

	
 
			void sendIQ(boost::shared_ptr<IQ> iq);
 
			void sendMessage(boost::shared_ptr<Message> message);
 
			void sendPresence(boost::shared_ptr<Presence> presence);
 

	
 
			void finishSession(const JID& to, boost::shared_ptr<Element> element, bool last = false);
 

	
 
			bool getStreamManagementEnabled() const {
 
				return false;
 
			}
 

	
 
			bool isAvailable() const {
 
				return true;
 
			}
 

	
 
		private:
 
			std::string getNewIQID();
 
			void send(boost::shared_ptr<Stanza> stanza);
 
			void handleSessionFinished(const boost::optional<Session::SessionError>&, const boost::shared_ptr<ServerFromClientSession> &session);
 
			void handleElement(boost::shared_ptr<Element> element, const boost::shared_ptr<ServerFromClientSession> &session);
 
			void handleDataRead(const SafeByteArray &data, const boost::shared_ptr<ServerFromClientSession> &session);
 
			void handleSessionInitialized();
 

	
 
		private:
 
			IDGenerator idGenerator;
 
			// [JID][resources][ServerFromClientSession]
 
			std::map<std::string, std::list<boost::shared_ptr<ServerFromClientSession> > > sessions;
 
	};
 

	
 
}
include/Swiften/TLS/OpenSSL/OpenSSLServerContext.cpp
Show inline comments
 
/*
 
 * Copyright (c) 2010 Remko Tronçon
 
 * Licensed under the GNU General Public License v3.
 
 * See Documentation/Licenses/GPLv3.txt for more information.
 
 */
 
#include "Swiften/Base/Platform.h"
 

	
 
#ifdef SWIFTEN_PLATFORM_WINDOWS
 
#include <windows.h>
 
#include <wincrypt.h>
 
#endif
 

	
 
#include <vector>
 
#include <openssl/err.h>
 
#include <openssl/pkcs12.h>
 

	
 
#include "log4cxx/logger.h"
 
#include "log4cxx/consoleappender.h"
 
#include "log4cxx/patternlayout.h"
 
#include "log4cxx/propertyconfigurator.h"
 
using namespace log4cxx;
 
static LoggerPtr logger = Logger::getLogger("OpenSSLServerContext");
 

	
 

	
 
#include "Swiften/TLS/OpenSSL/OpenSSLServerContext.h"
 
#include "Swiften/TLS/OpenSSL/OpenSSLCertificate.h"
 
#include "Swiften/TLS/PKCS12Certificate.h"
 
#ifndef _MSC_VER
 
#pragma GCC diagnostic ignored "-Wold-style-cast"
 
#endif
 
namespace Swift {
 

	
 
static const int MAX_FINISHED_SIZE = 4096;
 
static const int SSL_READ_BUFFERSIZE = 8192;
 

	
 
static void freeX509Stack(STACK_OF(X509)* stack) {
 
	sk_X509_free(stack);
 
}
 

	
 
// static int _sx_ssl_verify_callback(int preverify_ok, X509_STORE_CTX *ctx) {
 
// 	return 1;
 
// }
 

	
 
OpenSSLServerContext::OpenSSLServerContext() : state_(Start), context_(0), handle_(0), readBIO_(0), writeBIO_(0) {
 
	ensureLibraryInitialized();
 
	context_ = SSL_CTX_new(SSLv23_server_method());
 
// 	SSL_CTX_set_verify(context_, SSL_VERIFY_PEER, _sx_ssl_verify_callback);
 

	
 
	// Load system certs
 
#if defined(SWIFTEN_PLATFORM_WINDOWS)
 
	X509_STORE* store = SSL_CTX_get_cert_store(context_);
 
	HCERTSTORE systemStore = CertOpenSystemStore(0, "ROOT");
 
	if (systemStore) {
 
		PCCERT_CONTEXT certContext = NULL;
 
		while (true) {
 
			certContext = CertFindCertificateInStore(systemStore, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING, 0, CERT_FIND_ANY, NULL, certContext);
 
			if (!certContext) {
 
				break;
 
			}
 
			ByteArray certData(createByteArray(certContext->pbCertEncoded, certContext->cbCertEncoded));
 
			OpenSSLCertificate cert(certData);
 
			if (store && cert.getInternalX509()) {
 
				X509_STORE_add_cert(store, cert.getInternalX509().get());
 
			}
 
		}
 
	}
 
#elif !defined(SWIFTEN_PLATFORM_MACOSX)
 
	SSL_CTX_load_verify_locations(context_, NULL, "/etc/ssl/certs");
 
#endif
 
}
 

	
 
OpenSSLServerContext::~OpenSSLServerContext() {
 
	SSL_free(handle_);
 
	SSL_CTX_free(context_);
 
}
 

	
 
void OpenSSLServerContext::ensureLibraryInitialized() {
 
	static bool isLibraryInitialized = false;
 
	if (!isLibraryInitialized) {
 
		SSL_load_error_strings();
 
		SSL_library_init();
 
		OpenSSL_add_all_algorithms();
 

	
 
		// Disable compression
 
		/*
 
		STACK_OF(SSL_COMP)* compressionMethods = SSL_COMP_get_compression_methods();
 
		sk_SSL_COMP_zero(compressionMethods);*/
 

	
 
		isLibraryInitialized = true;
 
	}
 
}
 

	
 
void OpenSSLServerContext::connect() {
 
	handle_ = SSL_new(context_);
 
	// Ownership of BIOs is ransferred
 
	readBIO_ = BIO_new(BIO_s_mem());
 
	writeBIO_ = BIO_new(BIO_s_mem());
 
	SSL_set_bio(handle_, readBIO_, writeBIO_);
 

	
 
	state_ = Connecting;
 
	doConnect();
 
}
 

	
 
void OpenSSLServerContext::doConnect() {
 
	int connectResult = SSL_accept(handle_);
 
	int error = SSL_get_error(handle_, connectResult);
 
// 	std::cout << "DO CONNECT\n";
 
	switch (error) {
 
		case SSL_ERROR_NONE: {
 
			if (SSL_is_init_finished(handle_)) {
 
// 				std::cout << "FINISHED\n";
 
				state_ = Connected;
 
				//std::cout << x->name << std::endl;
 
				//const char* comp = SSL_get_current_compression(handle_);
 
				//std::cout << "Compression: " << SSL_COMP_get_name(comp) << std::endl;
 
				onConnected();
 
				ERR_print_errors_fp(stdout);
 
				sendPendingDataToNetwork();
 
			}
 
			break;
 
		}
 
		case SSL_ERROR_WANT_READ:
 
			sendPendingDataToNetwork();
 
			break;
 
		default:
 
			state_ = Error;
 
// 			std::cout << "AAAAAAAA 1 " << error << " " << connectResult <<  "\n";
 
			ERR_print_errors_fp(stdout);
 
			onError();
 
	}
 
}
 

	
 
void OpenSSLServerContext::sendPendingDataToNetwork() {
 
	int size = BIO_pending(writeBIO_);
 
	if (size > 0) {
 
		SafeByteArray data;
 
		data.resize(size);
 
		BIO_read(writeBIO_, vecptr(data), size);
 
		onDataForNetwork(data);
 
	}
 
}
 

	
 
void OpenSSLServerContext::handleDataFromNetwork(const SafeByteArray& data) {
 
	BIO_write(readBIO_, vecptr(data), data.size());
 
// 	std::cout << "handleDataFromNetwork\n";
 
	switch (state_) {
 
		case Connecting:
 
			doConnect();
 
			break;
 
		case Connected:
 
			sendPendingDataToApplication();
 
			break;
 
		case Start: assert(false); break;
 
		case Error: /*assert(false);*/ break;
 
	}
 
}
 

	
 
void OpenSSLServerContext::handleDataFromApplication(const SafeByteArray& data) {
 
// 	std::cout << "SSL_WRITE\n";
 
	if (SSL_write(handle_, vecptr(data), data.size()) >= 0) {
 
		sendPendingDataToNetwork();
 
	}
 
	else {
 
		state_ = Error;
 
// 		std::cout << "AAAAAAAA 2\n";
 
		onError();
 
	}
 
}
 

	
 
void OpenSSLServerContext::sendPendingDataToApplication() {
 
	SafeByteArray data;
 
	data.resize(SSL_READ_BUFFERSIZE);
 
	int ret = SSL_read(handle_, vecptr(data), data.size());
 
	while (ret > 0) {
 
		data.resize(ret);
 
		onDataForApplication(data);
 
		data.resize(SSL_READ_BUFFERSIZE);
 
		ret = SSL_read(handle_, vecptr(data), data.size());
 
	}
 
	if (ret < 0 && SSL_get_error(handle_, ret) != SSL_ERROR_WANT_READ) {
 
		state_ = Error;
 
// 		std::cout << "AAAAAAAA 3\n";
 
		onError();
 
	}
 
}
 

	
 
bool OpenSSLServerContext::setServerCertificate(const PKCS12Certificate& certificate) {
 
	if (certificate.isNull()) {
 
// 		std::cout << "error 1\n";
 
		LOG4CXX_ERROR(logger, "TLS WILL NOT WORK: Certificate can't be loaded.");
 
		return false;
 
	}
 

	
 
	// Create a PKCS12 structure
 
	BIO* bio = BIO_new(BIO_s_mem());
 
	BIO_write(bio, vecptr(certificate.getData()), certificate.getData().size());
 
	boost::shared_ptr<PKCS12> pkcs12(d2i_PKCS12_bio(bio, NULL), PKCS12_free);
 
	BIO_free(bio);
 
	if (!pkcs12) {
 
// 		std::cout << "error 2\n";
 
		LOG4CXX_ERROR(logger, "TLS WILL NOT WORK: Certificate is not in PKCS#12 format.");
 
		return false;
 
	}
 

	
 
	// Parse PKCS12
 
	X509 *certPtr = 0;
 
	EVP_PKEY* privateKeyPtr = 0;
 
	STACK_OF(X509)* caCertsPtr = 0;
 
	int result = PKCS12_parse(pkcs12.get(), reinterpret_cast<const char*>(vecptr(certificate.getPassword())), &privateKeyPtr, &certPtr, &caCertsPtr);
 
	if (result != 1) { 
 
// 		std::cout << "error 3\n";
 
		LOG4CXX_ERROR(logger, "TLS WILL NOT WORK: Certificate is not in PKCS#12 format.");
 
		return false;
 
	}
 
	boost::shared_ptr<X509> cert(certPtr, X509_free);
 
	boost::shared_ptr<EVP_PKEY> privateKey(privateKeyPtr, EVP_PKEY_free);
 
	boost::shared_ptr<STACK_OF(X509)> caCerts(caCertsPtr, freeX509Stack);
 

	
 
	// Use the key & certificates
 
	if (SSL_CTX_use_certificate(context_, cert.get()) != 1) {
 
// 		std::cout << "error 4\n";
 
		LOG4CXX_ERROR(logger, "TLS WILL NOT WORK: Can't use this certificate");
 
		return false;
 
	}
 
	if (SSL_CTX_use_PrivateKey(context_, privateKey.get()) != 1) {
 
// 		std::cout << "error 5\n";
 
		LOG4CXX_ERROR(logger, "TLS WILL NOT WORK: Can't use this private key");
 
		return false;
 
	}
 
	return true;
 
}
 

	
 
Certificate::ref OpenSSLServerContext::getPeerCertificate() const {
 
	boost::shared_ptr<X509> x509Cert(SSL_get_peer_certificate(handle_), X509_free);
 
	if (x509Cert) {
 
		return Certificate::ref(new OpenSSLCertificate(x509Cert));
 
	}
 
	else {
 
		return Certificate::ref();
 
	}
 
}
 

	
 
boost::shared_ptr<CertificateVerificationError> OpenSSLServerContext::getPeerCertificateVerificationError() const {
 
	int verifyResult = SSL_get_verify_result(handle_);
 
	if (verifyResult != X509_V_OK) {
 
		return boost::shared_ptr<CertificateVerificationError>(new CertificateVerificationError(getVerificationErrorTypeForResult(verifyResult)));
 
	}
 
	else {
 
		return boost::shared_ptr<CertificateVerificationError>();
 
	}
 
}
 

	
 
ByteArray OpenSSLServerContext::getFinishMessage() const {
 
	ByteArray data;
 
	data.resize(MAX_FINISHED_SIZE);
 
	size_t size = SSL_get_finished(handle_, vecptr(data), data.size());
 
	data.resize(size);
 
	return data;
 
}
 

	
 
CertificateVerificationError::Type OpenSSLServerContext::getVerificationErrorTypeForResult(int result) {
 
	assert(result != 0);
 
	switch (result) {
 
		case X509_V_ERR_CERT_NOT_YET_VALID:
 
		case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD:
 
			return CertificateVerificationError::NotYetValid;
 

	
 
		case X509_V_ERR_CERT_HAS_EXPIRED:
 
		case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD:
 
			return CertificateVerificationError::Expired;
 

	
 
		case X509_V_ERR_DEPTH_ZERO_SELF_SIGNED_CERT:
 
		case X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN:
 
			return CertificateVerificationError::SelfSigned;
 

	
 
		case X509_V_ERR_CERT_UNTRUSTED:
 
			return CertificateVerificationError::Untrusted;
 

	
 
		case X509_V_ERR_CERT_REJECTED:
 
			return CertificateVerificationError::Rejected;
 

	
 
		case X509_V_ERR_INVALID_PURPOSE:
 
			return CertificateVerificationError::InvalidPurpose;
 

	
 
		case X509_V_ERR_PATH_LENGTH_EXCEEDED:
 
			return CertificateVerificationError::PathLengthExceeded;
 

	
 
		case X509_V_ERR_UNABLE_TO_DECRYPT_CERT_SIGNATURE:
 
		case X509_V_ERR_CERT_SIGNATURE_FAILURE:
 
		case X509_V_ERR_UNABLE_TO_VERIFY_LEAF_SIGNATURE:
 
			return CertificateVerificationError::InvalidSignature;
 

	
 
		case X509_V_ERR_INVALID_CA:
 
		case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT:
 
		case X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY:
 
		case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY:
 
			return CertificateVerificationError::InvalidCA;
 

	
 
		case X509_V_ERR_SUBJECT_ISSUER_MISMATCH:
 
		case X509_V_ERR_AKID_SKID_MISMATCH:
 
		case X509_V_ERR_AKID_ISSUER_SERIAL_MISMATCH:
 
		case X509_V_ERR_KEYUSAGE_NO_CERTSIGN:
 
			return CertificateVerificationError::UnknownError;
 

	
 
		// Unused / should not happen
 
		case X509_V_ERR_CERT_REVOKED:
 
		case X509_V_ERR_OUT_OF_MEM:
 
		case X509_V_ERR_UNABLE_TO_GET_CRL:
 
		case X509_V_ERR_UNABLE_TO_DECRYPT_CRL_SIGNATURE:
 
		case X509_V_ERR_CRL_SIGNATURE_FAILURE:
 
		case X509_V_ERR_CRL_NOT_YET_VALID:
 
		case X509_V_ERR_CRL_HAS_EXPIRED:
 
		case X509_V_ERR_ERROR_IN_CRL_LAST_UPDATE_FIELD:
 
		case X509_V_ERR_ERROR_IN_CRL_NEXT_UPDATE_FIELD:
 
		case X509_V_ERR_CERT_CHAIN_TOO_LONG:
 
		case X509_V_ERR_APPLICATION_VERIFICATION:
 
		default:
 
			return CertificateVerificationError::UnknownError;
 
	}
 
}
 

	
 
}
include/transport/gatewayresponder.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/Responder.h"
 
#include "Swiften/Elements/GatewayPayload.h"
 

	
 
namespace Transport {
 

	
 
class UserManager;
 

	
 
class GatewayResponder : public Swift::Responder<Swift::GatewayPayload> {
 
	public:
 
		GatewayResponder(Swift::IQRouter *router, UserManager *userManager);
 
		~GatewayResponder();
 

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

	
 
}
 
\ No newline at end of file
include/transport/pqxxbackend.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
 

	
 
#ifdef WITH_PQXX
 

	
 
#include <string>
 
#include <map>
 
#include "Swiften/Swiften.h"
 
#include "transport/storagebackend.h"
 
#include "transport/config.h"
 
#include <pqxx/pqxx>
 

	
 
namespace Transport {
 

	
 
/// Used to store transport data into SQLite3 database.
 
class PQXXBackend : public StorageBackend
 
{
 
	public:
 
		/// Creates new PQXXBackend instance.
 
		/// \param config cofiguration, this class uses following Config values:
 
		/// 	- database.database - path to SQLite3 database file, database file is created automatically
 
		/// 	- service.prefix - prefix for tables created by createDatabase method
 
		PQXXBackend(Config *config);
 

	
 
		/// Destructor.
 
		~PQXXBackend();
 

	
 
		/// Connects to the database and creates it if it's needed. This method call createDatabase() function
 
		/// automatically.
 
		/// \return true if database is opened successfully.
 
		bool connect();
 
		void disconnect();
 

	
 
		/// Creates database structure.
 
		/// \see connect()
 
		/// \return true if database structure has been created successfully. Note that it returns True also if database structure
 
		/// already exists.
 
		bool createDatabase();
 

	
 
		/// Stores user into database.
 
		/// \param user user struct containing all information about user which have to be stored
 
		void setUser(const UserInfo &user);
 

	
 
		/// Gets user data from database and stores them into user reference.
 
		/// \param barejid barejid of user
 
		/// \param user UserInfo object where user data will be stored
 
		/// \return true if user has been found in database
 
		bool getUser(const std::string &barejid, UserInfo &user);
 

	
 
		/// Changes users online state variable in database.
 
		/// \param id id of user - UserInfo.id
 
		/// \param online online state
 
		void setUserOnline(long id, bool online);
 

	
 
		/// Removes user and all connected data from database.
 
		/// \param id id of user - UserInfo.id
 
		/// \return true if user has been found in database and removed
 
		bool removeUser(long id);
 

	
 
		/// Returns JIDs of all buddies in user's roster.
 
		/// \param id id of user - UserInfo.id
 
		/// \param roster string list used to store user's roster
 
		/// \return true if user has been found in database and roster has been fetched
 
		bool getBuddies(long id, std::list<BuddyInfo> &roster);
 

	
 
		bool getOnlineUsers(std::vector<std::string> &users);
 

	
 
		long addBuddy(long userId, const BuddyInfo &buddyInfo);
 

	
 
		void updateBuddy(long userId, const BuddyInfo &buddyInfo);
 
		void removeBuddy(long id) {}
 

	
 
		void getUserSetting(long userId, const std::string &variable, int &type, std::string &value);
 
		void updateUserSetting(long userId, const std::string &variable, const std::string &value);
 

	
 
		void beginTransaction();
 
		void commitTransaction();
 

	
 
	private:
 
		bool exec(const std::string &query, bool show_error = true);
 
		bool exec(pqxx::nontransaction &txn, const std::string &query, bool show_error = true);
 
		template<typename T>
 
		std::string quote(pqxx::nontransaction &txn, const T &t);
 

	
 
		Config *m_config;
 
		std::string m_prefix;
 

	
 
		pqxx::connection *m_conn;
 
};
 

	
 
}
 

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

	
 
#pragma once
 

	
 
#include <map>
 

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

	
 
#include <Swiften/Base/boost_bsignals.h>
 

	
 
namespace Transport {
 

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

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

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

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

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

	
 
}
 

	
include/transport/transport.h
Show inline comments
 
/**
 
 * 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/Server/Server.h"
 
#include "Swiften/Disco/GetDiscoInfoRequest.h"
 
#include "Swiften/Disco/EntityCapsManager.h"
 
#include "Swiften/Disco/CapsManager.h"
 
#include "Swiften/Disco/CapsMemoryStorage.h"
 
#include "Swiften/Presence/PresenceOracle.h"
 
#include "Swiften/Network/BoostTimerFactory.h"
 
#include "Swiften/Network/BoostIOServiceThread.h"
 
#include "Swiften/Server/UserRegistry.h"
 
#include "Swiften/Base/SafeByteArray.h"
 
#include "Swiften/Jingle/JingleSessionManager.h"
 

	
 
#include <boost/bind.hpp>
 
#include "transport/config.h"
 
#include "transport/factory.h"
 
#include "transport/presenceoracle.h"
 

	
 
namespace Transport {
 
	// typedef enum { 	CLIENT_FEATURE_ROSTERX = 2,
 
	// 				CLIENT_FEATURE_XHTML_IM = 4,
 
	// 				CLIENT_FEATURE_FILETRANSFER = 8,
 
	// 				CLIENT_FEATURE_CHATSTATES = 16
 
	// 				} SpectrumImportantFeatures;
 
	// 
 
	class StorageBackend;
 
	class DiscoInfoResponder;
 
	class DiscoItemsResponder;
 
	class Factory;
 
	class UserRegistry;
 

	
 
	/// Represents one transport instance.
 

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

	
 
			/// \param loop Main event loop.
 
			/// \param config Cofiguration; this class uses following Config values:
 
			/// 	- service.jid
 
			/// 	- service.password
 
			/// 	- service.server
 
			/// 	- service.port
 
			/// 	- service.server_mode
 
			/// \param factory Transport Abstract factory used to create basic transport structures.
 
			Component(Swift::EventLoop *loop, Swift::NetworkFactories *factories, Config *config, Factory *factory, Transport::UserRegistry *userRegistry = NULL);
 

	
 
			/// Component destructor.
 
			~Component();
 

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

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

	
 
			Swift::CapsInfo &getBuddyCapsInfo();
 

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

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

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

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

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

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

	
 
			/// Connects the Jabber server.
 

	
 
			void start();
 
			void stop();
 

	
 
			/// Sets disco#info features which are sent as answer to disco#info IQ-get.
 
			
 
			/// This sets features of transport contact (For example "j2j.domain.tld").
 
			/// \param features list of features as sent in disco#info response
 
			void setTransportFeatures(std::list<std::string> &features);
 

	
 
			/// Sets disco#info features which are sent as answer to disco#info IQ-get.
 
			
 
			/// This sets features of legacy network buddies (For example "me\40gmail.com@j2j.domain.tld").
 
			/// \param features list of features as sent in disco#info response
 
			void setBuddyFeatures(std::list<std::string> &features);
 

	
 
			/// Returns Jabber ID of this transport.
 

	
 
			/// \return Jabber ID of this transport
 
			Swift::JID &getJID() { return m_jid; }
 

	
 
			/// Returns Swift::NetworkFactories which can be used to create new connections.
 

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

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

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

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

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

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

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

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

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

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

	
 
			Config *getConfig() { return m_config; }
 

	
 
			/// This signal is emitted when presence from XMPP user is received.
 

	
 
			/// It's emitted only for presences addressed to transport itself
 
			/// (for example to="j2j.domain.tld").
 
			/// \param presence presence data
 
			boost::signal<void (Swift::Presence::ref presence)> onUserPresenceReceived;
 

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

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

	
 
		private:
 
			void handleConnected();
 
			void handleConnectionError(const Swift::ComponentError &error);
 
			void handlePresence(Swift::Presence::ref presence);
 
			void handleDataRead(const Swift::SafeByteArray &data);
 
			void handleDataWritten(const Swift::SafeByteArray &data);
 

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

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

	
 
		friend class User;
 
		friend class UserRegistration;
 
		friend class NetworkPluginServer;
 
	};
 
}
include/transport/user.h
Show inline comments
 
/**
 
 * 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 <time.h>
 
#include "Swiften/Swiften.h"
 
#include "Swiften/Presence/PresenceOracle.h"
 
#include "Swiften/Disco/EntityCapsManager.h"
 
#include "Swiften/Disco/EntityCapsProvider.h"
 
#include "storagebackend.h"
 
#include <Swiften/FileTransfer/OutgoingFileTransfer.h>
 
#include "Swiften/Elements/SpectrumErrorPayload.h"
 

	
 
namespace Transport {
 

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

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

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

	
 
		/// Returns JID of XMPP user who is currently connected using this User class.
 
		/// \return full JID
 
		const Swift::JID &getJID();
 

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

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

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

	
 
		RosterManager *getRosterManager() { return m_rosterManager; }
 

	
 
		ConversationManager *getConversationManager() { return m_conversationManager; }
 

	
 
		Component *getComponent() { return m_component; }
 

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

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

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

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

	
 
		time_t &getLastActivity() {
 
			return m_lastActivity;
 
		}
 

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

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

	
 
		void handleDisconnected(const std::string &error, Swift::SpectrumErrorPayload::Error e = Swift::SpectrumErrorPayload::CONNECTION_ERROR_OTHER_ERROR);
 

	
 
		bool isReadyToConnect() {
 
			return m_readyForConnect;
 
		}
 

	
 
		void setConnected(bool connected);
 

	
 
		void sendCurrentPresence();
 

	
 
		void setIgnoreDisconnect(bool ignoreDisconnect);
 

	
 
		bool isConnected() {
 
			return m_connected;
 
		}
 

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

	
 
	private:
 
		void onConnectingTimeout();
 

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

	
 
}
include/transport/usermanager.h
Show inline comments
 
@@ -11,126 +11,130 @@
 
 * This program is distributed in the hope that it will be useful,
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
 * GNU General Public License for more details.
 
 *
 
 * You should have received a copy of the GNU General Public License
 
 * along with this program; if not, write to the Free Software
 
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
 
 */
 

	
 
#pragma once
 

	
 
#include <string>
 
#include <map>
 
#include "Swiften/Swiften.h"
 
#include "transport/userregistry.h"
 

	
 
namespace Transport {
 

	
 
class User;
 
class Component;
 
class StorageBackend;
 
class StorageResponder;
 
class RosterResponder;
 

	
 
/// Manages online XMPP Users.
 

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

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

	
 
		/// Destroys UserManager.
 
		~UserManager();
 

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

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

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

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

	
 
		void removeAllUsers(bool onUserBehalf = true);
 

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

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

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

	
 
		/// Returns true if user is connected.
 
		/// \return True if user is connected.
 
		bool isUserConnected(const std::string &barejid) const {
 
			return m_users.find(barejid) != m_users.end();
 
		}
 

	
 
		/// Returns pointer to UserRegistry.
 
		/// \return Pointer to UserRegistry.
 
		UserRegistry *getUserRegistry() {
 
			return m_userRegistry;
 
		}
 

	
 
		Component *getComponent() {
 
			return m_component;
 
		}
 

	
 
		/// Connects user manually.
 
		/// \param user JID of user.
 
		void connectUser(const Swift::JID &user);
 

	
 
		/// Disconnects user manually.
 
		/// \param user JID of user.
 
		void disconnectUser(const Swift::JID &user);
 

	
 
	private:
 
		void handlePresence(Swift::Presence::ref presence);
 
		void handleMessageReceived(Swift::Message::ref message);
 
		void handleGeneralPresenceReceived(Swift::Presence::ref presence);
 
		void handleProbePresence(Swift::Presence::ref presence);
 
		void handleSubscription(Swift::Presence::ref presence);
 
		void handleRemoveTimeout(const std::string jid, User *user, bool reconnect);
 
		void handleDiscoInfo(const Swift::JID& jid, boost::shared_ptr<Swift::DiscoInfo> info);
 
		void addUser(User *user);
 

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

	
 
}
include/transport/util.h
Show inline comments
 
/**
 
 * 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 <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);
 

	
 
std::string serializeGroups(const std::vector<std::string> &groups);
 

	
 
std::vector<std::string> deserializeGroups(std::string &groups);
 

	
 
int getRandomPort(const std::string &s);
 

	
 
}
 

	
 
}
spectrum/src/main.cpp
Show inline comments
 
#include "transport/config.h"
 
#include "transport/transport.h"
 
#include "transport/filetransfermanager.h"
 
#include "transport/usermanager.h"
 
#include "transport/logger.h"
 
#include "transport/sqlite3backend.h"
 
#include "transport/mysqlbackend.h"
 
#include "transport/pqxxbackend.h"
 
#include "transport/userregistration.h"
 
#include "transport/networkpluginserver.h"
 
#include "transport/admininterface.h"
 
#include "transport/statsresponder.h"
 
#include "transport/usersreconnecter.h"
 
#include "transport/util.h"
 
#include "transport/gatewayresponder.h"
 
#include "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"
 
#else
 
#include <windows.h>
 
#endif
 
#include "log4cxx/logger.h"
 
#include "log4cxx/consoleappender.h"
 
#include "log4cxx/patternlayout.h"
 
#include "log4cxx/propertyconfigurator.h"
 
#include "log4cxx/helpers/properties.h"
 
#include "log4cxx/helpers/transcoder.h"
 
#include "log4cxx/helpers/fileinputstream.h"
 
#include <sys/stat.h>
 

	
 
using namespace log4cxx;
 

	
 
using namespace Transport;
 

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

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

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

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

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

	
 
static void removeOldIcons(std::string iconDir) {
 
	std::vector<std::string> dirs;
 
	dirs.push_back(iconDir);
 

	
 
	boost::thread thread(boost::bind(Util::removeEverythingOlderThan, dirs, time(NULL) - 3600*24*14));
 
}
 

	
 
#ifndef WIN32
 
static void daemonize(const char *cwd, const char *lock_file) {
 
	pid_t pid, sid;
 
	FILE* lock_file_f;
 
	char process_pid[20];
 
	/* already a daemon */
 
	if ( getppid() == 1 ) return;
 

	
 
	/* Fork off the parent process */
 
	pid = fork();
 
	if (pid < 0) {
 
		exit(1);
 
	}
 
	/* If we got a good PID, then we can exit the parent process. */
 
	if (pid > 0) {
 
		if (lock_file) {
 
			/* write our pid into it & close the file. */
 
			lock_file_f = fopen(lock_file, "w+");
 
			if (lock_file_f == NULL) {
 
				std::cerr << "Cannot create lock file " << lock_file << ". Exiting\n";
 
				exit(1);
 
			}
 
			sprintf(process_pid,"%d\n",pid);
 
			if (fwrite(process_pid,1,strlen(process_pid),lock_file_f) < strlen(process_pid)) {
 
				std::cerr << "Cannot write to lock file " << lock_file << ". Exiting\n";
 
				exit(1);
 
			}
 
			fclose(lock_file_f);
 
		}
 
		exit(0);
 
	}
 

	
 
	/* Change the file mode mask */
 
	umask(0);
 

	
 
	/* Create a new SID for the child process */
 
	sid = setsid();
 
	if (sid < 0) {
 
		exit(1);
 
	}
 

	
 
	/* Change the current working directory.  This prevents the current
 
		directory from being locked; hence not being able to remove it. */
 
	if ((chdir(cwd)) < 0) {
 
@@ -286,137 +288,156 @@ int main(int argc, char **argv)
 
					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) {
 
				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)) {
 
				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) {
 
				std::cerr << "Invalid service.user name " << CONFIG_STRING(&config, "service.user") << "\n";
 
				return 1;
 
			}
 

	
 
			if ((setuid(pw->pw_uid)) != 0) {
 
				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);
 

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

	
 
	StorageBackend *storageBackend = NULL;
 

	
 
#ifdef WITH_SQLITE
 
	if (CONFIG_STRING(&config, "database.type") == "sqlite3") {
 
		storageBackend = new SQLite3Backend(&config);
 
		if (!storageBackend->connect()) {
 
			std::cerr << "Can't connect to database. Check the log to find out the reason.\n";
 
			return -1;
 
		}
 
	}
 
#else
 
	if (CONFIG_STRING(&config, "database.type") == "sqlite3") {
 
		std::cerr << "Spectrum2 is not compiled with mysql backend.\n";
 
		return -2;
 
	}
 
#endif
 

	
 
#ifdef WITH_MYSQL
 
	if (CONFIG_STRING(&config, "database.type") == "mysql") {
 
		storageBackend = new MySQLBackend(&config);
 
		if (!storageBackend->connect()) {
 
			std::cerr << "Can't connect to database. Check the log to find out the reason.\n";
 
			return -1;
 
		}
 
	}
 
#else
 
	if (CONFIG_STRING(&config, "database.type") == "mysql") {
 
		std::cerr << "Spectrum2 is not compiled with mysql backend.\n";
 
		return -2;
 
	}
 
#endif
 

	
 
	if (CONFIG_STRING(&config, "database.type") != "mysql" && CONFIG_STRING(&config, "database.type") != "sqlite3") {
 
#ifdef WITH_PQXX
 
	if (CONFIG_STRING(&config, "database.type") == "pqxx") {
 
		storageBackend = new PQXXBackend(&config);
 
		if (!storageBackend->connect()) {
 
			std::cerr << "Can't connect to database. Check the log to find out the reason.\n";
 
			return -1;
 
		}
 
	}
 
#else
 
	if (CONFIG_STRING(&config, "database.type") == "pqxx") {
 
		std::cerr << "Spectrum2 is not compiled with pqxx backend.\n";
 
		return -2;
 
	}
 
#endif
 

	
 
	if (CONFIG_STRING(&config, "database.type") != "mysql" && CONFIG_STRING(&config, "database.type") != "sqlite3"
 
		&& CONFIG_STRING(&config, "database.type") != "pqxx" && CONFIG_STRING(&config, "database.type") != "none") {
 
		std::cerr << "Unknown storage backend " << CONFIG_STRING(&config, "database.type") << "\n";
 
		return -2;
 
	}
 

	
 
	UserManager userManager(&transport, &userRegistry, storageBackend);
 
	userManager_ = &userManager;
 

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

	
 
		usersReconnecter = new UsersReconnecter(&transport, storageBackend);
 
	}
 

	
 
	FileTransferManager ftManager(&transport, &userManager);
 

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

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

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

	
 
	eventLoop_ = &eventLoop;
 

	
 
	eventLoop.run();
 

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

	
 
	if (usersReconnecter) {
 
		delete usersReconnecter;
 
	}
 

	
 
	delete storageBackend;
 
	delete factories;
 
}
spectrum/src/sample.cfg
Show inline comments
 
[service]
 
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/smstools3/spectrum2_smstools3_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
 
#protocol=prpl-msn
 
protocol=any
 
#protocol=prpl-icq
 
irc_server=irc.freenode.org
 
working_dir=./
 

	
 
[backend]
 
#default_avatar=catmelonhead.jpg
 
#no_vcard_fetch=true
 
incoming_dir=/var/spool/sms/incoming
 

	
 
[logging]
 
#config=logging.cfg # log4cxx/log4j logging configuration file
 
#backend_config=/home/hanzz/code/libtransport/spectrum/src/backend-logging.cfg # log4cxx/log4j logging configuration file for backends
 

	
 
[database]
 
type = none # or "none" without database backend
 
database = test.sql
 
prefix=icq
 
#type = mysql # or "none" without database backend.......................................................................................................................
 
#database = test
 
#prefix=
 
#user=root
 
#password=yourrootsqlpassword
 
#encryption_key=hanzzik
spectrum/src/sample2.cfg
Show inline comments
 
[service]
 
# 1 if Spectrum should run in server mode.
 
server_mode = 1
 

	
 
# The name of user/group Spectrum runs as.
 
#user=spectrum
 
#group=spectrum
 

	
 
# JID of Spectrum instance.
 
jid = localhost
 

	
 
# Password used to connect the XMPP server in gateway mode.
 
# In server mode, this option is ignored.
 
password = secret
 

	
 
# XMPP server to which Spectrum connects in gateway mode.
 
# In server mode, this option is ignored.
 
server = 127.0.0.1
 

	
 
# XMPP server port.
 
port = 5222
 

	
 
# Interface on which Spectrum listens for backends.
 
backend_host = localhost
 

	
 
# Port on which Spectrum listens for backends.
 
backend_port=10001
 
# By default Spectrum chooses random backend port and there's
 
# no need to change it normally
 
#backend_port=10001
 

	
 
# Full path to PKCS#12 cetficiate used for TLS in server mode.
 
#cert=
 

	
 
# Certificate password if any.
 
#cert_password= 
 

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

	
 
# Full path to backend binary.
 
backend=/usr/bin/spectrum2_libpurple_backend
 
#backend=/usr/bin/spectrum2_libircclient-qt_backend
 
# For skype:
 
#backend=/usr/bin/xvfb-run -n BACKEND_ID -s "-screen 0 10x10x8" -f /tmp/x-skype-gw /usr/bin/spectrum2_skype_backend
 

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

	
 
# prpl-any means that user sets his protocol in his JID which has to be
 
# in following format: protocol.username@domain.tld
 
# So for example: prpl-jabber.hanzz.k%gmail.com@domain.tld
 
#protocol=prpl-any
 

	
 
[identity]
 
# Name of Spectrum instance in service discovery
 
name=Spectrum Jabber Transport
 

	
 
# Type of transport ("msn", "icq", "xmpp").
 
# Check http://xmpp.org/registrar/disco-categories.html#gateway
 
type=xmpp
 

	
 
# Category of transport, default is "gateway
 
#category=gateway
 

	
 
[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
 

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

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

	
 
# Server.
 
#server = localhost
 

	
 
# Port.
 
#port = 0
 

	
 
# User.
 
#user = spectrum
 

	
 
# Paasword.
 
#password = secret
 

	
 
# Prefix used for tables
 
#prefix = jabber_
 

	
 
[registration]
 
# Enable public registrations
 
enable_public_registration=1
 

	
 
# Text to display upon user registration form
 
#username_label=Jabber JID (e.g. user@server.tld):
 
#instructions=Enter your remote jabber JID and password as well as your local username and password
 

	
 
# If True a local jabber account on <local_account_server> is needed 
 
# for transport registration, the idea is to enable public registration
 
# from other servers, but only for users, who have already local accounts
 
#require_local_account=1
 
#local_username_label=Local username (without @server.tld):
 
#local_account_server=localhost
 
#local_account_server_timeout=10000
 

	
spectrum_manager/src/CMakeLists.txt
Show inline comments
 
cmake_minimum_required(VERSION 2.6)
 
FILE(GLOB SRC *.cpp)
 
 
ADD_EXECUTABLE(spectrum2_manager ${SRC} ../../src/config.cpp)
 
ADD_EXECUTABLE(spectrum2_manager ${SRC} ../../src/config.cpp ../../src/util.cpp)
 
 
target_link_libraries(spectrum2_manager ${SWIFTEN_LIBRARY})
 
 
INSTALL(TARGETS spectrum2_manager RUNTIME DESTINATION bin)
 
 
INSTALL(FILES
 
	spectrum_manager.cfg
 
	DESTINATION /etc/spectrum2
 
	)
src/CMakeLists.txt
Show inline comments
 
cmake_minimum_required(VERSION 2.6)
 
FILE(GLOB SRC *.cpp *.h)
 
FILE(GLOB_RECURSE SWIFTEN_SRC ../include/Swiften/*.cpp)
 
FILE(GLOB HEADERS ../include/transport/*.h)
 

	
 
if (CPPUNIT_FOUND)
 
	FILE(GLOB SRC_TEST tests/*.cpp)
 

	
 
	ADD_EXECUTABLE(libtransport_test ${SRC_TEST})
 

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

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

	
 
# SOURCE_GROUP(headers FILES ${HEADERS})
 

	
 

	
 
if (PROTOBUF_FOUND)
 
	if (CMAKE_COMPILER_IS_GNUCXX)
 
		ADD_LIBRARY(transport SHARED ${HEADERS} ${SRC} ${SWIFTEN_SRC} ${CMAKE_CURRENT_BINARY_DIR}/../include/transport/protocol.pb.cc)
 
		ADD_LIBRARY(transport SHARED ${HEADERS} ${SRC} ${SWIFTEN_SRC})
 
	else(CMAKE_COMPILER_IS_GNUCXX)
 
		ADD_LIBRARY(transport STATIC ${HEADERS} ${SRC} ${SWIFTEN_SRC} ${CMAKE_CURRENT_BINARY_DIR}/../include/transport/protocol.pb.cc)    
 
		ADD_LIBRARY(transport STATIC ${HEADERS} ${SRC} ${SWIFTEN_SRC})
 
	endif(CMAKE_COMPILER_IS_GNUCXX)
 
	SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/../include/transport/protocol.pb.cc PROPERTIES GENERATED 1)
 
#	SET_SOURCE_FILES_PROPERTIES(${CMAKE_CURRENT_BINARY_DIR}/../include/transport/protocol.pb.cc PROPERTIES GENERATED 1)
 
	ADD_DEPENDENCIES(transport pb) 
 
else(PROTOBUF_FOUND)
 
	ADD_LIBRARY(transport SHARED ${HEADERS} ${SRC} ${SWIFTEN_SRC})
 
endif(PROTOBUF_FOUND)
 

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

	
 
if (WIN32)
 
	TARGET_LINK_LIBRARIES(transport ${SQLITE3_LIBRARIES} ${MYSQL_LIBRARIES} ${SWIFTEN_LIBRARY} ${PROTOBUF_LIBRARIES} ${LOG4CXX_LIBRARIES})
 
	TARGET_LINK_LIBRARIES(transport transport-plugin ${PQXX_LIBRARY} ${PQ_LIBRARY} ${SQLITE3_LIBRARIES} ${MYSQL_LIBRARIES} ${SWIFTEN_LIBRARY} ${PROTOBUF_LIBRARIES} ${LOG4CXX_LIBRARIES})
 
else (WIN32)
 
	TARGET_LINK_LIBRARIES(transport ${SQLITE3_LIBRARIES} ${MYSQL_LIBRARIES} ${SWIFTEN_LIBRARY} ${PROTOBUF_LIBRARIES} ${LOG4CXX_LIBRARIES} ${POPT_LIBRARY})
 
	TARGET_LINK_LIBRARIES(transport transport-plugin ${PQXX_LIBRARY} ${PQ_LIBRARY} ${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}
 
)
 

	
 
INSTALL(TARGETS transport LIBRARY DESTINATION lib ARCHIVE DESTINATION lib COMPONENT libraries)
 

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

	
 
#include "transport/config.h"
 
#include "transport/util.h"
 
#include <fstream>
 
#ifdef _MSC_VER
 
#include <direct.h>
 
#define getcwd _getcwd
 
#include <windows.h>
 
#define PATH_MAX MAX_PATH
 
#endif
 

	
 
using namespace boost::program_options;
 

	
 
namespace Transport {
 

	
 
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, 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, 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/$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("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("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("utf8"), "Default encoding in registration form")
 
		("registration.require_local_account", value<bool>()->default_value(false), "True if users have to have a local account to register to this transport from remote servers.")
 
		("registration.local_username_label", value<std::string>()->default_value("Local username:"), "Label for local usernme field")
 
		("registration.local_account_server", value<std::string>()->default_value("localhost"), "The server on which the local accounts will be checked for validity")
 
		("registration.local_account_server_timeout", value<int>()->default_value(10000), "Timeout when checking local user on local_account_server (msecs)")
 
		("database.type", value<std::string>()->default_value("none"), "Database type.")
 
		("database.database", value<std::string>()->default_value(""), "Database used to store data")
 
		("database.database", value<std::string>()->default_value("/var/lib/spectrum2/$jid/database.sql"), "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);
 

	
 
	bool found_working = false;
 
	bool found_pidfile = false;
 
	bool found_backend_port = false;
 
	bool found_database = 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);
 
				opt.value[0] = boost::lexical_cast<std::string>(Util::getRandomPort(_jid.empty() ? jid : _jid));
 
			}
 
		}
 
		else if (opt.string_key == "service.working_dir") {
 
			found_working = true;
 
		}
 
		else if (opt.string_key == "service.pidfile") {
 
			found_pidfile = true;
 
		}
 
		else if (opt.string_key == "database.database") {
 
			found_database = 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));
 
		std::string p = boost::lexical_cast<std::string>(Util::getRandomPort(_jid.empty() ? jid : _jid));
 
		value.push_back(p);
 
		parsed.options.push_back(boost::program_options::basic_option<char>("service.backend_port", value));
 
	}
 
	if (!found_database) {
 
		std::vector<std::string> value;
 
		value.push_back("/var/lib/spectrum2/$jid/database.sql");
 
		parsed.options.push_back(boost::program_options::basic_option<char>("database.database", 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();
 

	
 
	return true;
 
}
 

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

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

	
 
bool Config::reload() {
 
	if (m_file.empty()) {
 
		return false;
 
	}
 

	
 
	return load(m_file);
 
}
 

	
 
}
src/gatewayresponder.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/gatewayresponder.h"
 

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

	
 
using namespace log4cxx;
 

	
 
using namespace Swift;
 
using namespace boost;
 

	
 
namespace Transport {
 

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

	
 
GatewayResponder::GatewayResponder(Swift::IQRouter *router, UserManager *userManager) : Swift::Responder<GatewayPayload>(router) {
 
	m_userManager = userManager;
 
}
 

	
 
GatewayResponder::~GatewayResponder() {
 
}
 

	
 
bool GatewayResponder::handleGetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr<Swift::GatewayPayload> payload) {
 
	sendResponse(from, id, boost::shared_ptr<GatewayPayload>(new GatewayPayload(Swift::JID(), "Enter legacy network contact ID.", "Contact ID")));
 
	return true;
 
}
 

	
 
bool GatewayResponder::handleSetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr<Swift::GatewayPayload> payload) {
 
	std::string prompt = payload->getPrompt();
 
	std::string escaped = Swift::JID::getEscapedNode(prompt);
 
	std::string jid = escaped + "@" + m_userManager->getComponent()->getJID().toBare().toString();
 
	
 
	sendResponse(from, id, boost::shared_ptr<GatewayPayload>(new GatewayPayload(jid)));
 
	return true;
 
}
 

	
 
}
src/localbuddy.cpp
Show inline comments
 
/**
 
 * 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/localbuddy.h"
 
#include "transport/user.h"
 

	
 
namespace Transport {
 

	
 
LocalBuddy::LocalBuddy(RosterManager *rosterManager, long id) : Buddy(rosterManager, id) {
 
	m_status = Swift::StatusShow::None;
 
	m_firstSet = true;
 
}
 

	
 
LocalBuddy::~LocalBuddy() {
 
}
 

	
 
void LocalBuddy::setAlias(const std::string &alias) {
 
	if (m_firstSet) {
 
		m_firstSet = false;
 
		m_alias = alias;
 
		return;
 
	}
 
//	if (m_firstSet) {
 
//		m_firstSet = false;
 
//		m_alias = alias;
 
//		return;
 
//	}
 
	bool changed = m_alias != alias;
 
	m_alias = alias;
 

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

	
 
}
src/mysqlbackend.cpp
Show inline comments
 
@@ -377,242 +377,246 @@ bool MySQLBackend::createDatabase() {
 
				"`language` varchar(25) collate utf8_bin NOT NULL,"
 
				"`encoding` varchar(50) collate utf8_bin NOT NULL default 'utf8',"
 
				"`last_login` datetime,"
 
				"`vip` tinyint(1) NOT NULL  default '0',"
 
				"`online` tinyint(1) NOT NULL  default '0',"
 
				"PRIMARY KEY (`id`),"
 
				"UNIQUE KEY `jid` (`jid`)"
 
			") ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;");
 

	
 
		exec("CREATE TABLE IF NOT EXISTS `" + m_prefix + "users_settings` ("
 
				"`user_id` int(10) unsigned NOT NULL,"
 
				"`var` varchar(50) collate utf8_bin NOT NULL,"
 
				"`type` smallint(4) unsigned NOT NULL,"
 
				"`value` varchar(255) collate utf8_bin NOT NULL,"
 
				"PRIMARY KEY (`user_id`,`var`),"
 
				"KEY `user_id` (`user_id`)"
 
			") ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;");
 

	
 
		exec("CREATE TABLE IF NOT EXISTS `" + m_prefix + "db_version` ("
 
				"`ver` int(10) unsigned NOT NULL default '1',"
 
				"UNIQUE KEY `ver` (`ver`)"
 
			") ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;");
 

	
 
		exec("INSERT IGNORE INTO db_version (ver) VALUES ('2');");
 
	}
 

	
 
	return true;
 
}
 

	
 
bool MySQLBackend::exec(const std::string &query) {
 
	if (mysql_query(&m_conn, query.c_str())) {
 
		LOG4CXX_ERROR(logger, query << " " << mysql_error(&m_conn));
 
		return false;
 
	}
 
	return true;
 
}
 

	
 
void MySQLBackend::setUser(const UserInfo &user) {
 
	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.uin << encrypted;
 
	EXEC(m_setUser, setUser(user));
 
}
 

	
 
bool MySQLBackend::getUser(const std::string &barejid, UserInfo &user) {
 
	*m_getUser << barejid;
 
	EXEC(m_getUser, getUser(barejid, user));
 
	if (!exec_ok)
 
		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) {
 
	*m_setUserOnline << online << id;
 
	EXEC(m_setUserOnline, setUserOnline(id, online));
 
}
 

	
 
bool MySQLBackend::getOnlineUsers(std::vector<std::string> &users) {
 
	EXEC(m_getOnlineUsers, getOnlineUsers(users));
 
	if (!exec_ok)
 
		return false;
 

	
 
	std::string jid;
 
	while (m_getOnlineUsers->fetch() == 0) {
 
		*m_getOnlineUsers >> jid;
 
		users.push_back(jid);
 
	}
 

	
 
	return true;
 
}
 

	
 
long MySQLBackend::addBuddy(long userId, const BuddyInfo &buddyInfo) {
 
// 	"INSERT INTO " + m_prefix + "buddies (user_id, uin, subscription, groups, nickname, flags) VALUES (?, ?, ?, ?, ?, ?)"
 
	std::string groups = Util::serializeGroups(buddyInfo.groups);
 
	*m_addBuddy << userId << buddyInfo.legacyName << buddyInfo.subscription;
 
	*m_addBuddy << groups;
 
	*m_addBuddy << buddyInfo.alias << buddyInfo.flags;
 

	
 
	EXEC(m_addBuddy, addBuddy(userId, buddyInfo));
 

	
 
	long id = (long) mysql_insert_id(&m_conn);
 

	
 
// 	INSERT OR REPLACE INTO " + m_prefix + "buddies_settings (user_id, buddy_id, var, type, value) VALUES (?, ?, ?, ?, ?)
 
	if (!buddyInfo.settings.find("icon_hash")->second.s.empty()) {
 
	if (buddyInfo.settings.find("icon_hash") != buddyInfo.settings.end() && !buddyInfo.settings.find("icon_hash")->second.s.empty()) {
 
		*m_updateBuddySetting << userId << id << buddyInfo.settings.find("icon_hash")->first << (int) TYPE_STRING << buddyInfo.settings.find("icon_hash")->second.s << buddyInfo.settings.find("icon_hash")->second.s;
 
		EXEC(m_updateBuddySetting, addBuddy(userId, buddyInfo));
 
	}
 

	
 
	return id;
 
}
 

	
 
void MySQLBackend::updateBuddy(long userId, const BuddyInfo &buddyInfo) {
 
// 	"UPDATE " + m_prefix + "buddies SET groups=?, nickname=?, flags=?, subscription=? WHERE user_id=? AND uin=?"
 
	std::string groups = Util::serializeGroups(buddyInfo.groups);
 
	*m_updateBuddy << groups;
 
	*m_updateBuddy << buddyInfo.alias << buddyInfo.flags << buddyInfo.subscription;
 
	*m_updateBuddy << userId << buddyInfo.legacyName;
 

	
 
	EXEC(m_updateBuddy, updateBuddy(userId, buddyInfo));
 
}
 

	
 
bool MySQLBackend::getBuddies(long id, std::list<BuddyInfo> &roster) {
 
//	SELECT id, uin, subscription, nickname, groups, flags FROM " + m_prefix + "buddies WHERE user_id=? ORDER BY id ASC
 
	*m_getBuddies << id;
 

	
 
// 	"SELECT buddy_id, type, var, value FROM " + m_prefix + "buddies_settings WHERE user_id=? ORDER BY buddy_id ASC"
 
	*m_getBuddiesSettings << id;
 

	
 
	SettingVariableInfo var;
 
	long buddy_id = -1;
 
	std::string key;
 

	
 
	EXEC(m_getBuddies, getBuddies(id, roster));
 
	if (!exec_ok)
 
		return false;
 

	
 
	while (m_getBuddies->fetch() == 0) {
 
		BuddyInfo b;
 

	
 
		std::string group;
 
		*m_getBuddies >> b.id >> b.legacyName >> b.subscription >> b.alias >> group >> b.flags;
 

	
 
		if (!group.empty()) {
 
			b.groups = Util::deserializeGroups(group);
 
		}
 

	
 
		roster.push_back(b);
 
	}
 

	
 
	EXEC(m_getBuddiesSettings, getBuddies(id, roster));
 
	if (!exec_ok)
 
		return false;
 

	
 
	BOOST_FOREACH(BuddyInfo &b, roster) {
 
		if (buddy_id == b.id) {
 
// 			std::cout << "Adding buddy info setting " << key << "\n";
 
			b.settings[key] = var;
 
			buddy_id = -1;
 
		}
 

	
 
		while(buddy_id == -1 && m_getBuddiesSettings->fetch() == 0) {
 
			std::string val;
 
			*m_getBuddiesSettings >> buddy_id >> var.type >> key >> val;
 

	
 
			switch (var.type) {
 
				case TYPE_BOOLEAN:
 
					var.b = atoi(val.c_str());
 
					break;
 
				case TYPE_STRING:
 
					var.s = val;
 
					break;
 
				default:
 
					if (buddy_id == b.id) {
 
						buddy_id = -1;
 
					}
 
					continue;
 
					break;
 
			}
 
			if (buddy_id == b.id) {
 
// 				std::cout << "Adding buddy info setting " << key << "=" << val << "\n";
 
				b.settings[key] = var;
 
				buddy_id = -1;
 
			}
 
		}
 
	}
 

	
 
	while(m_getBuddiesSettings->fetch() == 0) {
 
		// TODO: probably remove those settings, because there's no buddy for them.
 
		// It should not happend, but one never know...
 
	}
 
	
 
	return true;
 
}
 

	
 
bool MySQLBackend::removeUser(long id) {
 
	*m_removeUser << (int) id;
 
	EXEC(m_removeUser, removeUser(id));
 
	if (!exec_ok)
 
		return false;
 

	
 
	*m_removeUserSettings << (int) id;
 
	EXEC(m_removeUserSettings, removeUser(id));
 
	if (!exec_ok)
 
		return false;
 

	
 
	*m_removeUserBuddies << (int) id;
 
	EXEC(m_removeUserBuddies, removeUser(id));
 
	if (!exec_ok)
 
		return false;
 

	
 
	*m_removeUserBuddiesSettings << (int) id;
 
	EXEC(m_removeUserBuddiesSettings, removeUser(id));
 
	if (!exec_ok)
 
		return false;
 

	
 
	return true;
 
}
 

	
 
void MySQLBackend::getUserSetting(long id, const std::string &variable, int &type, std::string &value) {
 
// 	"SELECT type, value FROM " + m_prefix + "users_settings WHERE user_id=? AND var=?"
 
	*m_getUserSetting << id << variable;
 
	EXEC(m_getUserSetting, getUserSetting(id, variable, type, value));
 
	if (m_getUserSetting->fetch() != 0) {
 
// 		"INSERT INTO " + m_prefix + "users_settings (user_id, var, type, value) VALUES (?,?,?,?)"
 
		*m_setUserSetting << id << variable << type << value;
 
		EXEC(m_setUserSetting, getUserSetting(id, variable, type, value));
 
	}
 
	else {
 
		*m_getUserSetting >> type >> value;
 
	}
 

	
 
	while (m_getUserSetting->fetch() == 0) {
 

	
 
	}
 
}
 

	
 
void MySQLBackend::updateUserSetting(long id, const std::string &variable, const std::string &value) {
 
// 	"UPDATE " + m_prefix + "users_settings SET value=? WHERE user_id=? AND var=?"
 
	*m_updateUserSetting << value << id << variable;
 
	EXEC(m_updateUserSetting, updateUserSetting(id, variable, value));
 
}
 

	
 
void MySQLBackend::beginTransaction() {
 
	exec("START TRANSACTION;");
 
	//exec("START TRANSACTION;");
 
}
 

	
 
void MySQLBackend::commitTransaction() {
 
	exec("COMMIT;");
 
	//exec("COMMIT;");
 
}
 

	
 
}
 

	
 
#endif

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

0 comments (0 inline, 0 general)