From ca9ffed691fccb5fb13d86e9ca0d791f271bd325 Mon Sep 17 00:00:00 2001 From: HanzZ Date: Thu, 27 Oct 2011 16:54:08 +0200 Subject: [PATCH 01/48] Fixed bad rename --- src/usermanager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/usermanager.cpp b/src/usermanager.cpp index 6110c45e..a52690aa 100644 --- a/src/usermanager.cpp +++ b/src/usermanager.cpp @@ -149,7 +149,7 @@ void UserManager::handlePresence(Swift::Presence::ref presence) { // Create user class if it's not there if (!user) { // Admin user is not legacy network user, so do not create User class instance for him - if (CONFIG_STRING(m_component->getConfig(), "service.admin_username") == presence->getFrom().getNode()) { + if (CONFIG_STRING(m_component->getConfig(), "service.admin_jid") == presence->getFrom().toBare().toString()) { return; } From 0cd6ed850207c31403771faedb5fe0705840c959 Mon Sep 17 00:00:00 2001 From: HanzZ Date: Thu, 27 Oct 2011 20:04:46 +0200 Subject: [PATCH 02/48] more tests --- src/tests/rostermanager.cpp | 34 +++++++++++++++++++++++++++------- 1 file changed, 27 insertions(+), 7 deletions(-) diff --git a/src/tests/rostermanager.cpp b/src/tests/rostermanager.cpp index 85238a97..c9f3bf35 100644 --- a/src/tests/rostermanager.cpp +++ b/src/tests/rostermanager.cpp @@ -24,6 +24,7 @@ class RosterManagerTest : public CPPUNIT_NS :: TestFixture, public BasicTest { CPPUNIT_TEST_SUITE(RosterManagerTest); CPPUNIT_TEST(setBuddy); CPPUNIT_TEST(sendCurrentPresences); + CPPUNIT_TEST(sendCurrentPresence); CPPUNIT_TEST_SUITE_END(); public: @@ -132,13 +133,32 @@ class RosterManagerTest : public CPPUNIT_NS :: TestFixture, public BasicTest { user->getRosterManager()->sendCurrentPresences("user@localhost/resource"); CPPUNIT_ASSERT_EQUAL(2, (int) received.size()); -// CPPUNIT_ASSERT(dynamic_cast(getStanza(received[2]))); -// CPPUNIT_ASSERT_EQUAL(Swift::StatusShow::Away, dynamic_cast(getStanza(received[2]))->getShow()); -// CPPUNIT_ASSERT_EQUAL(std::string("status1"), dynamic_cast(getStanza(received[2]))->getStatus()); -// -// CPPUNIT_ASSERT(dynamic_cast(getStanza(received[3]))); -// CPPUNIT_ASSERT_EQUAL(Swift::StatusShow::Away, dynamic_cast(getStanza(received[3]))->getShow()); -// CPPUNIT_ASSERT_EQUAL(std::string("status2"), dynamic_cast(getStanza(received[3]))->getStatus()); + + for (int i = 0; i < 2; i++) { + CPPUNIT_ASSERT(dynamic_cast(getStanza(received[i]))); + CPPUNIT_ASSERT_EQUAL(Swift::StatusShow::Away, dynamic_cast(getStanza(received[i]))->getShow()); + CPPUNIT_ASSERT_EQUAL(std::string("user@localhost/resource"), dynamic_cast(getStanza(received[i]))->getTo().toString()); + } + } + + void sendCurrentPresence() { + setBuddy(); + received.clear(); + + User *user = userManager->getUser("user@localhost"); + user->getRosterManager()->sendCurrentPresence("buddy1@localhost", "user@localhost/resource"); + + CPPUNIT_ASSERT_EQUAL(1, (int) received.size()); + CPPUNIT_ASSERT(dynamic_cast(getStanza(received[0]))); + CPPUNIT_ASSERT_EQUAL(Swift::StatusShow::Away, dynamic_cast(getStanza(received[0]))->getShow()); + CPPUNIT_ASSERT_EQUAL(std::string("user@localhost/resource"), dynamic_cast(getStanza(received[0]))->getTo().toString()); + + received.clear(); + user->getRosterManager()->sendCurrentPresence("buddy_unknown@localhost", "user@localhost/resource"); + CPPUNIT_ASSERT_EQUAL(1, (int) received.size()); + CPPUNIT_ASSERT(dynamic_cast(getStanza(received[0]))); + CPPUNIT_ASSERT_EQUAL(Swift::Presence::Unavailable, dynamic_cast(getStanza(received[0]))->getType()); + CPPUNIT_ASSERT_EQUAL(std::string("user@localhost/resource"), dynamic_cast(getStanza(received[0]))->getTo().toString()); } void disconnectUser() { From 347ed286184677266220fc39a0c5dbf92c7c1594 Mon Sep 17 00:00:00 2001 From: HanzZ Date: Fri, 28 Oct 2011 08:55:47 +0200 Subject: [PATCH 03/48] Working variable --- backends/libpurple/main.cpp | 19 +++++++++++++++++++ src/config.cpp | 14 ++++++++++++-- 2 files changed, 31 insertions(+), 2 deletions(-) diff --git a/backends/libpurple/main.cpp b/backends/libpurple/main.cpp index 51943171..e9805f51 100644 --- a/backends/libpurple/main.cpp +++ b/backends/libpurple/main.cpp @@ -69,6 +69,20 @@ class SpectrumNetworkPlugin; GKeyFile *keyfile; SpectrumNetworkPlugin *np; +std::string replaceAll( + std::string result, + const std::string& replaceWhat, + const std::string& replaceWithWhat) +{ + while(1) + { + const int pos = result.find(replaceWhat); + if (pos==-1) break; + result.replace(pos,replaceWhat.size(),replaceWithWhat); + } + return result; +} + static std::string KEYFILE_STRING(const std::string &cat, const std::string &key, const std::string &def = "") { gchar *str = g_key_file_get_string(keyfile, cat.c_str(), key.c_str(), 0); if (!str) { @@ -83,6 +97,11 @@ static std::string KEYFILE_STRING(const std::string &cat, const std::string &key ret.erase(ret.end() - 1); } } + + if (ret.find("$jid") != std::string::npos) { + std::string jid = KEYFILE_STRING("service", "jid"); + ret = replaceAll(ret, "$jid", jid); + } return ret; } diff --git a/src/config.cpp b/src/config.cpp index 05473249..88e6e2c2 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -60,8 +60,8 @@ bool Config::load(std::istream &ifs, boost::program_options::options_description ("service.group", value()->default_value(""), "The name of group Spectrum runs as.") ("service.backend", value()->default_value("libpurple_backend"), "Backend") ("service.protocol", value()->default_value(""), "Protocol") - ("service.pidfile", value()->default_value("/var/run/spectrum2/spectrum2.pid"), "Full path to pid file") - ("service.working_dir", value()->default_value("/var/lib/spectrum2"), "Working dir") + ("service.pidfile", value()->default_value("/var/run/spectrum2/$jid.pid"), "Full path to pid file") + ("service.working_dir", value()->default_value("/var/lib/spectrum2/$jid"), "Working dir") ("service.allowed_servers", value()->default_value(""), "Only users from these servers can connect") ("service.server_mode", value()->default_value(false), "True if Spectrum should behave as server") ("service.users_per_backend", value()->default_value(100), "Number of users per one legacy network backend") @@ -101,10 +101,20 @@ bool Config::load(std::istream &ifs, boost::program_options::options_description parsed_options parsed = parse_config_file(ifs, opts, true); + std::string jid = ""; BOOST_FOREACH(option opt, parsed.options) { + if (opt.string_key == "service.jid") { + jid = opt.value[0]; + } + } + + BOOST_FOREACH(option &opt, parsed.options) { if (opt.unregistered) { m_unregistered[opt.string_key] = opt.value[0]; } + else if (opt.value[0].find("$jid") != std::string::npos) { + boost::replace_all(opt.value[0], "$jid", jid); + } } store(parsed, m_variables); From 0466b5b31207748563149f4991dfc8fd4399336a Mon Sep 17 00:00:00 2001 From: HanzZ Date: Sat, 29 Oct 2011 10:25:04 +0200 Subject: [PATCH 04/48] Fixed service jid parsing = fixed logging --- backends/libpurple/main.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/backends/libpurple/main.cpp b/backends/libpurple/main.cpp index e9805f51..89cc433a 100644 --- a/backends/libpurple/main.cpp +++ b/backends/libpurple/main.cpp @@ -1871,7 +1871,7 @@ int main(int argc, char **argv) { p.load(istream); LogString pid, jid; log4cxx::helpers::Transcoder::decode(stringOf(getpid()), pid); - log4cxx::helpers::Transcoder::decode(KEYFILE_STRING("service", "service.jid"), jid); + log4cxx::helpers::Transcoder::decode(KEYFILE_STRING("service", "jid"), jid); #ifdef _MSC_VER p.setProperty(L"pid", pid); p.setProperty(L"jid", jid); From 081b8258b26a59e3ad8de7e6807052e83a3ded3c Mon Sep 17 00:00:00 2001 From: HanzZ Date: Sat, 29 Oct 2011 19:57:56 +0200 Subject: [PATCH 05/48] Added ConnectionError enum to protocol.proto --- include/transport/protocol.proto | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/include/transport/protocol.proto b/include/transport/protocol.proto index 8370e617..336915a0 100644 --- a/include/transport/protocol.proto +++ b/include/transport/protocol.proto @@ -1,5 +1,25 @@ package pbnetwork; +enum ConnectionError { + CONNECTION_ERROR_NETWORK_ERROR = 0; + CONNECTION_ERROR_INVALID_USERNAME = 1; + CONNECTION_ERROR_AUTHENTICATION_FAILED = 2; + CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE = 3; + CONNECTION_ERROR_NO_SSL_SUPPORT = 4; + CONNECTION_ERROR_ENCRYPTION_ERROR = 5; + CONNECTION_ERROR_NAME_IN_USE = 6; + CONNECTION_ERROR_INVALID_SETTINGS = 7; + CONNECTION_ERROR_CERT_NOT_PROVIDED = 8; + CONNECTION_ERROR_CERT_UNTRUSTED = 9; + CONNECTION_ERROR_CERT_EXPIRED = 10; + CONNECTION_ERROR_CERT_NOT_ACTIVATED = 11; + CONNECTION_ERROR_CERT_HOSTNAME_MISMATCH = 12; + CONNECTION_ERROR_CERT_FINGERPRINT_MISMATCH = 13; + CONNECTION_ERROR_CERT_SELF_SIGNED = 14; + CONNECTION_ERROR_CERT_OTHER_ERROR = 15; + CONNECTION_ERROR_OTHER_ERROR = 16; +} + enum StatusType { STATUS_ONLINE = 0; STATUS_AWAY = 1; @@ -135,4 +155,4 @@ message WrapperMessage { required Type type = 1; optional bytes payload = 2; } -; \ No newline at end of file +; From 06ea1ee6642dc34285650c28115cda63c172d250 Mon Sep 17 00:00:00 2001 From: HanzZ Date: Sun, 30 Oct 2011 15:53:30 +0100 Subject: [PATCH 06/48] Config file tweaks --- spectrum/src/CMakeLists.txt | 2 +- spectrum/src/sample2.cfg | 11 ++++++----- 2 files changed, 7 insertions(+), 6 deletions(-) diff --git a/spectrum/src/CMakeLists.txt b/spectrum/src/CMakeLists.txt index 5a78327f..6c20b757 100644 --- a/spectrum/src/CMakeLists.txt +++ b/spectrum/src/CMakeLists.txt @@ -13,7 +13,7 @@ INSTALL(TARGETS spectrum2 RUNTIME DESTINATION bin) INSTALL(FILES sample2.cfg RENAME spectrum.cfg.example - DESTINATION /etc/spectrum2 + DESTINATION /etc/spectrum2/transports ) INSTALL(FILES diff --git a/spectrum/src/sample2.cfg b/spectrum/src/sample2.cfg index ca499f66..0482e4f8 100644 --- a/spectrum/src/sample2.cfg +++ b/spectrum/src/sample2.cfg @@ -36,8 +36,8 @@ backend_port=10001 users_per_backend=10 # Full path to backend binary. -backend=/usr/bin/spectrum_libpurple_backend -#backend=/usr/bin/spectrum_libircclient-qt_backend +backend=/usr/bin/spectrum2_libpurple_backend +#backend=/usr/bin/spectrum2_libircclient-qt_backend # Libpurple protocol-id for spectrum_libpurple_backend protocol=prpl-jabber @@ -62,18 +62,19 @@ type=xmpp [logging] # log4cxx/log4j logging configuration file in ini format used for main spectrum2 instance. -config = /etc/spectrum2/logging.cfg +config = /etc/spectrum2/logging.cfg # log4cxx/log4j logging configuration file in ini format used for backends. -backend_config = /etc/spectrum2/backend-logging.cfg # log4cxx/log4j logging configuration file for backends +backend_config = /etc/spectrum2/backend-logging.cfg [database] # Database backend type # "sqlite3", "mysql" or "none" without database backend -type = none +type = none # For SQLite3: Full path to database # For MySQL: name of database +# database = /var/lib/spectrum2/$jid/database.sql database = jabber_transport # Server. From 6d64a1858b5d34878dec5635c8b7bcd5e71c9483 Mon Sep 17 00:00:00 2001 From: HanzZ Date: Tue, 1 Nov 2011 22:13:35 +0100 Subject: [PATCH 07/48] Dummy encryption key implementation + logging glib errors in main log --- backends/libpurple/main.cpp | 71 +++++++++++++++++++++++++++++++++++-- include/transport/util.h | 5 +++ src/config.cpp | 1 + src/mysqlbackend.cpp | 11 +++++- src/util.cpp | 28 +++++++++++++++ 5 files changed, 113 insertions(+), 3 deletions(-) diff --git a/backends/libpurple/main.cpp b/backends/libpurple/main.cpp index 89cc433a..2b0b0491 100644 --- a/backends/libpurple/main.cpp +++ b/backends/libpurple/main.cpp @@ -1569,11 +1569,78 @@ static void transport_core_ui_init(void) // #endif } +/***** Core Ui Ops *****/ +static void +spectrum_glib_log_handler(const gchar *domain, + GLogLevelFlags flags, + const gchar *message, + gpointer user_data) +{ + const char *level; + char *new_msg = NULL; + char *new_domain = NULL; + + if ((flags & G_LOG_LEVEL_ERROR) == G_LOG_LEVEL_ERROR) + level = "ERROR"; + else if ((flags & G_LOG_LEVEL_CRITICAL) == G_LOG_LEVEL_CRITICAL) + level = "CRITICAL"; + else if ((flags & G_LOG_LEVEL_WARNING) == G_LOG_LEVEL_WARNING) + level = "WARNING"; + else if ((flags & G_LOG_LEVEL_MESSAGE) == G_LOG_LEVEL_MESSAGE) + level = "MESSAGE"; + else if ((flags & G_LOG_LEVEL_INFO) == G_LOG_LEVEL_INFO) + level = "INFO"; + else if ((flags & G_LOG_LEVEL_DEBUG) == G_LOG_LEVEL_DEBUG) + level = "DEBUG"; + else { + LOG4CXX_ERROR(logger, "Unknown glib logging level in " << (guint)flags); + level = "UNKNOWN"; /* This will never happen. */ + } + + if (message != NULL) + new_msg = purple_utf8_try_convert(message); + + if (domain != NULL) + new_domain = purple_utf8_try_convert(domain); + + if (new_msg != NULL) { + std::string area("glib"); + area.push_back('/'); + area.append(level); + + std::string message(new_domain ? new_domain : "g_log"); + message.push_back(' '); + message.append(new_msg); + + LOG4CXX_ERROR(logger, message); + g_free(new_msg); + } + + g_free(new_domain); +} + +static void +debug_init(void) +{ +#define REGISTER_G_LOG_HANDLER(name) \ + g_log_set_handler((name), \ + (GLogLevelFlags)(G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL \ + | G_LOG_FLAG_RECURSION), \ + spectrum_glib_log_handler, NULL) + + REGISTER_G_LOG_HANDLER(NULL); + REGISTER_G_LOG_HANDLER("GLib"); + REGISTER_G_LOG_HANDLER("GModule"); + REGISTER_G_LOG_HANDLER("GLib-GObject"); + REGISTER_G_LOG_HANDLER("GThread"); + +#undef REGISTER_G_LOD_HANDLER +} + static PurpleCoreUiOps coreUiOps = { NULL, -// debug_init, - NULL, + debug_init, transport_core_ui_init, NULL, spectrum_ui_get_info, diff --git a/include/transport/util.h b/include/transport/util.h index e5fc086f..79d52a47 100644 --- a/include/transport/util.h +++ b/include/transport/util.h @@ -24,6 +24,7 @@ #include #include #include +#include "Swiften/StringCodecs/Base64.h" namespace Transport { @@ -31,6 +32,10 @@ namespace Util { void removeEverythingOlderThan(const std::vector &dirs, time_t t); +std::string encryptPassword(const std::string &password, const std::string &key); + +std::string decryptPassword(std::string &encrypted, const std::string &key); + } } diff --git a/src/config.cpp b/src/config.cpp index 88e6e2c2..d0307788 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -92,6 +92,7 @@ bool Config::load(std::istream &ifs, boost::program_options::options_description ("database.password", value()->default_value(""), "Database Password.") ("database.port", value()->default_value(0), "Database port.") ("database.prefix", value()->default_value(""), "Prefix of tables in database") + ("database.encryption_key", value()->default_value(""), "Encryption key.") ("logging.config", value()->default_value(""), "Path to log4cxx config file which is used for Spectrum 2 instance") ("logging.backend_config", value()->default_value(""), "Path to log4cxx config file which is used for backends") ("backend.default_avatar", value()->default_value(""), "Full path to default avatar") diff --git a/src/mysqlbackend.cpp b/src/mysqlbackend.cpp index a10d89ec..1c45b738 100644 --- a/src/mysqlbackend.cpp +++ b/src/mysqlbackend.cpp @@ -21,6 +21,7 @@ #ifdef WITH_MYSQL #include "transport/mysqlbackend.h" +#include "transport/util.h" #include #include "log4cxx/logger.h" @@ -409,7 +410,11 @@ bool MySQLBackend::exec(const std::string &query) { } void MySQLBackend::setUser(const UserInfo &user) { - *m_setUser << user.jid << user.uin << user.password << user.language << user.encoding << user.vip << user.password; + std::string encrypted = user.password; + if (!CONFIG_STRING(m_config, "database.encryption_key").empty()) { + encrypted = Util::decryptPassword(encrypted, CONFIG_STRING(m_config, "database.encryption_key")); + } + *m_setUser << user.jid << user.uin << encrypted << user.language << user.encoding << user.vip << user.password; EXEC(m_setUser, setUser(user)); } @@ -423,6 +428,10 @@ bool MySQLBackend::getUser(const std::string &barejid, UserInfo &user) { while (m_getUser->fetch() == 0) { ret = true; *m_getUser >> user.id >> user.jid >> user.uin >> user.password >> user.encoding >> user.language >> user.vip; + + if (!CONFIG_STRING(m_config, "database.encryption_key").empty()) { + user.password = Util::decryptPassword(user.password, CONFIG_STRING(m_config, "database.encryption_key")); + } } return ret; diff --git a/src/util.cpp b/src/util.cpp index 322d06ad..0a5f3a04 100644 --- a/src/util.cpp +++ b/src/util.cpp @@ -75,6 +75,34 @@ void removeEverythingOlderThan(const std::vector &dirs, time_t t) { } } +std::string encryptPassword(const std::string &password, const std::string &key) { + std::string encrypted; + encrypted.resize(password.size()); + for (int i = 0; i < password.size(); i++) { + char c = password[i]; + char keychar = key[i % key.size()]; + c += keychar; + encrypted[i] = c; + } + + encrypted = Swift::Base64::encode(Swift::createByteArray(encrypted)); + return encrypted; +} + +std::string decryptPassword(std::string &encrypted, const std::string &key) { + encrypted = Swift::byteArrayToString(Swift::Base64::decode(encrypted)); + std::string password; + password.resize(encrypted.size()); + for (int i = 0; i < encrypted.size(); i++) { + char c = encrypted[i]; + char keychar = key[i % key.size()]; + c -= keychar; + password[i] = c; + } + + return password; +} + } } From 1fefc484a66fa5e385500845c60f0bd07af215b0 Mon Sep 17 00:00:00 2001 From: HanzZ Date: Tue, 1 Nov 2011 22:53:10 +0100 Subject: [PATCH 08/48] spectrum2_manager does not depend on libtransport --- spectrum_manager/src/CMakeLists.txt | 4 ++-- spectrum_manager/src/main.cpp | 8 ++------ 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/spectrum_manager/src/CMakeLists.txt b/spectrum_manager/src/CMakeLists.txt index 56543501..9bfa2090 100644 --- a/spectrum_manager/src/CMakeLists.txt +++ b/spectrum_manager/src/CMakeLists.txt @@ -1,9 +1,9 @@ cmake_minimum_required(VERSION 2.6) FILE(GLOB SRC *.cpp) -ADD_EXECUTABLE(spectrum2_manager ${SRC}) +ADD_EXECUTABLE(spectrum2_manager ${SRC} ../../src/config.cpp) -target_link_libraries(spectrum2_manager transport) +target_link_libraries(spectrum2_manager ${Boost_LIBRARIES} ${SWIFTEN_LIBRARY}) INSTALL(TARGETS spectrum2_manager RUNTIME DESTINATION bin) diff --git a/spectrum_manager/src/main.cpp b/spectrum_manager/src/main.cpp index 5353bf59..efa5038e 100644 --- a/spectrum_manager/src/main.cpp +++ b/spectrum_manager/src/main.cpp @@ -1,10 +1,6 @@ #include "managerconfig.h" -#include "transport/transport.h" -#include "transport/usermanager.h" -#include "transport/logger.h" -#include "transport/sqlite3backend.h" -#include "transport/userregistration.h" -#include "transport/networkpluginserver.h" +#include "transport/config.h" +#include "Swiften/Swiften.h" #include "Swiften/EventLoop/SimpleEventLoop.h" #include From cc9306d68aa610fc63af2d578c574a711e739918 Mon Sep 17 00:00:00 2001 From: HanzZ Date: Wed, 2 Nov 2011 00:17:54 +0100 Subject: [PATCH 09/48] Don't link against boost libraries and swiften libraries in the same time --- spectrum_manager/src/CMakeLists.txt | 2 +- src/CMakeLists.txt | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/spectrum_manager/src/CMakeLists.txt b/spectrum_manager/src/CMakeLists.txt index 9bfa2090..5024e70c 100644 --- a/spectrum_manager/src/CMakeLists.txt +++ b/spectrum_manager/src/CMakeLists.txt @@ -3,7 +3,7 @@ FILE(GLOB SRC *.cpp) ADD_EXECUTABLE(spectrum2_manager ${SRC} ../../src/config.cpp) -target_link_libraries(spectrum2_manager ${Boost_LIBRARIES} ${SWIFTEN_LIBRARY}) +target_link_libraries(spectrum2_manager ${SWIFTEN_LIBRARY}) INSTALL(TARGETS spectrum2_manager RUNTIME DESTINATION bin) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 346a4294..7a258e7a 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -35,9 +35,9 @@ if (CMAKE_COMPILER_IS_GNUCXX) endif() if (WIN32) - TARGET_LINK_LIBRARIES(transport ${Boost_LIBRARIES} ${SQLITE3_LIBRARIES} ${MYSQL_LIBRARIES} ${SWIFTEN_LIBRARY} ${PROTOBUF_LIBRARIES} ${LOG4CXX_LIBRARIES}) + TARGET_LINK_LIBRARIES(transport ${SQLITE3_LIBRARIES} ${MYSQL_LIBRARIES} ${SWIFTEN_LIBRARY} ${PROTOBUF_LIBRARIES} ${LOG4CXX_LIBRARIES}) else (WIN32) - TARGET_LINK_LIBRARIES(transport ${Boost_LIBRARIES} ${SQLITE3_LIBRARIES} ${MYSQL_LIBRARIES} ${SWIFTEN_LIBRARY} ${PROTOBUF_LIBRARIES} ${LOG4CXX_LIBRARIES} ${POPT_LIBRARY}) + TARGET_LINK_LIBRARIES(transport ${SQLITE3_LIBRARIES} ${MYSQL_LIBRARIES} ${SWIFTEN_LIBRARY} ${PROTOBUF_LIBRARIES} ${LOG4CXX_LIBRARIES} ${POPT_LIBRARY}) endif(WIN32) SET_TARGET_PROPERTIES(transport PROPERTIES From f6b01c4f4d6e9d9f9f4ef304d3bcd41303f999a4 Mon Sep 17 00:00:00 2001 From: Jan Kaluza Date: Wed, 2 Nov 2011 13:12:32 +0100 Subject: [PATCH 10/48] util.cpp tests --- src/tests/util.cpp | 45 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) create mode 100644 src/tests/util.cpp diff --git a/src/tests/util.cpp b/src/tests/util.cpp new file mode 100644 index 00000000..f5c66819 --- /dev/null +++ b/src/tests/util.cpp @@ -0,0 +1,45 @@ +#include "transport/userregistry.h" +#include "transport/config.h" +#include "transport/storagebackend.h" +#include "transport/user.h" +#include "transport/transport.h" +#include "transport/conversation.h" +#include "transport/usermanager.h" +#include "transport/localbuddy.h" +#include +#include +#include +#include +#include +#include +#include +#include "Swiften/Server/ServerStanzaChannel.h" +#include "Swiften/Server/ServerFromClientSession.h" +#include "Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.h" +#include "basictest.h" + +#include "transport/util.h" + +using namespace Transport; + +class UtilTest : public CPPUNIT_NS :: TestFixture{ + CPPUNIT_TEST_SUITE(UtilTest); + CPPUNIT_TEST(encryptDecryptPassword); + CPPUNIT_TEST_SUITE_END(); + + public: + void setUp (void) { + } + + void tearDown (void) { + + } + + void encryptDecryptPassword() { + std::string encrypted = Util::encryptPassword("password", "key"); + CPPUNIT_ASSERT_EQUAL(std::string("password"), Util::decryptPassword(encrypted, "key")); + } + +}; + +CPPUNIT_TEST_SUITE_REGISTRATION (UtilTest); From 5482733ed425294bd5fbe5be2962ab4b1586dde0 Mon Sep 17 00:00:00 2001 From: HanzZ Date: Wed, 2 Nov 2011 20:02:00 +0100 Subject: [PATCH 11/48] Proper password encrypting --- backends/libpurple/main.cpp | 3 +++ src/mysqlbackend.cpp | 2 +- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/backends/libpurple/main.cpp b/backends/libpurple/main.cpp index 2b0b0491..4e2c8240 100644 --- a/backends/libpurple/main.cpp +++ b/backends/libpurple/main.cpp @@ -589,11 +589,13 @@ class SpectrumNetworkPlugin : public NetworkPlugin { getProtocolAndName(legacyName, name, protocol); if (password.empty()) { + LOG4CXX_INFO(logger, name.c_str() << ": Empty password"); np->handleDisconnected(user, 0, "Empty password."); return; } if (!purple_find_prpl(protocol.c_str())) { + LOG4CXX_INFO(logger, name.c_str() << ": Invalid protocol '" << protocol << "'"); np->handleDisconnected(user, 0, "Invalid protocol " + protocol); return; } @@ -1836,6 +1838,7 @@ static int create_socket(char *host, int portno) { } static void transportDataReceived(gpointer data, gint source, PurpleInputCondition cond) { + std::cout << "RECV\n"; if (cond & PURPLE_INPUT_READ) { char buffer[65535]; char *ptr = buffer; diff --git a/src/mysqlbackend.cpp b/src/mysqlbackend.cpp index 1c45b738..60ac8b47 100644 --- a/src/mysqlbackend.cpp +++ b/src/mysqlbackend.cpp @@ -412,7 +412,7 @@ bool MySQLBackend::exec(const std::string &query) { void MySQLBackend::setUser(const UserInfo &user) { std::string encrypted = user.password; if (!CONFIG_STRING(m_config, "database.encryption_key").empty()) { - encrypted = Util::decryptPassword(encrypted, CONFIG_STRING(m_config, "database.encryption_key")); + encrypted = Util::encryptPassword(encrypted, CONFIG_STRING(m_config, "database.encryption_key")); } *m_setUser << user.jid << user.uin << encrypted << user.language << user.encoding << user.vip << user.password; EXEC(m_setUser, setUser(user)); From 6da474b615115240843fa2672d8a026182d485dc Mon Sep 17 00:00:00 2001 From: HanzZ Date: Thu, 3 Nov 2011 00:47:01 +0100 Subject: [PATCH 12/48] remove RECV --- backends/libpurple/main.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/backends/libpurple/main.cpp b/backends/libpurple/main.cpp index 4e2c8240..a76454c1 100644 --- a/backends/libpurple/main.cpp +++ b/backends/libpurple/main.cpp @@ -1838,7 +1838,6 @@ static int create_socket(char *host, int portno) { } static void transportDataReceived(gpointer data, gint source, PurpleInputCondition cond) { - std::cout << "RECV\n"; if (cond & PURPLE_INPUT_READ) { char buffer[65535]; char *ptr = buffer; From fe654d1ee63bd528a32e3b0c2fb231aebf6e96df Mon Sep 17 00:00:00 2001 From: HanzZ Date: Thu, 3 Nov 2011 15:38:56 +0100 Subject: [PATCH 13/48] remove more stdouts --- src/networkpluginserver.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/networkpluginserver.cpp b/src/networkpluginserver.cpp index 4da583eb..cdd4f9f0 100644 --- a/src/networkpluginserver.cpp +++ b/src/networkpluginserver.cpp @@ -1036,7 +1036,6 @@ void NetworkPluginServer::handleRoomLeft(User *user, const std::string &r) { } void NetworkPluginServer::handleUserDestroyed(User *user) { - std::cout << "HANDLE_DESTROYED\n"; m_waitingUsers.remove(user); UserInfo userInfo = user->getUserInfo(); From 02daddc0ce328f7fc77595ec68c349af8b15a0d3 Mon Sep 17 00:00:00 2001 From: HanzZ Date: Thu, 3 Nov 2011 20:44:33 +0100 Subject: [PATCH 14/48] Fixed some bugs in config parsing + added vhosts.vhost variable --- include/transport/config.h | 6 ++-- spectrum/src/main.cpp | 4 ++- spectrum_manager/src/main.cpp | 60 +++++++++++++++++++++++++---------- src/config.cpp | 51 +++++++++++++++++++++++++---- 4 files changed, 94 insertions(+), 27 deletions(-) diff --git a/include/transport/config.h b/include/transport/config.h index c0ad64e5..d6900d30 100644 --- a/include/transport/config.h +++ b/include/transport/config.h @@ -60,9 +60,9 @@ class Config { /// the parser using opts parameter. /// \param configfile path to config file /// \param opts extra options which will be recognized by a parser - bool load(const std::string &configfile, boost::program_options::options_description &opts); + bool load(const std::string &configfile, boost::program_options::options_description &opts, const std::string &jid = ""); - bool load(std::istream &ifs, boost::program_options::options_description &opts); + bool load(std::istream &ifs, boost::program_options::options_description &opts, const std::string &jid = ""); bool load(std::istream &ifs); @@ -71,7 +71,7 @@ class Config { /// This function loads only config variables needed by libtransport. /// \see load(const std::string &, boost::program_options::options_description &) /// \param configfile path to config file - bool load(const std::string &configfile); + bool load(const std::string &configfile, const std::string &jid = ""); bool reload(); diff --git a/spectrum/src/main.cpp b/spectrum/src/main.cpp index 5037e6d0..8074d354 100644 --- a/spectrum/src/main.cpp +++ b/spectrum/src/main.cpp @@ -122,6 +122,7 @@ int main(int argc, char **argv) boost::program_options::variables_map vm; bool no_daemon = false; std::string config_file; + std::string jid; #ifndef WIN32 @@ -139,6 +140,7 @@ int main(int argc, char **argv) desc.add_options() ("help,h", "help") ("no-daemonize,n", "Do not run spectrum as daemon") + ("jid,j", boost::program_options::value(&jid)->default_value(""), "Specify JID of transport manually") ("config", boost::program_options::value(&config_file)->default_value(""), "Config file") ; try @@ -177,7 +179,7 @@ int main(int argc, char **argv) return 1; } - if (!config.load(vm["config"].as())) { + if (!config.load(vm["config"].as(), jid)) { std::cerr << "Can't load configuration file.\n"; return 1; } diff --git a/spectrum_manager/src/main.cpp b/spectrum_manager/src/main.cpp index efa5038e..d4b8e383 100644 --- a/spectrum_manager/src/main.cpp +++ b/spectrum_manager/src/main.cpp @@ -82,12 +82,17 @@ static std::string searchForBinary(const std::string &binary) { } // Executes new backend -static unsigned long exec_(std::string path, std::string config) { +static unsigned long exec_(std::string path, std::string config, std::string jid = "") { // fork and exec pid_t pid = fork(); if ( pid == 0 ) { // child process - exit(execl(path.c_str(), path.c_str(), config.c_str(), NULL)); + if (jid.empty()) { + exit(execl(path.c_str(), path.c_str(), config.c_str(), NULL)); + } + else { + exit(execl(path.c_str(), path.c_str(), "-j", jid.c_str(), config.c_str(), NULL)); + } } else if ( pid < 0 ) { // fork failed } @@ -143,15 +148,27 @@ static void start_all_instances(ManagerConfig *config) { Config cfg; if (cfg.load(itr->path().string()) == false) { std::cerr << "Can't load config file " << itr->path().string() << ". Skipping...\n"; + continue; } - int pid = isRunning(CONFIG_STRING(&cfg, "service.pidfile")); - if (pid == 0) { - std::cout << "Starting " << itr->path() << ": OK\n"; - exec_(spectrum2_binary, itr->path().string()); - } - else { - std::cout << "Starting " << itr->path() << ": Already started (PID=" << pid << ")\n"; + std::vector vhosts = CONFIG_VECTOR(&cfg, "vhosts.vhost"); + vhosts.push_back(CONFIG_STRING(&cfg, "service.jid")); + + BOOST_FOREACH(std::string &vhost, vhosts) { + Config vhostCfg; + if (vhostCfg.load(itr->path().string(), vhost) == false) { + std::cerr << "Can't load config file " << itr->path().string() << ". Skipping...\n"; + continue; + } + + int pid = isRunning(CONFIG_STRING(&vhostCfg, "service.pidfile")); + if (pid == 0) { + std::cout << "Starting " << itr->path() << ": OK\n"; + exec_(spectrum2_binary, itr->path().string(), vhost); + } + else { + std::cout << "Starting " << itr->path() << ": Already started (PID=" << pid << ")\n"; + } } } } @@ -184,13 +201,24 @@ static void stop_all_instances(ManagerConfig *config) { std::cerr << "Can't load config file " << itr->path().string() << ". Skipping...\n"; } - int pid = isRunning(CONFIG_STRING(&cfg, "service.pidfile")); - if (pid) { - std::cout << "Stopping " << itr->path() << ": OK\n"; - kill(pid, SIGTERM); - } - else { - std::cout << "Stopping " << itr->path() << ": Not running\n"; + std::vector vhosts = CONFIG_VECTOR(&cfg, "vhosts.vhost"); + vhosts.push_back(CONFIG_STRING(&cfg, "service.jid")); + + BOOST_FOREACH(std::string &vhost, vhosts) { + Config vhostCfg; + if (vhostCfg.load(itr->path().string(), vhost) == false) { + std::cerr << "Can't load config file " << itr->path().string() << ". Skipping...\n"; + continue; + } + + int pid = isRunning(CONFIG_STRING(&vhostCfg, "service.pidfile")); + if (pid) { + std::cout << "Stopping " << itr->path() << ": OK\n"; + kill(pid, SIGTERM); + } + else { + std::cout << "Stopping " << itr->path() << ": Not running\n"; + } } } } diff --git a/src/config.cpp b/src/config.cpp index d0307788..655ce4b7 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -31,13 +31,13 @@ using namespace boost::program_options; namespace Transport { -bool Config::load(const std::string &configfile, boost::program_options::options_description &opts) { +bool Config::load(const std::string &configfile, boost::program_options::options_description &opts, const std::string &jid) { std::ifstream ifs(configfile.c_str()); if (!ifs.is_open()) return false; m_file = configfile; - bool ret = load(ifs, opts); + bool ret = load(ifs, opts, jid); ifs.close(); char path[PATH_MAX] = ""; @@ -49,7 +49,7 @@ bool Config::load(const std::string &configfile, boost::program_options::options return ret; } -bool Config::load(std::istream &ifs, boost::program_options::options_description &opts) { +bool Config::load(std::istream &ifs, boost::program_options::options_description &opts, const std::string &_jid) { m_unregistered.clear(); opts.add_options() ("service.jid", value()->default_value(""), "Transport Jabber ID") @@ -76,6 +76,7 @@ bool Config::load(std::istream &ifs, boost::program_options::options_description ("service.memory_collector_time", value()->default_value(0), "Time in seconds after which backend with most memory is set to die.") ("service.more_resources", value()->default_value(false), "Allow more resources to be connected in server mode at the same time.") ("service.enable_privacy_lists", value()->default_value(true), "") + ("vhosts.vhost", value >()->multitoken(), "") ("identity.name", value()->default_value("Spectrum 2 Transport"), "Name showed in service discovery.") ("identity.category", value()->default_value("gateway"), "Disco#info identity category. 'gateway' by default.") ("identity.type", value()->default_value(""), "Type of transport ('icq','msn','gg','irc', ...)") @@ -102,11 +103,47 @@ bool Config::load(std::istream &ifs, boost::program_options::options_description parsed_options parsed = parse_config_file(ifs, opts, true); + bool found_working = false; + bool found_pidfile = false; std::string jid = ""; - BOOST_FOREACH(option opt, parsed.options) { + BOOST_FOREACH(option &opt, parsed.options) { if (opt.string_key == "service.jid") { - jid = opt.value[0]; + if (_jid.empty()) { + jid = opt.value[0]; + } + else { + opt.value[0] = _jid; + jid = _jid; + } } + else if (opt.string_key == "service.backend_port") { + if (opt.value[0] == "0") { + unsigned long r = 0; + BOOST_FOREACH(char c, _jid) { + r += (int) c; + } + srand(time(NULL) + r); + int randomPort = 30000 + rand() % 10000; + opt.value[0] = boost::lexical_cast(randomPort); + } + } + else if (opt.string_key == "service.working_dir") { + found_working = true; + } + else if (opt.string_key == "service.pidfile") { + found_pidfile = true; + } + } + + if (!found_working) { + std::vector value; + value.push_back("/var/lib/spectrum2/$jid"); + parsed.options.push_back(boost::program_options::basic_option("service.working_dir", value)); + } + if (!found_pidfile) { + std::vector value; + value.push_back("/var/run/spectrum2/$jid.pid"); + parsed.options.push_back(boost::program_options::basic_option("service.pidfile", value)); } BOOST_FOREACH(option &opt, parsed.options) { @@ -131,9 +168,9 @@ bool Config::load(std::istream &ifs) { return load(ifs, opts); } -bool Config::load(const std::string &configfile) { +bool Config::load(const std::string &configfile, const std::string &jid) { options_description opts("Transport options"); - return load(configfile, opts); + return load(configfile, opts, jid); } bool Config::reload() { From 7cd4658101b259eefe0bcbdb51cf7f98b87580d2 Mon Sep 17 00:00:00 2001 From: HanzZ Date: Sun, 6 Nov 2011 12:47:13 +0100 Subject: [PATCH 15/48] Set auth_fb --- backends/libpurple/main.cpp | 4 ++++ src/usermanager.cpp | 5 +++++ 2 files changed, 9 insertions(+) diff --git a/backends/libpurple/main.cpp b/backends/libpurple/main.cpp index a76454c1..bbfcbb1c 100644 --- a/backends/libpurple/main.cpp +++ b/backends/libpurple/main.cpp @@ -542,6 +542,10 @@ class SpectrumNetworkPlugin : public NetworkPlugin { while (keys && keys[i] != NULL) { std::string key = keys[i]; + if (key == "fb_api_key" || key == "fb_api_secret") { + purple_account_set_bool(account, "auth_fb", TRUE); + } + PurplePlugin *plugin = purple_find_prpl(purple_account_get_protocol_id(account)); PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(plugin); bool found = false; diff --git a/src/usermanager.cpp b/src/usermanager.cpp index a52690aa..d193492d 100644 --- a/src/usermanager.cpp +++ b/src/usermanager.cpp @@ -319,6 +319,11 @@ void UserManager::handleSubscription(Swift::Presence::ref presence) { return; } + // Don't let RosterManager to handle presences for us + if (presence->getTo().getNode().empty()) { + return; + } + User *user = getUser(presence->getFrom().toBare().toString()); if (user) { From bf55d8c7b5b8e018f9206bb621856ba68f2c0a2c Mon Sep 17 00:00:00 2001 From: Jan Kaluza Date: Mon, 7 Nov 2011 13:10:42 +0100 Subject: [PATCH 16/48] Check if vhosts are configured before using them --- include/transport/config.h | 5 +++++ spectrum_manager/src/main.cpp | 9 +++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/include/transport/config.h b/include/transport/config.h index d6900d30..4ff5b8fa 100644 --- a/include/transport/config.h +++ b/include/transport/config.h @@ -34,6 +34,7 @@ #define CONFIG_BOOL(PTR, KEY) (*PTR)[KEY].as() #define CONFIG_LIST(PTR, KEY) (*PTR)[KEY].as >() #define CONFIG_VECTOR(PTR, KEY) (*PTR)[KEY].as >() +#define CONFIG_HAS_KEY(PTR, KEY) (*PTR).hasKey(KEY) namespace Transport { @@ -75,6 +76,10 @@ class Config { bool reload(); + bool hasKey(const std::string &key) { + return m_variables.find(key) != m_variables.end(); + } + /// Returns value of variable defined by key. /// For variables in sections you can use "section.variable" key format. diff --git a/spectrum_manager/src/main.cpp b/spectrum_manager/src/main.cpp index d4b8e383..227dc835 100644 --- a/spectrum_manager/src/main.cpp +++ b/spectrum_manager/src/main.cpp @@ -151,7 +151,10 @@ static void start_all_instances(ManagerConfig *config) { continue; } - std::vector vhosts = CONFIG_VECTOR(&cfg, "vhosts.vhost"); + + std::vector vhosts; + if (CONFIG_HAS_KEY(&cfg, "vhosts.vhost")) + vhosts = CONFIG_VECTOR(&cfg, "vhosts.vhost"); vhosts.push_back(CONFIG_STRING(&cfg, "service.jid")); BOOST_FOREACH(std::string &vhost, vhosts) { @@ -201,7 +204,9 @@ static void stop_all_instances(ManagerConfig *config) { std::cerr << "Can't load config file " << itr->path().string() << ". Skipping...\n"; } - std::vector vhosts = CONFIG_VECTOR(&cfg, "vhosts.vhost"); + std::vector vhosts; + if (CONFIG_HAS_KEY(&cfg, "vhosts.vhost")) + vhosts = CONFIG_VECTOR(&cfg, "vhosts.vhost"); vhosts.push_back(CONFIG_STRING(&cfg, "service.jid")); BOOST_FOREACH(std::string &vhost, vhosts) { From 6c6071f30bf0711cd3ed7a35d39537e5f17392e1 Mon Sep 17 00:00:00 2001 From: HanzZ Date: Mon, 7 Nov 2011 19:00:40 +0100 Subject: [PATCH 17/48] set RLIMIT_CORE --- spectrum/src/main.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/spectrum/src/main.cpp b/spectrum/src/main.cpp index 8074d354..565aaaeb 100644 --- a/spectrum/src/main.cpp +++ b/spectrum/src/main.cpp @@ -140,6 +140,7 @@ int main(int argc, char **argv) desc.add_options() ("help,h", "help") ("no-daemonize,n", "Do not run spectrum as daemon") + ("no-debug,d", "Create coredumps on crash") ("jid,j", boost::program_options::value(&jid)->default_value(""), "Specify JID of transport manually") ("config", boost::program_options::value(&config_file)->default_value(""), "Config file") ; @@ -268,6 +269,11 @@ int main(int argc, char **argv) } setrlimit(RLIMIT_CORE, &limit); } + + struct rlimit limit; + limit.rlim_max = RLIM_INFINITY; + limit.rlim_cur = RLIM_INFINITY; + setrlimit(RLIMIT_CORE, &limit); #endif Swift::SimpleEventLoop eventLoop; From 161b220ee132307ddc1269c5b60b60793aba14f2 Mon Sep 17 00:00:00 2001 From: HanzZ Date: Mon, 7 Nov 2011 19:25:43 +0100 Subject: [PATCH 18/48] Create working_dir after setuid/setgid --- spectrum/src/main.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/spectrum/src/main.cpp b/spectrum/src/main.cpp index 565aaaeb..2c14f3a9 100644 --- a/spectrum/src/main.cpp +++ b/spectrum/src/main.cpp @@ -188,13 +188,6 @@ int main(int argc, char **argv) #ifndef WIN32 if (!no_daemon) { // create directories - try { - boost::filesystem::create_directories(CONFIG_STRING(&config, "service.working_dir")); - } - catch (...) { - std::cerr << "Can't create service.working_dir directory " << CONFIG_STRING(&config, "service.working_dir") << ".\n"; - return 1; - } try { boost::filesystem::create_directories( boost::filesystem::path(CONFIG_STRING(&config, "service.pidfile")).parent_path().string() @@ -274,6 +267,15 @@ int main(int argc, char **argv) limit.rlim_max = RLIM_INFINITY; limit.rlim_cur = RLIM_INFINITY; setrlimit(RLIMIT_CORE, &limit); + + // create directories + try { + boost::filesystem::create_directories(CONFIG_STRING(&config, "service.working_dir")); + } + catch (...) { + std::cerr << "Can't create service.working_dir directory " << CONFIG_STRING(&config, "service.working_dir") << ".\n"; + return 1; + } #endif Swift::SimpleEventLoop eventLoop; From 5225465e2169e64c88bed2191e124627fbf2ee0b Mon Sep 17 00:00:00 2001 From: HanzZ Date: Mon, 7 Nov 2011 19:46:51 +0100 Subject: [PATCH 19/48] Stop backend in signal handler --- src/networkpluginserver.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/src/networkpluginserver.cpp b/src/networkpluginserver.cpp index cdd4f9f0..e1cb4606 100644 --- a/src/networkpluginserver.cpp +++ b/src/networkpluginserver.cpp @@ -257,6 +257,17 @@ NetworkPluginServer::NetworkPluginServer(Component *component, Config *config, U } NetworkPluginServer::~NetworkPluginServer() { + for (std::list::const_iterator it = m_clients.begin(); it != m_clients.end(); it++) { + LOG4CXX_INFO(logger, "Stopping backend " << *it); + std::string message; + pbnetwork::WrapperMessage wrap; + wrap.set_type(pbnetwork::WrapperMessage_Type_TYPE_EXIT); + wrap.SerializeToString(&message); + + Backend *c = (Backend *) *it; + send(c->connection, message); + } + m_pingTimer->stop(); m_server->stop(); m_server.reset(); From ddcdea8afc9c7316e1d81b1bc90155bc4d02a08b Mon Sep 17 00:00:00 2001 From: HanzZ Date: Mon, 7 Nov 2011 19:51:38 +0100 Subject: [PATCH 20/48] set backend port to 0 by default --- src/config.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config.cpp b/src/config.cpp index 655ce4b7..36e0e850 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -66,7 +66,7 @@ bool Config::load(std::istream &ifs, boost::program_options::options_description ("service.server_mode", value()->default_value(false), "True if Spectrum should behave as server") ("service.users_per_backend", value()->default_value(100), "Number of users per one legacy network backend") ("service.backend_host", value()->default_value("localhost"), "Host to bind backend server to") - ("service.backend_port", value()->default_value("10000"), "Port to bind backend server to") + ("service.backend_port", value()->default_value("0"), "Port to bind backend server to") ("service.cert", value()->default_value(""), "PKCS#12 Certificate.") ("service.cert_password", value()->default_value(""), "PKCS#12 Certificate password.") ("service.admin_jid", value()->default_value(""), "Administrator jid.") From e0d4583d24907315aecaeabcf7344b6fca24f4c3 Mon Sep 17 00:00:00 2001 From: HanzZ Date: Mon, 7 Nov 2011 19:59:38 +0100 Subject: [PATCH 21/48] Generate random port even when it's not set in config file --- src/config.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/src/config.cpp b/src/config.cpp index 36e0e850..0b0a5233 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -105,6 +105,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; std::string jid = ""; BOOST_FOREACH(option &opt, parsed.options) { if (opt.string_key == "service.jid") { @@ -117,6 +118,7 @@ bool Config::load(std::istream &ifs, boost::program_options::options_description } } else if (opt.string_key == "service.backend_port") { + found_backend_port = true; if (opt.value[0] == "0") { unsigned long r = 0; BOOST_FOREACH(char c, _jid) { @@ -145,6 +147,17 @@ bool Config::load(std::istream &ifs, boost::program_options::options_description value.push_back("/var/run/spectrum2/$jid.pid"); parsed.options.push_back(boost::program_options::basic_option("service.pidfile", value)); } + if (!found_backend_port) { + unsigned long r = 0; + BOOST_FOREACH(char c, _jid) { + r += (int) c; + } + srand(time(NULL) + r); + int randomPort = 30000 + rand() % 10000; + std::vector value; + value.push_back(boost::lexical_cast(randomPort)); + parsed.options.push_back(boost::program_options::basic_option("service.backend_port", value)); + } BOOST_FOREACH(option &opt, parsed.options) { if (opt.unregistered) { From bfe84737ee183b8328e4d3f876857e3e020aab91 Mon Sep 17 00:00:00 2001 From: HanzZ Date: Mon, 7 Nov 2011 20:11:49 +0100 Subject: [PATCH 22/48] Remove remoteRosterRequest in RosterManager destructor --- include/transport/rostermanager.h | 1 + src/rostermanager.cpp | 12 +++++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/include/transport/rostermanager.h b/include/transport/rostermanager.h index 2e67532a..81934f78 100644 --- a/include/transport/rostermanager.h +++ b/include/transport/rostermanager.h @@ -125,6 +125,7 @@ class RosterManager { Swift::Timer::ref m_RIETimer; std::list m_requests; bool m_supportRemoteRoster; + AddressedRosterRequest::ref m_remoteRosterRequest; }; } diff --git a/src/rostermanager.cpp b/src/rostermanager.cpp index dc024b7a..377ddffd 100644 --- a/src/rostermanager.cpp +++ b/src/rostermanager.cpp @@ -52,9 +52,9 @@ RosterManager::RosterManager(User *user, Component *component){ m_supportRemoteRoster = false; if (!m_component->inServerMode()) { - AddressedRosterRequest::ref request = AddressedRosterRequest::ref(new AddressedRosterRequest(m_component->getIQRouter(), m_user->getJID().toBare())); - request->onResponse.connect(boost::bind(&RosterManager::handleRemoteRosterResponse, this, _1, _2)); - request->send(); + m_remoteRosterRequest = AddressedRosterRequest::ref(new AddressedRosterRequest(m_component->getIQRouter(), m_user->getJID().toBare())); + m_remoteRosterRequest->onResponse.connect(boost::bind(&RosterManager::handleRemoteRosterResponse, this, _1, _2)); + m_remoteRosterRequest->send(); } } @@ -67,6 +67,11 @@ RosterManager::~RosterManager() { sendUnavailablePresences(m_user->getJID().toBare()); + if (m_remoteRosterRequest) { + m_remoteRosterRequest->onResponse.disconnect_all_slots(); + m_component->getIQRouter()->removeHandler(m_remoteRosterRequest); + } + for (std::map, boost::pool_allocator< std::pair > >::iterator it = m_buddies.begin(); it != m_buddies.end(); it++) { Buddy *buddy = (*it).second; if (!buddy) { @@ -198,6 +203,7 @@ void RosterManager::handleBuddyRosterPushResponse(Swift::ErrorPayload::ref error } void RosterManager::handleRemoteRosterResponse(boost::shared_ptr payload, Swift::ErrorPayload::ref error) { + m_remoteRosterRequest.reset(); if (error) { m_supportRemoteRoster = false; LOG4CXX_INFO(logger, m_user->getJID().toString() << ": This server does not support remote roster protoXEP"); From 6ff8b24992b11d140a2c8ee9ada21cd707172801 Mon Sep 17 00:00:00 2001 From: Jan Kaluza Date: Tue, 8 Nov 2011 11:03:27 +0100 Subject: [PATCH 23/48] Added StatsPayload, StatsParser, StatsSerializer --- include/Swiften/Elements/StatsPayload.cpp | 14 ++++ include/Swiften/Elements/StatsPayload.h | 67 +++++++++++++++++++ .../Parser/PayloadParsers/StatsParser.cpp | 43 ++++++++++++ .../Parser/PayloadParsers/StatsParser.h | 33 +++++++++ .../PayloadSerializers/StatsSerializer.cpp | 35 ++++++++++ .../PayloadSerializers/StatsSerializer.h | 19 ++++++ src/transport.cpp | 6 ++ 7 files changed, 217 insertions(+) create mode 100644 include/Swiften/Elements/StatsPayload.cpp create mode 100644 include/Swiften/Elements/StatsPayload.h create mode 100644 include/Swiften/Parser/PayloadParsers/StatsParser.cpp create mode 100644 include/Swiften/Parser/PayloadParsers/StatsParser.h create mode 100644 include/Swiften/Serializer/PayloadSerializers/StatsSerializer.cpp create mode 100644 include/Swiften/Serializer/PayloadSerializers/StatsSerializer.h diff --git a/include/Swiften/Elements/StatsPayload.cpp b/include/Swiften/Elements/StatsPayload.cpp new file mode 100644 index 00000000..e3718721 --- /dev/null +++ b/include/Swiften/Elements/StatsPayload.cpp @@ -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 + +namespace Swift { + +StatsPayload::StatsPayload() { +} + +} diff --git a/include/Swiften/Elements/StatsPayload.h b/include/Swiften/Elements/StatsPayload.h new file mode 100644 index 00000000..aa1619fe --- /dev/null +++ b/include/Swiften/Elements/StatsPayload.h @@ -0,0 +1,67 @@ +/* + * Copyright (c) 2011 Jan Kaluza + * Licensed under the Simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include + +#include +#include + +namespace Swift { + class StatsPayload : public Payload { + public: + class Item { + public: + Item(const std::string &name = "", const std::string &units = "", const std::string &value = "") : + name(name), units(units), value(value) { } + + void setName(const std::string &name) { + this->name = name; + } + + const std::string &getName() const { + return name; + } + + void setUnits(const std::string &units) { + this->units = units; + } + + const std::string &getUnits() const { + return units; + } + + void setValue(const std::string &value) { + this->value = value; + } + + const std::string &getValue() const { + return value; + } + + private: + std::string name; + std::string units; + std::string value; + }; + + typedef std::vector StatsPayloadItems; + + StatsPayload(); + + void addItem(const StatsPayload::Item &item) { + items.push_back(item); + } + + const StatsPayloadItems &getItems() const { + return items; + } + + private: + StatsPayloadItems items; + }; +} diff --git a/include/Swiften/Parser/PayloadParsers/StatsParser.cpp b/include/Swiften/Parser/PayloadParsers/StatsParser.cpp new file mode 100644 index 00000000..2c4e421b --- /dev/null +++ b/include/Swiften/Parser/PayloadParsers/StatsParser.cpp @@ -0,0 +1,43 @@ +/* + * Copyright (c) 2011 Jan Kaluza + * Licensed under the Simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include +#include + +namespace Swift { + +StatsParser::StatsParser() : level_(TopLevel), inItem_(false) { +} + +void StatsParser::handleStartElement(const std::string& element, const std::string& /*ns*/, const AttributeMap& attributes) { + if (level_ == PayloadLevel) { + if (element == "item") { + inItem_ = true; + + currentItem_ = StatsPayload::Item(); + + currentItem_.setName(attributes.getAttribute("name")); + currentItem_.setValue(attributes.getAttribute("value")); + currentItem_.setUnits(attributes.getAttribute("units")); + } + } + ++level_; +} + +void StatsParser::handleEndElement(const std::string& element, const std::string& /*ns*/) { + --level_; + if (level_ == PayloadLevel) { + if (inItem_) { + getPayloadInternal()->addItem(currentItem_); + inItem_ = false; + } + } +} + +void StatsParser::handleCharacterData(const std::string& data) { +} + +} diff --git a/include/Swiften/Parser/PayloadParsers/StatsParser.h b/include/Swiften/Parser/PayloadParsers/StatsParser.h new file mode 100644 index 00000000..53b0c97c --- /dev/null +++ b/include/Swiften/Parser/PayloadParsers/StatsParser.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2011 Jan Kaluza + * Licensed under the Simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include +#include + +namespace Swift { + class SerializingParser; + + class StatsParser : public GenericPayloadParser { + public: + StatsParser(); + + virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes); + virtual void handleEndElement(const std::string& element, const std::string&); + virtual void handleCharacterData(const std::string& data); + + private: + enum Level { + TopLevel = 0, + PayloadLevel = 1, + ItemLevel = 2 + }; + int level_; + bool inItem_; + StatsPayload::Item currentItem_; + }; +} diff --git a/include/Swiften/Serializer/PayloadSerializers/StatsSerializer.cpp b/include/Swiften/Serializer/PayloadSerializers/StatsSerializer.cpp new file mode 100644 index 00000000..e670a6ee --- /dev/null +++ b/include/Swiften/Serializer/PayloadSerializers/StatsSerializer.cpp @@ -0,0 +1,35 @@ +/* + * Copyright (c) 2011 Jan Kaluza + * Licensed under the Simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include + +#include + +#include +#include +#include +#include + +namespace Swift { + +StatsSerializer::StatsSerializer() : GenericPayloadSerializer() { +} + +std::string StatsSerializer::serializePayload(boost::shared_ptr stats) const { + XMLElement queryElement("query", "http://jabber.org/protocol/stats"); + foreach(const StatsPayload::Item& item, stats->getItems()) { + boost::shared_ptr statElement(new XMLElement("stat")); + statElement->setAttribute("name", item.getName()); + statElement->setAttribute("units", item.getUnits()); + statElement->setAttribute("value", item.getValue()); + + queryElement.addNode(statElement); + } + + return queryElement.serialize(); +} + +} diff --git a/include/Swiften/Serializer/PayloadSerializers/StatsSerializer.h b/include/Swiften/Serializer/PayloadSerializers/StatsSerializer.h new file mode 100644 index 00000000..cf45941d --- /dev/null +++ b/include/Swiften/Serializer/PayloadSerializers/StatsSerializer.h @@ -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 +#include + +namespace Swift { + class StatsSerializer : public GenericPayloadSerializer { + public: + StatsSerializer(); + + virtual std::string serializePayload(boost::shared_ptr) const; + }; +} diff --git a/src/transport.cpp b/src/transport.cpp index e9d87cb5..7d3677f1 100644 --- a/src/transport.cpp +++ b/src/transport.cpp @@ -34,6 +34,8 @@ #include "Swiften/Serializer/PayloadSerializers/AttentionSerializer.h" #include "Swiften/Parser/PayloadParsers/XHTMLIMParser.h" #include "Swiften/Serializer/PayloadSerializers/XHTMLIMSerializer.h" +#include "Swiften/Parser/PayloadParsers/StatsParser.h" +#include "Swiften/Serializer/PayloadSerializers/StatsSerializer.h" #include "transport/BlockParser.h" #include "transport/BlockSerializer.h" #include "Swiften/Parser/PayloadParsers/InvisibleParser.h" @@ -90,11 +92,13 @@ Component::Component(Swift::EventLoop *loop, Swift::NetworkFactories *factories, m_server->addPayloadParserFactory(new GenericPayloadParserFactory("html", "http://jabber.org/protocol/xhtml-im")); m_server->addPayloadParserFactory(new GenericPayloadParserFactory("block", "urn:xmpp:block:0")); m_server->addPayloadParserFactory(new GenericPayloadParserFactory("invisible", "urn:xmpp:invisible:0")); + m_server->addPayloadParserFactory(new GenericPayloadParserFactory("query", "http://jabber.org/protocol/stats")); m_server->addPayloadSerializer(new Swift::AttentionSerializer()); m_server->addPayloadSerializer(new Swift::XHTMLIMSerializer()); m_server->addPayloadSerializer(new Transport::BlockSerializer()); m_server->addPayloadSerializer(new Swift::InvisibleSerializer()); + m_server->addPayloadSerializer(new Swift::StatsSerializer()); m_server->onDataRead.connect(boost::bind(&Component::handleDataRead, this, _1)); m_server->onDataWritten.connect(boost::bind(&Component::handleDataWritten, this, _1)); @@ -113,11 +117,13 @@ Component::Component(Swift::EventLoop *loop, Swift::NetworkFactories *factories, m_component->addPayloadParserFactory(new GenericPayloadParserFactory("html", "http://jabber.org/protocol/xhtml-im")); m_component->addPayloadParserFactory(new GenericPayloadParserFactory("block", "urn:xmpp:block:0")); m_component->addPayloadParserFactory(new GenericPayloadParserFactory("invisible", "urn:xmpp:invisible:0")); + m_component->addPayloadParserFactory(new GenericPayloadParserFactory("query", "http://jabber.org/protocol/stats")); m_component->addPayloadSerializer(new Swift::AttentionSerializer()); m_component->addPayloadSerializer(new Swift::XHTMLIMSerializer()); m_component->addPayloadSerializer(new Transport::BlockSerializer()); m_component->addPayloadSerializer(new Swift::InvisibleSerializer()); + m_component->addPayloadSerializer(new Swift::StatsSerializer()); m_stanzaChannel = m_component->getStanzaChannel(); m_iqRouter = m_component->getIQRouter(); From 5c84b1bcaaa1f9d45823e7f9ca247f44c41bb204 Mon Sep 17 00:00:00 2001 From: HanzZ Date: Tue, 8 Nov 2011 17:14:34 +0100 Subject: [PATCH 24/48] Ignore empty messages in AdminInterface --- src/admininterface.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/admininterface.cpp b/src/admininterface.cpp index 3af032d4..7df84772 100644 --- a/src/admininterface.cpp +++ b/src/admininterface.cpp @@ -66,6 +66,11 @@ void AdminInterface::handleMessageReceived(Swift::Message::ref message) { return; } + // Ignore empty messages + if (message->getBody().empty()) { + return; + } + LOG4CXX_INFO(logger, "Message from admin received"); message->setTo(message->getFrom()); message->setFrom(m_component->getJID()); From fde0583877264c01f2c5edb0a9f6078ca2341d80 Mon Sep 17 00:00:00 2001 From: HanzZ Date: Tue, 8 Nov 2011 18:17:17 +0100 Subject: [PATCH 25/48] Don't log admin only in server-mode --- src/usermanager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/usermanager.cpp b/src/usermanager.cpp index d193492d..f4d7867e 100644 --- a/src/usermanager.cpp +++ b/src/usermanager.cpp @@ -149,7 +149,7 @@ void UserManager::handlePresence(Swift::Presence::ref presence) { // Create user class if it's not there if (!user) { // Admin user is not legacy network user, so do not create User class instance for him - if (CONFIG_STRING(m_component->getConfig(), "service.admin_jid") == presence->getFrom().toBare().toString()) { + if (m_component->inServerMode() && CONFIG_STRING(m_component->getConfig(), "service.admin_jid") == presence->getFrom().toBare().toString()) { return; } From 2131b86869ca04ae7cf2f5016233b3a9b2640632 Mon Sep 17 00:00:00 2001 From: HanzZ Date: Wed, 9 Nov 2011 09:11:42 +0100 Subject: [PATCH 26/48] Working uptime --- .../Parser/PayloadParsers/StatsParser.cpp | 2 +- include/transport/statsresponder.h | 51 ++++++++++++ spectrum/src/main.cpp | 3 + src/statsresponder.cpp | 78 +++++++++++++++++++ 4 files changed, 133 insertions(+), 1 deletion(-) create mode 100644 include/transport/statsresponder.h create mode 100644 src/statsresponder.cpp diff --git a/include/Swiften/Parser/PayloadParsers/StatsParser.cpp b/include/Swiften/Parser/PayloadParsers/StatsParser.cpp index 2c4e421b..1c795a8a 100644 --- a/include/Swiften/Parser/PayloadParsers/StatsParser.cpp +++ b/include/Swiften/Parser/PayloadParsers/StatsParser.cpp @@ -14,7 +14,7 @@ StatsParser::StatsParser() : level_(TopLevel), inItem_(false) { void StatsParser::handleStartElement(const std::string& element, const std::string& /*ns*/, const AttributeMap& attributes) { if (level_ == PayloadLevel) { - if (element == "item") { + if (element == "stat") { inItem_ = true; currentItem_ = StatsPayload::Item(); diff --git a/include/transport/statsresponder.h b/include/transport/statsresponder.h new file mode 100644 index 00000000..9c252d92 --- /dev/null +++ b/include/transport/statsresponder.h @@ -0,0 +1,51 @@ +/** + * libtransport -- C++ library for easy XMPP Transports development + * + * Copyright (C) 2011, Jan Kaluza + * + * 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 +#include "Swiften/Swiften.h" +#include "Swiften/Queries/SetResponder.h" +#include "Swiften/Elements/StatsPayload.h" + +namespace Transport { + +class Component; +class UserManager; +class NetworkPluginServer; +class StorageBackend; + +class StatsResponder : public Swift::Responder { + public: + StatsResponder(Component *component, UserManager *userManager, NetworkPluginServer *server, StorageBackend *storageBackend); + ~StatsResponder(); + + private: + virtual bool handleGetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr payload); + virtual bool handleSetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr payload); + + Component *m_component; + UserManager *m_userManager; + NetworkPluginServer *m_server; + StorageBackend *m_storageBackend; + time_t m_start; +}; + +} diff --git a/spectrum/src/main.cpp b/spectrum/src/main.cpp index 2c14f3a9..07a76ce8 100644 --- a/spectrum/src/main.cpp +++ b/spectrum/src/main.cpp @@ -8,6 +8,7 @@ #include "transport/userregistration.h" #include "transport/networkpluginserver.h" #include "transport/admininterface.h" +#include "transport/statsresponder.h" #include "transport/util.h" #include "Swiften/EventLoop/SimpleEventLoop.h" #include @@ -323,6 +324,8 @@ int main(int argc, char **argv) NetworkPluginServer plugin(&transport, &config, &userManager, &ftManager); AdminInterface adminInterface(&transport, &userManager, &plugin, storageBackend); + StatsResponder statsResponder(&transport, &userManager, &plugin, storageBackend); + statsResponder.start(); eventLoop_ = &eventLoop; diff --git a/src/statsresponder.cpp b/src/statsresponder.cpp new file mode 100644 index 00000000..bfa04aca --- /dev/null +++ b/src/statsresponder.cpp @@ -0,0 +1,78 @@ +/** + * XMPP - libpurple transport + * + * Copyright (C) 2009, Jan Kaluza + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ + +#include "transport/statsresponder.h" + +#include +#include +#include "Swiften/Queries/IQRouter.h" +#include "transport/BlockPayload.h" +#include "Swiften/Swiften.h" +#include "transport/usermanager.h" +#include "transport/user.h" +#include "transport/buddy.h" +#include "transport/rostermanager.h" +#include "log4cxx/logger.h" + +using namespace log4cxx; + +using namespace Swift; +using namespace boost; + +namespace Transport { + +static LoggerPtr logger = Logger::getLogger("StatsResponder"); + +StatsResponder::StatsResponder(Component *component, UserManager *userManager, NetworkPluginServer *server, StorageBackend *storageBackend) : Swift::Responder(component->getIQRouter()) { + m_component = component; + m_userManager = userManager; + m_server = server; + m_storageBackend = storageBackend; + m_start = time(0); +} + +StatsResponder::~StatsResponder() { + +} + +bool StatsResponder::handleGetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr stats) { + boost::shared_ptr response(new StatsPayload()); + + if (stats->getItems().empty()) { + response->addItem(StatsPayload::Item("uptime")); + } + else { + BOOST_FOREACH(const StatsPayload::Item &item, stats->getItems()) { + if (item.getName() == "uptime") { + response->addItem(StatsPayload::Item("uptime", "seconds", boost::lexical_cast(time(0) - m_start))); + } + } + } + + sendResponse(from, id, response); + + return true; +} + +bool StatsResponder::handleSetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr stats) { + return false; +} + +} From 35ef4b07784bfb10f2452fe604ddba139adb33b6 Mon Sep 17 00:00:00 2001 From: Jan Kaluza Date: Wed, 9 Nov 2011 12:47:43 +0100 Subject: [PATCH 27/48] StatsResponder --- include/transport/rostermanager.h | 5 +++ include/transport/statsresponder.h | 2 ++ src/statsresponder.cpp | 58 ++++++++++++++++++++++++++++++ 3 files changed, 65 insertions(+) diff --git a/include/transport/rostermanager.h b/include/transport/rostermanager.h index 81934f78..64f05fa7 100644 --- a/include/transport/rostermanager.h +++ b/include/transport/rostermanager.h @@ -49,6 +49,7 @@ class AddressedRosterRequest : public Swift::GenericRequest, boost::pool_allocator< std::pair > > BuddiesMap; /// Creates new RosterManager. /// \param user User associated with this RosterManager. /// \param component Transport instance associated with this roster. @@ -80,6 +81,10 @@ class RosterManager { /// \return User User *getUser() { return m_user; } + const BuddiesMap &getBuddies() { + return m_buddies; + } + bool isRemoteRosterSupported() { return m_supportRemoteRoster; } diff --git a/include/transport/statsresponder.h b/include/transport/statsresponder.h index 9c252d92..ecdd331f 100644 --- a/include/transport/statsresponder.h +++ b/include/transport/statsresponder.h @@ -41,6 +41,8 @@ class StatsResponder : public Swift::Responder { virtual bool handleGetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr payload); virtual bool handleSetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr payload); + unsigned long usedMemory(); + Component *m_component; UserManager *m_userManager; NetworkPluginServer *m_server; diff --git a/src/statsresponder.cpp b/src/statsresponder.cpp index bfa04aca..d91b8fea 100644 --- a/src/statsresponder.cpp +++ b/src/statsresponder.cpp @@ -29,6 +29,11 @@ #include "transport/user.h" #include "transport/buddy.h" #include "transport/rostermanager.h" +#include "transport/memoryusage.h" +#include "transport/conversationmanager.h" +#include "transport/rostermanager.h" +#include "transport/usermanager.h" +#include "transport/networkpluginserver.h" #include "log4cxx/logger.h" using namespace log4cxx; @@ -52,17 +57,70 @@ StatsResponder::~StatsResponder() { } +unsigned long StatsResponder::usedMemory() { + double shared = 0; + double rss = 0; +#ifndef WIN32 + process_mem_usage(shared, rss); +#endif + rss -= shared; + + const std::list &backends = m_server->getBackends(); + BOOST_FOREACH(NetworkPluginServer::Backend * backend, backends) { + rss += backend->res - backend->shared; + } + + return (unsigned long) rss; +} + bool StatsResponder::handleGetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr stats) { boost::shared_ptr response(new StatsPayload()); if (stats->getItems().empty()) { response->addItem(StatsPayload::Item("uptime")); + response->addItem(StatsPayload::Item("users/online")); + response->addItem(StatsPayload::Item("contacts/online")); + response->addItem(StatsPayload::Item("contacts/total")); + response->addItem(StatsPayload::Item("backends")); + response->addItem(StatsPayload::Item("memory-usage")); } else { + unsigned long contactsOnline = 0; + unsigned long contactsTotal = 0; + + Swift::StatusShow s; + std::string statusMessage; + for (std::map::const_iterator it = m_userManager->getUsers().begin(); it != m_userManager->getUsers().end(); it++) { + const RosterManager::BuddiesMap &buddies = (*it).second->getRosterManager()->getBuddies(); + contactsTotal += buddies.size(); + for(RosterManager::BuddiesMap::const_iterator it = buddies.begin(); it != buddies.end(); it++) { + if (!(*it).second->getStatus(s, statusMessage)) + continue; + if (s.getType() != Swift::StatusShow::None) { + contactsOnline++; + } + } + } + BOOST_FOREACH(const StatsPayload::Item &item, stats->getItems()) { if (item.getName() == "uptime") { response->addItem(StatsPayload::Item("uptime", "seconds", boost::lexical_cast(time(0) - m_start))); } + else if (item.getName() == "users/online") { + response->addItem(StatsPayload::Item("users/online", "users", boost::lexical_cast(m_userManager->getUserCount()))); + } + else if (item.getName() == "backends") { + response->addItem(StatsPayload::Item("backends", "backends", boost::lexical_cast(m_server->getBackendCount()))); + } + else if (item.getName() == "memory-usage") { + response->addItem(StatsPayload::Item("memory-usage", "KB", boost::lexical_cast(usedMemory()))); + } + else if (item.getName() == "contacts/online") { + response->addItem(StatsPayload::Item("contacts/online", "contacts", boost::lexical_cast(contactsOnline))); + } + else if (item.getName() == "contacts/total") { + response->addItem(StatsPayload::Item("contacts/total", "contacts", boost::lexical_cast(contactsTotal))); + } } } From f6d4966dd56d2a3b4320b341c6d92abf221d6acf Mon Sep 17 00:00:00 2001 From: HanzZ Date: Wed, 9 Nov 2011 22:48:39 +0100 Subject: [PATCH 28/48] Initialize logging after creating log directory --- spectrum/src/main.cpp | 96 +++++++++++++++++++++---------------------- 1 file changed, 48 insertions(+), 48 deletions(-) diff --git a/spectrum/src/main.cpp b/spectrum/src/main.cpp index 07a76ce8..c52011f5 100644 --- a/spectrum/src/main.cpp +++ b/spectrum/src/main.cpp @@ -205,6 +205,54 @@ int main(int argc, char **argv) } #endif +#ifndef WIN32 + if (!CONFIG_STRING(&config, "service.group").empty() ||!CONFIG_STRING(&config, "service.user").empty() ) { + struct rlimit limit; + getrlimit(RLIMIT_CORE, &limit); + + if (!CONFIG_STRING(&config, "service.group").empty()) { + struct group *gr; + if ((gr = getgrnam(CONFIG_STRING(&config, "service.group").c_str())) == NULL) { + std::cerr << "Invalid service.group name " << CONFIG_STRING(&config, "service.group") << "\n"; + return 1; + } + + if (((setgid(gr->gr_gid)) != 0) || (initgroups(CONFIG_STRING(&config, "service.user").c_str(), gr->gr_gid) != 0)) { + std::cerr << "Failed to set service.group name " << CONFIG_STRING(&config, "service.group") << " - " << gr->gr_gid << ":" << strerror(errno) << "\n"; + return 1; + } + } + + if (!CONFIG_STRING(&config, "service.user").empty()) { + struct passwd *pw; + if ((pw = getpwnam(CONFIG_STRING(&config, "service.user").c_str())) == NULL) { + std::cerr << "Invalid service.user name " << CONFIG_STRING(&config, "service.user") << "\n"; + return 1; + } + + if ((setuid(pw->pw_uid)) != 0) { + std::cerr << "Failed to set service.user name " << CONFIG_STRING(&config, "service.user") << " - " << pw->pw_uid << ":" << strerror(errno) << "\n"; + return 1; + } + } + setrlimit(RLIMIT_CORE, &limit); + } + + struct rlimit limit; + limit.rlim_max = RLIM_INFINITY; + limit.rlim_cur = RLIM_INFINITY; + setrlimit(RLIMIT_CORE, &limit); + + // create directories + try { + boost::filesystem::create_directories(CONFIG_STRING(&config, "service.working_dir")); + } + catch (...) { + std::cerr << "Can't create service.working_dir directory " << CONFIG_STRING(&config, "service.working_dir") << ".\n"; + return 1; + } +#endif + if (CONFIG_STRING(&config, "logging.config").empty()) { LoggerPtr root = log4cxx::Logger::getRootLogger(); #ifdef WIN32 @@ -231,54 +279,6 @@ int main(int argc, char **argv) log4cxx::PropertyConfigurator::configure(p); } -#ifndef WIN32 - if (!CONFIG_STRING(&config, "service.group").empty() ||!CONFIG_STRING(&config, "service.user").empty() ) { - struct rlimit limit; - getrlimit(RLIMIT_CORE, &limit); - - if (!CONFIG_STRING(&config, "service.group").empty()) { - struct group *gr; - if ((gr = getgrnam(CONFIG_STRING(&config, "service.group").c_str())) == NULL) { - LOG4CXX_ERROR(logger, "Invalid service.group name " << CONFIG_STRING(&config, "service.group")); - return 1; - } - - if (((setgid(gr->gr_gid)) != 0) || (initgroups(CONFIG_STRING(&config, "service.user").c_str(), gr->gr_gid) != 0)) { - LOG4CXX_ERROR(logger, "Failed to set service.group name " << CONFIG_STRING(&config, "service.group") << " - " << gr->gr_gid << ":" << strerror(errno)); - return 1; - } - } - - if (!CONFIG_STRING(&config, "service.user").empty()) { - struct passwd *pw; - if ((pw = getpwnam(CONFIG_STRING(&config, "service.user").c_str())) == NULL) { - LOG4CXX_ERROR(logger, "Invalid service.user name " << CONFIG_STRING(&config, "service.user")); - return 1; - } - - if ((setuid(pw->pw_uid)) != 0) { - LOG4CXX_ERROR(logger, "Failed to set service.user name " << CONFIG_STRING(&config, "service.user") << " - " << pw->pw_uid << ":" << strerror(errno)); - return 1; - } - } - setrlimit(RLIMIT_CORE, &limit); - } - - struct rlimit limit; - limit.rlim_max = RLIM_INFINITY; - limit.rlim_cur = RLIM_INFINITY; - setrlimit(RLIMIT_CORE, &limit); - - // create directories - try { - boost::filesystem::create_directories(CONFIG_STRING(&config, "service.working_dir")); - } - catch (...) { - std::cerr << "Can't create service.working_dir directory " << CONFIG_STRING(&config, "service.working_dir") << ".\n"; - return 1; - } -#endif - Swift::SimpleEventLoop eventLoop; Swift::BoostNetworkFactories *factories = new Swift::BoostNetworkFactories(&eventLoop); From 8e1c2b43a6e39a3e4fb0e1b642ca126a2595df5b Mon Sep 17 00:00:00 2001 From: Jan Kaluza Date: Thu, 10 Nov 2011 13:55:14 +0100 Subject: [PATCH 29/48] Send unavailable presences to particular resource which disconnects --- src/user.cpp | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/src/user.cpp b/src/user.cpp index c66da595..60054733 100644 --- a/src/user.cpp +++ b/src/user.cpp @@ -215,7 +215,24 @@ void User::handlePresence(Swift::Presence::ref presence) { return; } - sendCurrentPresence(); + + // User wants to disconnect this resource + if (!m_component->inServerMode()) { + if (presence->getType() == Swift::Presence::Unavailable) { + // Send unavailable presences for online contacts + m_rosterManager->sendUnavailablePresences(presence->getFrom()); + + // Send unavailable presence for transport contact itself + Swift::Presence::ref response = Swift::Presence::create(); + response->setTo(presence->getFrom()); + response->setFrom(m_component->getJID()); + response->setType(Swift::Presence::Unavailable); + m_component->getStanzaChannel()->sendPresence(response); + } + else { + sendCurrentPresence(); + } + } // Change legacy network presence From 2b836edd79856f640ec1bdcdf9a4fdfdde145e15 Mon Sep 17 00:00:00 2001 From: HanzZ Date: Fri, 11 Nov 2011 10:00:11 +0100 Subject: [PATCH 30/48] Send current presences to newly connected resource --- include/transport/user.h | 1 + src/user.cpp | 50 ++++++++++++++++++++++++++-------------- 2 files changed, 34 insertions(+), 17 deletions(-) diff --git a/include/transport/user.h b/include/transport/user.h index fe06277a..9d7f1118 100644 --- a/include/transport/user.h +++ b/include/transport/user.h @@ -135,6 +135,7 @@ class User : public Swift::EntityCapsProvider { time_t m_lastActivity; std::map m_legacyCaps; std::vector > m_filetransfers; + int m_resources; }; } diff --git a/src/user.cpp b/src/user.cpp index 60054733..aca25bae 100644 --- a/src/user.cpp +++ b/src/user.cpp @@ -43,7 +43,7 @@ namespace Transport { static LoggerPtr logger = Logger::getLogger("User"); User::User(const Swift::JID &jid, UserInfo &userInfo, Component *component, UserManager *userManager) { - m_jid = jid; + m_jid = jid.toBare(); m_data = NULL; m_component = component; @@ -54,6 +54,7 @@ User::User(const Swift::JID &jid, UserInfo &userInfo, Component *component, User m_connected = false; m_readyForConnect = false; m_ignoreDisconnect = false; + m_resources = 0; m_reconnectTimer = m_component->getNetworkFactories()->getTimerFactory()->createTimer(10000); m_reconnectTimer->onTick.connect(boost::bind(&User::onConnectingTimeout, this)); @@ -129,30 +130,37 @@ void User::sendCurrentPresence() { return; } - if (m_connected) { - Swift::Presence::ref highest = m_presenceOracle->getHighestPriorityPresence(m_jid.toBare()); - if (highest) { - Swift::Presence::ref response = Swift::Presence::create(highest); - response->setTo(m_jid); - response->setFrom(m_component->getJID()); - m_component->getStanzaChannel()->sendPresence(response); + std::vector presences = m_presenceOracle->getAllPresence(m_jid); + foreach(Swift::Presence::ref presence, presences) { + if (presence->getType() == Swift::Presence::Unavailable) { + continue; + } + + if (m_connected) { + Swift::Presence::ref highest = m_presenceOracle->getHighestPriorityPresence(m_jid.toBare()); + if (highest) { + Swift::Presence::ref response = Swift::Presence::create(highest); + response->setTo(presence->getFrom()); + response->setFrom(m_component->getJID()); + m_component->getStanzaChannel()->sendPresence(response); + } + else { + Swift::Presence::ref response = Swift::Presence::create(); + response->setTo(presence->getFrom()); + response->setFrom(m_component->getJID()); + response->setType(Swift::Presence::Unavailable); + m_component->getStanzaChannel()->sendPresence(response); + } } else { Swift::Presence::ref response = Swift::Presence::create(); - response->setTo(m_jid.toBare()); + response->setTo(presence->getFrom()); response->setFrom(m_component->getJID()); response->setType(Swift::Presence::Unavailable); + response->setStatus("Connecting"); m_component->getStanzaChannel()->sendPresence(response); } } - else { - Swift::Presence::ref response = Swift::Presence::create(); - response->setTo(m_jid.toBare()); - response->setFrom(m_component->getJID()); - response->setType(Swift::Presence::Unavailable); - response->setStatus("Connecting"); - m_component->getStanzaChannel()->sendPresence(response); - } } void User::setConnected(bool connected) { @@ -164,6 +172,8 @@ void User::setConnected(bool connected) { } void User::handlePresence(Swift::Presence::ref presence) { + int currentResourcesCount = m_presenceOracle->getAllPresence(m_jid).size(); + if (!m_connected) { // we are not connected to legacy network, so we should do it when disco#info arrive :) if (m_readyForConnect == false) { @@ -231,9 +241,15 @@ void User::handlePresence(Swift::Presence::ref presence) { } else { sendCurrentPresence(); + // This resource is new, so we have to send buddies presences + if (currentResourcesCount != m_resources) { + m_rosterManager->sendCurrentPresences(presence->getFrom()); + } } } + m_resources = currentResourcesCount; + // Change legacy network presence if (m_readyForConnect) { From 5b89dae8ca9afbb1c32e3947ebebd27b39da455d Mon Sep 17 00:00:00 2001 From: HanzZ Date: Fri, 11 Nov 2011 11:40:10 +0100 Subject: [PATCH 31/48] Forward messages to proper resources --- include/transport/conversation.h | 5 +++++ include/transport/conversationmanager.h | 2 ++ src/conversation.cpp | 9 +++++---- src/conversationmanager.cpp | 10 +++++++++- src/user.cpp | 2 ++ 5 files changed, 23 insertions(+), 5 deletions(-) diff --git a/include/transport/conversation.h b/include/transport/conversation.h index 8af86993..89f3a4ea 100644 --- a/include/transport/conversation.h +++ b/include/transport/conversation.h @@ -74,6 +74,10 @@ class Conversation { m_nickname = nickname; } + void setJID(const Swift::JID &jid) { + m_jid = jid; + } + /// Sends message to Legacy network. /// \param message Message. @@ -112,6 +116,7 @@ class Conversation { std::string m_nickname; std::string m_room; bool m_muc; + Swift::JID m_jid; }; } diff --git a/include/transport/conversationmanager.h b/include/transport/conversationmanager.h index 487e000a..17ca1467 100644 --- a/include/transport/conversationmanager.h +++ b/include/transport/conversationmanager.h @@ -73,6 +73,8 @@ class ConversationManager { /// \param conv Conversation. void removeConversation(Conversation *conv); + void resetResources(); + private: void handleMessageReceived(Swift::Message::ref message); diff --git a/src/conversation.cpp b/src/conversation.cpp index 81b1654d..96ae8144 100644 --- a/src/conversation.cpp +++ b/src/conversation.cpp @@ -37,6 +37,7 @@ Conversation::Conversation(ConversationManager *conversationManager, const std:: m_legacyName = legacyName; m_conversationManager->addConversation(this); m_muc = isMUC; + m_jid = m_conversationManager->getUser()->getJID().toBare(); } Conversation::~Conversation() { @@ -54,9 +55,9 @@ void Conversation::handleMessage(boost::shared_ptr &message, con else { message->setType(Swift::Message::Chat); } + if (message->getType() != Swift::Message::Groupchat) { - - message->setTo(m_conversationManager->getUser()->getJID().toBare()); + message->setTo(m_jid); // normal message if (nickname.empty()) { Buddy *buddy = m_conversationManager->getUser()->getRosterManager()->getBuddy(m_legacyName); @@ -83,7 +84,7 @@ void Conversation::handleMessage(boost::shared_ptr &message, con if (legacyName.find_last_of("@") != std::string::npos) { legacyName.replace(legacyName.find_last_of("@"), 1, "%"); // OK } - message->setTo(m_conversationManager->getUser()->getJID().toString()); + message->setTo(m_jid); message->setFrom(Swift::JID(legacyName, m_conversationManager->getComponent()->getJID().toBare(), nickname)); m_conversationManager->getComponent()->getStanzaChannel()->sendMessage(message); } @@ -99,7 +100,7 @@ void Conversation::handleParticipantChanged(const std::string &nick, int flag, i } } presence->setFrom(Swift::JID(legacyName, m_conversationManager->getComponent()->getJID().toBare(), nickname)); - presence->setTo(m_conversationManager->getUser()->getJID().toString()); + presence->setTo(m_jid); presence->setType(Swift::Presence::Available); if (!statusMessage.empty()) diff --git a/src/conversationmanager.cpp b/src/conversationmanager.cpp index 2f422ff3..a83803be 100644 --- a/src/conversationmanager.cpp +++ b/src/conversationmanager.cpp @@ -62,6 +62,12 @@ void ConversationManager::removeConversation(Conversation *conv) { m_convs.erase(conv->getLegacyName()); } +void ConversationManager::resetResources() { + for (std::map::const_iterator it = m_convs.begin(); it != m_convs.end(); it++) { + (*it).second->setJID(m_user->getJID().toBare()); + } +} + void ConversationManager::handleMessageReceived(Swift::Message::ref message) { // std::string name = message->getTo().getUnescapedNode(); // if (name.find_last_of("%") != std::string::npos) { // OK when commented @@ -87,7 +93,9 @@ void ConversationManager::handleMessageReceived(Swift::Message::ref message) { } } + // update resource and send the message + m_convs[name]->setJID(message->getFrom()); m_convs[name]->sendMessage(message); } -} \ No newline at end of file +} diff --git a/src/user.cpp b/src/user.cpp index aca25bae..7049dc33 100644 --- a/src/user.cpp +++ b/src/user.cpp @@ -174,6 +174,8 @@ void User::setConnected(bool connected) { void User::handlePresence(Swift::Presence::ref presence) { int currentResourcesCount = m_presenceOracle->getAllPresence(m_jid).size(); + m_conversationManager->resetResources(); + if (!m_connected) { // we are not connected to legacy network, so we should do it when disco#info arrive :) if (m_readyForConnect == false) { From c9288e615bd20092382b68cd8f3694f956e7f219 Mon Sep 17 00:00:00 2001 From: HanzZ Date: Fri, 11 Nov 2011 15:41:10 +0100 Subject: [PATCH 32/48] Do not ask for encoding --- src/userregistration.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/src/userregistration.cpp b/src/userregistration.cpp index 7b05216f..88354811 100644 --- a/src/userregistration.cpp +++ b/src/userregistration.cpp @@ -225,14 +225,14 @@ bool UserRegistration::handleGetRequest(const Swift::JID& from, const Swift::JID language->setValue(CONFIG_STRING(m_config, "registration.language")); form->addField(language); - TextSingleFormField::ref encoding = TextSingleFormField::create(); - encoding->setName("encoding"); - encoding->setLabel((("Encoding"))); - if (registered) - encoding->setValue(res.encoding); - else - encoding->setValue(CONFIG_STRING(m_config, "registration.encoding")); - form->addField(encoding); +// TextSingleFormField::ref encoding = TextSingleFormField::create(); +// encoding->setName("encoding"); +// encoding->setLabel((("Encoding"))); +// if (registered) +// encoding->setValue(res.encoding); +// else +// encoding->setValue(CONFIG_STRING(m_config, "registration.encoding")); +// form->addField(encoding); if (registered) { BooleanFormField::ref boolean = BooleanFormField::create(); From ece0179d3ebeccb2cbf3247214c452b9410759f4 Mon Sep 17 00:00:00 2001 From: HanzZ Date: Sat, 12 Nov 2011 12:56:56 +0100 Subject: [PATCH 33/48] Fixed registration form --- src/config.cpp | 6 +++--- src/userregistration.cpp | 3 ++- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/config.cpp b/src/config.cpp index 0b0a5233..b72caa86 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -82,10 +82,10 @@ bool Config::load(std::istream &ifs, boost::program_options::options_description ("identity.type", value()->default_value(""), "Type of transport ('icq','msn','gg','irc', ...)") ("registration.enable_public_registration", value()->default_value(true), "True if users should be able to register.") ("registration.language", value()->default_value("en"), "Default language for registration form") - ("registration.instructions", value()->default_value(""), "Instructions showed to user in registration form") - ("registration.username_field", value()->default_value(""), "Label for username field") + ("registration.instructions", value()->default_value("Enter your legacy network username and password."), "Instructions showed to user in registration form") + ("registration.username_label", value()->default_value("Legacy network username:"), "Label for username field") ("registration.username_mask", value()->default_value(""), "Username mask") - ("registration.encoding", value()->default_value("en"), "Default encoding in registration form") + ("registration.encoding", value()->default_value("utf8"), "Default encoding in registration form") ("database.type", value()->default_value("none"), "Database type.") ("database.database", value()->default_value(""), "Database used to store data") ("database.server", value()->default_value("localhost"), "Database server.") diff --git a/src/userregistration.cpp b/src/userregistration.cpp index 88354811..e1a1731a 100644 --- a/src/userregistration.cpp +++ b/src/userregistration.cpp @@ -181,7 +181,7 @@ bool UserRegistration::handleGetRequest(const Swift::JID& from, const Swift::JID bool registered = m_storageBackend->getUser(barejid, res); std::string instructions = CONFIG_STRING(m_config, "registration.instructions"); - std::string usernameField = CONFIG_STRING(m_config, "registration.username_field"); + std::string usernameField = CONFIG_STRING(m_config, "registration.username_label"); // normal jabber:iq:register reg->setInstructions(instructions); @@ -219,6 +219,7 @@ bool UserRegistration::handleGetRequest(const Swift::JID& from, const Swift::JID ListSingleFormField::ref language = ListSingleFormField::create(); language->setName("language"); language->setLabel((("Language"))); + language->addOption(Swift::FormField::Option(CONFIG_STRING(m_config, "registration.language"), CONFIG_STRING(m_config, "registration.language"))); if (registered) language->setValue(res.language); else From 2f61148b10d93e9f80c4fa3856125335b4463809 Mon Sep 17 00:00:00 2001 From: HanzZ Date: Mon, 14 Nov 2011 15:42:30 +0100 Subject: [PATCH 34/48] Fix potential crashes in statsresponder --- src/statsresponder.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/statsresponder.cpp b/src/statsresponder.cpp index d91b8fea..802a1bbd 100644 --- a/src/statsresponder.cpp +++ b/src/statsresponder.cpp @@ -91,10 +91,16 @@ bool StatsResponder::handleGetRequest(const Swift::JID& from, const Swift::JID& Swift::StatusShow s; std::string statusMessage; for (std::map::const_iterator it = m_userManager->getUsers().begin(); it != m_userManager->getUsers().end(); it++) { + if (!(*it).second) { + continue; + } const RosterManager::BuddiesMap &buddies = (*it).second->getRosterManager()->getBuddies(); contactsTotal += buddies.size(); - for(RosterManager::BuddiesMap::const_iterator it = buddies.begin(); it != buddies.end(); it++) { - if (!(*it).second->getStatus(s, statusMessage)) + for(RosterManager::BuddiesMap::const_iterator bt = buddies.begin(); bt != buddies.end(); bt++) { + if (!(*bt).second) { + continue; + } + if (!(*bt).second->getStatus(s, statusMessage)) continue; if (s.getType() != Swift::StatusShow::None) { contactsOnline++; From bcf60737f91990c417f36300f385ccc1d3c2a8e1 Mon Sep 17 00:00:00 2001 From: HanzZ Date: Mon, 14 Nov 2011 16:14:30 +0100 Subject: [PATCH 35/48] Don't send empty units/values in stats payload --- .../Serializer/PayloadSerializers/StatsSerializer.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/include/Swiften/Serializer/PayloadSerializers/StatsSerializer.cpp b/include/Swiften/Serializer/PayloadSerializers/StatsSerializer.cpp index e670a6ee..3675550f 100644 --- a/include/Swiften/Serializer/PayloadSerializers/StatsSerializer.cpp +++ b/include/Swiften/Serializer/PayloadSerializers/StatsSerializer.cpp @@ -23,8 +23,12 @@ std::string StatsSerializer::serializePayload(boost::shared_ptr st foreach(const StatsPayload::Item& item, stats->getItems()) { boost::shared_ptr statElement(new XMLElement("stat")); statElement->setAttribute("name", item.getName()); - statElement->setAttribute("units", item.getUnits()); - statElement->setAttribute("value", item.getValue()); + if (!item.getUnits().empty()) { + statElement->setAttribute("units", item.getUnits()); + } + if (!item.getUnits().empty()) { + statElement->setAttribute("value", item.getUnits()); + } queryElement.addNode(statElement); } From 6cabfd73ff78a162c2926566257229de0d7cca8d Mon Sep 17 00:00:00 2001 From: HanzZ Date: Mon, 14 Nov 2011 18:38:58 +0100 Subject: [PATCH 36/48] Fixed crash in getJIDWithFeature --- src/rostermanager.cpp | 24 +++++++++--------------- src/user.cpp | 4 ++++ 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/src/rostermanager.cpp b/src/rostermanager.cpp index 377ddffd..db888909 100644 --- a/src/rostermanager.cpp +++ b/src/rostermanager.cpp @@ -141,8 +141,6 @@ void RosterManager::handleBuddyChanged(Buddy *buddy) { } void RosterManager::setBuddyCallback(Buddy *buddy) { - m_setBuddyTimer->onTick.disconnect(boost::bind(&RosterManager::setBuddyCallback, this, buddy)); - LOG4CXX_INFO(logger, "Associating buddy " << buddy->getName() << " with " << m_user->getJID().toString()); m_buddies[buddy->getName()] = buddy; onBuddySet(buddy); @@ -153,21 +151,17 @@ void RosterManager::setBuddyCallback(Buddy *buddy) { sendBuddyRosterPush(buddy); } else { - if (m_setBuddyTimer->onTick.empty()) { - m_setBuddyTimer->stop(); - - if (m_supportRemoteRoster) { - sendBuddyRosterPush(buddy); + if (m_supportRemoteRoster) { + sendBuddyRosterPush(buddy); + } + else { + // Send RIE only if there's resource which supports it. + Swift::JID jidWithRIE = m_user->getJIDWithFeature("http://jabber.org/protocol/rosterx"); + if (jidWithRIE.isValid()) { + m_RIETimer->start(); } else { - // Send RIE only if there's resource which supports it. - Swift::JID jidWithRIE = m_user->getJIDWithFeature("http://jabber.org/protocol/rosterx"); - if (jidWithRIE.isValid()) { - m_RIETimer->start(); - } - else { - sendBuddySubscribePresence(buddy); - } + sendBuddySubscribePresence(buddy); } } } diff --git a/src/user.cpp b/src/user.cpp index 7049dc33..47d63065 100644 --- a/src/user.cpp +++ b/src/user.cpp @@ -97,6 +97,10 @@ Swift::JID User::getJIDWithFeature(const std::string &feature) { else { continue; } + + if (!discoInfo) { + continue; + } #else continue; #endif From 5811d83e0dd98670811402530bd912b518a79e55 Mon Sep 17 00:00:00 2001 From: HanzZ Date: Mon, 14 Nov 2011 19:18:43 +0100 Subject: [PATCH 37/48] getValue... --- .../Swiften/Serializer/PayloadSerializers/StatsSerializer.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/Swiften/Serializer/PayloadSerializers/StatsSerializer.cpp b/include/Swiften/Serializer/PayloadSerializers/StatsSerializer.cpp index 3675550f..0bd85f5f 100644 --- a/include/Swiften/Serializer/PayloadSerializers/StatsSerializer.cpp +++ b/include/Swiften/Serializer/PayloadSerializers/StatsSerializer.cpp @@ -26,8 +26,8 @@ std::string StatsSerializer::serializePayload(boost::shared_ptr st if (!item.getUnits().empty()) { statElement->setAttribute("units", item.getUnits()); } - if (!item.getUnits().empty()) { - statElement->setAttribute("value", item.getUnits()); + if (!item.getValue().empty()) { + statElement->setAttribute("value", item.getValue()); } queryElement.addNode(statElement); From b99313a73a915fbe30f512cf3cca89a4b5e4ce8c Mon Sep 17 00:00:00 2001 From: HanzZ Date: Mon, 14 Nov 2011 20:11:30 +0100 Subject: [PATCH 38/48] Create logging dir and change owner to user we run as --- spectrum/src/main.cpp | 93 +++++++++++++++++++++++++++++++------------ 1 file changed, 67 insertions(+), 26 deletions(-) diff --git a/spectrum/src/main.cpp b/spectrum/src/main.cpp index c52011f5..4e93edb5 100644 --- a/spectrum/src/main.cpp +++ b/spectrum/src/main.cpp @@ -12,6 +12,7 @@ #include "transport/util.h" #include "Swiften/EventLoop/SimpleEventLoop.h" #include +#include #ifndef WIN32 #include "sys/signal.h" #include @@ -205,6 +206,72 @@ int main(int argc, char **argv) } #endif + if (CONFIG_STRING(&config, "logging.config").empty()) { + LoggerPtr root = log4cxx::Logger::getRootLogger(); +#ifdef WIN32 + root->addAppender(new ConsoleAppender(new PatternLayout(L"%d %-5p %c: %m%n"))); +#else + root->addAppender(new ConsoleAppender(new PatternLayout("%d %-5p %c: %m%n"))); +#endif + } + else { + log4cxx::helpers::Properties p; + log4cxx::helpers::FileInputStream *istream = new log4cxx::helpers::FileInputStream(CONFIG_STRING(&config, "logging.config")); + + p.load(istream); + LogString pid, jid; + log4cxx::helpers::Transcoder::decode(boost::lexical_cast(getpid()), pid); + log4cxx::helpers::Transcoder::decode(CONFIG_STRING(&config, "service.jid"), jid); +#ifdef WIN32 + p.setProperty(L"pid", pid); + p.setProperty(L"jid", jid); +#else + p.setProperty("pid", pid); + p.setProperty("jid", jid); +#endif + + std::string dir; + BOOST_FOREACH(const log4cxx::LogString &prop, p.propertyNames()) { + if (boost::ends_with(prop, ".File")) { + dir = p.get(prop); + boost::replace_all(dir, "{$jid}", jid); + break; + } + } + + if (!dir.empty()) { + // create directories + try { + boost::filesystem::create_directories( + boost::filesystem::path(dir).parent_path().string() + ); + } + catch (...) { + std::cerr << "Can't create logging directory directory " << boost::filesystem::path(dir).parent_path().string() << ".\n"; + return 1; + } + +#ifndef WIN32 + if (!CONFIG_STRING(&config, "service.group").empty() && !CONFIG_STRING(&config, "service.user").empty()) { + struct group *gr; + if ((gr = getgrnam(CONFIG_STRING(&config, "service.group").c_str())) == NULL) { + std::cerr << "Invalid service.group name " << CONFIG_STRING(&config, "service.group") << "\n"; + return 1; + } + struct passwd *pw; + if ((pw = getpwnam(CONFIG_STRING(&config, "service.user").c_str())) == NULL) { + std::cerr << "Invalid service.user name " << CONFIG_STRING(&config, "service.user") << "\n"; + return 1; + } + chown(dir.c_str(), pw->pw_uid, gr->gr_gid); + } + +#endif + } + + log4cxx::PropertyConfigurator::configure(p); + } + #ifndef WIN32 if (!CONFIG_STRING(&config, "service.group").empty() ||!CONFIG_STRING(&config, "service.user").empty() ) { struct rlimit limit; @@ -253,32 +320,6 @@ int main(int argc, char **argv) } #endif - if (CONFIG_STRING(&config, "logging.config").empty()) { - LoggerPtr root = log4cxx::Logger::getRootLogger(); -#ifdef WIN32 - root->addAppender(new ConsoleAppender(new PatternLayout(L"%d %-5p %c: %m%n"))); -#else - root->addAppender(new ConsoleAppender(new PatternLayout("%d %-5p %c: %m%n"))); -#endif - } - else { - log4cxx::helpers::Properties p; - log4cxx::helpers::FileInputStream *istream = new log4cxx::helpers::FileInputStream(CONFIG_STRING(&config, "logging.config")); - - p.load(istream); - LogString pid, jid; - log4cxx::helpers::Transcoder::decode(boost::lexical_cast(getpid()), pid); - log4cxx::helpers::Transcoder::decode(CONFIG_STRING(&config, "service.jid"), jid); -#ifdef WIN32 - 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; Swift::BoostNetworkFactories *factories = new Swift::BoostNetworkFactories(&eventLoop); From 2626035bc26c7f61024f8c79fbec0f4b6fee7505 Mon Sep 17 00:00:00 2001 From: HanzZ Date: Mon, 14 Nov 2011 20:29:57 +0100 Subject: [PATCH 39/48] Disconnect if ping is not received for 30 seconds --- backends/libpurple/main.cpp | 6 ++++++ include/transport/networkplugin.h | 3 ++- plugin/src/networkplugin.cpp | 7 +++++++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/backends/libpurple/main.cpp b/backends/libpurple/main.cpp index bbfcbb1c..65d719e3 100644 --- a/backends/libpurple/main.cpp +++ b/backends/libpurple/main.cpp @@ -1230,6 +1230,11 @@ static gboolean disconnectMe(void *data) { return FALSE; } +static gboolean pingTimeout(void *data) { + np->checkPing(); + return TRUE; +} + static void connection_report_disconnect(PurpleConnection *gc, PurpleConnectionError reason, const char *text){ PurpleAccount *account = purple_connection_get_account(gc); np->handleDisconnected(np->m_accounts[account], (int) reason, text ? text : ""); @@ -1960,6 +1965,7 @@ int main(int argc, char **argv) { m_sock = create_socket(host, port); purple_input_add(m_sock, PURPLE_INPUT_READ, &transportDataReceived, NULL); + purple_timeout_add_seconds(30, pingTimeout, NULL); np = new SpectrumNetworkPlugin(host, port); bool libev = KEYFILE_STRING("service", "eventloop") == "libev"; diff --git a/include/transport/networkplugin.h b/include/transport/networkplugin.h index 334fab8b..8bfbf221 100644 --- a/include/transport/networkplugin.h +++ b/include/transport/networkplugin.h @@ -214,7 +214,8 @@ class NetworkPlugin { virtual void handleExitRequest() { exit(1); } void handleDataRead(std::string &data); virtual void sendData(const std::string &string) {} - + + void checkPing(); private: void handleLoginPayload(const std::string &payload); diff --git a/plugin/src/networkplugin.cpp b/plugin/src/networkplugin.cpp index 82aa3bb4..fb5d58fb 100644 --- a/plugin/src/networkplugin.cpp +++ b/plugin/src/networkplugin.cpp @@ -553,6 +553,13 @@ void NetworkPlugin::send(const std::string &data) { sendData(std::string(header, 4) + data); } +void NetworkPlugin::checkPing() { + if (m_pingReceived == false) { + handleExitRequest(); + } + m_pingReceived = false; +} + void NetworkPlugin::sendPong() { m_pingReceived = true; std::string message; From e17059a6a67799cb35bc06b958f2aa4eff7e0091 Mon Sep 17 00:00:00 2001 From: HanzZ Date: Tue, 15 Nov 2011 20:24:11 +0100 Subject: [PATCH 40/48] Create working_dir before switching to it when running as daemon --- spectrum/src/main.cpp | 53 +++++++++++++++++++++++++++---------------- 1 file changed, 33 insertions(+), 20 deletions(-) diff --git a/spectrum/src/main.cpp b/spectrum/src/main.cpp index 4e93edb5..573ff3c8 100644 --- a/spectrum/src/main.cpp +++ b/spectrum/src/main.cpp @@ -187,19 +187,41 @@ int main(int argc, char **argv) return 1; } -#ifndef WIN32 - if (!no_daemon) { - // create directories - try { - boost::filesystem::create_directories( - boost::filesystem::path(CONFIG_STRING(&config, "service.pidfile")).parent_path().string() - ); - } - catch (...) { - std::cerr << "Can't create service.pidfile directory " << boost::filesystem::path(CONFIG_STRING(&config, "service.pidfile")).parent_path().string() << ".\n"; + // create directories + try { + boost::filesystem::create_directories( + boost::filesystem::path(CONFIG_STRING(&config, "service.pidfile")).parent_path().string() + ); + } + catch (...) { + std::cerr << "Can't create service.pidfile directory " << boost::filesystem::path(CONFIG_STRING(&config, "service.pidfile")).parent_path().string() << ".\n"; + return 1; + } + // create directories + try { + boost::filesystem::create_directories(CONFIG_STRING(&config, "service.working_dir")); + } + catch (...) { + std::cerr << "Can't create service.working_dir directory " << CONFIG_STRING(&config, "service.working_dir") << ".\n"; + return 1; + } + + if (!CONFIG_STRING(&config, "service.group").empty() ||!CONFIG_STRING(&config, "service.user").empty() ) { + struct group *gr; + if ((gr = getgrnam(CONFIG_STRING(&config, "service.group").c_str())) == NULL) { + std::cerr << "Invalid service.group name " << CONFIG_STRING(&config, "service.group") << "\n"; return 1; } + struct passwd *pw; + if ((pw = getpwnam(CONFIG_STRING(&config, "service.user").c_str())) == NULL) { + std::cerr << "Invalid service.user name " << CONFIG_STRING(&config, "service.user") << "\n"; + return 1; + } + chown(CONFIG_STRING(&config, "service.working_dir").c_str(), pw->pw_uid, gr->gr_gid); + } +#ifndef WIN32 + if (!no_daemon) { // daemonize daemonize(CONFIG_STRING(&config, "service.working_dir").c_str(), CONFIG_STRING(&config, "service.pidfile").c_str()); // removeOldIcons(CONFIG_STRING(&config, "service.working_dir") + "/icons"); @@ -234,7 +256,7 @@ int main(int argc, char **argv) BOOST_FOREACH(const log4cxx::LogString &prop, p.propertyNames()) { if (boost::ends_with(prop, ".File")) { dir = p.get(prop); - boost::replace_all(dir, "{$jid}", jid); + boost::replace_all(dir, "${jid}", jid); break; } } @@ -309,15 +331,6 @@ int main(int argc, char **argv) limit.rlim_max = RLIM_INFINITY; limit.rlim_cur = RLIM_INFINITY; setrlimit(RLIMIT_CORE, &limit); - - // create directories - try { - boost::filesystem::create_directories(CONFIG_STRING(&config, "service.working_dir")); - } - catch (...) { - std::cerr << "Can't create service.working_dir directory " << CONFIG_STRING(&config, "service.working_dir") << ".\n"; - return 1; - } #endif Swift::SimpleEventLoop eventLoop; From 84de9b0ca6d80b2e2a0677621838b0f18f7d0d22 Mon Sep 17 00:00:00 2001 From: Jan Kaluza Date: Wed, 16 Nov 2011 08:56:28 +0100 Subject: [PATCH 41/48] Removed examples and tests since they were not used/compiled anymore --- CMakeLists.txt | 2 - examples/CMakeLists.txt | 6 -- .../external_network_plugin/CMakeLists.txt | 13 ---- examples/external_network_plugin/main.cpp | 39 ----------- .../external_network_plugin/pbnetwork.proto | 29 -------- examples/external_network_plugin/plugin.py | 29 -------- examples/server_connect/CMakeLists.txt | 6 -- examples/server_connect/main.cpp | 36 ---------- examples/server_connect/sample.cfg | 6 -- examples/usermanager/CMakeLists.txt | 6 -- examples/usermanager/main.cpp | 36 ---------- examples/usermanager/sample.cfg | 9 --- tests/CMakeLists.txt | 5 -- tests/login/CMakeLists.txt | 6 -- tests/login/main.cpp | 44 ------------ tests/login_bad_name/CMakeLists.txt | 6 -- tests/login_bad_name/main.cpp | 45 ------------ tests/login_bad_name2/.nolibircclient-qt | 0 tests/login_bad_name2/CMakeLists.txt | 6 -- tests/login_bad_name2/main.cpp | 45 ------------ tests/runtests.py | 70 ------------------- 21 files changed, 444 deletions(-) delete mode 100644 examples/CMakeLists.txt delete mode 100644 examples/external_network_plugin/CMakeLists.txt delete mode 100644 examples/external_network_plugin/main.cpp delete mode 100644 examples/external_network_plugin/pbnetwork.proto delete mode 100644 examples/external_network_plugin/plugin.py delete mode 100644 examples/server_connect/CMakeLists.txt delete mode 100644 examples/server_connect/main.cpp delete mode 100644 examples/server_connect/sample.cfg delete mode 100644 examples/usermanager/CMakeLists.txt delete mode 100644 examples/usermanager/main.cpp delete mode 100644 examples/usermanager/sample.cfg delete mode 100644 tests/CMakeLists.txt delete mode 100644 tests/login/CMakeLists.txt delete mode 100644 tests/login/main.cpp delete mode 100644 tests/login_bad_name/CMakeLists.txt delete mode 100644 tests/login_bad_name/main.cpp delete mode 100644 tests/login_bad_name2/.nolibircclient-qt delete mode 100644 tests/login_bad_name2/CMakeLists.txt delete mode 100644 tests/login_bad_name2/main.cpp delete mode 100644 tests/runtests.py diff --git a/CMakeLists.txt b/CMakeLists.txt index 16700072..d7dfa8bc 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -170,10 +170,8 @@ include_directories(${OPENSSL_INCLUDE_DIR}) ADD_SUBDIRECTORY(src) ADD_SUBDIRECTORY(plugin) ADD_SUBDIRECTORY(include) -#ADD_SUBDIRECTORY(examples) ADD_SUBDIRECTORY(spectrum) ADD_SUBDIRECTORY(backends) -#ADD_SUBDIRECTORY(tests) if (NOT WIN32) ADD_SUBDIRECTORY(spectrum_manager) endif() diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt deleted file mode 100644 index 8d793b28..00000000 --- a/examples/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -ADD_SUBDIRECTORY(server_connect) -ADD_SUBDIRECTORY(usermanager) - -if (PROTOBUF_FOUND) - ADD_SUBDIRECTORY(external_network_plugin) -endif() diff --git a/examples/external_network_plugin/CMakeLists.txt b/examples/external_network_plugin/CMakeLists.txt deleted file mode 100644 index e3c24cf4..00000000 --- a/examples/external_network_plugin/CMakeLists.txt +++ /dev/null @@ -1,13 +0,0 @@ -FILE(GLOB SRC *.cpp) - -add_custom_command( - OUTPUT "${CMAKE_CURRENT_BINARY_DIR}/pbnetwork_pb2.py" - COMMAND ${PROTOBUF_PROTOC_EXECUTABLE} - ARGS --python_out ${CMAKE_CURRENT_BINARY_DIR} pbnetwork.proto - COMMENT "Running Py protocol buffer compiler on pbnetwork.proto" - VERBATIM ) - -ADD_EXECUTABLE(external_network_plugin ${SRC} ${CMAKE_CURRENT_BINARY_DIR}/pbnetwork_pb2.py) - -TARGET_LINK_LIBRARIES(external_network_plugin transport ${SWIFTEN_LIBRARIES}) - diff --git a/examples/external_network_plugin/main.cpp b/examples/external_network_plugin/main.cpp deleted file mode 100644 index 6edd0e76..00000000 --- a/examples/external_network_plugin/main.cpp +++ /dev/null @@ -1,39 +0,0 @@ -#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/networkpluginserver.h" -#include "Swiften/EventLoop/SimpleEventLoop.h" - -using namespace Transport; - -int main(void) -{ - Config config; - if (!config.load("sample.cfg")) { - std::cout << "Can't open sample.cfg configuration file.\n"; - return 1; - } - - Swift::SimpleEventLoop eventLoop; - Component transport(&eventLoop, &config, NULL); - Logger logger(&transport); - - SQLite3Backend sql(&config); - logger.setStorageBackend(&sql); - if (!sql.connect()) { - std::cout << "Can't connect to database.\n"; - } - - UserManager userManager(&transport, &sql); - UserRegistration userRegistration(&transport, &userManager, &sql); - logger.setUserRegistration(&userRegistration); - logger.setUserManager(&userManager); - - NetworkPluginServer plugin(&transport, &config, &userManager); - - transport.connect(); - eventLoop.run(); -} diff --git a/examples/external_network_plugin/pbnetwork.proto b/examples/external_network_plugin/pbnetwork.proto deleted file mode 100644 index d3c2231a..00000000 --- a/examples/external_network_plugin/pbnetwork.proto +++ /dev/null @@ -1,29 +0,0 @@ -package pbnetwork; - -message Connected { - required string name = 1; -} - -message Disconnected { - required string name = 1; - required int32 error = 2; - optional string message = 3; -} - -message Login { - required string protocol = 1; - required string legacyName = 2; - required string password = 3; -} - -message WrapperMessage { - enum Type { - TYPE_CONNECTED = 1; - TYPE_DISCONNECTED = 2; - TYPE_LOGIN = 3; - TYPE_LOGOUT = 4; - } - required Type type = 1; - required bytes payload = 2; -} -; \ No newline at end of file diff --git a/examples/external_network_plugin/plugin.py b/examples/external_network_plugin/plugin.py deleted file mode 100644 index 51a5c58e..00000000 --- a/examples/external_network_plugin/plugin.py +++ /dev/null @@ -1,29 +0,0 @@ -#! /usr/bin/python - -from pbnetwork_pb2 import * -import time -import sys -import socket -import struct - - -connected = Connected() -connected.name = "hanzz.k@gmail.com" - -wrapper = WrapperMessage() -wrapper.type = WrapperMessage.TYPE_CONNECTED -wrapper.payload = connected.SerializeToString() - -sck = socket.socket() -sck.connect(("localhost", 10000)) - -message = wrapper.SerializeToString(); -header = struct.pack(">L", len(message)) -print [header] -sck.send(header + message+header + message); -sck.send(header + message); -sck.send(header + message); -sck.send(header + message); -sck.send(header + message); - -print sck.recv(255) diff --git a/examples/server_connect/CMakeLists.txt b/examples/server_connect/CMakeLists.txt deleted file mode 100644 index d71144af..00000000 --- a/examples/server_connect/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -FILE(GLOB SRC *.cpp) - -ADD_EXECUTABLE(transport_server_connect ${SRC}) - -TARGET_LINK_LIBRARIES(transport_server_connect transport ${SWIFTEN_LIBRARIES}) - diff --git a/examples/server_connect/main.cpp b/examples/server_connect/main.cpp deleted file mode 100644 index 0682e128..00000000 --- a/examples/server_connect/main.cpp +++ /dev/null @@ -1,36 +0,0 @@ -#include "transport/config.h" -#include "transport/transport.h" -#include "transport/logger.h" -#include "Swiften/EventLoop/SimpleEventLoop.h" -#include "Swiften/Network/BoostTimerFactory.h" -#include "Swiften/Network/BoostIOServiceThread.h" -#include "Swiften/Network/BoostNetworkFactories.h" -#include "Swiften/Server/UserRegistry.h" -#include "Swiften/Server/Server.h" -#include "Swiften/Swiften.h" - -using namespace Transport; - -class DummyUserRegistry : public Swift::UserRegistry { - public: - DummyUserRegistry() {} - - virtual bool isValidUserPassword(const Swift::JID&user, const Swift::SafeByteArray&) const { - onPasswordValid(user.toString()); - return true; - } -}; - -int main(void) -{ - Swift::logging = true; - - Swift::SimpleEventLoop loop; - - Swift::BoostNetworkFactories *m_factories = new Swift::BoostNetworkFactories(&loop); - DummyUserRegistry dummyregistry; - Swift::Server server(&loop, m_factories, &dummyregistry, "localhost", 5222); - server.start(); - - loop.run(); -} diff --git a/examples/server_connect/sample.cfg b/examples/server_connect/sample.cfg deleted file mode 100644 index 5db19bbe..00000000 --- a/examples/server_connect/sample.cfg +++ /dev/null @@ -1,6 +0,0 @@ -[service] -jid = icq.localhost -password = secret -server = 127.0.0.1 -port = 5222 -server_mode = 1 diff --git a/examples/usermanager/CMakeLists.txt b/examples/usermanager/CMakeLists.txt deleted file mode 100644 index 1438b57d..00000000 --- a/examples/usermanager/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -FILE(GLOB SRC *.cpp) - -ADD_EXECUTABLE(transport_usermanager ${SRC}) - -TARGET_LINK_LIBRARIES(transport_usermanager transport ${SWIFTEN_LIBRARIES}) - diff --git a/examples/usermanager/main.cpp b/examples/usermanager/main.cpp deleted file mode 100644 index c181334e..00000000 --- a/examples/usermanager/main.cpp +++ /dev/null @@ -1,36 +0,0 @@ -#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 "Swiften/EventLoop/SimpleEventLoop.h" - -using namespace Transport; - -int main(void) -{ - Config config; - if (!config.load("sample.cfg")) { - std::cout << "Can't open sample.cfg configuration file.\n"; - return 1; - } - - Swift::SimpleEventLoop eventLoop; - Component transport(&eventLoop, &config, NULL); - Logger logger(&transport); - - SQLite3Backend sql(&config); - logger.setStorageBackend(&sql); - if (!sql.connect()) { - std::cout << "Can't connect to database.\n"; - } - - UserManager userManager(&transport, &sql); - UserRegistration userRegistration(&transport, &userManager, &sql); - logger.setUserRegistration(&userRegistration); - logger.setUserManager(&userManager); - - transport.connect(); - eventLoop.run(); -} diff --git a/examples/usermanager/sample.cfg b/examples/usermanager/sample.cfg deleted file mode 100644 index fc90fdf8..00000000 --- a/examples/usermanager/sample.cfg +++ /dev/null @@ -1,9 +0,0 @@ -[service] -jid = icq.localhost -password = secret -server = 127.0.0.1 -port = 8888 - -[database] -database = test.sql -prefix=icq diff --git a/tests/CMakeLists.txt b/tests/CMakeLists.txt deleted file mode 100644 index 0688a10f..00000000 --- a/tests/CMakeLists.txt +++ /dev/null @@ -1,5 +0,0 @@ -ADD_SUBDIRECTORY(login) -ADD_SUBDIRECTORY(login_bad_name) -ADD_SUBDIRECTORY(login_bad_name2) - -add_custom_target(tests python runtests.py WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) diff --git a/tests/login/CMakeLists.txt b/tests/login/CMakeLists.txt deleted file mode 100644 index d153150f..00000000 --- a/tests/login/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -FILE(GLOB SRC *.cpp) - -ADD_EXECUTABLE(login_test ${SRC}) - - TARGET_LINK_LIBRARIES(login_test transport ${SWIFTEN_LIBRARIES}) - diff --git a/tests/login/main.cpp b/tests/login/main.cpp deleted file mode 100644 index 4ca5c246..00000000 --- a/tests/login/main.cpp +++ /dev/null @@ -1,44 +0,0 @@ -#include -#include - -#include -#include - -using namespace Swift; -using namespace boost; - -Client* client; - -static void handleDisconnected(const boost::optional &) { - exit(1); -} - -static void handleConnected() { - exit(0); -} - -static void handleMessageReceived(Message::ref message) { - // Echo back the incoming message - message->setTo(message->getFrom()); - message->setFrom(JID()); - client->sendMessage(message); -} - -int main(int, char **argv) { - SimpleEventLoop eventLoop; - BoostNetworkFactories networkFactories(&eventLoop); - - client = new Client(argv[1], argv[2], &networkFactories); - client->setAlwaysTrustCertificates(); - client->onConnected.connect(&handleConnected); - client->onDisconnected.connect(bind(&handleDisconnected, _1)); - client->onMessageReceived.connect(bind(&handleMessageReceived, _1)); - Swift::ClientOptions opt; - opt.allowPLAINWithoutTLS = true; - client->connect(opt); - - eventLoop.run(); - - delete client; - return 0; -} diff --git a/tests/login_bad_name/CMakeLists.txt b/tests/login_bad_name/CMakeLists.txt deleted file mode 100644 index 5536b9f7..00000000 --- a/tests/login_bad_name/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -FILE(GLOB SRC *.cpp) - -ADD_EXECUTABLE(login_bad_name_test ${SRC}) - -TARGET_LINK_LIBRARIES(login_bad_name_test transport ${SWIFTEN_LIBRARIES}) - diff --git a/tests/login_bad_name/main.cpp b/tests/login_bad_name/main.cpp deleted file mode 100644 index 652fb61a..00000000 --- a/tests/login_bad_name/main.cpp +++ /dev/null @@ -1,45 +0,0 @@ -#include -#include - -#include -#include - -using namespace Swift; -using namespace boost; - -Client* client; - -static void handleDisconnected(const boost::optional &error) { - exit(error->getType() != ClientError::AuthenticationFailedError); -} - -static void handleConnected() { - exit(1); -} - -static void handleMessageReceived(Message::ref message) { - // Echo back the incoming message - message->setTo(message->getFrom()); - message->setFrom(JID()); - client->sendMessage(message); -} - -int main(int, char **argv) { - SimpleEventLoop eventLoop; - BoostNetworkFactories networkFactories(&eventLoop); - - JID jid(JID(argv[1]).getNode() + "something", JID(argv[1]).getDomain()); - client = new Client(jid, argv[2], &networkFactories); - client->setAlwaysTrustCertificates(); - client->onConnected.connect(&handleConnected); - client->onDisconnected.connect(bind(&handleDisconnected, _1)); - client->onMessageReceived.connect(bind(&handleMessageReceived, _1)); - Swift::ClientOptions opt; - opt.allowPLAINWithoutTLS = true; - client->connect(opt); - - eventLoop.run(); - - delete client; - return 0; -} diff --git a/tests/login_bad_name2/.nolibircclient-qt b/tests/login_bad_name2/.nolibircclient-qt deleted file mode 100644 index e69de29b..00000000 diff --git a/tests/login_bad_name2/CMakeLists.txt b/tests/login_bad_name2/CMakeLists.txt deleted file mode 100644 index 41d4f73c..00000000 --- a/tests/login_bad_name2/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -FILE(GLOB SRC *.cpp) - -ADD_EXECUTABLE(login_bad_name2_test ${SRC}) - -TARGET_LINK_LIBRARIES(login_bad_name2_test transport ${SWIFTEN_LIBRARIES}) - diff --git a/tests/login_bad_name2/main.cpp b/tests/login_bad_name2/main.cpp deleted file mode 100644 index b2e232e5..00000000 --- a/tests/login_bad_name2/main.cpp +++ /dev/null @@ -1,45 +0,0 @@ -#include -#include - -#include -#include - -using namespace Swift; -using namespace boost; - -Client* client; - -static void handleDisconnected(const boost::optional &error) { - exit(error->getType() != ClientError::AuthenticationFailedError); -} - -static void handleConnected() { - exit(1); -} - -static void handleMessageReceived(Message::ref message) { - // Echo back the incoming message - message->setTo(message->getFrom()); - message->setFrom(JID()); - client->sendMessage(message); -} - -int main(int, char **argv) { - SimpleEventLoop eventLoop; - BoostNetworkFactories networkFactories(&eventLoop); - - JID jid(std::string("something") + JID(argv[1]).getNode(), JID(argv[1]).getDomain()); - client = new Client(jid, argv[2], &networkFactories); - client->setAlwaysTrustCertificates(); - client->onConnected.connect(&handleConnected); - client->onDisconnected.connect(bind(&handleDisconnected, _1)); - client->onMessageReceived.connect(bind(&handleMessageReceived, _1)); - Swift::ClientOptions opt; - opt.allowPLAINWithoutTLS = true; - client->connect(opt); - - eventLoop.run(); - - delete client; - return 0; -} diff --git a/tests/runtests.py b/tests/runtests.py deleted file mode 100644 index 391a1497..00000000 --- a/tests/runtests.py +++ /dev/null @@ -1,70 +0,0 @@ -import os -import sys -from subprocess import * -import time - -def run_spectrum(backend, test): - os.system("rm test.sql") - f = open("sample.cfg", "w") - f.write("\ - [service]\n\ - jid = localhost\n\ - password = secret\n\ - server = 127.0.0.1\n\ - port = 5222\n\ - server_mode = 1\n\ - backend=../backends/%s/%s_backend\n\ - protocol=prpl-jabber\n\ -\ - [database]\n\ - database = test.sql\n\ - prefix=icq\n\ - " % (backend, backend) - ) - f.close() - p = Popen("../spectrum/src/spectrum sample.cfg > " + backend + "_" + test + ".log 2>&1", shell=True) - time.sleep(4) - return p - -def one_test_run(): - os.system("killall spectrum 2> /dev/null") - os.system("rm *.log") - - for backend in os.listdir("../backends"): - if not os.path.isdir("../backends/" + backend) or backend == "CMakeFiles": - continue - - for d in os.listdir("."): - binary = d + "/" + d + "_test" - if not os.path.exists(binary): - continue - - if os.path.exists(d + "/.no" + backend): - continue - - p = run_spectrum(backend, d) - - if backend.find("purple") >= 0: - p = Popen(binary + " pyjim%jabber.cz@localhost test", shell=True) - else: - p = Popen(binary + " testnickname%irc.freenode.net@localhost test", shell=True) - - seconds = 0 - while p.poll() is None and seconds < 20: - time.sleep(1) - seconds += 1 - - if p.returncode == 0 and seconds < 20: - print "[ PASS ]", backend, binary - - else: - if seconds == 20: - print "[ TIME ]", backend, binary - else: - print "[ FAIL ]", backend, binary - - os.system("killall spectrum 2> /dev/null") - -one_test_run() - - From ee674bfe6b0370d27229a5928998201baa30dda5 Mon Sep 17 00:00:00 2001 From: Jan Kaluza Date: Wed, 16 Nov 2011 08:58:55 +0100 Subject: [PATCH 42/48] At least something in README --- README | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/README b/README index e69de29b..cd912fb4 100644 --- a/README +++ b/README @@ -0,0 +1,6 @@ +Spectrum is an XMPP transport/gateway. It allows XMPP users to communicate with +their friends who are using one of the supported networks. It supports a wide +range of different networks such as ICQ, XMPP (Jabber, GTalk), AIM, MSN, +Facebook, Twitter, Gadu-Gadu, IRC and SIMPLE. Spectrum is written in C++ +and uses the Swiften XMPP library and libpurple for “legacy networks”. +Spectrum is open source and released under the GNU GPL. From 29b5b7d27f6b6ebe1477cad2d2c47df2297d5af5 Mon Sep 17 00:00:00 2001 From: Jan Kaluza Date: Wed, 16 Nov 2011 09:39:29 +0100 Subject: [PATCH 43/48] Added spectrum2 --version + handle SPECTRUM_VERSION cmake variable --- CMakeLists.txt | 19 +++++++++++++++++++ spectrum/src/main.cpp | 8 ++++++-- 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index d7dfa8bc..c43cdf7b 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -64,6 +64,25 @@ ADD_DEFINITIONS(-DBOOST_FILESYSTEM_VERSION=2) message(" Supported features") message("-----------------------") + +if (SPECTRUM_VERSION) + ADD_DEFINITIONS(-DSPECTRUM_VERSION="${SPECTRUM_VERSION}") +else (SPECTRUM_VERSION) + if (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/.git) + execute_process(COMMAND git "--git-dir=${CMAKE_CURRENT_SOURCE_DIR}/.git" rev-parse --short HEAD + OUTPUT_VARIABLE GIT_REVISION + OUTPUT_STRIP_TRAILING_WHITESPACE + ) + set(SPECTRUM_VERSION 2.0.0-beta-git-${GIT_REVISION}) + ADD_DEFINITIONS(-DSPECTRUM_VERSION="${SPECTRUM_VERSION}") + else (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/.git) + set(SPECTRUM_VERSION 2.0.0-alpha) + ADD_DEFINITIONS(-DSPECTRUM_VERSION="${SPECTRUM_VERSION}") + endif (EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/.git) +endif (SPECTRUM_VERSION) + +message("Version : " ${SPECTRUM_VERSION}) + if (SQLITE3_FOUND) ADD_DEFINITIONS(-DWITH_SQLITE) include_directories(${SQLITE3_INCLUDE_DIR}) diff --git a/spectrum/src/main.cpp b/spectrum/src/main.cpp index 573ff3c8..fb52de18 100644 --- a/spectrum/src/main.cpp +++ b/spectrum/src/main.cpp @@ -138,13 +138,14 @@ int main(int argc, char **argv) return -1; } #endif - boost::program_options::options_description desc("Usage: spectrum [OPTIONS] \nAllowed options"); + boost::program_options::options_description desc(std::string("Spectrum version: ") + SPECTRUM_VERSION + "\nUsage: spectrum [OPTIONS] \nAllowed options"); desc.add_options() ("help,h", "help") ("no-daemonize,n", "Do not run spectrum as daemon") ("no-debug,d", "Create coredumps on crash") ("jid,j", boost::program_options::value(&jid)->default_value(""), "Specify JID of transport manually") ("config", boost::program_options::value(&config_file)->default_value(""), "Config file") + ("version,v", "Shows Spectrum version") ; try { @@ -154,7 +155,10 @@ int main(int argc, char **argv) options(desc).positional(p).run(), vm); boost::program_options::notify(vm); - + if (vm.count("version")) { + std::cout << SPECTRUM_VERSION << "\n"; + return 0; + } if(vm.count("help")) { From 5424e5c686e63c92f029a82fb3bf395e29f4a3d7 Mon Sep 17 00:00:00 2001 From: HanzZ Date: Wed, 23 Nov 2011 22:00:24 +0100 Subject: [PATCH 44/48] Added SingleIRCNetworkPlugin --- backends/libircclient-qt/main.cpp | 46 +++++++- backends/libircclient-qt/session.cpp | 49 +++++---- .../singleircnetworkplugin.cpp | 104 ++++++++++++++++++ .../libircclient-qt/singleircnetworkplugin.h | 39 +++++++ spectrum/src/sample.cfg | 6 +- src/userregistration.cpp | 5 +- 6 files changed, 219 insertions(+), 30 deletions(-) create mode 100644 backends/libircclient-qt/singleircnetworkplugin.cpp create mode 100644 backends/libircclient-qt/singleircnetworkplugin.h diff --git a/backends/libircclient-qt/main.cpp b/backends/libircclient-qt/main.cpp index 83723532..f5af84fb 100644 --- a/backends/libircclient-qt/main.cpp +++ b/backends/libircclient-qt/main.cpp @@ -15,11 +15,22 @@ #include #include "Swiften/EventLoop/Qt/QtEventLoop.h" #include "ircnetworkplugin.h" +#include "singleircnetworkplugin.h" + +#include "log4cxx/logger.h" +#include "log4cxx/consoleappender.h" +#include "log4cxx/patternlayout.h" +#include "log4cxx/propertyconfigurator.h" +#include "log4cxx/helpers/properties.h" +#include "log4cxx/helpers/fileinputstream.h" +#include "log4cxx/helpers/transcoder.h" using namespace boost::program_options; using namespace Transport; -IRCNetworkPlugin * np = NULL; +using namespace log4cxx; + +NetworkPlugin * np = NULL; int main (int argc, char* argv[]) { std::string host; @@ -72,8 +83,39 @@ int main (int argc, char* argv[]) { } QCoreApplication app(argc, argv); + if (CONFIG_STRING(&config, "logging.backend_config").empty()) { + LoggerPtr root = log4cxx::Logger::getRootLogger(); +#ifndef _MSC_VER + root->addAppender(new ConsoleAppender(new PatternLayout("%d %-5p %c: %m%n"))); +#else + root->addAppender(new ConsoleAppender(new PatternLayout(L"%d %-5p %c: %m%n"))); +#endif + } + else { + log4cxx::helpers::Properties p; + log4cxx::helpers::FileInputStream *istream = new log4cxx::helpers::FileInputStream(CONFIG_STRING(&config, "logging.backend_config")); + p.load(istream); + LogString pid, jid; + log4cxx::helpers::Transcoder::decode(boost::lexical_cast(getpid()), pid); + log4cxx::helpers::Transcoder::decode(CONFIG_STRING(&config, "service.jid"), jid); +#ifdef _MSC_VER + p.setProperty(L"pid", pid); + p.setProperty(L"jid", jid); +#else + p.setProperty("pid", pid); + p.setProperty("jid", jid); +#endif + log4cxx::PropertyConfigurator::configure(p); + } + Swift::QtEventLoop eventLoop; - np = new IRCNetworkPlugin(&config, &eventLoop, host, port); + + if (config.getUnregistered().find("service.irc_server") == config.getUnregistered().end()) { + np = new IRCNetworkPlugin(&config, &eventLoop, host, port); + } + else { + np = new SingleIRCNetworkPlugin(&config, &eventLoop, host, port); + } return app.exec(); } diff --git a/backends/libircclient-qt/session.cpp b/backends/libircclient-qt/session.cpp index 792bceed..1d216016 100644 --- a/backends/libircclient-qt/session.cpp +++ b/backends/libircclient-qt/session.cpp @@ -13,6 +13,12 @@ #include #include "Swiften/Elements/StatusShow.h" +#include "log4cxx/logger.h" + +using namespace log4cxx; + +static LoggerPtr logger = log4cxx::Logger::getLogger("IRCSession"); + MyIrcSession::MyIrcSession(const std::string &user, NetworkPlugin *np, const std::string &suffix, QObject* parent) : Irc::Session(parent) { this->np = np; @@ -23,24 +29,24 @@ MyIrcSession::MyIrcSession(const std::string &user, NetworkPlugin *np, const std } void MyIrcSession::on_connected(){ - std::cout << "connected:\n"; +// std::cout << "connected:\n"; } void MyIrcSession::on_disconnected() { - std::cout << "disconnected:\n"; +// std::cout << "disconnected:\n"; if (suffix.empty()) np->handleDisconnected(user, 0, ""); } void MyIrcSession::on_bufferAdded(Irc::Buffer* buffer) { - qDebug() << "buffer added:" << buffer->receiver(); +// qDebug() << "buffer added:" << buffer->receiver(); } void MyIrcSession::on_bufferRemoved(Irc::Buffer* buffer) { - qDebug() << "buffer removed:" << buffer->receiver(); +// qDebug() << "buffer removed:" << buffer->receiver(); } Irc::Buffer* MyIrcSession::createBuffer(const QString& receiver) @@ -80,7 +86,7 @@ MyIrcBuffer::MyIrcBuffer(const QString& receiver, const std::string &user, Netwo void MyIrcBuffer::on_receiverChanged(const QString& receiver) { - qDebug() << "receiver changed:" << receiver; +// qDebug() << "receiver changed:" << receiver; } bool MyIrcBuffer::correctNickname(std::string &nickname) { @@ -94,7 +100,7 @@ bool MyIrcBuffer::correctNickname(std::string &nickname) { } void MyIrcBuffer::on_joined(const QString& origin) { - qDebug() << "joined:" << receiver() << origin; + LOG4CXX_INFO(logger, user << ": " << origin.toStdString() << " joined " << receiver().toStdString() + suffix); bool flags = 0; std::string nickname = origin.toStdString(); flags = correctNickname(nickname); @@ -102,6 +108,7 @@ void MyIrcBuffer::on_joined(const QString& origin) { } void MyIrcBuffer::on_parted(const QString& origin, const QString& message) { + LOG4CXX_INFO(logger, user << ": " << origin.toStdString() << " parted " << receiver().toStdString() + suffix); qDebug() << "parted:" << receiver() << origin << message; bool flags = 0; std::string nickname = origin.toStdString(); @@ -109,14 +116,12 @@ void MyIrcBuffer::on_parted(const QString& origin, const QString& message) { np->handleParticipantChanged(user, nickname, receiver().toStdString() + suffix,(int) flags, pbnetwork::STATUS_NONE, message.toStdString()); } -void MyIrcBuffer::on_quit(const QString& origin, const QString& message) -{ - qDebug() << "quit:" << receiver() << origin << message; +void MyIrcBuffer::on_quit(const QString& origin, const QString& message) { on_parted(origin, message); } void MyIrcBuffer::on_nickChanged(const QString& origin, const QString& nick) { - qDebug() << "nick changed:" << receiver() << origin << nick; + LOG4CXX_INFO(logger, user << ": " << origin.toStdString() << " changed nickname to " << nick.toStdString()); std::string nickname = origin.toStdString(); bool flags = p->m_modes[receiver().toStdString() + nickname]; // std::cout << receiver().toStdString() + nickname << " " << flags << "\n"; @@ -125,10 +130,10 @@ void MyIrcBuffer::on_nickChanged(const QString& origin, const QString& nick) { void MyIrcBuffer::on_modeChanged(const QString& origin, const QString& mode, const QString& args) { // mode changed: "#testik" "HanzZ" "+o" "hanzz_k" - qDebug() << "mode changed:" << receiver() << origin << mode << args; std::string nickname = args.toStdString(); if (nickname.empty()) return; + LOG4CXX_INFO(logger, user << ": " << nickname << " changed mode to " << mode.toStdString()); if (mode == "+o") { p->m_modes[receiver().toStdString() + nickname] = 1; } @@ -141,29 +146,28 @@ void MyIrcBuffer::on_modeChanged(const QString& origin, const QString& mode, con void MyIrcBuffer::on_topicChanged(const QString& origin, const QString& topic) { //topic changed: "#testik" "HanzZ" "test" - qDebug() << "topic changed:" << receiver() << origin << topic; - np->handleSubject(user, receiver().toStdString() + suffix, topic.toStdString(), origin.toStdString()); + LOG4CXX_INFO(logger, user << ": " << origin.toStdString() << " topic changed to " << topic.toStdString()); + np->handleSubject(user, receiver().toStdString() + suffix, topic.toStdString(), origin.toStdString()); } -void MyIrcBuffer::on_invited(const QString& origin, const QString& receiver, const QString& channel) -{ - qDebug() << "invited:" << Irc::Buffer::receiver() << origin << receiver << channel; +void MyIrcBuffer::on_invited(const QString& origin, const QString& receiver, const QString& channel) { + qDebug() << "invited:" << Irc::Buffer::receiver() << origin << receiver << channel; } -void MyIrcBuffer::on_kicked(const QString& origin, const QString& nick, const QString& message) -{ - qDebug() << "kicked:" << receiver() << origin << nick << message; +void MyIrcBuffer::on_kicked(const QString& origin, const QString& nick, const QString& message) { + qDebug() << "kicked:" << receiver() << origin << nick << message; } void MyIrcBuffer::on_messageReceived(const QString& origin, const QString& message, Irc::Buffer::MessageFlags flags) { - qDebug() << "message received:" << receiver() << origin << message << (flags & Irc::Buffer::IdentifiedFlag ? "(identified!)" : "(not identified)"); + // qDebug() << "message received:" << receiver() << origin << message << (flags & Irc::Buffer::IdentifiedFlag ? "(identified!)" : "(not identified)"); + if (!receiver().startsWith("#") && (flags & Irc::Buffer::EchoFlag)) return; std::string r = receiver().toStdString(); // if (!suffix.empty()) { // r = receiver().replace('@', '%').toStdString(); // } - + LOG4CXX_INFO(logger, user << ": Message from " << r); if (r.find("#") == 0) { np->handleMessage(user, r + suffix, message.toStdString(), origin.toStdString()); } @@ -223,7 +227,8 @@ void MyIrcBuffer::on_numericMessageReceived(const QString& origin, uint code, co } break; } - qDebug() << "numeric message received:" << receiver() << origin << code << params; + LOG4CXX_INFO(logger, user << ": Numeric message received " << receiver().toStdString() << " " << origin.toStdString() << " " << code); + //qDebug() << "numeric message received:" << receiver() << origin << code << params; } void MyIrcBuffer::on_unknownMessageReceived(const QString& origin, const QStringList& params) diff --git a/backends/libircclient-qt/singleircnetworkplugin.cpp b/backends/libircclient-qt/singleircnetworkplugin.cpp new file mode 100644 index 00000000..64260a23 --- /dev/null +++ b/backends/libircclient-qt/singleircnetworkplugin.cpp @@ -0,0 +1,104 @@ +#include "singleircnetworkplugin.h" +#include "log4cxx/logger.h" + +using namespace log4cxx; + +static LoggerPtr logger = log4cxx::Logger::getLogger("SingleIRCNetworkPlugin"); + +SingleIRCNetworkPlugin::SingleIRCNetworkPlugin(Config *config, Swift::QtEventLoop *loop, const std::string &host, int port) { + this->config = config; + m_server = config->getUnregistered().find("service.irc_server")->second; + m_socket = new QTcpSocket(); + m_socket->connectToHost(QString::fromStdString(host), port); + connect(m_socket, SIGNAL(readyRead()), this, SLOT(readData())); + + LOG4CXX_INFO(logger, "SingleIRCNetworkPlugin for server " << m_server << " initialized."); +} + +void SingleIRCNetworkPlugin::readData() { + size_t availableBytes = m_socket->bytesAvailable(); + if (availableBytes == 0) + return; + + std::string d = std::string(m_socket->readAll().data(), availableBytes); + handleDataRead(d); +} + +void SingleIRCNetworkPlugin::sendData(const std::string &string) { + m_socket->write(string.c_str(), string.size()); +} + +void SingleIRCNetworkPlugin::handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password) { + // legacy name is users nickname + if (m_sessions[user] != NULL) { + LOG4CXX_WARN(logger, user << ": Already logged in."); + return; + } + LOG4CXX_INFO(logger, user << ": Connecting " << m_server << " as " << legacyName); + + MyIrcSession *session = new MyIrcSession(user, this); + session->setNick(QString::fromStdString(legacyName)); + session->connectToServer(QString::fromStdString(m_server), 6667); + m_sessions[user] = session; +} + +void SingleIRCNetworkPlugin::handleLogoutRequest(const std::string &user, const std::string &legacyName) { + if (m_sessions[user] == NULL) { + LOG4CXX_WARN(logger, user << ": Already disconnected."); + return; + } + LOG4CXX_INFO(logger, user << ": Disconnecting."); + + m_sessions[user]->disconnectFromServer(); + m_sessions[user]->deleteLater(); + m_sessions.erase(user); +} + +void SingleIRCNetworkPlugin::handleMessageSendRequest(const std::string &user, const std::string &legacyName, const std::string &message, const std::string &/*xhtml*/) { + if (m_sessions[user] == NULL) { + LOG4CXX_WARN(logger, user << ": Message received for unconnected user"); + return; + } + + // handle PMs + std::string r = legacyName; + if (legacyName.find("/") == std::string::npos) { + r = legacyName.substr(0, r.find("@")); + } + else { + r = legacyName.substr(legacyName.find("/") + 1); + } + + LOG4CXX_INFO(logger, user << ": Forwarding message to " << r); + m_sessions[user]->message(QString::fromStdString(r), QString::fromStdString(message)); +} + +void SingleIRCNetworkPlugin::handleJoinRoomRequest(const std::string &user, const std::string &room, const std::string &nickname, const std::string &password) { + if (m_sessions[user] == NULL) { + LOG4CXX_WARN(logger, user << ": Join room requested for unconnected user"); + return; + } + + LOG4CXX_INFO(logger, user << ": Joining " << room); + m_sessions[user]->addAutoJoinChannel(QString::fromStdString(room)); + m_sessions[user]->join(QString::fromStdString(room), QString::fromStdString(password)); + m_sessions[user]->rooms += 1; + + // update nickname, because we have nickname per session, no nickname per room. + handleRoomNicknameChanged(user, room, m_sessions[user]->nick().toStdString()); +} + +void SingleIRCNetworkPlugin::handleLeaveRoomRequest(const std::string &user, const std::string &room) { + std::string r = room; + std::string u = user; + + if (m_sessions[u] == NULL) { + LOG4CXX_WARN(logger, user << ": Leave room requested for unconnected user"); + return; + } + + LOG4CXX_INFO(logger, user << ": Leaving " << room); + m_sessions[u]->part(QString::fromStdString(r)); + m_sessions[u]->removeAutoJoinChannel(QString::fromStdString(r)); + m_sessions[u]->rooms -= 1; +} diff --git a/backends/libircclient-qt/singleircnetworkplugin.h b/backends/libircclient-qt/singleircnetworkplugin.h new file mode 100644 index 00000000..e59499d5 --- /dev/null +++ b/backends/libircclient-qt/singleircnetworkplugin.h @@ -0,0 +1,39 @@ + +#pragma once + +#include "transport/config.h" +#include "transport/networkplugin.h" +#include "session.h" +#include +#include +#include "Swiften/EventLoop/Qt/QtEventLoop.h" +#include "ircnetworkplugin.h" + + +class SingleIRCNetworkPlugin : public QObject, public NetworkPlugin { + Q_OBJECT + + public: + SingleIRCNetworkPlugin(Config *config, Swift::QtEventLoop *loop, const std::string &host, int port); + + void handleLoginRequest(const std::string &user, const std::string &legacyName, const std::string &password); + + void handleLogoutRequest(const std::string &user, const std::string &legacyName); + + void handleMessageSendRequest(const std::string &user, const std::string &legacyName, const std::string &message, const std::string &/*xhtml*/); + + void handleJoinRoomRequest(const std::string &user, const std::string &room, const std::string &nickname, const std::string &password); + + void handleLeaveRoomRequest(const std::string &user, const std::string &room); + + std::map m_sessions; + + public slots: + void readData(); + void sendData(const std::string &string); + + private: + Config *config; + QTcpSocket *m_socket; + std::string m_server; +}; diff --git a/spectrum/src/sample.cfg b/spectrum/src/sample.cfg index 71b1d23b..3fdca1d1 100644 --- a/spectrum/src/sample.cfg +++ b/spectrum/src/sample.cfg @@ -5,6 +5,7 @@ server = 127.0.0.1 port = 5222 server_mode = 1 backend_host=localhost +pidfile=./test.pid # < this option doesn't work yet backend_port=10001 admin_username=admin @@ -12,13 +13,14 @@ admin_password=test #cert=server.pfx #patch to PKCS#12 certificate #cert_password=test #password to that certificate if any users_per_backend=10 -backend=/home/hanzz/code/libtransport/backends/libpurple/spectrum2_libpurple_backend +#backend=/home/hanzz/code/libtransport/backends/libpurple/spectrum2_libpurple_backend #backend=/usr/bin/mono /home/hanzz/code/networkplugin-csharp/msnp-sharp-backend/bin/Debug/msnp-sharp-backend.exe #backend=/home/hanzz/code/libtransport/backends/frotz/spectrum2_frotz_backend -#backend=/home/hanzz/code/libtransport/backends/libircclient-qt/spectrum2_libircclient-qt_backend +backend=/home/hanzz/code/libtransport/backends/libircclient-qt/spectrum2_libircclient-qt_backend #protocol=prpl-msn protocol=any #protocol=prpl-icq +irc_server=irc.freenode.org [backend] #default_avatar=catmelonhead.jpg diff --git a/src/userregistration.cpp b/src/userregistration.cpp index e1a1731a..646722ed 100644 --- a/src/userregistration.cpp +++ b/src/userregistration.cpp @@ -329,10 +329,7 @@ bool UserRegistration::handleSetRequest(const Swift::JID& from, const Swift::JID } // Register or change password - if (payload->getUsername()->empty() || - (payload->getPassword()->empty() && CONFIG_STRING(m_config, "service.protocol") != "twitter" && CONFIG_STRING(m_config, "service.protocol") != "bonjour") - ) - { + if (payload->getUsername()->empty()) { sendError(from, id, ErrorPayload::NotAcceptable, ErrorPayload::Modify); return true; } From ff3adaa3f33ff71b5b1f1f1cdc2139361316d62f Mon Sep 17 00:00:00 2001 From: HanzZ Date: Thu, 24 Nov 2011 12:24:26 +0100 Subject: [PATCH 45/48] Working IRC nickserv + PMs --- backends/libircclient-qt/session.cpp | 8 +++++++- backends/libircclient-qt/session.h | 9 +++++++++ backends/libircclient-qt/singleircnetworkplugin.cpp | 13 +++++++++++++ backends/libircclient-qt/singleircnetworkplugin.h | 1 + include/transport/conversation.h | 4 ++++ src/conversation.cpp | 11 ++++++++--- src/conversationmanager.cpp | 1 + 7 files changed, 43 insertions(+), 4 deletions(-) diff --git a/backends/libircclient-qt/session.cpp b/backends/libircclient-qt/session.cpp index 1d216016..2fcc81a9 100644 --- a/backends/libircclient-qt/session.cpp +++ b/backends/libircclient-qt/session.cpp @@ -204,8 +204,14 @@ void MyIrcBuffer::on_numericMessageReceived(const QString& origin, uint code, co { switch (code) { case 251: - if (suffix.empty()) + if (suffix.empty()) { np->handleConnected(user); + } + if (p->getIdentify().find(" ") != std::string::npos) { + std::string to = p->getIdentify().substr(0, p->getIdentify().find(" ")); + std::string what = p->getIdentify().substr(p->getIdentify().find(" ") + 1); + p->message(QString::fromStdString(to), QString::fromStdString(what)); + } break; case 332: m_topicData = params.value(2).toStdString(); diff --git a/backends/libircclient-qt/session.h b/backends/libircclient-qt/session.h index 326ba4b4..1e1067ce 100644 --- a/backends/libircclient-qt/session.h +++ b/backends/libircclient-qt/session.h @@ -27,6 +27,14 @@ public: std::string suffix; int rooms; + void setIdentify(const std::string &identify) { + m_identify = identify; + } + + const std::string &getIdentify() { + return m_identify; + } + protected Q_SLOTS: void on_connected(); void on_disconnected(); @@ -37,6 +45,7 @@ protected Q_SLOTS: protected: NetworkPlugin *np; std::string user; + std::string m_identify; virtual Irc::Buffer* createBuffer(const QString& receiver); }; diff --git a/backends/libircclient-qt/singleircnetworkplugin.cpp b/backends/libircclient-qt/singleircnetworkplugin.cpp index 64260a23..657251ef 100644 --- a/backends/libircclient-qt/singleircnetworkplugin.cpp +++ b/backends/libircclient-qt/singleircnetworkplugin.cpp @@ -12,6 +12,13 @@ SingleIRCNetworkPlugin::SingleIRCNetworkPlugin(Config *config, Swift::QtEventLoo m_socket->connectToHost(QString::fromStdString(host), port); connect(m_socket, SIGNAL(readyRead()), this, SLOT(readData())); + if (config->getUnregistered().find("service.irc_identify") != config->getUnregistered().end()) { + m_identify = config->getUnregistered().find("service.irc_identify")->second; + } + else { + m_identify = "NickServ identify $name $password"; + } + LOG4CXX_INFO(logger, "SingleIRCNetworkPlugin for server " << m_server << " initialized."); } @@ -39,6 +46,12 @@ void SingleIRCNetworkPlugin::handleLoginRequest(const std::string &user, const s MyIrcSession *session = new MyIrcSession(user, this); session->setNick(QString::fromStdString(legacyName)); session->connectToServer(QString::fromStdString(m_server), 6667); + + std::string identify = m_identify; + boost::replace_all(identify, "$password", password); + boost::replace_all(identify, "$name", legacyName); + session->setIdentify(identify); + m_sessions[user] = session; } diff --git a/backends/libircclient-qt/singleircnetworkplugin.h b/backends/libircclient-qt/singleircnetworkplugin.h index e59499d5..e80dd151 100644 --- a/backends/libircclient-qt/singleircnetworkplugin.h +++ b/backends/libircclient-qt/singleircnetworkplugin.h @@ -36,4 +36,5 @@ class SingleIRCNetworkPlugin : public QObject, public NetworkPlugin { Config *config; QTcpSocket *m_socket; std::string m_server; + std::string m_identify; }; diff --git a/include/transport/conversation.h b/include/transport/conversation.h index 89f3a4ea..d3999d28 100644 --- a/include/transport/conversation.h +++ b/include/transport/conversation.h @@ -74,6 +74,10 @@ class Conversation { m_nickname = nickname; } + const std::string &getNickname() { + return m_nickname; + } + void setJID(const Swift::JID &jid) { m_jid = jid; } diff --git a/src/conversation.cpp b/src/conversation.cpp index 96ae8144..d903e320 100644 --- a/src/conversation.cpp +++ b/src/conversation.cpp @@ -56,10 +56,15 @@ void Conversation::handleMessage(boost::shared_ptr &message, con message->setType(Swift::Message::Chat); } + std::string n = nickname; + if (n.empty() && !m_room.empty() && !m_muc) { + n = m_nickname; + } + if (message->getType() != Swift::Message::Groupchat) { message->setTo(m_jid); // normal message - if (nickname.empty()) { + if (n.empty()) { Buddy *buddy = m_conversationManager->getUser()->getRosterManager()->getBuddy(m_legacyName); if (buddy) { message->setFrom(buddy->getJID()); @@ -71,10 +76,10 @@ void Conversation::handleMessage(boost::shared_ptr &message, con // PM message else { if (m_room.empty()) { - message->setFrom(Swift::JID(nickname, m_conversationManager->getComponent()->getJID().toBare(), "user")); + message->setFrom(Swift::JID(n, m_conversationManager->getComponent()->getJID().toBare(), "user")); } else { - message->setFrom(Swift::JID(m_room, m_conversationManager->getComponent()->getJID().toBare(), nickname)); + message->setFrom(Swift::JID(m_room, m_conversationManager->getComponent()->getJID().toBare(), n)); } } m_conversationManager->getComponent()->getStanzaChannel()->sendMessage(message); diff --git a/src/conversationmanager.cpp b/src/conversationmanager.cpp index a83803be..ee24ec1c 100644 --- a/src/conversationmanager.cpp +++ b/src/conversationmanager.cpp @@ -90,6 +90,7 @@ void ConversationManager::handleMessageReceived(Swift::Message::ref message) { if (!m_convs[name]) { m_convs[name] = m_component->getFactory()->createConversation(this, name); m_convs[name]->setRoom(room_name); + m_convs[name]->setNickname(name); } } From e312a8602ec798bf20bd7237f3ea835a94dace3b Mon Sep 17 00:00:00 2001 From: HanzZ Date: Thu, 24 Nov 2011 19:07:21 +0100 Subject: [PATCH 46/48] Works with libCommuni now (libircclient-qt renamed) --- CMakeLists.txt | 8 +- backends/CMakeLists.txt | 2 +- backends/libcommuni/CMakeLists.txt | 10 + .../ircnetworkplugin.cpp | 30 +- .../ircnetworkplugin.h | 0 .../{libircclient-qt => libcommuni}/main.cpp | 0 backends/libcommuni/session.cpp | 400 ++++++++++++++++++ backends/libcommuni/session.h | 103 +++++ .../singleircnetworkplugin.cpp | 29 +- .../singleircnetworkplugin.h | 0 backends/libircclient-qt/CMakeLists.txt | 10 - backends/libircclient-qt/session.cpp | 243 ----------- backends/libircclient-qt/session.h | 86 ---- cmake_modules/CommuniConfig.cmake | 10 + cmake_modules/IRCClientQtConfig.cmake | 10 - 15 files changed, 566 insertions(+), 375 deletions(-) create mode 100644 backends/libcommuni/CMakeLists.txt rename backends/{libircclient-qt => libcommuni}/ircnetworkplugin.cpp (79%) rename backends/{libircclient-qt => libcommuni}/ircnetworkplugin.h (100%) rename backends/{libircclient-qt => libcommuni}/main.cpp (100%) create mode 100644 backends/libcommuni/session.cpp create mode 100644 backends/libcommuni/session.h rename backends/{libircclient-qt => libcommuni}/singleircnetworkplugin.cpp (78%) rename backends/{libircclient-qt => libcommuni}/singleircnetworkplugin.h (100%) delete mode 100644 backends/libircclient-qt/CMakeLists.txt delete mode 100644 backends/libircclient-qt/session.cpp delete mode 100644 backends/libircclient-qt/session.h create mode 100644 cmake_modules/CommuniConfig.cmake delete mode 100644 cmake_modules/IRCClientQtConfig.cmake diff --git a/CMakeLists.txt b/CMakeLists.txt index c43cdf7b..d7cb5928 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -44,8 +44,8 @@ message( STATUS "Found Boost: ${Boost_LIBRARIES}, ${Boost_INCLUDE_DIR}") set(Protobuf_DIR "${CMAKE_SOURCE_DIR}/cmake_modules") find_package(Protobuf REQUIRED) -set(IRCClientQt_DIR "${CMAKE_SOURCE_DIR}/cmake_modules") -find_package(IRCClientQt) +set(Communi_DIR "${CMAKE_SOURCE_DIR}/cmake_modules") +find_package(Communi) set(log4cxx_DIR "${CMAKE_SOURCE_DIR}/cmake_modules") find_package(log4cxx) @@ -123,13 +123,13 @@ if (PROTOBUF_FOUND) endif() if(IRC_FOUND) - ADD_DEFINITIONS(-DIRC_SHARED) + ADD_DEFINITIONS(-DCOMMUNI_SHARED) message("IRC plugin : yes") include_directories(${QT_QTNETWORK_INCLUDE_DIR}) include_directories(${IRC_INCLUDE_DIR}) include(${QT_USE_FILE}) else() - message("IRC plugin : no (install libircclient-qt and libprotobuf-dev)") + message("IRC plugin : no (install libCommuni and libprotobuf-dev)") endif() message("Frotz plugin : yes") diff --git a/backends/CMakeLists.txt b/backends/CMakeLists.txt index 5a758c95..9ecb3b5c 100644 --- a/backends/CMakeLists.txt +++ b/backends/CMakeLists.txt @@ -4,7 +4,7 @@ if (PROTOBUF_FOUND) endif() if (IRC_FOUND) - ADD_SUBDIRECTORY(libircclient-qt) + ADD_SUBDIRECTORY(libcommuni) endif() if (NOT WIN32) diff --git a/backends/libcommuni/CMakeLists.txt b/backends/libcommuni/CMakeLists.txt new file mode 100644 index 00000000..a2a14730 --- /dev/null +++ b/backends/libcommuni/CMakeLists.txt @@ -0,0 +1,10 @@ +cmake_minimum_required(VERSION 2.6) +FILE(GLOB SRC *.cpp) +FILE(GLOB HEADERS *.h) +QT4_WRAP_CPP(SRC ${HEADERS}) +ADD_EXECUTABLE(spectrum2_libcommuni_backend ${SRC}) + +target_link_libraries(spectrum2_libcommuni_backend ${IRC_LIBRARY} ${QT_LIBRARIES} transport-plugin transport pthread) + +INSTALL(TARGETS spectrum2_libcommuni_backend RUNTIME DESTINATION bin) + diff --git a/backends/libircclient-qt/ircnetworkplugin.cpp b/backends/libcommuni/ircnetworkplugin.cpp similarity index 79% rename from backends/libircclient-qt/ircnetworkplugin.cpp rename to backends/libcommuni/ircnetworkplugin.cpp index 2ebe91d9..d7c9ae9e 100644 --- a/backends/libircclient-qt/ircnetworkplugin.cpp +++ b/backends/libcommuni/ircnetworkplugin.cpp @@ -1,4 +1,6 @@ #include "ircnetworkplugin.h" +#include +#include IRCNetworkPlugin::IRCNetworkPlugin(Config *config, Swift::QtEventLoop *loop, const std::string &host, int port) { this->config = config; @@ -26,8 +28,10 @@ void IRCNetworkPlugin::handleLoginRequest(const std::string &user, const std::st if (CONFIG_BOOL(config, "service.server_mode")) { MyIrcSession *session = new MyIrcSession(user, this); std::string h = user.substr(0, user.find("@")); - session->setNick(QString::fromStdString(h.substr(0, h.find("%")))); - session->connectToServer(QString::fromStdString(h.substr(h.find("%") + 1)), 6667); + session->setNickName(QString::fromStdString(h.substr(0, h.find("%")))); + session->setHost(QString::fromStdString(h.substr(h.find("%") + 1))); + session->setPort(6667); + session->open(); std::cout << "CONNECTING IRC NETWORK " << h.substr(h.find("%") + 1) << "\n"; m_sessions[user] = session; } @@ -39,7 +43,7 @@ void IRCNetworkPlugin::handleLoginRequest(const std::string &user, const std::st void IRCNetworkPlugin::handleLogoutRequest(const std::string &user, const std::string &legacyName) { if (m_sessions[user] == NULL) return; - m_sessions[user]->disconnectFromServer(); + m_sessions[user]->close(); m_sessions[user]->deleteLater(); m_sessions.erase(user); } @@ -68,7 +72,7 @@ void IRCNetworkPlugin::handleMessageSendRequest(const std::string &user, const s } } std::cout << "MESSAGE " << u << " " << r << "\n"; - m_sessions[u]->message(QString::fromStdString(r), QString::fromStdString(message)); + m_sessions[u]->sendCommand(IrcCommand::createMessage(QString::fromStdString(r), QString::fromStdString(message))); std::cout << "SENT\n"; } @@ -85,8 +89,10 @@ void IRCNetworkPlugin::handleJoinRoomRequest(const std::string &user, const std: if (room.find("@") != std::string::npos) { // suffix is %irc.freenode.net to let MyIrcSession return #room%irc.freenode.net MyIrcSession *session = new MyIrcSession(user, this, room.substr(room.find("@"))); - session->setNick(QString::fromStdString(nickname)); - session->connectToServer(QString::fromStdString(room.substr(room.find("@") + 1)), 6667); + session->setNickName(QString::fromStdString(nickname)); + session->setHost(QString::fromStdString(room.substr(room.find("@") + 1))); + session->setPort(6667); + session->open(); std::cout << "CONNECTING IRC NETWORK " << room.substr(room.find("@") + 1) << "\n"; std::cout << "SUFFIX " << room.substr(room.find("@")) << "\n"; m_sessions[u] = session; @@ -96,11 +102,11 @@ void IRCNetworkPlugin::handleJoinRoomRequest(const std::string &user, const std: } } std::cout << "JOINING " << r << "\n"; - m_sessions[u]->addAutoJoinChannel(QString::fromStdString(r)); - m_sessions[u]->join(QString::fromStdString(r), QString::fromStdString(password)); + m_sessions[u]->addAutoJoinChannel(r); + m_sessions[u]->sendCommand(IrcCommand::createJoin(QString::fromStdString(r), QString::fromStdString(password))); m_sessions[u]->rooms += 1; // update nickname, because we have nickname per session, no nickname per room. - handleRoomNicknameChanged(user, r, m_sessions[u]->nick().toStdString()); + handleRoomNicknameChanged(user, r, m_sessions[u]->nickName().toStdString()); } void IRCNetworkPlugin::handleLeaveRoomRequest(const std::string &user, const std::string &room) { @@ -114,12 +120,12 @@ void IRCNetworkPlugin::handleLeaveRoomRequest(const std::string &user, const std if (m_sessions[u] == NULL) return; - m_sessions[u]->part(QString::fromStdString(r)); - m_sessions[u]->removeAutoJoinChannel(QString::fromStdString(r)); + m_sessions[u]->sendCommand(IrcCommand::createPart(QString::fromStdString(r))); + m_sessions[u]->removeAutoJoinChannel(r); m_sessions[u]->rooms -= 1; if (m_sessions[u]->rooms <= 0) { - m_sessions[u]->disconnectFromServer(); + m_sessions[u]->close(); m_sessions[u]->deleteLater(); m_sessions.erase(u); } diff --git a/backends/libircclient-qt/ircnetworkplugin.h b/backends/libcommuni/ircnetworkplugin.h similarity index 100% rename from backends/libircclient-qt/ircnetworkplugin.h rename to backends/libcommuni/ircnetworkplugin.h diff --git a/backends/libircclient-qt/main.cpp b/backends/libcommuni/main.cpp similarity index 100% rename from backends/libircclient-qt/main.cpp rename to backends/libcommuni/main.cpp diff --git a/backends/libcommuni/session.cpp b/backends/libcommuni/session.cpp new file mode 100644 index 00000000..bab60b4c --- /dev/null +++ b/backends/libcommuni/session.cpp @@ -0,0 +1,400 @@ +/* + * Copyright (C) 2008-2009 J-P Nurmi jpnurmi@gmail.com + * + * This example is free, and not covered by LGPL license. There is no + * restriction applied to their modification, redistribution, using and so on. + * You can study them, modify them, use them in your own program - either + * completely or partially. By using it you may give me some credits in your + * program, but you don't have to. + */ + +#include "session.h" +#include +#include +#include "Swiften/Elements/StatusShow.h" +#include +#include + +#include "log4cxx/logger.h" + +using namespace log4cxx; + +static LoggerPtr logger = log4cxx::Logger::getLogger("IRCSession"); + +MyIrcSession::MyIrcSession(const std::string &user, NetworkPlugin *np, const std::string &suffix, QObject* parent) : IrcSession(parent) +{ + this->np = np; + this->user = user; + this->suffix = suffix; + rooms = 0; + connect(this, SIGNAL(disconnected()), SLOT(on_disconnected())); + connect(this, SIGNAL(connected()), SLOT(on_connected())); + connect(this, SIGNAL(messageReceived(IrcMessage*)), this, SLOT(onMessageReceived(IrcMessage*))); +} + +void MyIrcSession::on_connected() { + if (suffix.empty()) { + np->handleConnected(user); + } + + for(std::list::const_iterator it = m_autoJoin.begin(); it != m_autoJoin.end(); it++) { + sendCommand(IrcCommand::createJoin(QString::fromStdString(*it))); + } + + if (getIdentify().find(" ") != std::string::npos) { + std::string to = getIdentify().substr(0, getIdentify().find(" ")); + std::string what = getIdentify().substr(getIdentify().find(" ") + 1); + sendCommand(IrcCommand::createMessage(QString::fromStdString(to), QString::fromStdString(what))); + } +} + +void MyIrcSession::on_disconnected() { + if (suffix.empty()) + np->handleDisconnected(user, 0, ""); +} + +bool MyIrcSession::correctNickname(std::string &nickname) { + bool flags = 0; + switch(nickname.at(0)) { + case '@': nickname = nickname.substr(1); flags = 1; break; + case '+': nickname = nickname.substr(1); break; + default: break; + } + return flags; +} + +void MyIrcSession::on_joined(IrcMessage *message) { + IrcJoinMessage *m = (IrcJoinMessage *) message; + bool flags = 0; + std::string nickname = m->sender().name().toStdString(); + flags = correctNickname(nickname); + np->handleParticipantChanged(user, nickname, m->channel().toStdString() + suffix, (int) flags, pbnetwork::STATUS_ONLINE); + LOG4CXX_INFO(logger, user << ": Joined " << m->parameters()[0].toStdString()); +} + + +void MyIrcSession::on_parted(IrcMessage *message) { + IrcPartMessage *m = (IrcPartMessage *) message; + bool flags = 0; + std::string nickname = m->sender().name().toStdString(); + flags = correctNickname(nickname); + LOG4CXX_INFO(logger, user << ": " << nickname << " parted " << m->channel().toStdString() + suffix); + np->handleParticipantChanged(user, nickname, m->channel().toStdString() + suffix,(int) flags, pbnetwork::STATUS_NONE, m->reason().toStdString()); +} + +void MyIrcSession::on_quit(IrcMessage *message) { + IrcQuitMessage *m = (IrcQuitMessage *) message; + for(std::list::const_iterator it = m_autoJoin.begin(); it != m_autoJoin.end(); it++) { + bool flags = 0; + std::string nickname = m->sender().name().toStdString(); + flags = correctNickname(nickname); + LOG4CXX_INFO(logger, user << ": " << nickname << " quit " << (*it) + suffix); + np->handleParticipantChanged(user, nickname, (*it) + suffix,(int) flags, pbnetwork::STATUS_NONE, m->reason().toStdString()); + } +} + +void MyIrcSession::on_nickChanged(IrcMessage *message) { + IrcNickMessage *m = (IrcNickMessage *) message; + + for(std::list::const_iterator it = m_autoJoin.begin(); it != m_autoJoin.end(); it++) { + std::string nickname = m->sender().name().toStdString(); + bool flags = m_modes[(*it) + nickname]; + LOG4CXX_INFO(logger, user << ": " << nickname << " changed nickname to " << m->nick().toStdString()); + np->handleParticipantChanged(user, nickname, (*it) + suffix,(int) flags, pbnetwork::STATUS_ONLINE, "", m->nick().toStdString()); + } +} + +void MyIrcSession::on_modeChanged(IrcMessage *message) { + IrcModeMessage *m = (IrcModeMessage *) message; + + // mode changed: "#testik" "HanzZ" "+o" "hanzz_k" + std::string nickname = m->argument().toStdString(); + std::string mode = m->mode().toStdString(); + if (nickname.empty()) + return; + LOG4CXX_INFO(logger, user << ": " << nickname << " changed mode to " << mode); + for(std::list::const_iterator it = m_autoJoin.begin(); it != m_autoJoin.end(); it++) { + if (mode == "+o") { + m_modes[(*it) + nickname] = 1; + } + else { + m_modes[(*it) + nickname] = 0; + } + bool flags = m_modes[(*it) + nickname]; + np->handleParticipantChanged(user, nickname, (*it) + suffix,(int) flags, pbnetwork::STATUS_ONLINE, ""); + } +} + +void MyIrcSession::on_topicChanged(IrcMessage *message) { + IrcTopicMessage *m = (IrcTopicMessage *) message; + + bool flags = 0; + std::string nickname = m->sender().name().toStdString(); + flags = correctNickname(nickname); + + LOG4CXX_INFO(logger, user << ": " << nickname << " topic changed to " << m->topic().toStdString()); + np->handleSubject(user, m->channel().toStdString() + suffix, m->topic().toStdString(), nickname); +} + +void MyIrcSession::on_messageReceived(IrcMessage *message) { + IrcPrivateMessage *m = (IrcPrivateMessage *) message; + + std::string target = m->target().toStdString(); + LOG4CXX_INFO(logger, user << ": Message from " << target); + if (target.find("#") == 0) { + bool flags = 0; + std::string nickname = m->sender().name().toStdString(); + flags = correctNickname(nickname); + np->handleMessage(user, target + suffix, m->message().toStdString(), nickname); + } + else { + bool flags = 0; + std::string nickname = m->sender().name().toStdString(); + flags = correctNickname(nickname); + np->handleMessage(user, nickname, m->message().toStdString()); + } +} + +void MyIrcSession::on_numericMessageReceived(IrcMessage *message) { + IrcNumericMessage *m = (IrcNumericMessage *) message; + switch (m->code()) { + case 332: + m_topicData = m->parameters().value(2).toStdString(); + break; + case 333: + np->handleSubject(user, m->parameters().value(1).toStdString() + suffix, m_topicData, m->parameters().value(2).toStdString()); + break; + case 353: + QString channel = m->parameters().value(2); + QStringList members = m->parameters().value(3).split(" "); + + for (int i = 0; i < members.size(); i++) { + bool flags = 0; + std::string nickname = members.at(i).toStdString(); + flags = correctNickname(nickname); + m_modes[channel.toStdString() + nickname] = flags; + np->handleParticipantChanged(user, nickname, channel.toStdString() + suffix,(int) flags, pbnetwork::STATUS_ONLINE); + } + break; + } + + //qDebug() << "numeric message received:" << receiver() << origin << code << params; +} + +void MyIrcSession::onMessageReceived(IrcMessage *message) { + LOG4CXX_INFO(logger, user << ": " << message->toString().toStdString()); + switch (message->type()) { + case IrcMessage::Join: + on_joined(message); + break; + case IrcMessage::Part: + on_parted(message); + break; + case IrcMessage::Quit: + on_quit(message); + break; + case IrcMessage::Nick: + on_nickChanged(message); + break; + case IrcMessage::Mode: + on_modeChanged(message); + break; + case IrcMessage::Topic: + on_topicChanged(message); + break; + case IrcMessage::Private: + on_messageReceived(message); + break; + case IrcMessage::Numeric: + on_numericMessageReceived(message); + break; + } +} + +//MyIrcBuffer::MyIrcBuffer(const QString& receiver, const std::string &user, NetworkPlugin *np, const std::string &suffix, Irc::Session* parent) +// : Irc::Buffer(receiver, parent) +//{ +// this->np = np; +// this->user = user; +// this->suffix = suffix; +// p = (MyIrcSession *) parent; +// connect(this, SIGNAL(receiverChanged(QString)), SLOT(on_receiverChanged(QString))); +// connect(this, SIGNAL(joined(QString)), SLOT(on_joined(QString))); +// connect(this, SIGNAL(parted(QString, QString)), SLOT(on_parted(QString, QString))); +// connect(this, SIGNAL(quit(QString, QString)), SLOT(on_quit(QString, QString))); +// connect(this, SIGNAL(nickChanged(QString, QString)), SLOT(on_nickChanged(QString, QString))); +// connect(this, SIGNAL(modeChanged(QString, QString, QString)), SLOT(on_modeChanged(QString, QString, QString))); +// connect(this, SIGNAL(topicChanged(QString, QString)), SLOT(on_topicChanged(QString, QString))); +// connect(this, SIGNAL(invited(QString, QString, QString)), SLOT(on_invited(QString, QString, QString))); +// connect(this, SIGNAL(kicked(QString, QString, QString)), SLOT(on_kicked(QString, QString, QString))); +// connect(this, SIGNAL(messageReceived(QString, QString, Irc::Buffer::MessageFlags)), +// SLOT(on_messageReceived(QString, QString, Irc::Buffer::MessageFlags))); +// connect(this, SIGNAL(noticeReceived(QString, QString, Irc::Buffer::MessageFlags)), +// SLOT(on_noticeReceived(QString, QString, Irc::Buffer::MessageFlags))); +// connect(this, SIGNAL(ctcpRequestReceived(QString, QString, Irc::Buffer::MessageFlags)), +// SLOT(on_ctcpRequestReceived(QString, QString, Irc::Buffer::MessageFlags))); +// connect(this, SIGNAL(ctcpReplyReceived(QString, QString, Irc::Buffer::MessageFlags)), +// SLOT(on_ctcpReplyReceived(QString, QString, Irc::Buffer::MessageFlags))); +// connect(this, SIGNAL(ctcpActionReceived(QString, QString, Irc::Buffer::MessageFlags)), +// SLOT(on_ctcpActionReceived(QString, QString, Irc::Buffer::MessageFlags))); +// connect(this, SIGNAL(numericMessageReceived(QString, uint, QStringList)), SLOT(on_numericMessageReceived(QString, uint, QStringList))); +// connect(this, SIGNAL(unknownMessageReceived(QString, QStringList)), SLOT(on_unknownMessageReceived(QString, QStringList))); +//} + +//void MyIrcBuffer::on_receiverChanged(const QString& receiver) +//{ +//// qDebug() << "receiver changed:" << receiver; +//} + +//bool MyIrcBuffer::correctNickname(std::string &nickname) { +// bool flags = 0; +// switch(nickname.at(0)) { +// case '@': nickname = nickname.substr(1); flags = 1; break; +// case '+': nickname = nickname.substr(1); break; +// default: break; +// } +// return flags; +//} + +//void MyIrcBuffer::on_joined(const QString& origin) { +// LOG4CXX_INFO(logger, user << ": " << origin.toStdString() << " joined " << receiver().toStdString() + suffix); +// bool flags = 0; +// std::string nickname = origin.toStdString(); +// flags = correctNickname(nickname); +// np->handleParticipantChanged(user, origin.toStdString(), receiver().toStdString() + suffix, (int) flags, pbnetwork::STATUS_ONLINE); +//} + +//void MyIrcBuffer::on_parted(const QString& origin, const QString& message) { +// LOG4CXX_INFO(logger, user << ": " << origin.toStdString() << " parted " << receiver().toStdString() + suffix); +// qDebug() << "parted:" << receiver() << origin << message; +// bool flags = 0; +// std::string nickname = origin.toStdString(); +// flags = correctNickname(nickname); +// np->handleParticipantChanged(user, nickname, receiver().toStdString() + suffix,(int) flags, pbnetwork::STATUS_NONE, message.toStdString()); +//} + +//void MyIrcBuffer::on_quit(const QString& origin, const QString& message) { +// on_parted(origin, message); +//} + +//void MyIrcBuffer::on_nickChanged(const QString& origin, const QString& nick) { +// LOG4CXX_INFO(logger, user << ": " << origin.toStdString() << " changed nickname to " << nick.toStdString()); +// std::string nickname = origin.toStdString(); +// bool flags = p->m_modes[receiver().toStdString() + nickname]; +//// std::cout << receiver().toStdString() + nickname << " " << flags << "\n"; +// np->handleParticipantChanged(user, nickname, receiver().toStdString() + suffix,(int) flags, pbnetwork::STATUS_ONLINE, "", nick.toStdString()); +//} + +//void MyIrcBuffer::on_modeChanged(const QString& origin, const QString& mode, const QString& args) { +// // mode changed: "#testik" "HanzZ" "+o" "hanzz_k" +// std::string nickname = args.toStdString(); +// if (nickname.empty()) +// return; +// LOG4CXX_INFO(logger, user << ": " << nickname << " changed mode to " << mode.toStdString()); +// if (mode == "+o") { +// p->m_modes[receiver().toStdString() + nickname] = 1; +// } +// else { +// p->m_modes[receiver().toStdString() + nickname] = 0; +// } +// bool flags = p->m_modes[receiver().toStdString() + nickname]; +// np->handleParticipantChanged(user, nickname, receiver().toStdString() + suffix,(int) flags, pbnetwork::STATUS_ONLINE, ""); +//} + +//void MyIrcBuffer::on_topicChanged(const QString& origin, const QString& topic) { +// //topic changed: "#testik" "HanzZ" "test" +// LOG4CXX_INFO(logger, user << ": " << origin.toStdString() << " topic changed to " << topic.toStdString()); +// np->handleSubject(user, receiver().toStdString() + suffix, topic.toStdString(), origin.toStdString()); +//} + +//void MyIrcBuffer::on_invited(const QString& origin, const QString& receiver, const QString& channel) { +// qDebug() << "invited:" << Irc::Buffer::receiver() << origin << receiver << channel; +//} + +//void MyIrcBuffer::on_kicked(const QString& origin, const QString& nick, const QString& message) { +// qDebug() << "kicked:" << receiver() << origin << nick << message; +//} + +//void MyIrcBuffer::on_messageReceived(const QString& origin, const QString& message, Irc::Buffer::MessageFlags flags) { +// // qDebug() << "message received:" << receiver() << origin << message << (flags & Irc::Buffer::IdentifiedFlag ? "(identified!)" : "(not identified)"); + +// if (!receiver().startsWith("#") && (flags & Irc::Buffer::EchoFlag)) +// return; +// std::string r = receiver().toStdString(); +//// if (!suffix.empty()) { +//// r = receiver().replace('@', '%').toStdString(); +//// } +// LOG4CXX_INFO(logger, user << ": Message from " << r); +// if (r.find("#") == 0) { +// np->handleMessage(user, r + suffix, message.toStdString(), origin.toStdString()); +// } +// else { +// np->handleMessage(user, r + suffix, message.toStdString()); +// } +//} + +//void MyIrcBuffer::on_noticeReceived(const QString& origin, const QString& notice, Irc::Buffer::MessageFlags flags) +//{ +// qDebug() << "notice received:" << receiver() << origin << notice +// << (flags & Irc::Buffer::IdentifiedFlag ? "(identified!)" : "(not identified)"); +//} + +//void MyIrcBuffer::on_ctcpRequestReceived(const QString& origin, const QString& request, Irc::Buffer::MessageFlags flags) +//{ +// qDebug() << "ctcp request received:" << receiver() << origin << request +// << (flags & Irc::Buffer::IdentifiedFlag ? "(identified!)" : "(not identified)"); +//} + +//void MyIrcBuffer::on_ctcpReplyReceived(const QString& origin, const QString& reply, Irc::Buffer::MessageFlags flags) +//{ +// qDebug() << "ctcp reply received:" << receiver() << origin << reply +// << (flags & Irc::Buffer::IdentifiedFlag ? "(identified!)" : "(not identified)"); +//} + +//void MyIrcBuffer::on_ctcpActionReceived(const QString& origin, const QString& action, Irc::Buffer::MessageFlags flags) +//{ +// qDebug() << "ctcp action received:" << receiver() << origin << action +// << (flags & Irc::Buffer::IdentifiedFlag ? "(identified!)" : "(not identified)"); +//} + +//void MyIrcBuffer::on_numericMessageReceived(const QString& origin, uint code, const QStringList& params) +//{ +// switch (code) { +// case 251: +// if (suffix.empty()) { +// np->handleConnected(user); +// } +// if (p->getIdentify().find(" ") != std::string::npos) { +// std::string to = p->getIdentify().substr(0, p->getIdentify().find(" ")); +// std::string what = p->getIdentify().substr(p->getIdentify().find(" ") + 1); +// p->message(QString::fromStdString(to), QString::fromStdString(what)); +// } +// break; +// case 332: +// m_topicData = params.value(2).toStdString(); +// break; +// case 333: +// np->handleSubject(user, params.value(1).toStdString() + suffix, m_topicData, params.value(2).toStdString()); +// break; +// case 353: +// QString channel = params.value(2); +// QStringList members = params.value(3).split(" "); + +// for (int i = 0; i < members.size(); i++) { +// bool flags = 0; +// std::string nickname = members.at(i).toStdString(); +// flags = correctNickname(nickname); +// p->m_modes[channel.toStdString() + nickname] = flags; +// std::cout << channel.toStdString() + suffix << " " << flags << "\n"; +// np->handleParticipantChanged(user, nickname, channel.toStdString() + suffix,(int) flags, pbnetwork::STATUS_ONLINE); +// } +// break; +// } +// LOG4CXX_INFO(logger, user << ": Numeric message received " << receiver().toStdString() << " " << origin.toStdString() << " " << code); +// //qDebug() << "numeric message received:" << receiver() << origin << code << params; +//} + +//void MyIrcBuffer::on_unknownMessageReceived(const QString& origin, const QStringList& params) +//{ +// qDebug() << "unknown message received:" << receiver() << origin << params; +//} diff --git a/backends/libcommuni/session.h b/backends/libcommuni/session.h new file mode 100644 index 00000000..3589dcb4 --- /dev/null +++ b/backends/libcommuni/session.h @@ -0,0 +1,103 @@ +/* + * Copyright (C) 2008-2009 J-P Nurmi jpnurmi@gmail.com + * + * This example is free, and not covered by LGPL license. There is no + * restriction applied to their modification, redistribution, using and so on. + * You can study them, modify them, use them in your own program - either + * completely or partially. By using it you may give me some credits in your + * program, but you don't have to. + */ + +#ifndef SESSION_H +#define SESSION_H + +#include +#include + +using namespace Transport; + +class MyIrcSession : public IrcSession +{ + Q_OBJECT + +public: + MyIrcSession(const std::string &user, NetworkPlugin *np, const std::string &suffix = "", QObject* parent = 0); + std::map m_modes; + std::string suffix; + int rooms; + + void addAutoJoinChannel(const std::string &channel) { + m_autoJoin.push_back(channel); + } + + void removeAutoJoinChannel(const std::string &channel) { + m_autoJoin.remove(channel); + } + + void setIdentify(const std::string &identify) { + m_identify = identify; + } + + const std::string &getIdentify() { + return m_identify; + } + + bool correctNickname(std::string &nickname); + + void on_joined(IrcMessage *message); + void on_parted(IrcMessage *message); + void on_quit(IrcMessage *message); + void on_nickChanged(IrcMessage *message); + void on_modeChanged(IrcMessage *message); + void on_topicChanged(IrcMessage *message); + void on_messageReceived(IrcMessage *message); + void on_numericMessageReceived(IrcMessage *message); + +protected Q_SLOTS: + void on_connected(); + void on_disconnected(); + + void onMessageReceived(IrcMessage* message); + +protected: + NetworkPlugin *np; + std::string user; + std::string m_identify; + std::list m_autoJoin; + std::string m_topicData; +}; + +//class MyIrcBuffer : public Irc::Buffer +//{ +// Q_OBJECT + +//public: +// MyIrcBuffer(const QString& receiver, const std::string &user, NetworkPlugin *np, const std::string &suffix, Irc::Session* parent); +// NetworkPlugin *np; +// std::string user; +// MyIrcSession *p; +// std::string m_topicData; +// std::string suffix; + +//protected Q_SLOTS: +// void on_receiverChanged(const QString& receiver); +// void on_joined(const QString& origin); +// void on_parted(const QString& origin, const QString& message); +// void on_quit(const QString& origin, const QString& message); +// void on_nickChanged(const QString& origin, const QString& nick); +// void on_modeChanged(const QString& origin, const QString& mode, const QString& args); +// void on_topicChanged(const QString& origin, const QString& topic); +// void on_invited(const QString& origin, const QString& receiver, const QString& channel); +// void on_kicked(const QString& origin, const QString& nick, const QString& message); +// void on_messageReceived(const QString& origin, const QString& message, Irc::Buffer::MessageFlags flags); +// void on_noticeReceived(const QString& origin, const QString& notice, Irc::Buffer::MessageFlags flags); +// void on_ctcpRequestReceived(const QString& origin, const QString& request, Irc::Buffer::MessageFlags flags); +// void on_ctcpReplyReceived(const QString& origin, const QString& reply, Irc::Buffer::MessageFlags flags); +// void on_ctcpActionReceived(const QString& origin, const QString& action, Irc::Buffer::MessageFlags flags); +// void on_numericMessageReceived(const QString& origin, uint code, const QStringList& params); +// void on_unknownMessageReceived(const QString& origin, const QStringList& params); + +// bool correctNickname(std::string &nickname); +//}; + +#endif // SESSION_H diff --git a/backends/libircclient-qt/singleircnetworkplugin.cpp b/backends/libcommuni/singleircnetworkplugin.cpp similarity index 78% rename from backends/libircclient-qt/singleircnetworkplugin.cpp rename to backends/libcommuni/singleircnetworkplugin.cpp index 657251ef..06bd378c 100644 --- a/backends/libircclient-qt/singleircnetworkplugin.cpp +++ b/backends/libcommuni/singleircnetworkplugin.cpp @@ -1,5 +1,7 @@ #include "singleircnetworkplugin.h" #include "log4cxx/logger.h" +#include +#include using namespace log4cxx; @@ -44,14 +46,19 @@ void SingleIRCNetworkPlugin::handleLoginRequest(const std::string &user, const s LOG4CXX_INFO(logger, user << ": Connecting " << m_server << " as " << legacyName); MyIrcSession *session = new MyIrcSession(user, this); - session->setNick(QString::fromStdString(legacyName)); - session->connectToServer(QString::fromStdString(m_server), 6667); + session->setUserName(QString::fromStdString(legacyName)); + session->setNickName(QString::fromStdString(legacyName)); + session->setRealName(QString::fromStdString(legacyName)); + session->setHost(QString::fromStdString(m_server)); + session->setPort(6667); std::string identify = m_identify; boost::replace_all(identify, "$password", password); boost::replace_all(identify, "$name", legacyName); session->setIdentify(identify); + session->open(); + m_sessions[user] = session; } @@ -62,7 +69,7 @@ void SingleIRCNetworkPlugin::handleLogoutRequest(const std::string &user, const } LOG4CXX_INFO(logger, user << ": Disconnecting."); - m_sessions[user]->disconnectFromServer(); + m_sessions[user]->close(); m_sessions[user]->deleteLater(); m_sessions.erase(user); } @@ -83,7 +90,11 @@ void SingleIRCNetworkPlugin::handleMessageSendRequest(const std::string &user, c } LOG4CXX_INFO(logger, user << ": Forwarding message to " << r); - m_sessions[user]->message(QString::fromStdString(r), QString::fromStdString(message)); + m_sessions[user]->sendCommand(IrcCommand::createMessage(QString::fromStdString(r), QString::fromStdString(message))); + + if (r.find("#") == 0) { + handleMessage(user, legacyName, message, m_sessions[user]->nickName().toStdString()); + } } void SingleIRCNetworkPlugin::handleJoinRoomRequest(const std::string &user, const std::string &room, const std::string &nickname, const std::string &password) { @@ -93,12 +104,12 @@ void SingleIRCNetworkPlugin::handleJoinRoomRequest(const std::string &user, cons } LOG4CXX_INFO(logger, user << ": Joining " << room); - m_sessions[user]->addAutoJoinChannel(QString::fromStdString(room)); - m_sessions[user]->join(QString::fromStdString(room), QString::fromStdString(password)); + m_sessions[user]->addAutoJoinChannel(room); + m_sessions[user]->sendCommand(IrcCommand::createJoin(QString::fromStdString(room), QString::fromStdString(password))); m_sessions[user]->rooms += 1; // update nickname, because we have nickname per session, no nickname per room. - handleRoomNicknameChanged(user, room, m_sessions[user]->nick().toStdString()); + handleRoomNicknameChanged(user, room, m_sessions[user]->userName().toStdString()); } void SingleIRCNetworkPlugin::handleLeaveRoomRequest(const std::string &user, const std::string &room) { @@ -111,7 +122,7 @@ void SingleIRCNetworkPlugin::handleLeaveRoomRequest(const std::string &user, con } LOG4CXX_INFO(logger, user << ": Leaving " << room); - m_sessions[u]->part(QString::fromStdString(r)); - m_sessions[u]->removeAutoJoinChannel(QString::fromStdString(r)); + m_sessions[u]->sendCommand(IrcCommand::createPart(QString::fromStdString(r))); + m_sessions[u]->removeAutoJoinChannel(r); m_sessions[u]->rooms -= 1; } diff --git a/backends/libircclient-qt/singleircnetworkplugin.h b/backends/libcommuni/singleircnetworkplugin.h similarity index 100% rename from backends/libircclient-qt/singleircnetworkplugin.h rename to backends/libcommuni/singleircnetworkplugin.h diff --git a/backends/libircclient-qt/CMakeLists.txt b/backends/libircclient-qt/CMakeLists.txt deleted file mode 100644 index 61cf35d9..00000000 --- a/backends/libircclient-qt/CMakeLists.txt +++ /dev/null @@ -1,10 +0,0 @@ -cmake_minimum_required(VERSION 2.6) -FILE(GLOB SRC *.cpp) -FILE(GLOB HEADERS *.h) -QT4_WRAP_CPP(SRC ${HEADERS}) -ADD_EXECUTABLE(spectrum2_libircclient-qt_backend ${SRC}) - -target_link_libraries(spectrum2_libircclient-qt_backend ${IRC_LIBRARY} ${QT_LIBRARIES} transport-plugin transport pthread) - -INSTALL(TARGETS spectrum2_libircclient-qt_backend RUNTIME DESTINATION bin) - diff --git a/backends/libircclient-qt/session.cpp b/backends/libircclient-qt/session.cpp deleted file mode 100644 index 2fcc81a9..00000000 --- a/backends/libircclient-qt/session.cpp +++ /dev/null @@ -1,243 +0,0 @@ -/* - * Copyright (C) 2008-2009 J-P Nurmi jpnurmi@gmail.com - * - * This example is free, and not covered by LGPL license. There is no - * restriction applied to their modification, redistribution, using and so on. - * You can study them, modify them, use them in your own program - either - * completely or partially. By using it you may give me some credits in your - * program, but you don't have to. - */ - -#include "session.h" -#include -#include -#include "Swiften/Elements/StatusShow.h" - -#include "log4cxx/logger.h" - -using namespace log4cxx; - -static LoggerPtr logger = log4cxx::Logger::getLogger("IRCSession"); - -MyIrcSession::MyIrcSession(const std::string &user, NetworkPlugin *np, const std::string &suffix, QObject* parent) : Irc::Session(parent) -{ - this->np = np; - this->user = user; - this->suffix = suffix; - rooms = 0; - connect(this, SIGNAL(disconnected()), SLOT(on_disconnected())); -} - -void MyIrcSession::on_connected(){ -// std::cout << "connected:\n"; -} - -void MyIrcSession::on_disconnected() -{ -// std::cout << "disconnected:\n"; - if (suffix.empty()) - np->handleDisconnected(user, 0, ""); -} - -void MyIrcSession::on_bufferAdded(Irc::Buffer* buffer) -{ -// qDebug() << "buffer added:" << buffer->receiver(); -} - -void MyIrcSession::on_bufferRemoved(Irc::Buffer* buffer) -{ -// qDebug() << "buffer removed:" << buffer->receiver(); -} - -Irc::Buffer* MyIrcSession::createBuffer(const QString& receiver) -{ - return new MyIrcBuffer(receiver, user, np, suffix, this); -} - -MyIrcBuffer::MyIrcBuffer(const QString& receiver, const std::string &user, NetworkPlugin *np, const std::string &suffix, Irc::Session* parent) - : Irc::Buffer(receiver, parent) -{ - this->np = np; - this->user = user; - this->suffix = suffix; - p = (MyIrcSession *) parent; - connect(this, SIGNAL(receiverChanged(QString)), SLOT(on_receiverChanged(QString))); - connect(this, SIGNAL(joined(QString)), SLOT(on_joined(QString))); - connect(this, SIGNAL(parted(QString, QString)), SLOT(on_parted(QString, QString))); - connect(this, SIGNAL(quit(QString, QString)), SLOT(on_quit(QString, QString))); - connect(this, SIGNAL(nickChanged(QString, QString)), SLOT(on_nickChanged(QString, QString))); - connect(this, SIGNAL(modeChanged(QString, QString, QString)), SLOT(on_modeChanged(QString, QString, QString))); - connect(this, SIGNAL(topicChanged(QString, QString)), SLOT(on_topicChanged(QString, QString))); - connect(this, SIGNAL(invited(QString, QString, QString)), SLOT(on_invited(QString, QString, QString))); - connect(this, SIGNAL(kicked(QString, QString, QString)), SLOT(on_kicked(QString, QString, QString))); - connect(this, SIGNAL(messageReceived(QString, QString, Irc::Buffer::MessageFlags)), - SLOT(on_messageReceived(QString, QString, Irc::Buffer::MessageFlags))); - connect(this, SIGNAL(noticeReceived(QString, QString, Irc::Buffer::MessageFlags)), - SLOT(on_noticeReceived(QString, QString, Irc::Buffer::MessageFlags))); - connect(this, SIGNAL(ctcpRequestReceived(QString, QString, Irc::Buffer::MessageFlags)), - SLOT(on_ctcpRequestReceived(QString, QString, Irc::Buffer::MessageFlags))); - connect(this, SIGNAL(ctcpReplyReceived(QString, QString, Irc::Buffer::MessageFlags)), - SLOT(on_ctcpReplyReceived(QString, QString, Irc::Buffer::MessageFlags))); - connect(this, SIGNAL(ctcpActionReceived(QString, QString, Irc::Buffer::MessageFlags)), - SLOT(on_ctcpActionReceived(QString, QString, Irc::Buffer::MessageFlags))); - connect(this, SIGNAL(numericMessageReceived(QString, uint, QStringList)), SLOT(on_numericMessageReceived(QString, uint, QStringList))); - connect(this, SIGNAL(unknownMessageReceived(QString, QStringList)), SLOT(on_unknownMessageReceived(QString, QStringList))); -} - -void MyIrcBuffer::on_receiverChanged(const QString& receiver) -{ -// qDebug() << "receiver changed:" << receiver; -} - -bool MyIrcBuffer::correctNickname(std::string &nickname) { - bool flags = 0; - switch(nickname.at(0)) { - case '@': nickname = nickname.substr(1); flags = 1; break; - case '+': nickname = nickname.substr(1); break; - default: break; - } - return flags; -} - -void MyIrcBuffer::on_joined(const QString& origin) { - LOG4CXX_INFO(logger, user << ": " << origin.toStdString() << " joined " << receiver().toStdString() + suffix); - bool flags = 0; - std::string nickname = origin.toStdString(); - flags = correctNickname(nickname); - np->handleParticipantChanged(user, origin.toStdString(), receiver().toStdString() + suffix, (int) flags, pbnetwork::STATUS_ONLINE); -} - -void MyIrcBuffer::on_parted(const QString& origin, const QString& message) { - LOG4CXX_INFO(logger, user << ": " << origin.toStdString() << " parted " << receiver().toStdString() + suffix); - qDebug() << "parted:" << receiver() << origin << message; - bool flags = 0; - std::string nickname = origin.toStdString(); - flags = correctNickname(nickname); - np->handleParticipantChanged(user, nickname, receiver().toStdString() + suffix,(int) flags, pbnetwork::STATUS_NONE, message.toStdString()); -} - -void MyIrcBuffer::on_quit(const QString& origin, const QString& message) { - on_parted(origin, message); -} - -void MyIrcBuffer::on_nickChanged(const QString& origin, const QString& nick) { - LOG4CXX_INFO(logger, user << ": " << origin.toStdString() << " changed nickname to " << nick.toStdString()); - std::string nickname = origin.toStdString(); - bool flags = p->m_modes[receiver().toStdString() + nickname]; -// std::cout << receiver().toStdString() + nickname << " " << flags << "\n"; - np->handleParticipantChanged(user, nickname, receiver().toStdString() + suffix,(int) flags, pbnetwork::STATUS_ONLINE, "", nick.toStdString()); -} - -void MyIrcBuffer::on_modeChanged(const QString& origin, const QString& mode, const QString& args) { - // mode changed: "#testik" "HanzZ" "+o" "hanzz_k" - std::string nickname = args.toStdString(); - if (nickname.empty()) - return; - LOG4CXX_INFO(logger, user << ": " << nickname << " changed mode to " << mode.toStdString()); - if (mode == "+o") { - p->m_modes[receiver().toStdString() + nickname] = 1; - } - else { - p->m_modes[receiver().toStdString() + nickname] = 0; - } - bool flags = p->m_modes[receiver().toStdString() + nickname]; - np->handleParticipantChanged(user, nickname, receiver().toStdString() + suffix,(int) flags, pbnetwork::STATUS_ONLINE, ""); -} - -void MyIrcBuffer::on_topicChanged(const QString& origin, const QString& topic) { - //topic changed: "#testik" "HanzZ" "test" - LOG4CXX_INFO(logger, user << ": " << origin.toStdString() << " topic changed to " << topic.toStdString()); - np->handleSubject(user, receiver().toStdString() + suffix, topic.toStdString(), origin.toStdString()); -} - -void MyIrcBuffer::on_invited(const QString& origin, const QString& receiver, const QString& channel) { - qDebug() << "invited:" << Irc::Buffer::receiver() << origin << receiver << channel; -} - -void MyIrcBuffer::on_kicked(const QString& origin, const QString& nick, const QString& message) { - qDebug() << "kicked:" << receiver() << origin << nick << message; -} - -void MyIrcBuffer::on_messageReceived(const QString& origin, const QString& message, Irc::Buffer::MessageFlags flags) { - // qDebug() << "message received:" << receiver() << origin << message << (flags & Irc::Buffer::IdentifiedFlag ? "(identified!)" : "(not identified)"); - - if (!receiver().startsWith("#") && (flags & Irc::Buffer::EchoFlag)) - return; - std::string r = receiver().toStdString(); -// if (!suffix.empty()) { -// r = receiver().replace('@', '%').toStdString(); -// } - LOG4CXX_INFO(logger, user << ": Message from " << r); - if (r.find("#") == 0) { - np->handleMessage(user, r + suffix, message.toStdString(), origin.toStdString()); - } - else { - np->handleMessage(user, r + suffix, message.toStdString()); - } -} - -void MyIrcBuffer::on_noticeReceived(const QString& origin, const QString& notice, Irc::Buffer::MessageFlags flags) -{ - qDebug() << "notice received:" << receiver() << origin << notice - << (flags & Irc::Buffer::IdentifiedFlag ? "(identified!)" : "(not identified)"); -} - -void MyIrcBuffer::on_ctcpRequestReceived(const QString& origin, const QString& request, Irc::Buffer::MessageFlags flags) -{ - qDebug() << "ctcp request received:" << receiver() << origin << request - << (flags & Irc::Buffer::IdentifiedFlag ? "(identified!)" : "(not identified)"); -} - -void MyIrcBuffer::on_ctcpReplyReceived(const QString& origin, const QString& reply, Irc::Buffer::MessageFlags flags) -{ - qDebug() << "ctcp reply received:" << receiver() << origin << reply - << (flags & Irc::Buffer::IdentifiedFlag ? "(identified!)" : "(not identified)"); -} - -void MyIrcBuffer::on_ctcpActionReceived(const QString& origin, const QString& action, Irc::Buffer::MessageFlags flags) -{ - qDebug() << "ctcp action received:" << receiver() << origin << action - << (flags & Irc::Buffer::IdentifiedFlag ? "(identified!)" : "(not identified)"); -} - -void MyIrcBuffer::on_numericMessageReceived(const QString& origin, uint code, const QStringList& params) -{ - switch (code) { - case 251: - if (suffix.empty()) { - np->handleConnected(user); - } - if (p->getIdentify().find(" ") != std::string::npos) { - std::string to = p->getIdentify().substr(0, p->getIdentify().find(" ")); - std::string what = p->getIdentify().substr(p->getIdentify().find(" ") + 1); - p->message(QString::fromStdString(to), QString::fromStdString(what)); - } - break; - case 332: - m_topicData = params.value(2).toStdString(); - break; - case 333: - np->handleSubject(user, params.value(1).toStdString() + suffix, m_topicData, params.value(2).toStdString()); - break; - case 353: - QString channel = params.value(2); - QStringList members = params.value(3).split(" "); - - for (int i = 0; i < members.size(); i++) { - bool flags = 0; - std::string nickname = members.at(i).toStdString(); - flags = correctNickname(nickname); - p->m_modes[channel.toStdString() + nickname] = flags; - std::cout << channel.toStdString() + suffix << " " << flags << "\n"; - np->handleParticipantChanged(user, nickname, channel.toStdString() + suffix,(int) flags, pbnetwork::STATUS_ONLINE); - } - break; - } - LOG4CXX_INFO(logger, user << ": Numeric message received " << receiver().toStdString() << " " << origin.toStdString() << " " << code); - //qDebug() << "numeric message received:" << receiver() << origin << code << params; -} - -void MyIrcBuffer::on_unknownMessageReceived(const QString& origin, const QStringList& params) -{ - qDebug() << "unknown message received:" << receiver() << origin << params; -} diff --git a/backends/libircclient-qt/session.h b/backends/libircclient-qt/session.h deleted file mode 100644 index 1e1067ce..00000000 --- a/backends/libircclient-qt/session.h +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (C) 2008-2009 J-P Nurmi jpnurmi@gmail.com - * - * This example is free, and not covered by LGPL license. There is no - * restriction applied to their modification, redistribution, using and so on. - * You can study them, modify them, use them in your own program - either - * completely or partially. By using it you may give me some credits in your - * program, but you don't have to. - */ - -#ifndef SESSION_H -#define SESSION_H - -#include -#include -#include - -using namespace Transport; - -class MyIrcSession : public Irc::Session -{ - Q_OBJECT - -public: - MyIrcSession(const std::string &user, NetworkPlugin *np, const std::string &suffix = "", QObject* parent = 0); - std::map m_modes; - std::string suffix; - int rooms; - - void setIdentify(const std::string &identify) { - m_identify = identify; - } - - const std::string &getIdentify() { - return m_identify; - } - -protected Q_SLOTS: - void on_connected(); - void on_disconnected(); - - void on_bufferAdded(Irc::Buffer* buffer); - void on_bufferRemoved(Irc::Buffer* buffer); - -protected: - NetworkPlugin *np; - std::string user; - std::string m_identify; - - virtual Irc::Buffer* createBuffer(const QString& receiver); -}; - -class MyIrcBuffer : public Irc::Buffer -{ - Q_OBJECT - -public: - MyIrcBuffer(const QString& receiver, const std::string &user, NetworkPlugin *np, const std::string &suffix, Irc::Session* parent); - NetworkPlugin *np; - std::string user; - MyIrcSession *p; - std::string m_topicData; - std::string suffix; - -protected Q_SLOTS: - void on_receiverChanged(const QString& receiver); - void on_joined(const QString& origin); - void on_parted(const QString& origin, const QString& message); - void on_quit(const QString& origin, const QString& message); - void on_nickChanged(const QString& origin, const QString& nick); - void on_modeChanged(const QString& origin, const QString& mode, const QString& args); - void on_topicChanged(const QString& origin, const QString& topic); - void on_invited(const QString& origin, const QString& receiver, const QString& channel); - void on_kicked(const QString& origin, const QString& nick, const QString& message); - void on_messageReceived(const QString& origin, const QString& message, Irc::Buffer::MessageFlags flags); - void on_noticeReceived(const QString& origin, const QString& notice, Irc::Buffer::MessageFlags flags); - void on_ctcpRequestReceived(const QString& origin, const QString& request, Irc::Buffer::MessageFlags flags); - void on_ctcpReplyReceived(const QString& origin, const QString& reply, Irc::Buffer::MessageFlags flags); - void on_ctcpActionReceived(const QString& origin, const QString& action, Irc::Buffer::MessageFlags flags); - void on_numericMessageReceived(const QString& origin, uint code, const QStringList& params); - void on_unknownMessageReceived(const QString& origin, const QStringList& params); - - bool correctNickname(std::string &nickname); -}; - -#endif // SESSION_H diff --git a/cmake_modules/CommuniConfig.cmake b/cmake_modules/CommuniConfig.cmake new file mode 100644 index 00000000..7f803847 --- /dev/null +++ b/cmake_modules/CommuniConfig.cmake @@ -0,0 +1,10 @@ +FIND_LIBRARY(IRC_LIBRARY NAMES Communi) +FIND_PATH(IRC_INCLUDE_DIR NAMES "ircglobal.h" PATH_SUFFIXES Communi qt4/Communi ) + +# message( STATUS ${IRC_LIBRARY}) +if( IRC_LIBRARY AND IRC_INCLUDE_DIR ) + message( STATUS "Found libCommuni ${IRC_LIBRARY}, ${IRC_INCLUDE_DIR}") + set( IRC_FOUND 1 ) +else() + message( STATUS "Could NOT find libCommuni" ) +endif() diff --git a/cmake_modules/IRCClientQtConfig.cmake b/cmake_modules/IRCClientQtConfig.cmake deleted file mode 100644 index 58118610..00000000 --- a/cmake_modules/IRCClientQtConfig.cmake +++ /dev/null @@ -1,10 +0,0 @@ -FIND_LIBRARY(IRC_LIBRARY NAMES ircclient-qt) -FIND_PATH(IRC_INCLUDE_DIR NAMES "ircglobal.h" PATH_SUFFIXES ircclient-qt qt4/ircclient-qt ) - -# message( STATUS ${IRC_LIBRARY}) -if( IRC_LIBRARY AND IRC_INCLUDE_DIR ) - message( STATUS "Found libircclient-qt: ${IRC_LIBRARY}, ${IRC_INCLUDE_DIR}") - set( IRC_FOUND 1 ) -else() - message( STATUS "Could NOT find libircclient-qt" ) -endif() From 196afcf3a36a72af2320cd7e089a1739abce544b Mon Sep 17 00:00:00 2001 From: HanzZ Date: Thu, 24 Nov 2011 19:37:38 +0100 Subject: [PATCH 47/48] Set proper resource in MUCs --- include/transport/networkpluginserver.h | 2 +- include/transport/user.h | 2 +- src/conversationmanager.cpp | 3 +++ src/networkpluginserver.cpp | 5 +++-- src/user.cpp | 2 +- 5 files changed, 9 insertions(+), 5 deletions(-) diff --git a/include/transport/networkpluginserver.h b/include/transport/networkpluginserver.h index a678c247..c04ae834 100644 --- a/include/transport/networkpluginserver.h +++ b/include/transport/networkpluginserver.h @@ -96,7 +96,7 @@ class NetworkPluginServer { void handleFTDataPayload(Backend *b ,const std::string &payload); void handleUserCreated(User *user); - void handleRoomJoined(User *user, const std::string &room, const std::string &nickname, const std::string &password); + void handleRoomJoined(User *user, const Swift::JID &who, const std::string &room, const std::string &nickname, const std::string &password); void handleRoomLeft(User *user, const std::string &room); void handleUserReadyToConnect(User *user); void handleUserPresenceChanged(User *user, Swift::Presence::ref presence); diff --git a/include/transport/user.h b/include/transport/user.h index 9d7f1118..952bb3b4 100644 --- a/include/transport/user.h +++ b/include/transport/user.h @@ -111,7 +111,7 @@ class User : public Swift::EntityCapsProvider { boost::signal onReadyToConnect; boost::signal onPresenceChanged; - boost::signal onRoomJoined; + boost::signal onRoomJoined; boost::signal onRoomLeft; boost::signal onDisconnected; diff --git a/src/conversationmanager.cpp b/src/conversationmanager.cpp index ee24ec1c..bc08d7a7 100644 --- a/src/conversationmanager.cpp +++ b/src/conversationmanager.cpp @@ -64,6 +64,9 @@ void ConversationManager::removeConversation(Conversation *conv) { void ConversationManager::resetResources() { for (std::map::const_iterator it = m_convs.begin(); it != m_convs.end(); it++) { + if ((*it).second->isMUC()) { + continue; + } (*it).second->setJID(m_user->getJID().toBare()); } } diff --git a/src/networkpluginserver.cpp b/src/networkpluginserver.cpp index e1cb4606..b284390c 100644 --- a/src/networkpluginserver.cpp +++ b/src/networkpluginserver.cpp @@ -935,7 +935,7 @@ void NetworkPluginServer::handleUserCreated(User *user) { // UserInfo userInfo = user->getUserInfo(); user->onReadyToConnect.connect(boost::bind(&NetworkPluginServer::handleUserReadyToConnect, this, user)); user->onPresenceChanged.connect(boost::bind(&NetworkPluginServer::handleUserPresenceChanged, this, user, _1)); - user->onRoomJoined.connect(boost::bind(&NetworkPluginServer::handleRoomJoined, this, user, _1, _2, _3)); + user->onRoomJoined.connect(boost::bind(&NetworkPluginServer::handleRoomJoined, this, user, _1, _2, _3, _4)); user->onRoomLeft.connect(boost::bind(&NetworkPluginServer::handleRoomLeft, this, user, _1)); } @@ -991,7 +991,7 @@ void NetworkPluginServer::handleUserPresenceChanged(User *user, Swift::Presence: send(c->connection, message); } -void NetworkPluginServer::handleRoomJoined(User *user, const std::string &r, const std::string &nickname, const std::string &password) { +void NetworkPluginServer::handleRoomJoined(User *user, const Swift::JID &who, const std::string &r, const std::string &nickname, const std::string &password) { UserInfo userInfo = user->getUserInfo(); pbnetwork::Room room; @@ -1014,6 +1014,7 @@ void NetworkPluginServer::handleRoomJoined(User *user, const std::string &r, con NetworkConversation *conv = new NetworkConversation(user->getConversationManager(), r, true); conv->onMessageToSend.connect(boost::bind(&NetworkPluginServer::handleMessageReceived, this, _1, _2)); conv->setNickname(nickname); + conv->setJID(who); } void NetworkPluginServer::handleRoomLeft(User *user, const std::string &r) { diff --git a/src/user.cpp b/src/user.cpp index 47d63065..9b1d7fd6 100644 --- a/src/user.cpp +++ b/src/user.cpp @@ -226,7 +226,7 @@ void User::handlePresence(Swift::Presence::ref presence) { if (presence->getPayload() != NULL) { password = presence->getPayload()->getPassword() ? *presence->getPayload()->getPassword() : ""; } - onRoomJoined(room, presence->getTo().getResource(), password); + onRoomJoined(presence->getFrom(), room, presence->getTo().getResource(), password); } return; } From f0c6b4239acfb383b9f75714bc0303ae2e03aa08 Mon Sep 17 00:00:00 2001 From: HanzZ Date: Fri, 25 Nov 2011 10:02:53 +0100 Subject: [PATCH 48/48] Removed commented MyIrcBuffer classs --- backends/libcommuni/session.cpp | 188 -------------------------------- 1 file changed, 188 deletions(-) diff --git a/backends/libcommuni/session.cpp b/backends/libcommuni/session.cpp index bab60b4c..088ebd1a 100644 --- a/backends/libcommuni/session.cpp +++ b/backends/libcommuni/session.cpp @@ -210,191 +210,3 @@ void MyIrcSession::onMessageReceived(IrcMessage *message) { break; } } - -//MyIrcBuffer::MyIrcBuffer(const QString& receiver, const std::string &user, NetworkPlugin *np, const std::string &suffix, Irc::Session* parent) -// : Irc::Buffer(receiver, parent) -//{ -// this->np = np; -// this->user = user; -// this->suffix = suffix; -// p = (MyIrcSession *) parent; -// connect(this, SIGNAL(receiverChanged(QString)), SLOT(on_receiverChanged(QString))); -// connect(this, SIGNAL(joined(QString)), SLOT(on_joined(QString))); -// connect(this, SIGNAL(parted(QString, QString)), SLOT(on_parted(QString, QString))); -// connect(this, SIGNAL(quit(QString, QString)), SLOT(on_quit(QString, QString))); -// connect(this, SIGNAL(nickChanged(QString, QString)), SLOT(on_nickChanged(QString, QString))); -// connect(this, SIGNAL(modeChanged(QString, QString, QString)), SLOT(on_modeChanged(QString, QString, QString))); -// connect(this, SIGNAL(topicChanged(QString, QString)), SLOT(on_topicChanged(QString, QString))); -// connect(this, SIGNAL(invited(QString, QString, QString)), SLOT(on_invited(QString, QString, QString))); -// connect(this, SIGNAL(kicked(QString, QString, QString)), SLOT(on_kicked(QString, QString, QString))); -// connect(this, SIGNAL(messageReceived(QString, QString, Irc::Buffer::MessageFlags)), -// SLOT(on_messageReceived(QString, QString, Irc::Buffer::MessageFlags))); -// connect(this, SIGNAL(noticeReceived(QString, QString, Irc::Buffer::MessageFlags)), -// SLOT(on_noticeReceived(QString, QString, Irc::Buffer::MessageFlags))); -// connect(this, SIGNAL(ctcpRequestReceived(QString, QString, Irc::Buffer::MessageFlags)), -// SLOT(on_ctcpRequestReceived(QString, QString, Irc::Buffer::MessageFlags))); -// connect(this, SIGNAL(ctcpReplyReceived(QString, QString, Irc::Buffer::MessageFlags)), -// SLOT(on_ctcpReplyReceived(QString, QString, Irc::Buffer::MessageFlags))); -// connect(this, SIGNAL(ctcpActionReceived(QString, QString, Irc::Buffer::MessageFlags)), -// SLOT(on_ctcpActionReceived(QString, QString, Irc::Buffer::MessageFlags))); -// connect(this, SIGNAL(numericMessageReceived(QString, uint, QStringList)), SLOT(on_numericMessageReceived(QString, uint, QStringList))); -// connect(this, SIGNAL(unknownMessageReceived(QString, QStringList)), SLOT(on_unknownMessageReceived(QString, QStringList))); -//} - -//void MyIrcBuffer::on_receiverChanged(const QString& receiver) -//{ -//// qDebug() << "receiver changed:" << receiver; -//} - -//bool MyIrcBuffer::correctNickname(std::string &nickname) { -// bool flags = 0; -// switch(nickname.at(0)) { -// case '@': nickname = nickname.substr(1); flags = 1; break; -// case '+': nickname = nickname.substr(1); break; -// default: break; -// } -// return flags; -//} - -//void MyIrcBuffer::on_joined(const QString& origin) { -// LOG4CXX_INFO(logger, user << ": " << origin.toStdString() << " joined " << receiver().toStdString() + suffix); -// bool flags = 0; -// std::string nickname = origin.toStdString(); -// flags = correctNickname(nickname); -// np->handleParticipantChanged(user, origin.toStdString(), receiver().toStdString() + suffix, (int) flags, pbnetwork::STATUS_ONLINE); -//} - -//void MyIrcBuffer::on_parted(const QString& origin, const QString& message) { -// LOG4CXX_INFO(logger, user << ": " << origin.toStdString() << " parted " << receiver().toStdString() + suffix); -// qDebug() << "parted:" << receiver() << origin << message; -// bool flags = 0; -// std::string nickname = origin.toStdString(); -// flags = correctNickname(nickname); -// np->handleParticipantChanged(user, nickname, receiver().toStdString() + suffix,(int) flags, pbnetwork::STATUS_NONE, message.toStdString()); -//} - -//void MyIrcBuffer::on_quit(const QString& origin, const QString& message) { -// on_parted(origin, message); -//} - -//void MyIrcBuffer::on_nickChanged(const QString& origin, const QString& nick) { -// LOG4CXX_INFO(logger, user << ": " << origin.toStdString() << " changed nickname to " << nick.toStdString()); -// std::string nickname = origin.toStdString(); -// bool flags = p->m_modes[receiver().toStdString() + nickname]; -//// std::cout << receiver().toStdString() + nickname << " " << flags << "\n"; -// np->handleParticipantChanged(user, nickname, receiver().toStdString() + suffix,(int) flags, pbnetwork::STATUS_ONLINE, "", nick.toStdString()); -//} - -//void MyIrcBuffer::on_modeChanged(const QString& origin, const QString& mode, const QString& args) { -// // mode changed: "#testik" "HanzZ" "+o" "hanzz_k" -// std::string nickname = args.toStdString(); -// if (nickname.empty()) -// return; -// LOG4CXX_INFO(logger, user << ": " << nickname << " changed mode to " << mode.toStdString()); -// if (mode == "+o") { -// p->m_modes[receiver().toStdString() + nickname] = 1; -// } -// else { -// p->m_modes[receiver().toStdString() + nickname] = 0; -// } -// bool flags = p->m_modes[receiver().toStdString() + nickname]; -// np->handleParticipantChanged(user, nickname, receiver().toStdString() + suffix,(int) flags, pbnetwork::STATUS_ONLINE, ""); -//} - -//void MyIrcBuffer::on_topicChanged(const QString& origin, const QString& topic) { -// //topic changed: "#testik" "HanzZ" "test" -// LOG4CXX_INFO(logger, user << ": " << origin.toStdString() << " topic changed to " << topic.toStdString()); -// np->handleSubject(user, receiver().toStdString() + suffix, topic.toStdString(), origin.toStdString()); -//} - -//void MyIrcBuffer::on_invited(const QString& origin, const QString& receiver, const QString& channel) { -// qDebug() << "invited:" << Irc::Buffer::receiver() << origin << receiver << channel; -//} - -//void MyIrcBuffer::on_kicked(const QString& origin, const QString& nick, const QString& message) { -// qDebug() << "kicked:" << receiver() << origin << nick << message; -//} - -//void MyIrcBuffer::on_messageReceived(const QString& origin, const QString& message, Irc::Buffer::MessageFlags flags) { -// // qDebug() << "message received:" << receiver() << origin << message << (flags & Irc::Buffer::IdentifiedFlag ? "(identified!)" : "(not identified)"); - -// if (!receiver().startsWith("#") && (flags & Irc::Buffer::EchoFlag)) -// return; -// std::string r = receiver().toStdString(); -//// if (!suffix.empty()) { -//// r = receiver().replace('@', '%').toStdString(); -//// } -// LOG4CXX_INFO(logger, user << ": Message from " << r); -// if (r.find("#") == 0) { -// np->handleMessage(user, r + suffix, message.toStdString(), origin.toStdString()); -// } -// else { -// np->handleMessage(user, r + suffix, message.toStdString()); -// } -//} - -//void MyIrcBuffer::on_noticeReceived(const QString& origin, const QString& notice, Irc::Buffer::MessageFlags flags) -//{ -// qDebug() << "notice received:" << receiver() << origin << notice -// << (flags & Irc::Buffer::IdentifiedFlag ? "(identified!)" : "(not identified)"); -//} - -//void MyIrcBuffer::on_ctcpRequestReceived(const QString& origin, const QString& request, Irc::Buffer::MessageFlags flags) -//{ -// qDebug() << "ctcp request received:" << receiver() << origin << request -// << (flags & Irc::Buffer::IdentifiedFlag ? "(identified!)" : "(not identified)"); -//} - -//void MyIrcBuffer::on_ctcpReplyReceived(const QString& origin, const QString& reply, Irc::Buffer::MessageFlags flags) -//{ -// qDebug() << "ctcp reply received:" << receiver() << origin << reply -// << (flags & Irc::Buffer::IdentifiedFlag ? "(identified!)" : "(not identified)"); -//} - -//void MyIrcBuffer::on_ctcpActionReceived(const QString& origin, const QString& action, Irc::Buffer::MessageFlags flags) -//{ -// qDebug() << "ctcp action received:" << receiver() << origin << action -// << (flags & Irc::Buffer::IdentifiedFlag ? "(identified!)" : "(not identified)"); -//} - -//void MyIrcBuffer::on_numericMessageReceived(const QString& origin, uint code, const QStringList& params) -//{ -// switch (code) { -// case 251: -// if (suffix.empty()) { -// np->handleConnected(user); -// } -// if (p->getIdentify().find(" ") != std::string::npos) { -// std::string to = p->getIdentify().substr(0, p->getIdentify().find(" ")); -// std::string what = p->getIdentify().substr(p->getIdentify().find(" ") + 1); -// p->message(QString::fromStdString(to), QString::fromStdString(what)); -// } -// break; -// case 332: -// m_topicData = params.value(2).toStdString(); -// break; -// case 333: -// np->handleSubject(user, params.value(1).toStdString() + suffix, m_topicData, params.value(2).toStdString()); -// break; -// case 353: -// QString channel = params.value(2); -// QStringList members = params.value(3).split(" "); - -// for (int i = 0; i < members.size(); i++) { -// bool flags = 0; -// std::string nickname = members.at(i).toStdString(); -// flags = correctNickname(nickname); -// p->m_modes[channel.toStdString() + nickname] = flags; -// std::cout << channel.toStdString() + suffix << " " << flags << "\n"; -// np->handleParticipantChanged(user, nickname, channel.toStdString() + suffix,(int) flags, pbnetwork::STATUS_ONLINE); -// } -// break; -// } -// LOG4CXX_INFO(logger, user << ": Numeric message received " << receiver().toStdString() << " " << origin.toStdString() << " " << code); -// //qDebug() << "numeric message received:" << receiver() << origin << code << params; -//} - -//void MyIrcBuffer::on_unknownMessageReceived(const QString& origin, const QStringList& params) -//{ -// qDebug() << "unknown message received:" << receiver() << origin << params; -//}