diff --git a/include/transport/networkpluginserver.h b/include/transport/networkpluginserver.h index 3aef279d..b0d742b8 100644 --- a/include/transport/networkpluginserver.h +++ b/include/transport/networkpluginserver.h @@ -65,6 +65,8 @@ class NetworkPluginServer { virtual ~NetworkPluginServer(); + void start(); + void setAdminInterface(AdminInterface *adminInterface) { m_adminInterface = adminInterface; } @@ -87,7 +89,7 @@ class NetworkPluginServer { void handleMessageReceived(NetworkConversation *conv, boost::shared_ptr &message); - private: + public: void handleNewClientConnection(boost::shared_ptr c); void handleSessionFinished(Backend *c); void handlePongReceived(Backend *c); @@ -133,6 +135,7 @@ class NetworkPluginServer { void handleFTRejected(User *user, const std::string &buddyName, const std::string &fileName, unsigned long size); void handleFTDataNeeded(Backend *b, unsigned long ftid); + private: void send(boost::shared_ptr &, const std::string &data); void pingTimeout(); diff --git a/spectrum/src/main.cpp b/spectrum/src/main.cpp index 587df261..962b9d60 100644 --- a/spectrum/src/main.cpp +++ b/spectrum/src/main.cpp @@ -402,6 +402,7 @@ int main(int argc, char **argv) FileTransferManager ftManager(&transport, &userManager); NetworkPluginServer plugin(&transport, &config, &userManager, &ftManager, &discoItemsResponder); + plugin.start(); AdminInterface adminInterface(&transport, &userManager, &plugin, storageBackend, userRegistration); plugin.setAdminInterface(&adminInterface); diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6c815564..27fbfae7 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -15,6 +15,7 @@ if (CPPUNIT_FOUND) FILE(GLOB SRC_TEST tests/*.cpp) ADD_EXECUTABLE(libtransport_test ${SRC_TEST}) + set_target_properties(libtransport_test PROPERTIES COMPILE_DEFINITIONS LIBTRANSPORT_TEST=1) target_link_libraries(libtransport_test transport ${CPPUNIT_LIBRARY} ${Boost_LIBRARIES}) endif() diff --git a/src/config.cpp b/src/config.cpp index cda6af24..5e134db0 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -98,6 +98,7 @@ bool Config::load(std::istream &ifs, boost::program_options::options_description ("service.enable_privacy_lists", value()->default_value(true), "") ("service.enable_xhtml", value()->default_value(true), "") ("service.max_room_list_size", value()->default_value(100), "") + ("service.jid_escaping", 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.") diff --git a/src/conversation.cpp b/src/conversation.cpp index f6105461..67a5c386 100644 --- a/src/conversation.cpp +++ b/src/conversation.cpp @@ -91,7 +91,17 @@ void Conversation::handleMessage(boost::shared_ptr &message, con message->setFrom(buddy->getJID()); } else { - message->setFrom(Swift::JID(Swift::JID::getEscapedNode(m_legacyName), m_conversationManager->getComponent()->getJID().toBare())); + std::string name = m_legacyName; + if (CONFIG_BOOL_DEFAULTED(m_conversationManager->getComponent()->getConfig(), "service.jid_escaping", true)) { + name = Swift::JID::getEscapedNode(m_legacyName); + } + else { + if (name.find_last_of("@") != std::string::npos) { + name.replace(name.find_last_of("@"), 1, "%"); + } + } + + message->setFrom(Swift::JID(name, m_conversationManager->getComponent()->getJID().toBare(), "bot")); } } // PM message diff --git a/src/networkpluginserver.cpp b/src/networkpluginserver.cpp index 58789709..51c4aded 100644 --- a/src/networkpluginserver.cpp +++ b/src/networkpluginserver.cpp @@ -285,6 +285,30 @@ NetworkPluginServer::NetworkPluginServer(Component *component, Config *config, U m_server = component->getNetworkFactories()->getConnectionServerFactory()->createConnectionServer(Swift::HostAddress(CONFIG_STRING(m_config, "service.backend_host")), boost::lexical_cast(CONFIG_STRING(m_config, "service.backend_port"))); m_server->onNewConnection.connect(boost::bind(&NetworkPluginServer::handleNewClientConnection, this, _1)); +} + +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(); + delete m_component->m_factory; + delete m_vcardResponder; + delete m_rosterResponder; + delete m_blockResponder; +} + +void NetworkPluginServer::start() { m_server->start(); LOG4CXX_INFO(logger, "Listening on host " << CONFIG_STRING(m_config, "service.backend_host") << " port " << CONFIG_STRING(m_config, "service.backend_port")); @@ -318,28 +342,6 @@ NetworkPluginServer::NetworkPluginServer(Component *component, Config *config, U // quit the while loop break; } - -} - -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(); - delete m_component->m_factory; - delete m_vcardResponder; - delete m_rosterResponder; - delete m_blockResponder; } void NetworkPluginServer::handleNewClientConnection(boost::shared_ptr c) { @@ -479,11 +481,14 @@ void NetworkPluginServer::handleAuthorizationPayload(const std::string &data) { response->setTo(user->getJID()); std::string name = payload.buddyname(); - name = Swift::JID::getEscapedNode(name); - -// if (name.find_last_of("@") != std::string::npos) { // OK when commented -// name.replace(name.find_last_of("@"), 1, "%"); // OK when commented -// } + if (CONFIG_BOOL_DEFAULTED(m_config, "service.jid_escaping", true)) { + name = Swift::JID::getEscapedNode(name); + } + else { + if (name.find_last_of("@") != std::string::npos) { + name.replace(name.find_last_of("@"), 1, "%"); + } + } response->setFrom(Swift::JID(name, m_component->getJID().toString())); response->setType(Swift::Presence::Subscribe); @@ -536,7 +541,12 @@ void NetworkPluginServer::handleBuddyChangedPayload(const std::string &data) { for (int i = 0; i < payload.group_size(); i++) { groups.push_back(payload.group(i)); } - buddy = new LocalBuddy(user->getRosterManager(), -1, payload.buddyname(), payload.alias(), groups, BUDDY_JID_ESCAPING); + if (CONFIG_BOOL_DEFAULTED(m_config, "service.jid_escaping", true)) { + buddy = new LocalBuddy(user->getRosterManager(), -1, payload.buddyname(), payload.alias(), groups, BUDDY_JID_ESCAPING); + } + else { + buddy = new LocalBuddy(user->getRosterManager(), -1, payload.buddyname(), payload.alias(), groups, BUDDY_NO_FLAG); + } if (!buddy->isValid()) { delete buddy; return; diff --git a/src/tests/conversationmanager.cpp b/src/tests/conversationmanager.cpp index 9aa739fa..ef31975d 100644 --- a/src/tests/conversationmanager.cpp +++ b/src/tests/conversationmanager.cpp @@ -127,7 +127,7 @@ class ConversationManagerTest : public CPPUNIT_NS :: TestFixture, public BasicTe void handleNormalMessages() { User *user = userManager->getUser("user@localhost"); - TestingConversation *conv = new TestingConversation(user->getConversationManager(), "buddy1"); + TestingConversation *conv = new TestingConversation(user->getConversationManager(), "buddy1@test"); user->getConversationManager()->addConversation(conv); conv->onMessageToSend.connect(boost::bind(&ConversationManagerTest::handleMessageReceived, this, _1, _2)); @@ -142,13 +142,13 @@ class ConversationManagerTest : public CPPUNIT_NS :: TestFixture, public BasicTe CPPUNIT_ASSERT(dynamic_cast(getStanza(received[0]))); CPPUNIT_ASSERT_EQUAL(std::string("hi there!"), dynamic_cast(getStanza(received[0]))->getBody()); CPPUNIT_ASSERT_EQUAL(std::string("user@localhost"), dynamic_cast(getStanza(received[0]))->getTo().toString()); - CPPUNIT_ASSERT_EQUAL(std::string("buddy1@localhost/bot"), dynamic_cast(getStanza(received[0]))->getFrom().toString()); + CPPUNIT_ASSERT_EQUAL(std::string("buddy1\\40test@localhost/bot"), dynamic_cast(getStanza(received[0]))->getFrom().toString()); received.clear(); // send response msg->setFrom("user@localhost/resource"); - msg->setTo("buddy1@localhost/bot"); + msg->setTo("buddy1\\40test@localhost/bot"); msg->setBody("response!"); injectMessage(msg); loop->processEvents(); @@ -169,20 +169,28 @@ class ConversationManagerTest : public CPPUNIT_NS :: TestFixture, public BasicTe CPPUNIT_ASSERT(dynamic_cast(getStanza(received[0]))); CPPUNIT_ASSERT_EQUAL(std::string("hi there!"), dynamic_cast(getStanza(received[0]))->getBody()); CPPUNIT_ASSERT_EQUAL(std::string("user@localhost/resource"), dynamic_cast(getStanza(received[0]))->getTo().toString()); - CPPUNIT_ASSERT_EQUAL(std::string("buddy1@localhost/bot"), dynamic_cast(getStanza(received[0]))->getFrom().toString()); + CPPUNIT_ASSERT_EQUAL(std::string("buddy1\\40test@localhost/bot"), dynamic_cast(getStanza(received[0]))->getFrom().toString()); received.clear(); + // disable jid_escaping + std::istringstream ifs("service.server_mode = 1\nservice.jid_escaping=0\nservice.jid=localhost\nservice.more_resources=1\n"); + cfg->load(ifs); + // and now to bare JID again... user->getConversationManager()->resetResources(); conv->handleMessage(msg2); loop->processEvents(); + + // enable jid_escaping again + std::istringstream ifs2("service.server_mode = 1\nservice.jid_escaping=1\nservice.jid=localhost\nservice.more_resources=1\n"); + cfg->load(ifs2); CPPUNIT_ASSERT_EQUAL(1, (int) received.size()); CPPUNIT_ASSERT(dynamic_cast(getStanza(received[0]))); CPPUNIT_ASSERT_EQUAL(std::string("hi there!"), dynamic_cast(getStanza(received[0]))->getBody()); CPPUNIT_ASSERT_EQUAL(std::string("user@localhost"), dynamic_cast(getStanza(received[0]))->getTo().toString()); - CPPUNIT_ASSERT_EQUAL(std::string("buddy1@localhost/bot"), dynamic_cast(getStanza(received[0]))->getFrom().toString()); + CPPUNIT_ASSERT_EQUAL(std::string("buddy1%test@localhost/bot"), dynamic_cast(getStanza(received[0]))->getFrom().toString()); received.clear(); } diff --git a/src/tests/localbuddy.cpp b/src/tests/localbuddy.cpp index fdc6fb87..3a0ee795 100644 --- a/src/tests/localbuddy.cpp +++ b/src/tests/localbuddy.cpp @@ -25,6 +25,7 @@ class LocalBuddyTest : public CPPUNIT_NS :: TestFixture, public BasicTest { CPPUNIT_TEST(createWithInvalidName); CPPUNIT_TEST(buddyFlagsFromJID); CPPUNIT_TEST(JIDToLegacyName); + CPPUNIT_TEST(getSafeName); CPPUNIT_TEST(handleBuddyChanged); CPPUNIT_TEST(setAlias); CPPUNIT_TEST_SUITE_END(); @@ -70,6 +71,20 @@ class LocalBuddyTest : public CPPUNIT_NS :: TestFixture, public BasicTest { CPPUNIT_ASSERT_EQUAL(std::string("hanzz@test"), Buddy::JIDToLegacyName("hanzz%test@localhost/bot")); } + void getSafeName() { + User *user = userManager->getUser("user@localhost"); + CPPUNIT_ASSERT(user); + + std::vector grp; + grp.push_back("group1"); + LocalBuddy *buddy = new LocalBuddy(user->getRosterManager(), -1, "buddy1@test", "Buddy 1", grp, BUDDY_JID_ESCAPING); + + CPPUNIT_ASSERT_EQUAL(std::string("buddy1\\40test"), buddy->getSafeName()); + + buddy->setFlags(BUDDY_NO_FLAG); + CPPUNIT_ASSERT_EQUAL(std::string("buddy1%test"), buddy->getSafeName()); + } + void buddyFlagsFromJID() { CPPUNIT_ASSERT_EQUAL(BUDDY_JID_ESCAPING, Buddy::buddyFlagsFromJID("hanzz\\40test@localhost/bot")); CPPUNIT_ASSERT_EQUAL(BUDDY_NO_FLAG, Buddy::buddyFlagsFromJID("hanzz%test@localhost/bot")); diff --git a/src/tests/networkpluginserver.cpp b/src/tests/networkpluginserver.cpp new file mode 100644 index 00000000..9a9d921c --- /dev/null +++ b/src/tests/networkpluginserver.cpp @@ -0,0 +1,95 @@ +#include "transport/userregistry.h" +#include "transport/userregistration.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 "transport/settingsadhoccommand.h" +#include "transport/adhocmanager.h" +#include "transport/protocol.pb.h" +#include "transport/networkpluginserver.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" + +using namespace Transport; + +class NetworkPluginServerTest : public CPPUNIT_NS :: TestFixture, public BasicTest { + CPPUNIT_TEST_SUITE(NetworkPluginServerTest); + CPPUNIT_TEST(handleBuddyChangedPayload); + CPPUNIT_TEST(handleBuddyChangedPayloadNoEscaping); + CPPUNIT_TEST_SUITE_END(); + + public: + NetworkPluginServer *serv; + + void setUp (void) { + setMeUp(); + + serv = new NetworkPluginServer(component, cfg, userManager, NULL, NULL); + connectUser(); + received.clear(); + } + + void tearDown (void) { + received.clear(); + disconnectUser(); + delete serv; + tearMeDown(); + } + + void handleBuddyChangedPayload() { + User *user = userManager->getUser("user@localhost"); + + pbnetwork::Buddy buddy; + buddy.set_username("user@localhost"); + buddy.set_buddyname("buddy1@test"); + + std::string message; + buddy.SerializeToString(&message); + + serv->handleBuddyChangedPayload(message); + CPPUNIT_ASSERT_EQUAL(1, (int) received.size()); + Swift::RosterPayload::ref payload1 = getStanza(received[0])->getPayload(); + CPPUNIT_ASSERT_EQUAL(1, (int) payload1->getItems().size()); + Swift::RosterItemPayload item = payload1->getItems()[0]; + CPPUNIT_ASSERT_EQUAL(std::string("buddy1\\40test@localhost"), item.getJID().toString()); + } + + void handleBuddyChangedPayloadNoEscaping() { + std::istringstream ifs("service.server_mode = 1\nservice.jid_escaping=0\nservice.jid=localhost\nservice.more_resources=1\n"); + cfg->load(ifs); + User *user = userManager->getUser("user@localhost"); + + pbnetwork::Buddy buddy; + buddy.set_username("user@localhost"); + buddy.set_buddyname("buddy1@test"); + + std::string message; + buddy.SerializeToString(&message); + + serv->handleBuddyChangedPayload(message); + CPPUNIT_ASSERT_EQUAL(1, (int) received.size()); + Swift::RosterPayload::ref payload1 = getStanza(received[0])->getPayload(); + CPPUNIT_ASSERT_EQUAL(1, (int) payload1->getItems().size()); + Swift::RosterItemPayload item = payload1->getItems()[0]; + CPPUNIT_ASSERT_EQUAL(std::string("buddy1%test@localhost"), item.getJID().toString()); + + std::istringstream ifs2("service.server_mode = 1\nservice.jid_escaping=1\nservice.jid=localhost\nservice.more_resources=1\n"); + cfg->load(ifs2); + } + +}; + +CPPUNIT_TEST_SUITE_REGISTRATION (NetworkPluginServerTest); diff --git a/src/userregistration.cpp b/src/userregistration.cpp index a13006ca..4160f9e0 100644 --- a/src/userregistration.cpp +++ b/src/userregistration.cpp @@ -94,7 +94,15 @@ void UserRegistration::handleUnregisterRemoteRosterResponse(boost::shared_ptr roster; m_storageBackend->getBuddies(userInfo.id, roster); for(std::list::iterator u = roster.begin(); u != roster.end() ; u++){ - std::string name = Swift::JID::getEscapedNode((*u).legacyName); + std::string name = (*u).legacyName; + if ((*u).flags & BUDDY_JID_ESCAPING) { + name = Swift::JID::getEscapedNode((*u).legacyName); + } + else { + if (name.find_last_of("@") != std::string::npos) { + name.replace(name.find_last_of("@"), 1, "%"); + } + } Swift::Presence::ref response; response = Swift::Presence::create();