From c80c02ccb158daa62fbc28f774e7d1388c322e6c Mon Sep 17 00:00:00 2001 From: Jan Kaluza Date: Wed, 10 Feb 2016 17:02:06 +0100 Subject: [PATCH] Libtransport: Rename user when he tries to connect to room from second client with different nickname than he used with first client --- include/transport/Conversation.h | 3 +- libtransport/Conversation.cpp | 39 ++++++++++++-- libtransport/User.cpp | 2 +- tests/libtransport/conversationmanager.cpp | 62 ++++++++++++++-------- 4 files changed, 76 insertions(+), 30 deletions(-) diff --git a/include/transport/Conversation.h b/include/transport/Conversation.h index ee48d82e..ab210e98 100644 --- a/include/transport/Conversation.h +++ b/include/transport/Conversation.h @@ -139,7 +139,7 @@ class Conversation { void destroyRoom(); std::string getParticipants(); - void sendParticipants(const Swift::JID &to); + void sendParticipants(const Swift::JID &to, const std::string &nickname); void sendCachedMessages(const Swift::JID &to = Swift::JID()); @@ -160,6 +160,7 @@ class Conversation { bool m_sentInitialPresence; bool m_nicknameChanged; bool m_mucEscaping; + bool m_sentInitialSubject; // TODO: Move this to some extra class to cache the most used // rooms across different accounts. Just now if we have 10 users diff --git a/libtransport/Conversation.cpp b/libtransport/Conversation.cpp index 6ac34628..8786a242 100644 --- a/libtransport/Conversation.cpp +++ b/libtransport/Conversation.cpp @@ -47,6 +47,7 @@ Conversation::Conversation(ConversationManager *conversationManager, const std:: m_sentInitialPresence = false; m_nicknameChanged = false; m_mucEscaping = false; + m_sentInitialSubject = false; if (CONFIG_BOOL_DEFAULTED(conversationManager->getComponent()->getConfig(), "features.rawxml", false)) { m_sentInitialPresence = true; @@ -128,9 +129,11 @@ void Conversation::handleRawMessage(boost::shared_ptr &message) BOOST_FOREACH(const Swift::JID &jid, m_jids) { message->setTo(jid); // Subject has to be sent after our own presence (the one with code 110) - if (!message->getSubject().empty() && m_sentInitialPresence == false) { + if (!message->getSubject().empty()) { m_subject = message; - return; + if (m_sentInitialPresence == false) { + return; + } } m_conversationManager->getComponent()->getFrontend()->sendMessage(message); } @@ -227,7 +230,33 @@ std::string Conversation::getParticipants() { return ret; } -void Conversation::sendParticipants(const Swift::JID &to) { +void Conversation::sendParticipants(const Swift::JID &to, const std::string &nickname) { + // When user tries to join this room from another resource using + // different nickname than the original one has, we have to rename + // him. + if (m_nickname != nickname && !nickname.empty()) { + Swift::Presence::ref presence; + std::string tmp = m_nickname; + + // At first connect the user. + m_nickname = nickname; + presence = generatePresence(nickname, 0, (int) Swift::StatusShow::Online, "", "", ""); + presence->setTo(to); + m_conversationManager->getComponent()->getFrontend()->sendPresence(presence); + + // Now change his nickname to the right one. + m_nicknameChanged = true; + presence = generatePresence(nickname, 0, (int) Swift::StatusShow::Online, "", tmp, ""); + presence->setTo(to); + m_conversationManager->getComponent()->getFrontend()->sendPresence(presence); + + // And send the presence from as new user + m_nickname = tmp; + presence = generatePresence(m_nickname, 0, (int) Swift::StatusShow::Online, "", "", ""); + presence->setTo(to); + m_conversationManager->getComponent()->getFrontend()->sendPresence(presence); + } + for (std::map::iterator it = m_participants.begin(); it != m_participants.end(); it++) { (*it).second.presence->setTo(to); m_conversationManager->getComponent()->getFrontend()->sendPresence((*it).second.presence); @@ -385,9 +414,9 @@ void Conversation::handleParticipantChanged(const std::string &nick, Conversatio handleParticipantChanged(newname, flag, status, statusMessage, "", iconhash); } - if (m_sentInitialPresence && m_subject) { + if (m_sentInitialPresence && !m_sentInitialSubject && m_subject) { + m_sentInitialSubject = true; m_conversationManager->getComponent()->getFrontend()->sendMessage(m_subject); - m_subject.reset(); } // We send error presences only to inform user that he is disconnected diff --git a/libtransport/User.cpp b/libtransport/User.cpp index e8dbacfa..fffc4eb5 100644 --- a/libtransport/User.cpp +++ b/libtransport/User.cpp @@ -259,7 +259,7 @@ void User::handlePresence(Swift::Presence::ref presence, bool forceJoin) { } else { conv->addJID(presence->getFrom()); - conv->sendParticipants(presence->getFrom()); + conv->sendParticipants(presence->getFrom(), presence->getTo().getResource()); conv->sendCachedMessages(presence->getFrom()); } diff --git a/tests/libtransport/conversationmanager.cpp b/tests/libtransport/conversationmanager.cpp index b7c52aab..7fc14631 100644 --- a/tests/libtransport/conversationmanager.cpp +++ b/tests/libtransport/conversationmanager.cpp @@ -122,7 +122,7 @@ class ConversationManagerTest : public CPPUNIT_NS :: TestFixture, public BasicTe // this user presence - status code 110 conv->handleParticipantChanged("nickname", Conversation::PARTICIPANT_FLAG_MODERATOR, Swift::StatusShow::Away, "my status message"); loop->processEvents(); - + CPPUNIT_ASSERT_EQUAL(2, (int) received.size()); CPPUNIT_ASSERT(dynamic_cast(getStanza(received[1]))); CPPUNIT_ASSERT_EQUAL(std::string("subject"), dynamic_cast(getStanza(received[1]))->getSubject()); @@ -410,21 +410,29 @@ class ConversationManagerTest : public CPPUNIT_NS :: TestFixture, public BasicTe injectPresence(response); loop->processEvents(); - CPPUNIT_ASSERT_EQUAL(4, (int) received.size()); - CPPUNIT_ASSERT(dynamic_cast(getStanza(received[1]))); - CPPUNIT_ASSERT_EQUAL(std::string("hi there!"), dynamic_cast(getStanza(received[1]))->getBody()); - CPPUNIT_ASSERT_EQUAL(std::string("user@localhost/resource"), dynamic_cast(getStanza(received[1]))->getTo().toString()); - CPPUNIT_ASSERT_EQUAL(std::string("#room@localhost/anotheruser"), dynamic_cast(getStanza(received[1]))->getFrom().toString()); + CPPUNIT_ASSERT_EQUAL(7, (int) received.size()); + CPPUNIT_ASSERT(dynamic_cast(getStanza(received[2]))); + CPPUNIT_ASSERT_EQUAL(Swift::Presence::Unavailable, dynamic_cast(getStanza(received[2]))->getType()); + CPPUNIT_ASSERT_EQUAL(std::string("user@localhost/resource"), dynamic_cast(getStanza(received[2]))->getTo().toString()); + CPPUNIT_ASSERT_EQUAL(std::string("#room@localhost/hanzz"), dynamic_cast(getStanza(received[2]))->getFrom().toString()); + CPPUNIT_ASSERT(getStanza(received[2])->getPayload()); + CPPUNIT_ASSERT_EQUAL(std::string("nickname"), *getStanza(received[2])->getPayload()->getItems()[0].nick); + CPPUNIT_ASSERT_EQUAL(303, getStanza(received[2])->getPayload()->getStatusCodes()[2].code); - CPPUNIT_ASSERT(dynamic_cast(getStanza(received[2]))); - CPPUNIT_ASSERT_EQUAL(std::string("hi there2!"), dynamic_cast(getStanza(received[2]))->getBody()); - CPPUNIT_ASSERT_EQUAL(std::string("user@localhost/resource"), dynamic_cast(getStanza(received[2]))->getTo().toString()); - CPPUNIT_ASSERT_EQUAL(std::string("#room@localhost/anotheruser"), dynamic_cast(getStanza(received[2]))->getFrom().toString()); + CPPUNIT_ASSERT(dynamic_cast(getStanza(received[4]))); + CPPUNIT_ASSERT_EQUAL(std::string("hi there!"), dynamic_cast(getStanza(received[4]))->getBody()); + CPPUNIT_ASSERT_EQUAL(std::string("user@localhost/resource"), dynamic_cast(getStanza(received[4]))->getTo().toString()); + CPPUNIT_ASSERT_EQUAL(std::string("#room@localhost/anotheruser"), dynamic_cast(getStanza(received[4]))->getFrom().toString()); - CPPUNIT_ASSERT(dynamic_cast(getStanza(received[3]))); - CPPUNIT_ASSERT_EQUAL(std::string("subject"), dynamic_cast(getStanza(received[3]))->getSubject()); - CPPUNIT_ASSERT_EQUAL(std::string("user@localhost/resource"), dynamic_cast(getStanza(received[3]))->getTo().toString()); - CPPUNIT_ASSERT_EQUAL(std::string("#room@localhost/anotheruser"), dynamic_cast(getStanza(received[3]))->getFrom().toString()); + CPPUNIT_ASSERT(dynamic_cast(getStanza(received[5]))); + CPPUNIT_ASSERT_EQUAL(std::string("hi there2!"), dynamic_cast(getStanza(received[5]))->getBody()); + CPPUNIT_ASSERT_EQUAL(std::string("user@localhost/resource"), dynamic_cast(getStanza(received[5]))->getTo().toString()); + CPPUNIT_ASSERT_EQUAL(std::string("#room@localhost/anotheruser"), dynamic_cast(getStanza(received[5]))->getFrom().toString()); + + CPPUNIT_ASSERT(dynamic_cast(getStanza(received[6]))); + CPPUNIT_ASSERT_EQUAL(std::string("subject"), dynamic_cast(getStanza(received[6]))->getSubject()); + CPPUNIT_ASSERT_EQUAL(std::string("user@localhost/resource"), dynamic_cast(getStanza(received[6]))->getTo().toString()); + CPPUNIT_ASSERT_EQUAL(std::string("#room@localhost/anotheruser"), dynamic_cast(getStanza(received[6]))->getFrom().toString()); } void handleGroupchatMessagesBouncerLeave() { @@ -479,16 +487,24 @@ class ConversationManagerTest : public CPPUNIT_NS :: TestFixture, public BasicTe injectPresence(response); loop->processEvents(); - CPPUNIT_ASSERT_EQUAL(3, (int) received.size()); - CPPUNIT_ASSERT(dynamic_cast(getStanza(received[1]))); - CPPUNIT_ASSERT_EQUAL(std::string("hi there!"), dynamic_cast(getStanza(received[1]))->getBody()); - CPPUNIT_ASSERT_EQUAL(std::string("user@localhost/resource"), dynamic_cast(getStanza(received[1]))->getTo().toString()); - CPPUNIT_ASSERT_EQUAL(std::string("#room@localhost/anotheruser"), dynamic_cast(getStanza(received[1]))->getFrom().toString()); + CPPUNIT_ASSERT_EQUAL(6, (int) received.size()); + CPPUNIT_ASSERT(dynamic_cast(getStanza(received[2]))); + CPPUNIT_ASSERT_EQUAL(Swift::Presence::Unavailable, dynamic_cast(getStanza(received[2]))->getType()); + CPPUNIT_ASSERT_EQUAL(std::string("user@localhost/resource"), dynamic_cast(getStanza(received[2]))->getTo().toString()); + CPPUNIT_ASSERT_EQUAL(std::string("#room@localhost/hanzz"), dynamic_cast(getStanza(received[2]))->getFrom().toString()); + CPPUNIT_ASSERT(getStanza(received[2])->getPayload()); + CPPUNIT_ASSERT_EQUAL(std::string("nickname"), *getStanza(received[2])->getPayload()->getItems()[0].nick); + CPPUNIT_ASSERT_EQUAL(303, getStanza(received[2])->getPayload()->getStatusCodes()[2].code); - CPPUNIT_ASSERT(dynamic_cast(getStanza(received[2]))); - CPPUNIT_ASSERT_EQUAL(std::string("hi there2!"), dynamic_cast(getStanza(received[2]))->getBody()); - CPPUNIT_ASSERT_EQUAL(std::string("user@localhost/resource"), dynamic_cast(getStanza(received[2]))->getTo().toString()); - CPPUNIT_ASSERT_EQUAL(std::string("#room@localhost/anotheruser"), dynamic_cast(getStanza(received[2]))->getFrom().toString()); + CPPUNIT_ASSERT(dynamic_cast(getStanza(received[4]))); + CPPUNIT_ASSERT_EQUAL(std::string("hi there!"), dynamic_cast(getStanza(received[4]))->getBody()); + CPPUNIT_ASSERT_EQUAL(std::string("user@localhost/resource"), dynamic_cast(getStanza(received[4]))->getTo().toString()); + CPPUNIT_ASSERT_EQUAL(std::string("#room@localhost/anotheruser"), dynamic_cast(getStanza(received[4]))->getFrom().toString()); + + CPPUNIT_ASSERT(dynamic_cast(getStanza(received[5]))); + CPPUNIT_ASSERT_EQUAL(std::string("hi there2!"), dynamic_cast(getStanza(received[5]))->getBody()); + CPPUNIT_ASSERT_EQUAL(std::string("user@localhost/resource"), dynamic_cast(getStanza(received[5]))->getTo().toString()); + CPPUNIT_ASSERT_EQUAL(std::string("#room@localhost/anotheruser"), dynamic_cast(getStanza(received[5]))->getFrom().toString()); }