Merge branch 'master' of github.com:vitalyster/libtransport

This commit is contained in:
Vitaly Takmazov 2012-03-06 12:09:44 +04:00
commit e4800fcf0f
88 changed files with 147311 additions and 191 deletions

View file

@ -6,8 +6,12 @@ set(CMAKE_MODULE_PATH "cmake_modules")
set(cppunit_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
find_package(cppunit)
if (WIN32)
ADD_SUBDIRECTORY(msvc-deps)
else()
set(sqlite3_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
find_package(sqlite3)
endif()
set(mysql_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
find_package(mysql)
@ -29,16 +33,18 @@ find_package(event)
set(Swiften_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
find_package(Swiften REQUIRED)
if (NOT WIN32)
set(openssl_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
find_package(openssl REQUIRED)
endif()
set(Boost_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
if (WIN32)
set(Boost_USE_STATIC_LIBS ON)
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")
@ -56,6 +62,11 @@ find_package(event)
set(pqxx_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
find_package(pqxx)
if (NOT WIN32)
set(dbus_DIR "${CMAKE_SOURCE_DIR}/cmake_modules")
find_package(dbus)
endif()
find_package(Doxygen)
INCLUDE(FindQt4)
@ -72,7 +83,10 @@ if (SPECTRUM_VERSION)
ADD_DEFINITIONS(-DSPECTRUM_VERSION="${SPECTRUM_VERSION}")
else (SPECTRUM_VERSION)
if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/.git)
execute_process(COMMAND git "--git-dir=${CMAKE_CURRENT_SOURCE_DIR}/.git" rev-parse --short HEAD
if (NOT GIT_EXECUTABLE)
set (GIT_EXECUTABLE git)
endif()
execute_process(COMMAND ${GIT_EXECUTABLE} "--git-dir=${CMAKE_CURRENT_SOURCE_DIR}/.git" rev-parse --short HEAD
OUTPUT_VARIABLE GIT_REVISION
OUTPUT_STRIP_TRAILING_WHITESPACE
)
@ -91,8 +105,15 @@ if (SQLITE3_FOUND)
include_directories(${SQLITE3_INCLUDE_DIR})
message("SQLite3 : yes")
else (SQLITE3_FOUND)
if (WIN32)
ADD_DEFINITIONS(-DWITH_SQLITE)
include_directories(msvc-deps/sqlite3)
set (SQLITE3_LIBRARIES "${CMAKE_SOURCE_DIR}/msvc-deps/sqlite3/sqlite3.lib")
message("SQLite3 : bundled")
else()
set(SQLITE3_LIBRARIES "")
message("SQLite3 : no")
endif()
endif (SQLITE3_FOUND)
if (MYSQL_FOUND)
@ -145,23 +166,35 @@ if (PROTOBUF_FOUND)
message("IRC plugin : no (install libCommuni and libprotobuf-dev)")
endif()
if (NOT WIN32)
message("Frotz plugin : yes")
message("SMSTools3 plugin : yes")
else()
message("Frotz plugin : no")
message("SMSTools3 plugin : no")
if(${LIBDBUSGLIB_FOUND})
message("Skype plugin : yes")
include_directories(${LIBDBUSGLIB_INCLUDE_DIRS})
else()
message("Skype plugin : no (install dbus-glib-devel)")
endif()
endif()
else()
message("Network plugins : no (install libprotobuf-dev)")
message("Libpurple plugin : no (install libpurple and libprotobuf-dev)")
message("IRC plugin : no (install libircclient-qt and libprotobuf-dev)")
message("Frotz plugin : no (install libprotobuf-dev)")
message("SMSTools3 plugin : no (install libprotobuf-dev)")
endif()
if (LOG4CXX_FOUND)
message("Logging : yes")
include_directories(${LOG4CXX_INCLUDE_DIR})
else()
message(FATAL_ERROR "Logging : no (install log4cxx-devel)")
endif()
if (WIN32)
ADD_DEFINITIONS(-DLOG4CXX_STATIC)
ADD_DEFINITIONS(-D_WIN32_WINNT=0x501)
ADD_DEFINITIONS(-DWIN32_LEAN_AND_MEAN)
endif()
@ -197,7 +230,10 @@ include_directories(include)
include_directories(${EVENT_INCLUDE_DIRS})
include_directories(${SWIFTEN_INCLUDE_DIR})
include_directories(${Boost_INCLUDE_DIRS})
if (NOT WIN32)
include_directories(${OPENSSL_INCLUDE_DIR})
endif()
ADD_SUBDIRECTORY(src)
ADD_SUBDIRECTORY(plugin)

View file

@ -1,11 +1,28 @@
Version 2.0.0-beta (X-X-X):
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

60
README.win32 Normal file
View file

@ -0,0 +1,60 @@
Prerequisites
=============
1. Microsoft Visual C++ 2010 Express or higher edition (http://www.microsoft.com/visualstudio/en-us/products/2010-editions/visual-cpp-express)
2. Git for Windows (http://code.google.com/p/msysgit/downloads/list)
3. CMake 2.8 or newer (http://www.cmake.org/cmake/resources/software.html)
Libraries
=========
3. Swiften library and Python for run scons (http://swift.im/git/swift)
4. Boost 1.48 or newer (http://sourceforge.net/projects/boost/files/boost/1.49.0/)
5. Google ProtoBuf library (http://code.google.com/p/protobuf/downloads/list)
6. Apache log4cxx, apr, apr-util (http://logging.apache.org/log4cxx/download.html)
Environment
===========
To create spectrum build environment do:
0. Create directory where we'll install all dependencies, e.g. C:\env-msvc-x64
Assuming you have git, python and cmake in %PATH%,
launch "Visual Studio 2010 command prompt" or
"Visual Studio 2010(x64) command prompt", depends on your target (Windows x86 or Windows x86_64).
1. unpack and build boost libraries:
bootstrap.bat
b2.exe --without-mpi --without-python
b2.exe --without-mpi --without-python install --prefix=C:\env-msvc-x64
2. clone swift repository and build it. Don't forget to point it to our env directory:
git clone http://swift.im/git/swift
cd swift
echo boost_includedir="c:/env-msvc-x64/include/boost-1_48" > config.py
echo boost_libdir="c:/env-msvc-x64/lib" >> config.py
scons.bat debug=no SWIFTEN_INSTALLDIR=C:\env-msvc-x64
scons.bat debug=no SWIFTEN_INSTALLDIR=C:\env-msvc-x64 C:\env-msvc-x64
TODO: fix in upstream
You may need manually copy compiled 3rdParty libs to C:\env-msvc-x64\lib\3rdParty\Expat,
C:\env-msvc-x64\lib\3rdParty\LibIDN, C:\env-msvc-x64\lib\3rdParty\Zlib
3. unpack and compile protobuf as described in its documentation.
Run extract_includes.bat in vsprojects/ directory and move resulting google/ directory to our C:\env-msvc-x64\include
Move protoc.exe to C:\env-msvc-x64\bin\ and libprotobuf.lib to C:\env-msvc-x64\lib
4. unpack and compile log4cxx, apr, apr-util as described here:
http://www.lextm.com/2010/09/how-to-build-log4cxx-in-visual-studio.html
Also you need to make output type="Static Library" and add LOG4CXX_STATIC in Preprocessor Definitions of log4cxx vsproject.
Move include/log4cxx and resulting log4cxx.lib to C:\env-msvc-x64\include and C:\env-msvc-x64\lib
5. You're ready! :) Clone libtransport and compile it as:
set CMAKE_INCLUDE_PATH=C:\env-msvc-x64\include
cmake . -G "NMake Makefiles" -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=C:\env-msvc-x64 -DGIT_EXECUTABLE="c:\Program Files (x86)\git\bin\git.exe"
nmake
TODO: libpurple_backend compilation

View file

@ -7,8 +7,14 @@ if (PROTOBUF_FOUND)
ADD_SUBDIRECTORY(libcommuni)
endif()
ADD_SUBDIRECTORY(template)
if (NOT WIN32)
ADD_SUBDIRECTORY(smstools3)
ADD_SUBDIRECTORY(frotz)
if (${LIBDBUSGLIB_FOUND})
ADD_SUBDIRECTORY(skype)
endif()
endif()
endif()

View file

@ -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)

View file

@ -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)

View file

@ -915,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) {

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

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

View file

@ -0,0 +1,14 @@
cmake_minimum_required(VERSION 2.6)
FILE(GLOB SRC *.c *.cpp)
ADD_EXECUTABLE(spectrum2_template_backend ${SRC})
if (NOT WIN32)
target_link_libraries(spectrum2_template_backend transport pthread ${Boost_LIBRARIES} ${SWIFTEN_LIBRARY} ${LOG4CXX_LIBRARIES})
else()
target_link_libraries(spectrum2_template_backend transport ${Boost_LIBRARIES} ${SWIFTEN_LIBRARY} ${LOG4CXX_LIBRARIES})
endif()
#INSTALL(TARGETS spectrum2_template_backend RUNTIME DESTINATION bin)

1
backends/template/README Normal file
View file

@ -0,0 +1 @@
This is just template for creating new generic spectrum2 backends. It does not do anything!

185
backends/template/main.cpp Normal file
View file

@ -0,0 +1,185 @@
// Transport includes
#include "transport/config.h"
#include "transport/networkplugin.h"
// Swiften
#include "Swiften/Swiften.h"
#ifndef _MSC_VER
// for signal handler
#include "unistd.h"
#include "signal.h"
#include "sys/wait.h"
#include "sys/signal.h"
#endif
// 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;
};
#ifndef _MSC_VER
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);
}
}
#endif
int main (int argc, char* argv[]) {
std::string host;
int port;
#ifndef _MSC_VER
if (signal(SIGCHLD, spectrum_sigchld_handler) == SIG_ERR) {
std::cout << "SIGCHLD handler can't be set\n";
return -1;
}
#endif
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;
}

View 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 )

View file

@ -2,7 +2,7 @@
# LOG4CXX_INCLUDE_DIR - the liblog4cxx include directory
# LOG4CXX_LIBRARIES - liblog4cxx library
FIND_PATH(LOG4CXX_INCLUDE_DIR logger.h PATHS /include/log4cxx /usr/include/log4cxx /usr/local/include/log4cxx )
FIND_PATH(LOG4CXX_INCLUDE_DIR log4cxx/logger.h PATHS /include /usr/include /usr/local/include )
FIND_LIBRARY(LOG4CXX_LIBRARIES NAMES log4cxx log4cxxd PATHS /lib /usr/lib /usr/local/lib )
IF(LOG4CXX_INCLUDE_DIR AND LOG4CXX_LIBRARIES)

View 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) {
}
}

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

View 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() {
}
}

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

View 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() {
}
}

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

View 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) {
}
}

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

View 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) {
}
}

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

View 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) {
}
}

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

View file

@ -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() {

View file

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

View file

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

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

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

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

View file

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

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

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

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

View file

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

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

View file

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

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View 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.
*/
#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();
}
}

View file

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

View file

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

View file

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

View 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.
*/
#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();
}
}

View file

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

View file

@ -149,7 +149,7 @@ void Server::handleSessionFinished(boost::shared_ptr<ServerFromClientSession> se
boost::bind(&Server::handleSessionFinished, this, session));
}
void Server::addTLSEncryption(TLSServerContextFactory* tlsContextFactory, const PKCS12Certificate& cert) {
void Server::addTLSEncryption(TLSServerContextFactory* tlsContextFactory, CertificateWithKey::ref cert) {
tlsFactory = tlsContextFactory;
this->cert = cert;
}

View file

@ -21,7 +21,7 @@
#include "Swiften/Entity/Entity.h"
#include "Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.h"
#include "Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.h"
#include "Swiften/TLS/PKCS12Certificate.h"
#include <Swiften/TLS/CertificateWithKey.h>
#include <Swiften/Parser/PlatformXMLParserFactory.h>
namespace Swift {
@ -60,7 +60,7 @@ namespace Swift {
boost::signal<void (const SafeByteArray&)> onDataRead;
boost::signal<void (const SafeByteArray&)> onDataWritten;
void addTLSEncryption(TLSServerContextFactory* tlsContextFactory, const PKCS12Certificate& cert);
void addTLSEncryption(TLSServerContextFactory* tlsContextFactory, CertificateWithKey::ref cert);
private:
void handleNewClientConnection(boost::shared_ptr<Connection> c);
@ -84,7 +84,7 @@ namespace Swift {
StanzaChannel *stanzaChannel_;
IQRouter *iqRouter_;
TLSServerContextFactory *tlsFactory;
PKCS12Certificate cert;
CertificateWithKey::ref cert;
PlatformXMLParserFactory *parserFactory_;
};
}

View file

@ -27,6 +27,7 @@
#include <Swiften/Elements/StartTLSRequest.h>
#include <Swiften/Elements/TLSProceed.h>
#include <iostream>
#include <Swiften/TLS/CertificateWithKey.h>
namespace Swift {
@ -162,7 +163,7 @@ void ServerFromClientSession::handleSessionFinished(const boost::optional<Sessio
userRegistry_->stopLogin(JID(user_, getLocalJID().getDomain()), this);
}
void ServerFromClientSession::addTLSEncryption(TLSServerContextFactory* tlsContextFactory, const PKCS12Certificate& cert) {
void ServerFromClientSession::addTLSEncryption(TLSServerContextFactory* tlsContextFactory, CertificateWithKey::ref cert) {
tlsLayer = new TLSServerLayer(tlsContextFactory);
if (!tlsLayer->setServerCertificate(cert)) {
// std::cout << "error\n";

View file

@ -15,6 +15,7 @@
#include <Swiften/JID/JID.h>
#include <Swiften/Network/Connection.h>
#include <Swiften/Base/ByteArray.h>
#include <Swiften/TLS/CertificateWithKey.h>
namespace Swift {
class ProtocolHeader;
@ -49,7 +50,7 @@ namespace Swift {
return user_;
}
void addTLSEncryption(TLSServerContextFactory* tlsContextFactory, const PKCS12Certificate& cert);
void addTLSEncryption(TLSServerContextFactory* tlsContextFactory, CertificateWithKey::ref cert);
Swift::JID getBareJID() {
return Swift::JID(user_, getLocalJID().getDomain());

View file

@ -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) {

View file

@ -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:

View file

@ -37,7 +37,7 @@ void TLSServerLayer::handleDataRead(const SafeByteArray& data) {
context->handleDataFromNetwork(data);
}
bool TLSServerLayer::setServerCertificate(const PKCS12Certificate& certificate) {
bool TLSServerLayer::setServerCertificate(CertificateWithKey::ref certificate) {
return context->setServerCertificate(certificate);
}

View file

@ -9,6 +9,7 @@
#include "Swiften/Base/SafeByteArray.h"
#include "Swiften/StreamStack/StreamLayer.h"
#include "Swiften/TLS/Certificate.h"
#include <Swiften/TLS/CertificateWithKey.h>
#include "Swiften/TLS/CertificateVerificationError.h"
namespace Swift {
@ -22,7 +23,7 @@ namespace Swift {
~TLSServerLayer();
void connect();
bool setServerCertificate(const PKCS12Certificate&);
bool setServerCertificate(CertificateWithKey::ref cert);
Certificate::ref getPeerCertificate() const;
boost::shared_ptr<CertificateVerificationError> getPeerCertificateVerificationError() const;

View file

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

View file

@ -11,6 +11,7 @@
#include "Swiften/Base/SafeByteArray.h"
#include "Swiften/TLS/Certificate.h"
#include <Swiften/TLS/CertificateWithKey.h>
#include "Swiften/TLS/CertificateVerificationError.h"
namespace Swift {
@ -22,7 +23,7 @@ namespace Swift {
virtual void connect() = 0;
virtual bool setServerCertificate(const PKCS12Certificate& cert) = 0;
virtual bool setServerCertificate(CertificateWithKey::ref cert) = 0;
virtual void handleDataFromNetwork(const SafeByteArray&) = 0;
virtual void handleDataFromApplication(const SafeByteArray&) = 0;

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

View file

@ -97,7 +97,10 @@ class PQXXBackend : public StorageBackend
private:
bool exec(const std::string &query, bool show_error = true);
bool exec(pqxx::work &txn, 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;

View file

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

View file

@ -0,0 +1,6 @@
cmake_minimum_required(VERSION 2.6)
FILE(GLOB SRC *.c *.h)
ADD_LIBRARY(sqlite3 STATIC ${HEADERS} ${SRC})
INSTALL(TARGETS sqlite3 LIBRARY DESTINATION lib ARCHIVE DESTINATION lib COMPONENT libraries)

2988
msvc-deps/sqlite3/shell.c Normal file

File diff suppressed because it is too large Load diff

133611
msvc-deps/sqlite3/sqlite3.c Normal file

File diff suppressed because it is too large Load diff

6949
msvc-deps/sqlite3/sqlite3.h Normal file

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,447 @@
/*
** 2006 June 7
**
** The author disclaims copyright to this source code. In place of
** a legal notice, here is a blessing:
**
** May you do good and not evil.
** May you find forgiveness for yourself and forgive others.
** May you share freely, never taking more than you give.
**
*************************************************************************
** This header file defines the SQLite interface for use by
** shared libraries that want to be imported as extensions into
** an SQLite instance. Shared libraries that intend to be loaded
** as extensions by SQLite should #include this file instead of
** sqlite3.h.
*/
#ifndef _SQLITE3EXT_H_
#define _SQLITE3EXT_H_
#include "sqlite3.h"
typedef struct sqlite3_api_routines sqlite3_api_routines;
/*
** The following structure holds pointers to all of the SQLite API
** routines.
**
** WARNING: In order to maintain backwards compatibility, add new
** interfaces to the end of this structure only. If you insert new
** interfaces in the middle of this structure, then older different
** versions of SQLite will not be able to load each others' shared
** libraries!
*/
struct sqlite3_api_routines {
void * (*aggregate_context)(sqlite3_context*,int nBytes);
int (*aggregate_count)(sqlite3_context*);
int (*bind_blob)(sqlite3_stmt*,int,const void*,int n,void(*)(void*));
int (*bind_double)(sqlite3_stmt*,int,double);
int (*bind_int)(sqlite3_stmt*,int,int);
int (*bind_int64)(sqlite3_stmt*,int,sqlite_int64);
int (*bind_null)(sqlite3_stmt*,int);
int (*bind_parameter_count)(sqlite3_stmt*);
int (*bind_parameter_index)(sqlite3_stmt*,const char*zName);
const char * (*bind_parameter_name)(sqlite3_stmt*,int);
int (*bind_text)(sqlite3_stmt*,int,const char*,int n,void(*)(void*));
int (*bind_text16)(sqlite3_stmt*,int,const void*,int,void(*)(void*));
int (*bind_value)(sqlite3_stmt*,int,const sqlite3_value*);
int (*busy_handler)(sqlite3*,int(*)(void*,int),void*);
int (*busy_timeout)(sqlite3*,int ms);
int (*changes)(sqlite3*);
int (*close)(sqlite3*);
int (*collation_needed)(sqlite3*,void*,void(*)(void*,sqlite3*,
int eTextRep,const char*));
int (*collation_needed16)(sqlite3*,void*,void(*)(void*,sqlite3*,
int eTextRep,const void*));
const void * (*column_blob)(sqlite3_stmt*,int iCol);
int (*column_bytes)(sqlite3_stmt*,int iCol);
int (*column_bytes16)(sqlite3_stmt*,int iCol);
int (*column_count)(sqlite3_stmt*pStmt);
const char * (*column_database_name)(sqlite3_stmt*,int);
const void * (*column_database_name16)(sqlite3_stmt*,int);
const char * (*column_decltype)(sqlite3_stmt*,int i);
const void * (*column_decltype16)(sqlite3_stmt*,int);
double (*column_double)(sqlite3_stmt*,int iCol);
int (*column_int)(sqlite3_stmt*,int iCol);
sqlite_int64 (*column_int64)(sqlite3_stmt*,int iCol);
const char * (*column_name)(sqlite3_stmt*,int);
const void * (*column_name16)(sqlite3_stmt*,int);
const char * (*column_origin_name)(sqlite3_stmt*,int);
const void * (*column_origin_name16)(sqlite3_stmt*,int);
const char * (*column_table_name)(sqlite3_stmt*,int);
const void * (*column_table_name16)(sqlite3_stmt*,int);
const unsigned char * (*column_text)(sqlite3_stmt*,int iCol);
const void * (*column_text16)(sqlite3_stmt*,int iCol);
int (*column_type)(sqlite3_stmt*,int iCol);
sqlite3_value* (*column_value)(sqlite3_stmt*,int iCol);
void * (*commit_hook)(sqlite3*,int(*)(void*),void*);
int (*complete)(const char*sql);
int (*complete16)(const void*sql);
int (*create_collation)(sqlite3*,const char*,int,void*,
int(*)(void*,int,const void*,int,const void*));
int (*create_collation16)(sqlite3*,const void*,int,void*,
int(*)(void*,int,const void*,int,const void*));
int (*create_function)(sqlite3*,const char*,int,int,void*,
void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
void (*xStep)(sqlite3_context*,int,sqlite3_value**),
void (*xFinal)(sqlite3_context*));
int (*create_function16)(sqlite3*,const void*,int,int,void*,
void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
void (*xStep)(sqlite3_context*,int,sqlite3_value**),
void (*xFinal)(sqlite3_context*));
int (*create_module)(sqlite3*,const char*,const sqlite3_module*,void*);
int (*data_count)(sqlite3_stmt*pStmt);
sqlite3 * (*db_handle)(sqlite3_stmt*);
int (*declare_vtab)(sqlite3*,const char*);
int (*enable_shared_cache)(int);
int (*errcode)(sqlite3*db);
const char * (*errmsg)(sqlite3*);
const void * (*errmsg16)(sqlite3*);
int (*exec)(sqlite3*,const char*,sqlite3_callback,void*,char**);
int (*expired)(sqlite3_stmt*);
int (*finalize)(sqlite3_stmt*pStmt);
void (*free)(void*);
void (*free_table)(char**result);
int (*get_autocommit)(sqlite3*);
void * (*get_auxdata)(sqlite3_context*,int);
int (*get_table)(sqlite3*,const char*,char***,int*,int*,char**);
int (*global_recover)(void);
void (*interruptx)(sqlite3*);
sqlite_int64 (*last_insert_rowid)(sqlite3*);
const char * (*libversion)(void);
int (*libversion_number)(void);
void *(*malloc)(int);
char * (*mprintf)(const char*,...);
int (*open)(const char*,sqlite3**);
int (*open16)(const void*,sqlite3**);
int (*prepare)(sqlite3*,const char*,int,sqlite3_stmt**,const char**);
int (*prepare16)(sqlite3*,const void*,int,sqlite3_stmt**,const void**);
void * (*profile)(sqlite3*,void(*)(void*,const char*,sqlite_uint64),void*);
void (*progress_handler)(sqlite3*,int,int(*)(void*),void*);
void *(*realloc)(void*,int);
int (*reset)(sqlite3_stmt*pStmt);
void (*result_blob)(sqlite3_context*,const void*,int,void(*)(void*));
void (*result_double)(sqlite3_context*,double);
void (*result_error)(sqlite3_context*,const char*,int);
void (*result_error16)(sqlite3_context*,const void*,int);
void (*result_int)(sqlite3_context*,int);
void (*result_int64)(sqlite3_context*,sqlite_int64);
void (*result_null)(sqlite3_context*);
void (*result_text)(sqlite3_context*,const char*,int,void(*)(void*));
void (*result_text16)(sqlite3_context*,const void*,int,void(*)(void*));
void (*result_text16be)(sqlite3_context*,const void*,int,void(*)(void*));
void (*result_text16le)(sqlite3_context*,const void*,int,void(*)(void*));
void (*result_value)(sqlite3_context*,sqlite3_value*);
void * (*rollback_hook)(sqlite3*,void(*)(void*),void*);
int (*set_authorizer)(sqlite3*,int(*)(void*,int,const char*,const char*,
const char*,const char*),void*);
void (*set_auxdata)(sqlite3_context*,int,void*,void (*)(void*));
char * (*snprintf)(int,char*,const char*,...);
int (*step)(sqlite3_stmt*);
int (*table_column_metadata)(sqlite3*,const char*,const char*,const char*,
char const**,char const**,int*,int*,int*);
void (*thread_cleanup)(void);
int (*total_changes)(sqlite3*);
void * (*trace)(sqlite3*,void(*xTrace)(void*,const char*),void*);
int (*transfer_bindings)(sqlite3_stmt*,sqlite3_stmt*);
void * (*update_hook)(sqlite3*,void(*)(void*,int ,char const*,char const*,
sqlite_int64),void*);
void * (*user_data)(sqlite3_context*);
const void * (*value_blob)(sqlite3_value*);
int (*value_bytes)(sqlite3_value*);
int (*value_bytes16)(sqlite3_value*);
double (*value_double)(sqlite3_value*);
int (*value_int)(sqlite3_value*);
sqlite_int64 (*value_int64)(sqlite3_value*);
int (*value_numeric_type)(sqlite3_value*);
const unsigned char * (*value_text)(sqlite3_value*);
const void * (*value_text16)(sqlite3_value*);
const void * (*value_text16be)(sqlite3_value*);
const void * (*value_text16le)(sqlite3_value*);
int (*value_type)(sqlite3_value*);
char *(*vmprintf)(const char*,va_list);
/* Added ??? */
int (*overload_function)(sqlite3*, const char *zFuncName, int nArg);
/* Added by 3.3.13 */
int (*prepare_v2)(sqlite3*,const char*,int,sqlite3_stmt**,const char**);
int (*prepare16_v2)(sqlite3*,const void*,int,sqlite3_stmt**,const void**);
int (*clear_bindings)(sqlite3_stmt*);
/* Added by 3.4.1 */
int (*create_module_v2)(sqlite3*,const char*,const sqlite3_module*,void*,
void (*xDestroy)(void *));
/* Added by 3.5.0 */
int (*bind_zeroblob)(sqlite3_stmt*,int,int);
int (*blob_bytes)(sqlite3_blob*);
int (*blob_close)(sqlite3_blob*);
int (*blob_open)(sqlite3*,const char*,const char*,const char*,sqlite3_int64,
int,sqlite3_blob**);
int (*blob_read)(sqlite3_blob*,void*,int,int);
int (*blob_write)(sqlite3_blob*,const void*,int,int);
int (*create_collation_v2)(sqlite3*,const char*,int,void*,
int(*)(void*,int,const void*,int,const void*),
void(*)(void*));
int (*file_control)(sqlite3*,const char*,int,void*);
sqlite3_int64 (*memory_highwater)(int);
sqlite3_int64 (*memory_used)(void);
sqlite3_mutex *(*mutex_alloc)(int);
void (*mutex_enter)(sqlite3_mutex*);
void (*mutex_free)(sqlite3_mutex*);
void (*mutex_leave)(sqlite3_mutex*);
int (*mutex_try)(sqlite3_mutex*);
int (*open_v2)(const char*,sqlite3**,int,const char*);
int (*release_memory)(int);
void (*result_error_nomem)(sqlite3_context*);
void (*result_error_toobig)(sqlite3_context*);
int (*sleep)(int);
void (*soft_heap_limit)(int);
sqlite3_vfs *(*vfs_find)(const char*);
int (*vfs_register)(sqlite3_vfs*,int);
int (*vfs_unregister)(sqlite3_vfs*);
int (*xthreadsafe)(void);
void (*result_zeroblob)(sqlite3_context*,int);
void (*result_error_code)(sqlite3_context*,int);
int (*test_control)(int, ...);
void (*randomness)(int,void*);
sqlite3 *(*context_db_handle)(sqlite3_context*);
int (*extended_result_codes)(sqlite3*,int);
int (*limit)(sqlite3*,int,int);
sqlite3_stmt *(*next_stmt)(sqlite3*,sqlite3_stmt*);
const char *(*sql)(sqlite3_stmt*);
int (*status)(int,int*,int*,int);
int (*backup_finish)(sqlite3_backup*);
sqlite3_backup *(*backup_init)(sqlite3*,const char*,sqlite3*,const char*);
int (*backup_pagecount)(sqlite3_backup*);
int (*backup_remaining)(sqlite3_backup*);
int (*backup_step)(sqlite3_backup*,int);
const char *(*compileoption_get)(int);
int (*compileoption_used)(const char*);
int (*create_function_v2)(sqlite3*,const char*,int,int,void*,
void (*xFunc)(sqlite3_context*,int,sqlite3_value**),
void (*xStep)(sqlite3_context*,int,sqlite3_value**),
void (*xFinal)(sqlite3_context*),
void(*xDestroy)(void*));
int (*db_config)(sqlite3*,int,...);
sqlite3_mutex *(*db_mutex)(sqlite3*);
int (*db_status)(sqlite3*,int,int*,int*,int);
int (*extended_errcode)(sqlite3*);
void (*log)(int,const char*,...);
sqlite3_int64 (*soft_heap_limit64)(sqlite3_int64);
const char *(*sourceid)(void);
int (*stmt_status)(sqlite3_stmt*,int,int);
int (*strnicmp)(const char*,const char*,int);
int (*unlock_notify)(sqlite3*,void(*)(void**,int),void*);
int (*wal_autocheckpoint)(sqlite3*,int);
int (*wal_checkpoint)(sqlite3*,const char*);
void *(*wal_hook)(sqlite3*,int(*)(void*,sqlite3*,const char*,int),void*);
int (*blob_reopen)(sqlite3_blob*,sqlite3_int64);
int (*vtab_config)(sqlite3*,int op,...);
int (*vtab_on_conflict)(sqlite3*);
};
/*
** The following macros redefine the API routines so that they are
** redirected throught the global sqlite3_api structure.
**
** This header file is also used by the loadext.c source file
** (part of the main SQLite library - not an extension) so that
** it can get access to the sqlite3_api_routines structure
** definition. But the main library does not want to redefine
** the API. So the redefinition macros are only valid if the
** SQLITE_CORE macros is undefined.
*/
#ifndef SQLITE_CORE
#define sqlite3_aggregate_context sqlite3_api->aggregate_context
#ifndef SQLITE_OMIT_DEPRECATED
#define sqlite3_aggregate_count sqlite3_api->aggregate_count
#endif
#define sqlite3_bind_blob sqlite3_api->bind_blob
#define sqlite3_bind_double sqlite3_api->bind_double
#define sqlite3_bind_int sqlite3_api->bind_int
#define sqlite3_bind_int64 sqlite3_api->bind_int64
#define sqlite3_bind_null sqlite3_api->bind_null
#define sqlite3_bind_parameter_count sqlite3_api->bind_parameter_count
#define sqlite3_bind_parameter_index sqlite3_api->bind_parameter_index
#define sqlite3_bind_parameter_name sqlite3_api->bind_parameter_name
#define sqlite3_bind_text sqlite3_api->bind_text
#define sqlite3_bind_text16 sqlite3_api->bind_text16
#define sqlite3_bind_value sqlite3_api->bind_value
#define sqlite3_busy_handler sqlite3_api->busy_handler
#define sqlite3_busy_timeout sqlite3_api->busy_timeout
#define sqlite3_changes sqlite3_api->changes
#define sqlite3_close sqlite3_api->close
#define sqlite3_collation_needed sqlite3_api->collation_needed
#define sqlite3_collation_needed16 sqlite3_api->collation_needed16
#define sqlite3_column_blob sqlite3_api->column_blob
#define sqlite3_column_bytes sqlite3_api->column_bytes
#define sqlite3_column_bytes16 sqlite3_api->column_bytes16
#define sqlite3_column_count sqlite3_api->column_count
#define sqlite3_column_database_name sqlite3_api->column_database_name
#define sqlite3_column_database_name16 sqlite3_api->column_database_name16
#define sqlite3_column_decltype sqlite3_api->column_decltype
#define sqlite3_column_decltype16 sqlite3_api->column_decltype16
#define sqlite3_column_double sqlite3_api->column_double
#define sqlite3_column_int sqlite3_api->column_int
#define sqlite3_column_int64 sqlite3_api->column_int64
#define sqlite3_column_name sqlite3_api->column_name
#define sqlite3_column_name16 sqlite3_api->column_name16
#define sqlite3_column_origin_name sqlite3_api->column_origin_name
#define sqlite3_column_origin_name16 sqlite3_api->column_origin_name16
#define sqlite3_column_table_name sqlite3_api->column_table_name
#define sqlite3_column_table_name16 sqlite3_api->column_table_name16
#define sqlite3_column_text sqlite3_api->column_text
#define sqlite3_column_text16 sqlite3_api->column_text16
#define sqlite3_column_type sqlite3_api->column_type
#define sqlite3_column_value sqlite3_api->column_value
#define sqlite3_commit_hook sqlite3_api->commit_hook
#define sqlite3_complete sqlite3_api->complete
#define sqlite3_complete16 sqlite3_api->complete16
#define sqlite3_create_collation sqlite3_api->create_collation
#define sqlite3_create_collation16 sqlite3_api->create_collation16
#define sqlite3_create_function sqlite3_api->create_function
#define sqlite3_create_function16 sqlite3_api->create_function16
#define sqlite3_create_module sqlite3_api->create_module
#define sqlite3_create_module_v2 sqlite3_api->create_module_v2
#define sqlite3_data_count sqlite3_api->data_count
#define sqlite3_db_handle sqlite3_api->db_handle
#define sqlite3_declare_vtab sqlite3_api->declare_vtab
#define sqlite3_enable_shared_cache sqlite3_api->enable_shared_cache
#define sqlite3_errcode sqlite3_api->errcode
#define sqlite3_errmsg sqlite3_api->errmsg
#define sqlite3_errmsg16 sqlite3_api->errmsg16
#define sqlite3_exec sqlite3_api->exec
#ifndef SQLITE_OMIT_DEPRECATED
#define sqlite3_expired sqlite3_api->expired
#endif
#define sqlite3_finalize sqlite3_api->finalize
#define sqlite3_free sqlite3_api->free
#define sqlite3_free_table sqlite3_api->free_table
#define sqlite3_get_autocommit sqlite3_api->get_autocommit
#define sqlite3_get_auxdata sqlite3_api->get_auxdata
#define sqlite3_get_table sqlite3_api->get_table
#ifndef SQLITE_OMIT_DEPRECATED
#define sqlite3_global_recover sqlite3_api->global_recover
#endif
#define sqlite3_interrupt sqlite3_api->interruptx
#define sqlite3_last_insert_rowid sqlite3_api->last_insert_rowid
#define sqlite3_libversion sqlite3_api->libversion
#define sqlite3_libversion_number sqlite3_api->libversion_number
#define sqlite3_malloc sqlite3_api->malloc
#define sqlite3_mprintf sqlite3_api->mprintf
#define sqlite3_open sqlite3_api->open
#define sqlite3_open16 sqlite3_api->open16
#define sqlite3_prepare sqlite3_api->prepare
#define sqlite3_prepare16 sqlite3_api->prepare16
#define sqlite3_prepare_v2 sqlite3_api->prepare_v2
#define sqlite3_prepare16_v2 sqlite3_api->prepare16_v2
#define sqlite3_profile sqlite3_api->profile
#define sqlite3_progress_handler sqlite3_api->progress_handler
#define sqlite3_realloc sqlite3_api->realloc
#define sqlite3_reset sqlite3_api->reset
#define sqlite3_result_blob sqlite3_api->result_blob
#define sqlite3_result_double sqlite3_api->result_double
#define sqlite3_result_error sqlite3_api->result_error
#define sqlite3_result_error16 sqlite3_api->result_error16
#define sqlite3_result_int sqlite3_api->result_int
#define sqlite3_result_int64 sqlite3_api->result_int64
#define sqlite3_result_null sqlite3_api->result_null
#define sqlite3_result_text sqlite3_api->result_text
#define sqlite3_result_text16 sqlite3_api->result_text16
#define sqlite3_result_text16be sqlite3_api->result_text16be
#define sqlite3_result_text16le sqlite3_api->result_text16le
#define sqlite3_result_value sqlite3_api->result_value
#define sqlite3_rollback_hook sqlite3_api->rollback_hook
#define sqlite3_set_authorizer sqlite3_api->set_authorizer
#define sqlite3_set_auxdata sqlite3_api->set_auxdata
#define sqlite3_snprintf sqlite3_api->snprintf
#define sqlite3_step sqlite3_api->step
#define sqlite3_table_column_metadata sqlite3_api->table_column_metadata
#define sqlite3_thread_cleanup sqlite3_api->thread_cleanup
#define sqlite3_total_changes sqlite3_api->total_changes
#define sqlite3_trace sqlite3_api->trace
#ifndef SQLITE_OMIT_DEPRECATED
#define sqlite3_transfer_bindings sqlite3_api->transfer_bindings
#endif
#define sqlite3_update_hook sqlite3_api->update_hook
#define sqlite3_user_data sqlite3_api->user_data
#define sqlite3_value_blob sqlite3_api->value_blob
#define sqlite3_value_bytes sqlite3_api->value_bytes
#define sqlite3_value_bytes16 sqlite3_api->value_bytes16
#define sqlite3_value_double sqlite3_api->value_double
#define sqlite3_value_int sqlite3_api->value_int
#define sqlite3_value_int64 sqlite3_api->value_int64
#define sqlite3_value_numeric_type sqlite3_api->value_numeric_type
#define sqlite3_value_text sqlite3_api->value_text
#define sqlite3_value_text16 sqlite3_api->value_text16
#define sqlite3_value_text16be sqlite3_api->value_text16be
#define sqlite3_value_text16le sqlite3_api->value_text16le
#define sqlite3_value_type sqlite3_api->value_type
#define sqlite3_vmprintf sqlite3_api->vmprintf
#define sqlite3_overload_function sqlite3_api->overload_function
#define sqlite3_prepare_v2 sqlite3_api->prepare_v2
#define sqlite3_prepare16_v2 sqlite3_api->prepare16_v2
#define sqlite3_clear_bindings sqlite3_api->clear_bindings
#define sqlite3_bind_zeroblob sqlite3_api->bind_zeroblob
#define sqlite3_blob_bytes sqlite3_api->blob_bytes
#define sqlite3_blob_close sqlite3_api->blob_close
#define sqlite3_blob_open sqlite3_api->blob_open
#define sqlite3_blob_read sqlite3_api->blob_read
#define sqlite3_blob_write sqlite3_api->blob_write
#define sqlite3_create_collation_v2 sqlite3_api->create_collation_v2
#define sqlite3_file_control sqlite3_api->file_control
#define sqlite3_memory_highwater sqlite3_api->memory_highwater
#define sqlite3_memory_used sqlite3_api->memory_used
#define sqlite3_mutex_alloc sqlite3_api->mutex_alloc
#define sqlite3_mutex_enter sqlite3_api->mutex_enter
#define sqlite3_mutex_free sqlite3_api->mutex_free
#define sqlite3_mutex_leave sqlite3_api->mutex_leave
#define sqlite3_mutex_try sqlite3_api->mutex_try
#define sqlite3_open_v2 sqlite3_api->open_v2
#define sqlite3_release_memory sqlite3_api->release_memory
#define sqlite3_result_error_nomem sqlite3_api->result_error_nomem
#define sqlite3_result_error_toobig sqlite3_api->result_error_toobig
#define sqlite3_sleep sqlite3_api->sleep
#define sqlite3_soft_heap_limit sqlite3_api->soft_heap_limit
#define sqlite3_vfs_find sqlite3_api->vfs_find
#define sqlite3_vfs_register sqlite3_api->vfs_register
#define sqlite3_vfs_unregister sqlite3_api->vfs_unregister
#define sqlite3_threadsafe sqlite3_api->xthreadsafe
#define sqlite3_result_zeroblob sqlite3_api->result_zeroblob
#define sqlite3_result_error_code sqlite3_api->result_error_code
#define sqlite3_test_control sqlite3_api->test_control
#define sqlite3_randomness sqlite3_api->randomness
#define sqlite3_context_db_handle sqlite3_api->context_db_handle
#define sqlite3_extended_result_codes sqlite3_api->extended_result_codes
#define sqlite3_limit sqlite3_api->limit
#define sqlite3_next_stmt sqlite3_api->next_stmt
#define sqlite3_sql sqlite3_api->sql
#define sqlite3_status sqlite3_api->status
#define sqlite3_backup_finish sqlite3_api->backup_finish
#define sqlite3_backup_init sqlite3_api->backup_init
#define sqlite3_backup_pagecount sqlite3_api->backup_pagecount
#define sqlite3_backup_remaining sqlite3_api->backup_remaining
#define sqlite3_backup_step sqlite3_api->backup_step
#define sqlite3_compileoption_get sqlite3_api->compileoption_get
#define sqlite3_compileoption_used sqlite3_api->compileoption_used
#define sqlite3_create_function_v2 sqlite3_api->create_function_v2
#define sqlite3_db_config sqlite3_api->db_config
#define sqlite3_db_mutex sqlite3_api->db_mutex
#define sqlite3_db_status sqlite3_api->db_status
#define sqlite3_extended_errcode sqlite3_api->extended_errcode
#define sqlite3_log sqlite3_api->log
#define sqlite3_soft_heap_limit64 sqlite3_api->soft_heap_limit64
#define sqlite3_sourceid sqlite3_api->sourceid
#define sqlite3_stmt_status sqlite3_api->stmt_status
#define sqlite3_strnicmp sqlite3_api->strnicmp
#define sqlite3_unlock_notify sqlite3_api->unlock_notify
#define sqlite3_wal_autocheckpoint sqlite3_api->wal_autocheckpoint
#define sqlite3_wal_checkpoint sqlite3_api->wal_checkpoint
#define sqlite3_wal_hook sqlite3_api->wal_hook
#define sqlite3_blob_reopen sqlite3_api->blob_reopen
#define sqlite3_vtab_config sqlite3_api->vtab_config
#define sqlite3_vtab_on_conflict sqlite3_api->vtab_on_conflict
#endif /* SQLITE_CORE */
#define SQLITE_EXTENSION_INIT1 const sqlite3_api_routines *sqlite3_api = 0;
#define SQLITE_EXTENSION_INIT2(v) sqlite3_api = v;
#endif /* _SQLITE3EXT_H_ */

View file

@ -12,6 +12,7 @@
#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>
@ -360,7 +361,7 @@ int main(int argc, char **argv)
}
#else
if (CONFIG_STRING(&config, "database.type") == "sqlite3") {
std::cerr << "Spectrum2 is not compiled with mysql backend.\n";
std::cerr << "Spectrum2 is not compiled with sqlite3 backend.\n";
return -2;
}
#endif
@ -421,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();

View file

@ -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

View file

@ -40,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
@ -71,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
@ -93,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

View file

@ -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 ${PQXX_LIBRARY} ${PQ_LIBRARY} ${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 ${PQXX_LIBRARY} ${PQ_LIBRARY} ${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

View file

@ -87,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.")
@ -107,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") {
@ -130,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,6 +156,11 @@ bool Config::load(std::istream &ifs, boost::program_options::options_description
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
View 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;
}
}

View file

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

View file

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

View file

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

View file

@ -57,7 +57,14 @@ bool PQXXBackend::connect() {
str += CONFIG_STRING(m_config, "database.database") + " ";
str += "user=" + CONFIG_STRING(m_config, "database.user") + " ";
m_conn = new pqxx::connection(str);
try {
m_conn = new pqxx::connection(str);
}
catch (std::exception& e) {
LOG4CXX_ERROR(logger, e.what());
return false;
}
createDatabase();
@ -99,8 +106,8 @@ bool PQXXBackend::createDatabase() {
"language varchar(25) NOT NULL,"
"encoding varchar(50) NOT NULL default 'utf8',"
"last_login timestamp,"
"vip boolean NOT NULL default '0',"
"online boolean NOT NULL default '0',"
"vip boolean NOT NULL default 'false',"
"online boolean NOT NULL default 'false',"
"PRIMARY KEY (id),"
"UNIQUE (jid)"
");");
@ -118,18 +125,23 @@ bool PQXXBackend::createDatabase() {
"UNIQUE (ver)"
");");
// exec("INSERT INTO db_version (ver) VALUES ('2');");
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::work txn(*m_conn);
pqxx::nontransaction txn(*m_conn);
return exec(txn, query, show_error);
}
bool PQXXBackend::exec(pqxx::work &txn, const std::string &query, bool show_error) {
bool PQXXBackend::exec(pqxx::nontransaction &txn, const std::string &query, bool show_error) {
try {
txn.exec(query);
txn.commit();
@ -147,24 +159,28 @@ void PQXXBackend::setUser(const UserInfo &user) {
if (!CONFIG_STRING(m_config, "database.encryption_key").empty()) {
encrypted = Util::encryptPassword(encrypted, CONFIG_STRING(m_config, "database.encryption_key"));
}
pqxx::work txn(*m_conn);
exec(txn, "UPDATE " + m_prefix + "users SET uin=" + txn.quote(user.uin) + ", password=" + txn.quote(encrypted) + ";"
"INSERT INTO " + m_prefix + "users (jid, uin, password, language, encoding, last_login, vip) VALUES "
"(" + txn.quote(user.jid) + ","
+ txn.quote(user.uin) + ","
+ txn.quote(encrypted) + ","
+ txn.quote(user.language) + ","
+ txn.quote(user.encoding) + ","
+ "NOW(),"
+ txn.quote(user.vip) +")");
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::work txn(*m_conn);
pqxx::nontransaction txn(*m_conn);
pqxx::result r = txn.exec("SELECT id, jid, uin, password, encoding, language, vip FROM " + m_prefix + "users WHERE jid="
+ txn.quote(barejid));
+ quote(txn, barejid));
if (r.size() == 0) {
return false;
@ -188,8 +204,8 @@ bool PQXXBackend::getUser(const std::string &barejid, UserInfo &user) {
void PQXXBackend::setUserOnline(long id, bool online) {
try {
pqxx::work txn(*m_conn);
exec(txn, "UPDATE " + m_prefix + "users SET online=" + txn.quote(online) + ", last_login=NOW() WHERE id=" + txn.quote(id));
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());
@ -198,8 +214,8 @@ void PQXXBackend::setUserOnline(long id, bool online) {
bool PQXXBackend::getOnlineUsers(std::vector<std::string> &users) {
try {
pqxx::work txn(*m_conn);
pqxx::result r = txn.exec("SELECT jid FROM " + m_prefix + "users WHERE online=1");
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>());
@ -214,158 +230,160 @@ bool PQXXBackend::getOnlineUsers(std::vector<std::string> &users) {
}
long PQXXBackend::addBuddy(long userId, const BuddyInfo &buddyInfo) {
// "INSERT INTO " + m_prefix + "buddies (user_id, uin, subscription, groups, nickname, flags) VALUES (?, ?, ?, ?, ?, ?)"
// std::string groups = Util::serializeGroups(buddyInfo.groups);
// *m_addBuddy << userId << buddyInfo.legacyName << buddyInfo.subscription;
// *m_addBuddy << groups;
// *m_addBuddy << buddyInfo.alias << buddyInfo.flags;
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");
// EXEC(m_addBuddy, addBuddy(userId, buddyInfo));
long id = r[0][0].as<long>();
// long id = (long) mysql_insert_id(&m_conn);
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) + ")");
}
// 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()) {
// *m_updateBuddySetting << userId << id << buddyInfo.settings.find("icon_hash")->first << (int) TYPE_STRING << buddyInfo.settings.find("icon_hash")->second.s << buddyInfo.settings.find("icon_hash")->second.s;
// EXEC(m_updateBuddySetting, addBuddy(userId, buddyInfo));
// }
return 0;
return id;
}
catch (std::exception& e) {
LOG4CXX_ERROR(logger, e.what());
return -1;
}
}
void PQXXBackend::updateBuddy(long userId, const BuddyInfo &buddyInfo) {
// "UPDATE " + m_prefix + "buddies SET groups=?, nickname=?, flags=?, subscription=? WHERE user_id=? AND uin=?"
// std::string groups = Util::serializeGroups(buddyInfo.groups);
// *m_updateBuddy << groups;
// *m_updateBuddy << buddyInfo.alias << buddyInfo.flags << buddyInfo.subscription;
// *m_updateBuddy << userId << buddyInfo.legacyName;
// EXEC(m_updateBuddy, updateBuddy(userId, buddyInfo));
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) {
// SELECT id, uin, subscription, nickname, groups, flags FROM " + m_prefix + "buddies WHERE user_id=? ORDER BY id ASC
// *m_getBuddies << id;
try {
pqxx::nontransaction txn(*m_conn);
// "SELECT buddy_id, type, var, value FROM " + m_prefix + "buddies_settings WHERE user_id=? ORDER BY buddy_id ASC"
// *m_getBuddiesSettings << id;
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;
// SettingVariableInfo var;
// long buddy_id = -1;
// std::string key;
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>();
// EXEC(m_getBuddies, getBuddies(id, roster));
// if (!exec_ok)
// return false;
if (!group.empty()) {
b.groups = Util::deserializeGroups(group);
}
// while (m_getBuddies->fetch() == 0) {
// BuddyInfo b;
roster.push_back(b);
}
// std::string group;
// *m_getBuddies >> b.id >> b.legacyName >> b.subscription >> b.alias >> group >> b.flags;
// if (!group.empty()) {
// b.groups = Util::deserializeGroups(group);
// }
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;
// roster.push_back(b);
// }
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;
}
// EXEC(m_getBuddiesSettings, getBuddies(id, roster));
// if (!exec_ok)
// return false;
BOOST_FOREACH(BuddyInfo &b, roster) {
if (buddy_id == b.id) {
b.settings[key] = var;
break;
}
}
}
// BOOST_FOREACH(BuddyInfo &b, roster) {
// if (buddy_id == b.id) {
//// std::cout << "Adding buddy info setting " << key << "\n";
// b.settings[key] = var;
// buddy_id = -1;
// }
return true;
}
catch (std::exception& e) {
LOG4CXX_ERROR(logger, e.what());
}
// while(buddy_id == -1 && m_getBuddiesSettings->fetch() == 0) {
// std::string val;
// *m_getBuddiesSettings >> buddy_id >> var.type >> key >> val;
// switch (var.type) {
// case TYPE_BOOLEAN:
// var.b = atoi(val.c_str());
// break;
// case TYPE_STRING:
// var.s = val;
// break;
// default:
// if (buddy_id == b.id) {
// buddy_id = -1;
// }
// continue;
// break;
// }
// if (buddy_id == b.id) {
//// std::cout << "Adding buddy info setting " << key << "=" << val << "\n";
// b.settings[key] = var;
// buddy_id = -1;
// }
// }
// }
// while(m_getBuddiesSettings->fetch() == 0) {
// // TODO: probably remove those settings, because there's no buddy for them.
// // It should not happend, but one never know...
// }
return true;
return false;
}
bool PQXXBackend::removeUser(long id) {
// *m_removeUser << (int) id;
// EXEC(m_removeUser, removeUser(id));
// if (!exec_ok)
// return false;
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));
// *m_removeUserSettings << (int) id;
// EXEC(m_removeUserSettings, removeUser(id));
// if (!exec_ok)
// return false;
// *m_removeUserBuddies << (int) id;
// EXEC(m_removeUserBuddies, removeUser(id));
// if (!exec_ok)
// return false;
// *m_removeUserBuddiesSettings << (int) id;
// EXEC(m_removeUserBuddiesSettings, removeUser(id));
// if (!exec_ok)
// return false;
return true;
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) {
//// "SELECT type, value FROM " + m_prefix + "users_settings WHERE user_id=? AND var=?"
// *m_getUserSetting << id << variable;
// EXEC(m_getUserSetting, getUserSetting(id, variable, type, value));
// if (m_getUserSetting->fetch() != 0) {
//// "INSERT INTO " + m_prefix + "users_settings (user_id, var, type, value) VALUES (?,?,?,?)"
// *m_setUserSetting << id << variable << type << value;
// EXEC(m_setUserSetting, getUserSetting(id, variable, type, value));
// }
// else {
// *m_getUserSetting >> type >> value;
// }
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) {
//// "UPDATE " + m_prefix + "users_settings SET value=? WHERE user_id=? AND var=?"
// *m_updateUserSetting << value << id << variable;
// EXEC(m_updateUserSetting, updateUserSetting(id, variable, 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("START TRANSACTION;");
exec("BEGIN;");
}
void PQXXBackend::commitTransaction() {
// exec("COMMIT;");
exec("COMMIT;");
}
}

View file

@ -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) {

View file

@ -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) {

View file

@ -20,6 +20,7 @@
#include "transport/transport.h"
#include <boost/bind.hpp>
#include <boost/smart_ptr/make_shared.hpp>
#include <boost/algorithm/string/predicate.hpp>
#include "transport/storagebackend.h"
#include "transport/factory.h"
@ -27,15 +28,23 @@
#include "discoinforesponder.h"
#include "discoitemsresponder.h"
#include "storageparser.h"
#include "Swiften/TLS/OpenSSL/OpenSSLServerContext.h"
#ifdef _WIN32
#include <Swiften/TLS/CAPICertificate.h>
#include "Swiften/TLS/Schannel/SchannelServerContext.h"
#include "Swiften/TLS/Schannel/SchannelServerContextFactory.h"
#else
#include "Swiften/TLS/PKCS12Certificate.h"
#include "Swiften/TLS/OpenSSL/OpenSSLServerContext.h"
#include "Swiften/TLS/OpenSSL/OpenSSLServerContextFactory.h"
#endif
#include "Swiften/Parser/PayloadParsers/AttentionParser.h"
#include "Swiften/Serializer/PayloadSerializers/AttentionSerializer.h"
#include "Swiften/Parser/PayloadParsers/XHTMLIMParser.h"
#include "Swiften/Serializer/PayloadSerializers/XHTMLIMSerializer.h"
#include "Swiften/Parser/PayloadParsers/StatsParser.h"
#include "Swiften/Serializer/PayloadSerializers/StatsSerializer.h"
#include "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"
@ -79,8 +88,14 @@ Component::Component(Swift::EventLoop *loop, Swift::NetworkFactories *factories,
if (!CONFIG_STRING(m_config, "service.cert").empty()) {
LOG4CXX_INFO(logger, "Using PKCS#12 certificate " << CONFIG_STRING(m_config, "service.cert"));
LOG4CXX_INFO(logger, "SSLv23_server_method used.");
#ifdef _WIN32
TLSServerContextFactory *f = new SchannelServerContextFactory();
m_server->addTLSEncryption(f, boost::make_shared<CAPICertificate>(CONFIG_STRING(m_config, "service.cert")));
#else
TLSServerContextFactory *f = new OpenSSLServerContextFactory();
m_server->addTLSEncryption(f, PKCS12Certificate(CONFIG_STRING(m_config, "service.cert"), createSafeByteArray(CONFIG_STRING(m_config, "service.cert_password"))));
m_server->addTLSEncryption(f, boost::make_shared<PKCS12Certificate>(CONFIG_STRING(m_config, "service.cert"), createSafeByteArray(CONFIG_STRING(m_config, "service.cert_password"))));
#endif
}
else {
LOG4CXX_WARN(logger, "No PKCS#12 certificate used. TLS is disabled.");
@ -95,6 +110,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());
@ -102,6 +118,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));
@ -121,6 +138,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());
@ -128,6 +146,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();

View file

@ -213,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 {
@ -224,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() : "";

View file

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

View file

@ -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) {
@ -290,6 +308,13 @@ bool UserRegistration::handleSetRequest(const Swift::JID& from, const Swift::JID
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;
}
@ -298,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;
}
@ -327,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;