Merge branch 'master' of https://github.com/hanzz/libtransport
This commit is contained in:
commit
285502c6ef
87 changed files with 3857 additions and 70 deletions
|
@ -38,7 +38,7 @@ 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")
|
||||
|
@ -53,6 +53,12 @@ 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)
|
||||
|
@ -101,6 +107,16 @@ else (MYSQL_FOUND)
|
|||
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})
|
||||
|
@ -133,12 +149,21 @@ if (PROTOBUF_FOUND)
|
|||
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)
|
||||
|
|
25
ChangeLog
25
ChangeLog
|
@ -1,3 +1,28 @@
|
|||
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
|
||||
|
|
|
@ -7,8 +7,15 @@ if (PROTOBUF_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()
|
||||
|
|
|
@ -6,7 +6,7 @@ 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)
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@ 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)
|
||||
|
||||
|
|
|
@ -26,6 +26,7 @@ MyIrcSession::MyIrcSession(const std::string &user, NetworkPlugin *np, const std
|
|||
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()));
|
||||
|
@ -33,6 +34,7 @@ MyIrcSession::MyIrcSession(const std::string &user, NetworkPlugin *np, const std
|
|||
}
|
||||
|
||||
void MyIrcSession::on_connected() {
|
||||
m_connected = true;
|
||||
if (suffix.empty()) {
|
||||
np->handleConnected(user);
|
||||
}
|
||||
|
@ -51,6 +53,7 @@ void MyIrcSession::on_connected() {
|
|||
void MyIrcSession::on_disconnected() {
|
||||
if (suffix.empty())
|
||||
np->handleDisconnected(user, 0, "");
|
||||
m_connected = false;
|
||||
}
|
||||
|
||||
bool MyIrcSession::correctNickname(std::string &nickname) {
|
||||
|
@ -156,6 +159,9 @@ void MyIrcSession::on_messageReceived(IrcMessage *message) {
|
|||
}
|
||||
|
||||
void MyIrcSession::on_numericMessageReceived(IrcMessage *message) {
|
||||
QString channel;
|
||||
QStringList members;
|
||||
|
||||
IrcNumericMessage *m = (IrcNumericMessage *) message;
|
||||
switch (m->code()) {
|
||||
case 332:
|
||||
|
@ -165,8 +171,8 @@ void MyIrcSession::on_numericMessageReceived(IrcMessage *message) {
|
|||
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;
|
||||
|
@ -176,6 +182,13 @@ void MyIrcSession::on_numericMessageReceived(IrcMessage *message) {
|
|||
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;
|
||||
|
@ -208,5 +221,6 @@ void MyIrcSession::onMessageReceived(IrcMessage *message) {
|
|||
case IrcMessage::Numeric:
|
||||
on_numericMessageReceived(message);
|
||||
break;
|
||||
default:break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -65,6 +65,7 @@ protected:
|
|||
std::string m_identify;
|
||||
std::list<std::string> m_autoJoin;
|
||||
std::string m_topicData;
|
||||
bool m_connected;
|
||||
};
|
||||
|
||||
//class MyIrcBuffer : public Irc::Buffer
|
||||
|
|
|
@ -441,6 +441,16 @@ static void * requestInput(const char *title, const char *primary,const char *se
|
|||
((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);
|
||||
}
|
||||
|
@ -604,11 +614,13 @@ class SpectrumNetworkPlugin : public NetworkPlugin {
|
|||
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);
|
||||
}
|
||||
|
@ -903,6 +915,41 @@ class SpectrumNetworkPlugin : public NetworkPlugin {
|
|||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
|
@ -1078,6 +1125,8 @@ static void buddyListNewNode(PurpleBlistNode *node) {
|
|||
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;
|
||||
|
|
9
backends/skype/CMakeLists.txt
Normal file
9
backends/skype/CMakeLists.txt
Normal file
|
@ -0,0 +1,9 @@
|
|||
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)
|
||||
|
865
backends/skype/main.cpp
Normal file
865
backends/skype/main.cpp
Normal file
|
@ -0,0 +1,865 @@
|
|||
#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);
|
||||
}
|
10
backends/smstools3/CMakeLists.txt
Normal file
10
backends/smstools3/CMakeLists.txt
Normal file
|
@ -0,0 +1,10 @@
|
|||
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)
|
||||
|
397
backends/smstools3/main.cpp
Normal file
397
backends/smstools3/main.cpp
Normal file
|
@ -0,0 +1,397 @@
|
|||
/*
|
||||
* 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;
|
||||
}
|
10
backends/template/CMakeLists.txt
Normal file
10
backends/template/CMakeLists.txt
Normal file
|
@ -0,0 +1,10 @@
|
|||
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)
|
||||
|
1
backends/template/README
Normal file
1
backends/template/README
Normal file
|
@ -0,0 +1 @@
|
|||
This is just template for creating new generic spectrum2 backends. It does not do anything!
|
181
backends/template/main.cpp
Normal file
181
backends/template/main.cpp
Normal file
|
@ -0,0 +1,181 @@
|
|||
// 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;
|
||||
}
|
53
cmake_modules/dbusConfig.cmake
Normal file
53
cmake_modules/dbusConfig.cmake
Normal file
|
@ -0,0 +1,53 @@
|
|||
# - 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 )
|
16
cmake_modules/pqxxConfig.cmake
Normal file
16
cmake_modules/pqxxConfig.cmake
Normal file
|
@ -0,0 +1,16 @@
|
|||
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()
|
||||
|
16
include/Swiften/Elements/GatewayPayload.cpp
Normal file
16
include/Swiften/Elements/GatewayPayload.cpp
Normal file
|
@ -0,0 +1,16 @@
|
|||
/*
|
||||
* 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) {
|
||||
|
||||
}
|
||||
|
||||
}
|
49
include/Swiften/Elements/GatewayPayload.h
Normal file
49
include/Swiften/Elements/GatewayPayload.h
Normal file
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* 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;
|
||||
};
|
||||
}
|
14
include/Swiften/Elements/PubSubItem.cpp
Normal file
14
include/Swiften/Elements/PubSubItem.cpp
Normal file
|
@ -0,0 +1,14 @@
|
|||
/*
|
||||
* 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() {
|
||||
}
|
||||
|
||||
}
|
64
include/Swiften/Elements/PubSubItem.h
Normal file
64
include/Swiften/Elements/PubSubItem.h
Normal file
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* 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;
|
||||
};
|
||||
}
|
14
include/Swiften/Elements/PubSubPayload.cpp
Normal file
14
include/Swiften/Elements/PubSubPayload.cpp
Normal file
|
@ -0,0 +1,14 @@
|
|||
/*
|
||||
* 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() {
|
||||
}
|
||||
|
||||
}
|
57
include/Swiften/Elements/PubSubPayload.h
Normal file
57
include/Swiften/Elements/PubSubPayload.h
Normal file
|
@ -0,0 +1,57 @@
|
|||
/*
|
||||
* 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;
|
||||
};
|
||||
}
|
16
include/Swiften/Elements/PubSubPublishPayload.cpp
Normal file
16
include/Swiften/Elements/PubSubPublishPayload.cpp
Normal file
|
@ -0,0 +1,16 @@
|
|||
/*
|
||||
* 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) {
|
||||
|
||||
}
|
||||
|
||||
}
|
43
include/Swiften/Elements/PubSubPublishPayload.h
Normal file
43
include/Swiften/Elements/PubSubPublishPayload.h
Normal file
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* 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;
|
||||
};
|
||||
}
|
16
include/Swiften/Elements/PubSubSubscribePayload.cpp
Normal file
16
include/Swiften/Elements/PubSubSubscribePayload.cpp
Normal file
|
@ -0,0 +1,16 @@
|
|||
/*
|
||||
* 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) {
|
||||
|
||||
}
|
||||
|
||||
}
|
40
include/Swiften/Elements/PubSubSubscribePayload.h
Normal file
40
include/Swiften/Elements/PubSubSubscribePayload.h
Normal file
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* 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;
|
||||
};
|
||||
}
|
16
include/Swiften/Elements/PubSubSubscriptionPayload.cpp
Normal file
16
include/Swiften/Elements/PubSubSubscriptionPayload.cpp
Normal file
|
@ -0,0 +1,16 @@
|
|||
/*
|
||||
* 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) {
|
||||
|
||||
}
|
||||
|
||||
}
|
60
include/Swiften/Elements/PubSubSubscriptionPayload.h
Normal file
60
include/Swiften/Elements/PubSubSubscriptionPayload.h
Normal file
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* 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;
|
||||
};
|
||||
}
|
|
@ -18,13 +18,12 @@
|
|||
#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();
|
||||
}
|
||||
|
||||
|
|
|
@ -11,6 +11,8 @@
|
|||
|
||||
#include <Swiften/JID/JID.h>
|
||||
|
||||
#include "transport/presenceoracle.h"
|
||||
|
||||
namespace Swift {
|
||||
|
||||
class JingleSessionManager;
|
||||
|
@ -30,7 +32,7 @@ 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&);
|
||||
|
@ -46,7 +48,7 @@ private:
|
|||
IDGenerator *idGenerator;
|
||||
SOCKS5BytestreamRegistry* bytestreamRegistry;
|
||||
SOCKS5BytestreamProxy* bytestreamProxy;
|
||||
PresenceOracle* presenceOracle;
|
||||
Transport::PresenceOracle* presenceOracle;
|
||||
SOCKS5BytestreamServer *bytestreamServer;
|
||||
};
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ DummyNetworkFactories::DummyNetworkFactories(EventLoop* eventLoop) {
|
|||
domainNameResolver = new PlatformDomainNameResolver(eventLoop);
|
||||
connectionServerFactory = new DummyConnectionServerFactory(eventLoop);
|
||||
m_platformXMLParserFactory = new PlatformXMLParserFactory();
|
||||
this->eventLoop = eventLoop;
|
||||
}
|
||||
|
||||
DummyNetworkFactories::~DummyNetworkFactories() {
|
||||
|
|
|
@ -41,6 +41,10 @@ namespace Swift {
|
|||
return m_platformXMLParserFactory;
|
||||
}
|
||||
|
||||
EventLoop *getEventLoop() const {
|
||||
return eventLoop;
|
||||
}
|
||||
|
||||
Swift::TLSContextFactory* getTLSContextFactory() const {
|
||||
return 0;
|
||||
}
|
||||
|
@ -55,5 +59,6 @@ namespace Swift {
|
|||
ConnectionFactory* connectionFactory;
|
||||
DomainNameResolver* domainNameResolver;
|
||||
ConnectionServerFactory* connectionServerFactory;
|
||||
EventLoop *eventLoop;
|
||||
};
|
||||
}
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* 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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
21
include/Swiften/Parser/PayloadParsers/GatewayPayloadParser.h
Normal file
21
include/Swiften/Parser/PayloadParsers/GatewayPayloadParser.h
Normal file
|
@ -0,0 +1,21 @@
|
|||
/*
|
||||
* 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);
|
||||
};
|
||||
}
|
30
include/Swiften/Parser/PayloadParsers/PubSubItemParser.cpp
Normal file
30
include/Swiften/Parser/PayloadParsers/PubSubItemParser.cpp
Normal file
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* 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));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
24
include/Swiften/Parser/PayloadParsers/PubSubItemParser.h
Normal file
24
include/Swiften/Parser/PayloadParsers/PubSubItemParser.h
Normal file
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* 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;
|
||||
};
|
||||
}
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* 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));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
24
include/Swiften/Parser/PayloadParsers/PubSubPayloadParser.h
Normal file
24
include/Swiften/Parser/PayloadParsers/PubSubPayloadParser.h
Normal file
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* 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;
|
||||
};
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* 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));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* 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;
|
||||
};
|
||||
}
|
|
@ -0,0 +1,32 @@
|
|||
/*
|
||||
* 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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* 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;
|
||||
};
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* 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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* 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;
|
||||
};
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
/*
|
||||
* 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();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* 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;
|
||||
};
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
/*
|
||||
* 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();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* 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;
|
||||
};
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* 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();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* 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;
|
||||
};
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* 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();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* 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;
|
||||
};
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* 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();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* 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;
|
||||
};
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
* 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();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* 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;
|
||||
};
|
||||
}
|
|
@ -32,11 +32,13 @@ void ServerStanzaChannel::addSession(boost::shared_ptr<ServerFromClientSession>
|
|||
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());
|
||||
}
|
||||
|
@ -53,6 +55,15 @@ 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) {
|
||||
|
|
|
@ -41,6 +41,7 @@ namespace Swift {
|
|||
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:
|
||||
|
|
|
@ -14,6 +14,13 @@
|
|||
#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"
|
||||
|
@ -179,7 +186,7 @@ void OpenSSLServerContext::sendPendingDataToApplication() {
|
|||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -189,7 +196,7 @@ bool OpenSSLServerContext::setServerCertificate(const PKCS12Certificate& certifi
|
|||
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;
|
||||
}
|
||||
|
||||
|
@ -199,7 +206,7 @@ bool OpenSSLServerContext::setServerCertificate(const PKCS12Certificate& certifi
|
|||
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);
|
||||
|
@ -208,11 +215,11 @@ bool OpenSSLServerContext::setServerCertificate(const PKCS12Certificate& certifi
|
|||
|
||||
// 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;
|
||||
|
|
43
include/transport/gatewayresponder.h
Normal file
43
include/transport/gatewayresponder.h
Normal file
|
@ -0,0 +1,43 @@
|
|||
/**
|
||||
* 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;
|
||||
};
|
||||
|
||||
}
|
112
include/transport/pqxxbackend.h
Normal file
112
include/transport/pqxxbackend.h
Normal file
|
@ -0,0 +1,112 @@
|
|||
/**
|
||||
* 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
|
57
include/transport/presenceoracle.h
Normal file
57
include/transport/presenceoracle.h
Normal file
|
@ -0,0 +1,57 @@
|
|||
/**
|
||||
* 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_;
|
||||
};
|
||||
|
||||
}
|
||||
|
|
@ -27,7 +27,6 @@
|
|||
#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"
|
||||
|
@ -37,6 +36,7 @@
|
|||
#include <boost/bind.hpp>
|
||||
#include "transport/config.h"
|
||||
#include "transport/factory.h"
|
||||
#include "transport/presenceoracle.h"
|
||||
|
||||
namespace Transport {
|
||||
// typedef enum { CLIENT_FEATURE_ROSTERX = 2,
|
||||
|
@ -92,7 +92,7 @@ namespace Transport {
|
|||
|
||||
/// 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.
|
||||
|
||||
|
@ -179,7 +179,7 @@ namespace Transport {
|
|||
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;
|
||||
|
||||
|
|
|
@ -22,7 +22,6 @@
|
|||
|
||||
#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"
|
||||
|
@ -35,6 +34,7 @@ class Component;
|
|||
class RosterManager;
|
||||
class ConversationManager;
|
||||
class UserManager;
|
||||
class PresenceOracle;
|
||||
struct UserInfo;
|
||||
|
||||
/// Represents online XMPP user.
|
||||
|
@ -125,7 +125,7 @@ class User : public Swift::EntityCapsProvider {
|
|||
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;
|
||||
|
|
|
@ -104,6 +104,10 @@ class UserManager : public Swift::EntityCapsProvider {
|
|||
return m_userRegistry;
|
||||
}
|
||||
|
||||
Component *getComponent() {
|
||||
return m_component;
|
||||
}
|
||||
|
||||
/// Connects user manually.
|
||||
/// \param user JID of user.
|
||||
void connectUser(const Swift::JID &user);
|
||||
|
|
|
@ -40,6 +40,8 @@ std::string serializeGroups(const std::vector<std::string> &groups);
|
|||
|
||||
std::vector<std::string> deserializeGroups(std::string &groups);
|
||||
|
||||
int getRandomPort(const std::string &s);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -5,12 +5,14 @@
|
|||
#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>
|
||||
|
@ -379,7 +381,23 @@ int main(int argc, char **argv)
|
|||
}
|
||||
#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;
|
||||
}
|
||||
|
@ -404,6 +422,9 @@ int main(int argc, char **argv)
|
|||
StatsResponder statsResponder(&transport, &userManager, &plugin, storageBackend);
|
||||
statsResponder.start();
|
||||
|
||||
GatewayResponder gatewayResponder(transport.getIQRouter(), &userManager);
|
||||
gatewayResponder.start();
|
||||
|
||||
eventLoop_ = &eventLoop;
|
||||
|
||||
eventLoop.run();
|
||||
|
|
|
@ -14,6 +14,7 @@ admin_password=test
|
|||
#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
|
||||
|
@ -21,10 +22,12 @@ backend=/home/hanzz/code/libtransport/backends/libpurple/spectrum2_libpurple_bac
|
|||
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
|
||||
|
@ -34,3 +37,9 @@ irc_server=irc.freenode.org
|
|||
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
|
||||
|
|
|
@ -24,7 +24,9 @@ port = 5222
|
|||
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=
|
||||
|
@ -38,6 +40,8 @@ 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
|
||||
|
@ -69,11 +73,11 @@ 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
|
||||
|
||||
|
@ -91,3 +95,20 @@ type = none
|
|||
|
||||
# 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
|
||||
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
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})
|
||||
|
||||
|
|
|
@ -20,11 +20,11 @@ endif()
|
|||
|
||||
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})
|
||||
|
@ -35,9 +35,9 @@ if (CMAKE_COMPILER_IS_GNUCXX)
|
|||
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
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
*/
|
||||
|
||||
#include "transport/config.h"
|
||||
#include "transport/util.h"
|
||||
#include <fstream>
|
||||
#ifdef _MSC_VER
|
||||
#include <direct.h>
|
||||
|
@ -86,8 +87,12 @@ bool Config::load(std::istream &ifs, boost::program_options::options_description
|
|||
("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.")
|
||||
|
@ -106,6 +111,7 @@ bool Config::load(std::istream &ifs, boost::program_options::options_description
|
|||
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") {
|
||||
|
@ -120,13 +126,7 @@ bool Config::load(std::istream &ifs, boost::program_options::options_description
|
|||
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") {
|
||||
|
@ -135,6 +135,9 @@ bool Config::load(std::istream &ifs, boost::program_options::options_description
|
|||
else if (opt.string_key == "service.pidfile") {
|
||||
found_pidfile = true;
|
||||
}
|
||||
else if (opt.string_key == "database.database") {
|
||||
found_database = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found_working) {
|
||||
|
@ -148,16 +151,16 @@ bool Config::load(std::istream &ifs, boost::program_options::options_description
|
|||
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) {
|
||||
|
|
63
src/gatewayresponder.cpp
Normal file
63
src/gatewayresponder.cpp
Normal file
|
@ -0,0 +1,63 @@
|
|||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
}
|
|
@ -32,11 +32,11 @@ 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;
|
||||
|
||||
|
|
|
@ -470,7 +470,7 @@ long MySQLBackend::addBuddy(long userId, const BuddyInfo &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));
|
||||
}
|
||||
|
@ -597,6 +597,10 @@ void MySQLBackend::getUserSetting(long id, const std::string &variable, int &typ
|
|||
else {
|
||||
*m_getUserSetting >> type >> value;
|
||||
}
|
||||
|
||||
while (m_getUserSetting->fetch() == 0) {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
void MySQLBackend::updateUserSetting(long id, const std::string &variable, const std::string &value) {
|
||||
|
@ -606,11 +610,11 @@ void MySQLBackend::updateUserSetting(long id, const std::string &variable, const
|
|||
}
|
||||
|
||||
void MySQLBackend::beginTransaction() {
|
||||
exec("START TRANSACTION;");
|
||||
//exec("START TRANSACTION;");
|
||||
}
|
||||
|
||||
void MySQLBackend::commitTransaction() {
|
||||
exec("COMMIT;");
|
||||
//exec("COMMIT;");
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -157,6 +157,7 @@ static unsigned long exec_(std::string path, const char *host, const char *port,
|
|||
// fork and exec
|
||||
pid_t pid = fork();
|
||||
if ( pid == 0 ) {
|
||||
setsid();
|
||||
// child process
|
||||
exit(execv(argv[0], argv));
|
||||
} else if ( pid < 0 ) {
|
||||
|
@ -174,7 +175,7 @@ static void SigCatcher(int n) {
|
|||
int status;
|
||||
// Read exit code from all children to not have zombies arround
|
||||
// WARNING: Do not put LOG4CXX_ here, because it can lead to deadlock
|
||||
while ((result = waitpid(0, &status, WNOHANG)) > 0) {
|
||||
while ((result = waitpid(-1, &status, WNOHANG)) > 0) {
|
||||
if (result != 0) {
|
||||
if (WIFEXITED(status)) {
|
||||
if (WEXITSTATUS(status) != 0) {
|
||||
|
@ -194,6 +195,7 @@ static void handleBuddyPayload(LocalBuddy *buddy, const pbnetwork::Buddy &payloa
|
|||
// Set alias only if it's not empty. Backends are allowed to send empty alias if it has
|
||||
// not changed.
|
||||
if (!payload.alias().empty()) {
|
||||
LOG4CXX_INFO(logger, "Setting alias to " << payload.alias() << " " << buddy->getAlias());
|
||||
buddy->setAlias(payload.alias());
|
||||
}
|
||||
|
||||
|
@ -257,6 +259,7 @@ NetworkPluginServer::NetworkPluginServer(Component *component, Config *config, U
|
|||
#endif
|
||||
|
||||
exec_(CONFIG_STRING(m_config, "service.backend"), CONFIG_STRING(m_config, "service.backend_host").c_str(), CONFIG_STRING(m_config, "service.backend_port").c_str(), m_config->getConfigFile().c_str());
|
||||
LOG4CXX_INFO(logger, "Backend should now connect to Spectrum2 instance. Spectrum2 won't accept any connection before backend connects");
|
||||
}
|
||||
|
||||
NetworkPluginServer::~NetworkPluginServer() {
|
||||
|
@ -476,6 +479,8 @@ void NetworkPluginServer::handleBuddyChangedPayload(const std::string &data) {
|
|||
if (!user)
|
||||
return;
|
||||
|
||||
LOG4CXX_INFO(logger, "HANDLE BUDDY CHANGED " << payload.buddyname() << "-" << payload.alias());
|
||||
|
||||
LocalBuddy *buddy = (LocalBuddy *) user->getRosterManager()->getBuddy(payload.buddyname());
|
||||
if (buddy) {
|
||||
handleBuddyPayload(buddy, payload);
|
||||
|
|
391
src/pqxxbackend.cpp
Normal file
391
src/pqxxbackend.cpp
Normal file
|
@ -0,0 +1,391 @@
|
|||
/**
|
||||
* 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
|
||||
*/
|
||||
|
||||
#ifdef WITH_PQXX
|
||||
|
||||
#include "transport/pqxxbackend.h"
|
||||
#include "transport/util.h"
|
||||
#include <boost/bind.hpp>
|
||||
#include "log4cxx/logger.h"
|
||||
|
||||
using namespace log4cxx;
|
||||
using namespace boost;
|
||||
|
||||
namespace Transport {
|
||||
|
||||
static LoggerPtr logger = Logger::getLogger("PQXXBackend");
|
||||
|
||||
PQXXBackend::PQXXBackend(Config *config) {
|
||||
m_config = config;
|
||||
m_prefix = CONFIG_STRING(m_config, "database.prefix");
|
||||
}
|
||||
|
||||
PQXXBackend::~PQXXBackend(){
|
||||
disconnect();
|
||||
}
|
||||
|
||||
void PQXXBackend::disconnect() {
|
||||
LOG4CXX_INFO(logger, "Disconnecting");
|
||||
|
||||
delete m_conn;
|
||||
}
|
||||
|
||||
bool PQXXBackend::connect() {
|
||||
LOG4CXX_INFO(logger, "Connecting PostgreSQL server " << CONFIG_STRING(m_config, "database.server") << ", user " <<
|
||||
CONFIG_STRING(m_config, "database.user") << ", database " << CONFIG_STRING(m_config, "database.database") <<
|
||||
", port " << CONFIG_INT(m_config, "database.port")
|
||||
);
|
||||
|
||||
std::string str = "dbname=";
|
||||
str += CONFIG_STRING(m_config, "database.database") + " ";
|
||||
|
||||
str += "user=" + CONFIG_STRING(m_config, "database.user") + " ";
|
||||
|
||||
try {
|
||||
m_conn = new pqxx::connection(str);
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
LOG4CXX_ERROR(logger, e.what());
|
||||
return false;
|
||||
}
|
||||
|
||||
createDatabase();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PQXXBackend::createDatabase() {
|
||||
|
||||
int exist = exec("SELECT * FROM " + m_prefix + "buddies_settings LIMIT 1;", false);
|
||||
|
||||
if (!exist) {
|
||||
exec("CREATE TABLE " + m_prefix + "buddies_settings ("
|
||||
"user_id integer NOT NULL,"
|
||||
"buddy_id integer NOT NULL,"
|
||||
"var varchar(50) NOT NULL,"
|
||||
"type smallint NOT NULL,"
|
||||
"value varchar(255) NOT NULL,"
|
||||
"PRIMARY KEY (buddy_id,var)"
|
||||
");");
|
||||
|
||||
exec("CREATE TYPE Subscription AS ENUM ('to','from','both','ask','none');");
|
||||
exec("CREATE TABLE " + m_prefix + "buddies ("
|
||||
"id SERIAL,"
|
||||
"user_id integer NOT NULL,"
|
||||
"uin varchar(255) NOT NULL,"
|
||||
"subscription Subscription NOT NULL,"
|
||||
"nickname varchar(255) NOT NULL,"
|
||||
"groups varchar(255) NOT NULL,"
|
||||
"flags smallint NOT NULL DEFAULT '0',"
|
||||
"PRIMARY KEY (id),"
|
||||
"UNIQUE (user_id,uin)"
|
||||
");");
|
||||
|
||||
exec("CREATE TABLE " + m_prefix + "users ("
|
||||
"id SERIAL,"
|
||||
"jid varchar(255) NOT NULL,"
|
||||
"uin varchar(4095) NOT NULL,"
|
||||
"password varchar(255) NOT NULL,"
|
||||
"language varchar(25) NOT NULL,"
|
||||
"encoding varchar(50) NOT NULL default 'utf8',"
|
||||
"last_login timestamp,"
|
||||
"vip boolean NOT NULL default 'false',"
|
||||
"online boolean NOT NULL default 'false',"
|
||||
"PRIMARY KEY (id),"
|
||||
"UNIQUE (jid)"
|
||||
");");
|
||||
|
||||
exec("CREATE TABLE " + m_prefix + "users_settings ("
|
||||
"user_id integer NOT NULL,"
|
||||
"var varchar(50) NOT NULL,"
|
||||
"type smallint NOT NULL,"
|
||||
"value varchar(255) NOT NULL,"
|
||||
"PRIMARY KEY (user_id,var)"
|
||||
");");
|
||||
|
||||
exec("CREATE TABLE " + m_prefix + "db_version ("
|
||||
"ver integer NOT NULL default '1',"
|
||||
"UNIQUE (ver)"
|
||||
");");
|
||||
|
||||
exec("INSERT INTO db_version (ver) VALUES ('1');");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
template<typename T>
|
||||
std::string PQXXBackend::quote(pqxx::nontransaction &txn, const T &t) {
|
||||
return "'" + txn.esc(pqxx::to_string(t)) + "'";
|
||||
}
|
||||
|
||||
bool PQXXBackend::exec(const std::string &query, bool show_error) {
|
||||
pqxx::nontransaction txn(*m_conn);
|
||||
return exec(txn, query, show_error);
|
||||
}
|
||||
|
||||
bool PQXXBackend::exec(pqxx::nontransaction &txn, const std::string &query, bool show_error) {
|
||||
try {
|
||||
txn.exec(query);
|
||||
txn.commit();
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
if (show_error)
|
||||
LOG4CXX_ERROR(logger, e.what());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void PQXXBackend::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"));
|
||||
}
|
||||
try {
|
||||
pqxx::nontransaction txn(*m_conn);
|
||||
txn.exec("INSERT INTO " + m_prefix + "users (jid, uin, password, language, encoding, last_login, vip) VALUES "
|
||||
+ "(" + quote(txn, user.jid) + ","
|
||||
+ quote(txn, user.uin) + ","
|
||||
+ quote(txn, encrypted) + ","
|
||||
+ quote(txn, user.language) + ","
|
||||
+ quote(txn, user.encoding) + ","
|
||||
+ "NOW(),"
|
||||
+ (user.vip ? "'true'" : "'false'") +")");
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
LOG4CXX_ERROR(logger, e.what());
|
||||
}
|
||||
}
|
||||
|
||||
bool PQXXBackend::getUser(const std::string &barejid, UserInfo &user) {
|
||||
try {
|
||||
pqxx::nontransaction txn(*m_conn);
|
||||
|
||||
pqxx::result r = txn.exec("SELECT id, jid, uin, password, encoding, language, vip FROM " + m_prefix + "users WHERE jid="
|
||||
+ quote(txn, barejid));
|
||||
|
||||
if (r.size() == 0) {
|
||||
return false;
|
||||
}
|
||||
|
||||
user.id = r[0][0].as<int>();
|
||||
user.jid = r[0][1].as<std::string>();
|
||||
user.uin = r[0][2].as<std::string>();
|
||||
user.password = r[0][3].as<std::string>();
|
||||
user.encoding = r[0][4].as<std::string>();
|
||||
user.language = r[0][5].as<std::string>();
|
||||
user.vip = r[0][6].as<bool>();
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
LOG4CXX_ERROR(logger, e.what());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void PQXXBackend::setUserOnline(long id, bool online) {
|
||||
try {
|
||||
pqxx::nontransaction txn(*m_conn);
|
||||
txn.exec("UPDATE " + m_prefix + "users SET online=" + (online ? "'true'" : "'false'") + ", last_login=NOW() WHERE id=" + pqxx::to_string(id));
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
LOG4CXX_ERROR(logger, e.what());
|
||||
}
|
||||
}
|
||||
|
||||
bool PQXXBackend::getOnlineUsers(std::vector<std::string> &users) {
|
||||
try {
|
||||
pqxx::nontransaction txn(*m_conn);
|
||||
pqxx::result r = txn.exec("SELECT jid FROM " + m_prefix + "users WHERE online='true'");
|
||||
|
||||
for (pqxx::result::const_iterator it = r.begin(); it != r.end(); it++) {
|
||||
users.push_back((*it)[0].as<std::string>());
|
||||
}
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
LOG4CXX_ERROR(logger, e.what());
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
long PQXXBackend::addBuddy(long userId, const BuddyInfo &buddyInfo) {
|
||||
try {
|
||||
pqxx::nontransaction txn(*m_conn);
|
||||
pqxx::result r = txn.exec("INSERT INTO " + m_prefix + "buddies (user_id, uin, subscription, groups, nickname, flags) VALUES "
|
||||
+ "(" + pqxx::to_string(userId) + ","
|
||||
+ quote(txn, buddyInfo.legacyName) + ","
|
||||
+ quote(txn, buddyInfo.subscription) + ","
|
||||
+ quote(txn, Util::serializeGroups(buddyInfo.groups)) + ","
|
||||
+ quote(txn, buddyInfo.alias) + ","
|
||||
+ pqxx::to_string(buddyInfo.flags) + ") RETURNING id");
|
||||
|
||||
long id = r[0][0].as<long>();
|
||||
|
||||
r = txn.exec("UPDATE " + m_prefix + "buddies_settings SET var = " + quote(txn, buddyInfo.settings.find("icon_hash")->first) + ", type = " + pqxx::to_string((int)TYPE_STRING) + ", value = " + quote(txn, buddyInfo.settings.find("icon_hash")->second.s) + " WHERE user_id = " + pqxx::to_string(userId) + " AND buddy_id = " + pqxx::to_string(id));
|
||||
if (r.affected_rows() == 0) {
|
||||
txn.exec("INSERT INTO " + m_prefix + "buddies_settings (user_id, buddy_id, var, type, value) VALUES "
|
||||
+ "(" + pqxx::to_string(userId) + ","
|
||||
+ pqxx::to_string(id) + ","
|
||||
+ quote(txn, buddyInfo.settings.find("icon_hash")->first) + ","
|
||||
+ pqxx::to_string((int)TYPE_STRING) + ","
|
||||
+ quote(txn, buddyInfo.settings.find("icon_hash")->second.s) + ")");
|
||||
}
|
||||
|
||||
return id;
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
LOG4CXX_ERROR(logger, e.what());
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
void PQXXBackend::updateBuddy(long userId, const BuddyInfo &buddyInfo) {
|
||||
try {
|
||||
pqxx::nontransaction txn(*m_conn);
|
||||
txn.exec("UPDATE " + m_prefix + "buddies SET groups=" + quote(txn, Util::serializeGroups(buddyInfo.groups)) + ", nickname=" + quote(txn, buddyInfo.alias) + ", flags=" + pqxx::to_string(buddyInfo.flags) + ", subscription=" + quote(txn, buddyInfo.subscription) + " WHERE user_id=" + pqxx::to_string(userId) + " AND uin=" + quote(txn, buddyInfo.legacyName));
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
LOG4CXX_ERROR(logger, e.what());
|
||||
}
|
||||
}
|
||||
|
||||
bool PQXXBackend::getBuddies(long id, std::list<BuddyInfo> &roster) {
|
||||
try {
|
||||
pqxx::nontransaction txn(*m_conn);
|
||||
|
||||
pqxx::result r = txn.exec("SELECT id, uin, subscription, nickname, groups, flags FROM " + m_prefix + "buddies WHERE user_id=" + pqxx::to_string(id) + " ORDER BY id ASC");
|
||||
for (pqxx::result::const_iterator it = r.begin(); it != r.end(); it++) {
|
||||
BuddyInfo b;
|
||||
std::string group;
|
||||
|
||||
b.id = r[0][0].as<long>();
|
||||
b.legacyName = r[0][1].as<std::string>();
|
||||
b.subscription = r[0][2].as<std::string>();
|
||||
b.alias = r[0][3].as<std::string>();
|
||||
group = r[0][4].as<std::string>();
|
||||
b.flags = r[0][5].as<long>();
|
||||
|
||||
if (!group.empty()) {
|
||||
b.groups = Util::deserializeGroups(group);
|
||||
}
|
||||
|
||||
roster.push_back(b);
|
||||
}
|
||||
|
||||
|
||||
r = txn.exec("SELECT buddy_id, type, var, value FROM " + m_prefix + "buddies_settings WHERE user_id=" + pqxx::to_string(id) + " ORDER BY buddy_id ASC");
|
||||
for (pqxx::result::const_iterator it = r.begin(); it != r.end(); it++) {
|
||||
SettingVariableInfo var;
|
||||
long buddy_id = -1;
|
||||
std::string key;
|
||||
std::string val;
|
||||
|
||||
buddy_id = r[0][0].as<long>();
|
||||
var.type = r[0][1].as<long>();
|
||||
key = r[0][2].as<std::string>();
|
||||
val = r[0][3].as<std::string>();
|
||||
switch (var.type) {
|
||||
case TYPE_BOOLEAN:
|
||||
var.b = atoi(val.c_str());
|
||||
break;
|
||||
case TYPE_STRING:
|
||||
var.s = val;
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
break;
|
||||
}
|
||||
|
||||
BOOST_FOREACH(BuddyInfo &b, roster) {
|
||||
if (buddy_id == b.id) {
|
||||
b.settings[key] = var;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
LOG4CXX_ERROR(logger, e.what());
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool PQXXBackend::removeUser(long id) {
|
||||
try {
|
||||
pqxx::nontransaction txn(*m_conn);
|
||||
txn.exec("DELETE FROM " + m_prefix + "users SET id=" + pqxx::to_string(id));
|
||||
txn.exec("DELETE FROM " + m_prefix + "buddies SET user_id=" + pqxx::to_string(id));
|
||||
txn.exec("DELETE FROM " + m_prefix + "user_settings SET user_id=" + pqxx::to_string(id));
|
||||
txn.exec("DELETE FROM " + m_prefix + "buddies_settings SET user_id=" + pqxx::to_string(id));
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
LOG4CXX_ERROR(logger, e.what());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void PQXXBackend::getUserSetting(long id, const std::string &variable, int &type, std::string &value) {
|
||||
try {
|
||||
pqxx::nontransaction txn(*m_conn);
|
||||
|
||||
pqxx::result r = txn.exec("SELECT type, value FROM " + m_prefix + "users_settings WHERE user_id=" + pqxx::to_string(id) + " AND var=" + quote(txn, variable));
|
||||
if (r.size() == 0) {
|
||||
txn.exec("INSERT INTO " + m_prefix + "users_settings (user_id, var, type, value) VALUES(" + pqxx::to_string(id) + "," + quote(txn, variable) + "," + pqxx::to_string((int)type) + "," + quote(txn, value) + ")");
|
||||
}
|
||||
else {
|
||||
type = r[0][0].as<int>();
|
||||
value = r[0][1].as<std::string>();
|
||||
}
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
LOG4CXX_ERROR(logger, e.what());
|
||||
}
|
||||
}
|
||||
|
||||
void PQXXBackend::updateUserSetting(long id, const std::string &variable, const std::string &value) {
|
||||
try {
|
||||
pqxx::nontransaction txn(*m_conn);
|
||||
txn.exec("UPDATE " + m_prefix + "users_settings SET value=" + quote(txn, value) + " WHERE user_id=" + pqxx::to_string(id) + " AND var=" + quote(txn, variable));
|
||||
}
|
||||
catch (std::exception& e) {
|
||||
LOG4CXX_ERROR(logger, e.what());
|
||||
}
|
||||
}
|
||||
|
||||
void PQXXBackend::beginTransaction() {
|
||||
exec("BEGIN;");
|
||||
}
|
||||
|
||||
void PQXXBackend::commitTransaction() {
|
||||
exec("COMMIT;");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
136
src/presenceoracle.cpp
Normal file
136
src/presenceoracle.cpp
Normal file
|
@ -0,0 +1,136 @@
|
|||
/**
|
||||
* 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/presenceoracle.h"
|
||||
#include "Swiften/Swiften.h"
|
||||
|
||||
#include <boost/bind.hpp>
|
||||
|
||||
using namespace Swift;
|
||||
|
||||
namespace Transport {
|
||||
|
||||
PresenceOracle::PresenceOracle(StanzaChannel* stanzaChannel) {
|
||||
stanzaChannel_ = stanzaChannel;
|
||||
stanzaChannel_->onPresenceReceived.connect(boost::bind(&PresenceOracle::handleIncomingPresence, this, _1));
|
||||
stanzaChannel_->onAvailableChanged.connect(boost::bind(&PresenceOracle::handleStanzaChannelAvailableChanged, this, _1));
|
||||
}
|
||||
|
||||
PresenceOracle::~PresenceOracle() {
|
||||
stanzaChannel_->onPresenceReceived.disconnect(boost::bind(&PresenceOracle::handleIncomingPresence, this, _1));
|
||||
stanzaChannel_->onAvailableChanged.disconnect(boost::bind(&PresenceOracle::handleStanzaChannelAvailableChanged, this, _1));
|
||||
}
|
||||
|
||||
void PresenceOracle::handleStanzaChannelAvailableChanged(bool available) {
|
||||
if (available) {
|
||||
entries_.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void PresenceOracle::handleIncomingPresence(Presence::ref presence) {
|
||||
// ignore presences for some contact, we're checking only presences for the transport itself here.
|
||||
bool isMUC = presence->getPayload<MUCPayload>() != NULL || *presence->getTo().getNode().c_str() == '#';
|
||||
// filter out login/logout presence spam
|
||||
if (!presence->getTo().getNode().empty() && isMUC == false)
|
||||
return;
|
||||
|
||||
JID bareJID(presence->getFrom().toBare());
|
||||
if (presence->getType() == Presence::Subscribe || presence->getType() == Presence::Subscribed) {
|
||||
}
|
||||
else {
|
||||
Presence::ref passedPresence = presence;
|
||||
if (presence->getType() == Presence::Unsubscribe || presence->getType() == Presence::Unsubscribed) {
|
||||
/* 3921bis says that we don't follow up with an unavailable, so simulate this ourselves */
|
||||
passedPresence = Presence::ref(new Presence());
|
||||
passedPresence->setType(Presence::Unavailable);
|
||||
passedPresence->setFrom(bareJID);
|
||||
passedPresence->setStatus(presence->getStatus());
|
||||
}
|
||||
std::map<JID, boost::shared_ptr<Presence> > jidMap = entries_[bareJID];
|
||||
if (passedPresence->getFrom().isBare() && presence->getType() == Presence::Unavailable) {
|
||||
/* Have a bare-JID only presence of offline */
|
||||
jidMap.clear();
|
||||
} else if (passedPresence->getType() == Presence::Available) {
|
||||
/* Don't have a bare-JID only offline presence once there are available presences */
|
||||
jidMap.erase(bareJID);
|
||||
}
|
||||
if (passedPresence->getType() == Presence::Unavailable && jidMap.size() > 1) {
|
||||
jidMap.erase(passedPresence->getFrom());
|
||||
} else {
|
||||
jidMap[passedPresence->getFrom()] = passedPresence;
|
||||
}
|
||||
entries_[bareJID] = jidMap;
|
||||
onPresenceChange(passedPresence);
|
||||
}
|
||||
}
|
||||
|
||||
Presence::ref PresenceOracle::getLastPresence(const JID& jid) const {
|
||||
PresencesMap::const_iterator i = entries_.find(jid.toBare());
|
||||
if (i == entries_.end()) {
|
||||
return Presence::ref();
|
||||
}
|
||||
PresenceMap presenceMap = i->second;
|
||||
PresenceMap::const_iterator j = presenceMap.find(jid);
|
||||
if (j != presenceMap.end()) {
|
||||
return j->second;
|
||||
}
|
||||
else {
|
||||
return Presence::ref();
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<Presence::ref> PresenceOracle::getAllPresence(const JID& bareJID) const {
|
||||
std::vector<Presence::ref> results;
|
||||
PresencesMap::const_iterator i = entries_.find(bareJID);
|
||||
if (i == entries_.end()) {
|
||||
return results;
|
||||
}
|
||||
PresenceMap presenceMap = i->second;
|
||||
PresenceMap::const_iterator j = presenceMap.begin();
|
||||
for (; j != presenceMap.end(); ++j) {
|
||||
Presence::ref current = j->second;
|
||||
results.push_back(current);
|
||||
}
|
||||
return results;
|
||||
}
|
||||
|
||||
Presence::ref PresenceOracle::getHighestPriorityPresence(const JID& bareJID) const {
|
||||
PresencesMap::const_iterator i = entries_.find(bareJID);
|
||||
if (i == entries_.end()) {
|
||||
return Presence::ref();
|
||||
}
|
||||
PresenceMap presenceMap = i->second;
|
||||
PresenceMap::const_iterator j = presenceMap.begin();
|
||||
Presence::ref highest;
|
||||
for (; j != presenceMap.end(); ++j) {
|
||||
Presence::ref current = j->second;
|
||||
if (!highest
|
||||
|| current->getPriority() > highest->getPriority()
|
||||
|| (current->getPriority() == highest->getPriority()
|
||||
&& StatusShow::typeToAvailabilityOrdering(current->getShow()) > StatusShow::typeToAvailabilityOrdering(highest->getShow()))) {
|
||||
highest = current;
|
||||
}
|
||||
|
||||
}
|
||||
return highest;
|
||||
}
|
||||
|
||||
}
|
|
@ -110,7 +110,12 @@ void RosterManager::sendBuddyRosterPush(Buddy *buddy) {
|
|||
Swift::RosterPayload::ref payload = Swift::RosterPayload::ref(new Swift::RosterPayload());
|
||||
Swift::RosterItemPayload item;
|
||||
item.setJID(buddy->getJID().toBare());
|
||||
item.setName(buddy->getAlias());
|
||||
if (buddy->getAlias().empty()) {
|
||||
item.setName(buddy->getJID().toBare().toString());
|
||||
}
|
||||
else {
|
||||
item.setName(buddy->getAlias());
|
||||
}
|
||||
item.setGroups(buddy->getGroups());
|
||||
item.setSubscription(Swift::RosterItemPayload::Both);
|
||||
|
||||
|
@ -285,8 +290,8 @@ void RosterManager::handleSubscription(Swift::Presence::ref presence) {
|
|||
// using roster pushes.
|
||||
if (m_component->inServerMode()) {
|
||||
Swift::Presence::ref response = Swift::Presence::create();
|
||||
response->setTo(presence->getFrom());
|
||||
response->setFrom(presence->getTo());
|
||||
response->setTo(presence->getFrom().toBare());
|
||||
response->setFrom(presence->getTo().toBare());
|
||||
Buddy *buddy = getBuddy(Buddy::JIDToLegacyName(presence->getTo()));
|
||||
if (buddy) {
|
||||
LOG4CXX_INFO(logger, m_user->getJID().toString() << ": Subscription received and buddy " << Buddy::JIDToLegacyName(presence->getTo()) << " is already there => answering");
|
||||
|
@ -342,7 +347,7 @@ void RosterManager::handleSubscription(Swift::Presence::ref presence) {
|
|||
Swift::Presence::ref response = Swift::Presence::create();
|
||||
Swift::Presence::ref currentPresence;
|
||||
response->setTo(presence->getFrom().toBare());
|
||||
response->setFrom(presence->getTo().toBare().toString() + "/bot");
|
||||
response->setFrom(presence->getTo().toBare());
|
||||
|
||||
Buddy *buddy = getBuddy(Buddy::JIDToLegacyName(presence->getTo()));
|
||||
if (buddy) {
|
||||
|
|
|
@ -111,6 +111,8 @@ bool SQLite3Backend::connect() {
|
|||
return false;
|
||||
}
|
||||
|
||||
sqlite3_busy_timeout(m_db, 1500);
|
||||
|
||||
if (createDatabase() == false)
|
||||
return false;
|
||||
|
||||
|
@ -234,6 +236,8 @@ bool SQLite3Backend::getUser(const std::string &barejid, UserInfo &user) {
|
|||
user.encoding = (const char *) sqlite3_column_text(m_getUser, 4);
|
||||
user.language = (const char *) sqlite3_column_text(m_getUser, 5);
|
||||
user.vip = sqlite3_column_int(m_getUser, 6) != 0;
|
||||
while((ret = sqlite3_step(m_getUser)) == SQLITE_ROW) {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
@ -388,6 +392,9 @@ bool SQLite3Backend::getBuddies(long id, std::list<BuddyInfo> &roster) {
|
|||
roster.push_back(b);
|
||||
}
|
||||
|
||||
while((ret = sqlite3_step(m_getBuddiesSettings)) == SQLITE_ROW) {
|
||||
}
|
||||
|
||||
if (ret != SQLITE_DONE) {
|
||||
LOG4CXX_ERROR(logger, "getBuddies query"<< (sqlite3_errmsg(m_db) == NULL ? "" : sqlite3_errmsg(m_db)));
|
||||
return false;
|
||||
|
@ -444,6 +451,10 @@ void SQLite3Backend::getUserSetting(long id, const std::string &variable, int &t
|
|||
type = GET_INT(m_getUserSetting);
|
||||
value = GET_STR(m_getUserSetting);
|
||||
}
|
||||
|
||||
int ret;
|
||||
while((ret = sqlite3_step(m_getUserSetting)) == SQLITE_ROW) {
|
||||
}
|
||||
}
|
||||
|
||||
void SQLite3Backend::updateUserSetting(long id, const std::string &variable, const std::string &value) {
|
||||
|
|
|
@ -71,11 +71,19 @@ bool StorageResponder::handleSetRequest(const Swift::JID& from, const Swift::JID
|
|||
return true;
|
||||
}
|
||||
|
||||
StorageSerializer serializer;
|
||||
std::string value = serializer.serializePayload(boost::dynamic_pointer_cast<Storage>(payload->getPayload()));
|
||||
m_storageBackend->updateUserSetting(user->getUserInfo().id, "storage", value);
|
||||
LOG4CXX_INFO(logger, from.toBare().toString() << ": Storing jabber:iq:storage");
|
||||
sendResponse(from, id, boost::shared_ptr<PrivateStorage>());
|
||||
boost::shared_ptr<Storage> storage = boost::dynamic_pointer_cast<Storage>(payload->getPayload());
|
||||
|
||||
if (storage) {
|
||||
StorageSerializer serializer;
|
||||
std::string value = serializer.serializePayload(boost::dynamic_pointer_cast<Storage>(payload->getPayload()));
|
||||
m_storageBackend->updateUserSetting(user->getUserInfo().id, "storage", value);
|
||||
LOG4CXX_INFO(logger, from.toBare().toString() << ": Storing jabber:iq:storage");
|
||||
sendResponse(from, id, boost::shared_ptr<PrivateStorage>());
|
||||
}
|
||||
else {
|
||||
LOG4CXX_INFO(logger, from.toBare().toString() << ": Unknown element. Libtransport does not support serialization of this.");
|
||||
sendError(from, id, ErrorPayload::NotAcceptable, ErrorPayload::Cancel);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
|
|
@ -36,6 +36,8 @@
|
|||
#include "Swiften/Serializer/PayloadSerializers/XHTMLIMSerializer.h"
|
||||
#include "Swiften/Parser/PayloadParsers/StatsParser.h"
|
||||
#include "Swiften/Serializer/PayloadSerializers/StatsSerializer.h"
|
||||
#include "Swiften/Parser/PayloadParsers/GatewayPayloadParser.h"
|
||||
#include "Swiften/Serializer/PayloadSerializers/GatewayPayloadSerializer.h"
|
||||
#include "Swiften/Serializer/PayloadSerializers/SpectrumErrorSerializer.h"
|
||||
#include "transport/BlockParser.h"
|
||||
#include "transport/BlockSerializer.h"
|
||||
|
@ -45,6 +47,7 @@
|
|||
#include "log4cxx/consoleappender.h"
|
||||
#include "log4cxx/patternlayout.h"
|
||||
#include "log4cxx/propertyconfigurator.h"
|
||||
#include "Swiften/Swiften.h"
|
||||
|
||||
using namespace Swift;
|
||||
using namespace boost;
|
||||
|
@ -94,6 +97,7 @@ Component::Component(Swift::EventLoop *loop, Swift::NetworkFactories *factories,
|
|||
m_server->addPayloadParserFactory(new GenericPayloadParserFactory<Transport::BlockParser>("block", "urn:xmpp:block:0"));
|
||||
m_server->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::InvisibleParser>("invisible", "urn:xmpp:invisible:0"));
|
||||
m_server->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::StatsParser>("query", "http://jabber.org/protocol/stats"));
|
||||
m_server->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::GatewayPayloadParser>("query", "jabber:iq:gateway"));
|
||||
|
||||
m_server->addPayloadSerializer(new Swift::AttentionSerializer());
|
||||
m_server->addPayloadSerializer(new Swift::XHTMLIMSerializer());
|
||||
|
@ -101,6 +105,7 @@ Component::Component(Swift::EventLoop *loop, Swift::NetworkFactories *factories,
|
|||
m_server->addPayloadSerializer(new Swift::InvisibleSerializer());
|
||||
m_server->addPayloadSerializer(new Swift::StatsSerializer());
|
||||
m_server->addPayloadSerializer(new Swift::SpectrumErrorSerializer());
|
||||
m_server->addPayloadSerializer(new Swift::GatewayPayloadSerializer());
|
||||
|
||||
m_server->onDataRead.connect(boost::bind(&Component::handleDataRead, this, _1));
|
||||
m_server->onDataWritten.connect(boost::bind(&Component::handleDataWritten, this, _1));
|
||||
|
@ -120,6 +125,7 @@ Component::Component(Swift::EventLoop *loop, Swift::NetworkFactories *factories,
|
|||
m_component->addPayloadParserFactory(new GenericPayloadParserFactory<Transport::BlockParser>("block", "urn:xmpp:block:0"));
|
||||
m_component->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::InvisibleParser>("invisible", "urn:xmpp:invisible:0"));
|
||||
m_component->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::StatsParser>("query", "http://jabber.org/protocol/stats"));
|
||||
m_component->addPayloadParserFactory(new GenericPayloadParserFactory<Swift::GatewayPayloadParser>("query", "jabber:iq:gateway"));
|
||||
|
||||
m_component->addPayloadSerializer(new Swift::AttentionSerializer());
|
||||
m_component->addPayloadSerializer(new Swift::XHTMLIMSerializer());
|
||||
|
@ -127,6 +133,7 @@ Component::Component(Swift::EventLoop *loop, Swift::NetworkFactories *factories,
|
|||
m_component->addPayloadSerializer(new Swift::InvisibleSerializer());
|
||||
m_component->addPayloadSerializer(new Swift::StatsSerializer());
|
||||
m_component->addPayloadSerializer(new Swift::SpectrumErrorSerializer());
|
||||
m_component->addPayloadSerializer(new Swift::GatewayPayloadSerializer());
|
||||
|
||||
m_stanzaChannel = m_component->getStanzaChannel();
|
||||
m_iqRouter = m_component->getIQRouter();
|
||||
|
@ -137,7 +144,7 @@ Component::Component(Swift::EventLoop *loop, Swift::NetworkFactories *factories,
|
|||
m_entityCapsManager = new EntityCapsManager(m_capsManager, m_stanzaChannel);
|
||||
m_entityCapsManager->onCapsChanged.connect(boost::bind(&Component::handleCapsChanged, this, _1));
|
||||
|
||||
m_presenceOracle = new PresenceOracle(m_stanzaChannel);
|
||||
m_presenceOracle = new Transport::PresenceOracle(m_stanzaChannel);
|
||||
m_presenceOracle->onPresenceChange.connect(bind(&Component::handlePresence, this, _1));
|
||||
|
||||
m_discoInfoResponder = new DiscoInfoResponder(m_iqRouter, m_config);
|
||||
|
@ -170,7 +177,7 @@ Swift::StanzaChannel *Component::getStanzaChannel() {
|
|||
return m_stanzaChannel;
|
||||
}
|
||||
|
||||
Swift::PresenceOracle *Component::getPresenceOracle() {
|
||||
Transport::PresenceOracle *Component::getPresenceOracle() {
|
||||
return m_presenceOracle;
|
||||
}
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#include "transport/rostermanager.h"
|
||||
#include "transport/usermanager.h"
|
||||
#include "transport/conversationmanager.h"
|
||||
#include "transport/presenceoracle.h"
|
||||
#include "Swiften/Swiften.h"
|
||||
#include "Swiften/Server/ServerStanzaChannel.h"
|
||||
#include "Swiften/Elements/StreamError.h"
|
||||
|
@ -212,8 +213,8 @@ void User::handlePresence(Swift::Presence::ref presence) {
|
|||
bool isMUC = presence->getPayload<Swift::MUCPayload>() != NULL || *presence->getTo().getNode().c_str() == '#';
|
||||
if (isMUC) {
|
||||
if (presence->getType() == Swift::Presence::Unavailable) {
|
||||
LOG4CXX_INFO(logger, m_jid.toString() << ": Going to left room " << presence->getTo().getNode());
|
||||
std::string room = Buddy::JIDToLegacyName(presence->getTo());
|
||||
LOG4CXX_INFO(logger, m_jid.toString() << ": Going to left room " << room);
|
||||
onRoomLeft(room);
|
||||
}
|
||||
else {
|
||||
|
@ -223,8 +224,8 @@ void User::handlePresence(Swift::Presence::ref presence) {
|
|||
m_readyForConnect = true;
|
||||
onReadyToConnect();
|
||||
}
|
||||
LOG4CXX_INFO(logger, m_jid.toString() << ": Going to join room " << presence->getTo().getNode() << " as " << presence->getTo().getResource());
|
||||
std::string room = Buddy::JIDToLegacyName(presence->getTo());
|
||||
LOG4CXX_INFO(logger, m_jid.toString() << ": Going to join room " << room << " as " << presence->getTo().getResource());
|
||||
std::string password = "";
|
||||
if (presence->getPayload<Swift::MUCPayload>() != NULL) {
|
||||
password = presence->getPayload<Swift::MUCPayload>()->getPassword() ? *presence->getPayload<Swift::MUCPayload>()->getPassword() : "";
|
||||
|
|
|
@ -306,8 +306,8 @@ void UserManager::handleSubscription(Swift::Presence::ref presence) {
|
|||
// answer to subscibe for transport itself
|
||||
if (presence->getType() == Swift::Presence::Subscribe && presence->getTo().getNode().empty()) {
|
||||
Swift::Presence::ref response = Swift::Presence::create();
|
||||
response->setFrom(presence->getTo());
|
||||
response->setTo(presence->getFrom());
|
||||
response->setFrom(presence->getTo().toBare());
|
||||
response->setTo(presence->getFrom().toBare());
|
||||
response->setType(Swift::Presence::Subscribed);
|
||||
m_component->getStanzaChannel()->sendPresence(response);
|
||||
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
#include "transport/user.h"
|
||||
#include "Swiften/Elements/ErrorPayload.h"
|
||||
#include <boost/shared_ptr.hpp>
|
||||
#include <boost/thread.hpp>
|
||||
#include <boost/date_time/posix_time/posix_time.hpp>
|
||||
#include "log4cxx/logger.h"
|
||||
|
||||
using namespace Swift;
|
||||
|
@ -241,6 +243,20 @@ bool UserRegistration::handleGetRequest(const Swift::JID& from, const Swift::JID
|
|||
boolean->setLabel((("Remove your registration")));
|
||||
boolean->setValue(0);
|
||||
form->addField(boolean);
|
||||
} else {
|
||||
if (CONFIG_BOOL(m_config,"registration.require_local_account")) {
|
||||
std::string localUsernameField = CONFIG_STRING(m_config, "registration.local_username_label");
|
||||
TextSingleFormField::ref local_username = TextSingleFormField::create();
|
||||
local_username->setName("local_username");
|
||||
local_username->setLabel((localUsernameField));
|
||||
local_username->setRequired(true);
|
||||
form->addField(local_username);
|
||||
TextPrivateFormField::ref local_password = TextPrivateFormField::create();
|
||||
local_password->setName("local_password");
|
||||
local_password->setLabel((("Local Password")));
|
||||
local_password->setRequired(true);
|
||||
form->addField(local_password);
|
||||
}
|
||||
}
|
||||
|
||||
reg->setForm(form);
|
||||
|
@ -273,6 +289,8 @@ bool UserRegistration::handleSetRequest(const Swift::JID& from, const Swift::JID
|
|||
|
||||
std::string encoding;
|
||||
std::string language;
|
||||
std::string local_username("");
|
||||
std::string local_password("");
|
||||
|
||||
Form::ref form = payload->getForm();
|
||||
if (form) {
|
||||
|
@ -286,6 +304,17 @@ bool UserRegistration::handleSetRequest(const Swift::JID& from, const Swift::JID
|
|||
else if (textSingle->getName() == "encoding") {
|
||||
encoding = textSingle->getValue();
|
||||
}
|
||||
// Pidgin sends it as textSingle, not sure why...
|
||||
else if (textSingle->getName() == "password") {
|
||||
payload->setPassword(textSingle->getValue());
|
||||
}
|
||||
else if (textSingle->getName() == "local_username") {
|
||||
local_username = textSingle->getValue();
|
||||
}
|
||||
// Pidgin sends it as textSingle, not sure why...
|
||||
else if (textSingle->getName() == "local_password") {
|
||||
local_password = textSingle->getValue();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -294,6 +323,9 @@ bool UserRegistration::handleSetRequest(const Swift::JID& from, const Swift::JID
|
|||
if (textPrivate->getName() == "password") {
|
||||
payload->setPassword(textPrivate->getValue());
|
||||
}
|
||||
else if (textPrivate->getName() == "local_password") {
|
||||
local_password = textPrivate->getValue();
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -323,6 +355,50 @@ bool UserRegistration::handleSetRequest(const Swift::JID& from, const Swift::JID
|
|||
return true;
|
||||
}
|
||||
|
||||
if (CONFIG_BOOL(m_config,"registration.require_local_account")) {
|
||||
/* if (!local_username || !local_password) {
|
||||
sendResponse(from, id, InBandRegistrationPayload::ref());
|
||||
return true
|
||||
} else */ if (local_username == "" || local_password == "") {
|
||||
sendResponse(from, id, InBandRegistrationPayload::ref());
|
||||
return true;
|
||||
}
|
||||
// Swift::logging = true;
|
||||
bool validLocal = false;
|
||||
std::string localLookupServer = CONFIG_STRING(m_config, "registration.local_account_server");
|
||||
std::string localLookupJID = local_username + std::string("@") + localLookupServer;
|
||||
SimpleEventLoop localLookupEventLoop;
|
||||
BoostNetworkFactories localLookupNetworkFactories(&localLookupEventLoop);
|
||||
Client localLookupClient(localLookupJID, local_password, &localLookupNetworkFactories);
|
||||
|
||||
// TODO: this is neccessary on my server ... but should maybe omitted
|
||||
localLookupClient.setAlwaysTrustCertificates();
|
||||
localLookupClient.connect();
|
||||
|
||||
class SimpleLoopRunner {
|
||||
public:
|
||||
SimpleLoopRunner() {};
|
||||
|
||||
static void run(SimpleEventLoop * loop) {
|
||||
loop->run();
|
||||
};
|
||||
};
|
||||
|
||||
// TODO: Really ugly and hacky solution, any other ideas more than welcome!
|
||||
boost::thread thread(boost::bind(&(SimpleLoopRunner::run), &localLookupEventLoop));
|
||||
thread.timed_join(boost::posix_time::millisec(CONFIG_INT(m_config, "registration.local_account_server_timeout")));
|
||||
localLookupEventLoop.stop();
|
||||
thread.join();
|
||||
validLocal = localLookupClient.isAvailable();
|
||||
localLookupClient.disconnect();
|
||||
if (!validLocal) {
|
||||
sendError(from, id, ErrorPayload::NotAuthorized, ErrorPayload::Modify);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
printf("here\n");
|
||||
|
||||
if (!payload->getUsername() || !payload->getPassword()) {
|
||||
sendError(from, id, ErrorPayload::NotAcceptable, ErrorPayload::Modify);
|
||||
return true;
|
||||
|
|
|
@ -128,6 +128,15 @@ std::vector<std::string> deserializeGroups(std::string &groups) {
|
|||
return ret;
|
||||
}
|
||||
|
||||
int getRandomPort(const std::string &s) {
|
||||
unsigned long r = 0;
|
||||
BOOST_FOREACH(char c, s) {
|
||||
r += (int) c;
|
||||
}
|
||||
srand(time(NULL) + r);
|
||||
return 30000 + rand() % 10000;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue