diff options
author | Tobias Markmann <tm@ayena.de> | 2016-01-12 17:23:05 (GMT) |
---|---|---|
committer | Kevin Smith <kevin.smith@isode.com> | 2016-02-02 11:33:06 (GMT) |
commit | 1b9ccc1fef6104eaf951153ddccdc6bb15899e9a (patch) | |
tree | 428232448e9846265605820db6f380a5b98c018a /Swift/Controllers/Chat | |
parent | 3afd061b713ce5fff604dee62dec8410a1de6a9c (diff) | |
download | swift-1b9ccc1fef6104eaf951153ddccdc6bb15899e9a.zip swift-1b9ccc1fef6104eaf951153ddccdc6bb15899e9a.tar.bz2 |
Change stanza body to boost::optional<std::string> type
Changed MUCController to only handle message stanzas as
subject change if <subject/> is present and neither <body/>
nor <thread/> is present in the message stanza.
Test-Information:
Added unit tests verifying behavior described in XEP-0045
section 8.1.
Unit tests pass on OS X 10.11.2.
Change-Id: I1d22272da1675176be131ab360b214a98f20533f
Diffstat (limited to 'Swift/Controllers/Chat')
-rw-r--r-- | Swift/Controllers/Chat/ChatController.cpp | 2 | ||||
-rw-r--r-- | Swift/Controllers/Chat/ChatControllerBase.cpp | 8 | ||||
-rw-r--r-- | Swift/Controllers/Chat/ChatsManager.cpp | 2 | ||||
-rw-r--r-- | Swift/Controllers/Chat/MUCController.cpp | 9 | ||||
-rw-r--r-- | Swift/Controllers/Chat/UnitTest/MUCControllerTest.cpp | 115 |
5 files changed, 121 insertions, 15 deletions
diff --git a/Swift/Controllers/Chat/ChatController.cpp b/Swift/Controllers/Chat/ChatController.cpp index eb86766..11ba89e 100644 --- a/Swift/Controllers/Chat/ChatController.cpp +++ b/Swift/Controllers/Chat/ChatController.cpp @@ -177,7 +177,7 @@ void ChatController::preHandleIncomingMessage(boost::shared_ptr<MessageEvent> me if (toJID_.equals(from, JID::WithoutResource) && toJID_.isBare()){ // Bind controller to a full JID if message contains body text or is a typing chat state. ChatState::ref chatState = message->getPayload<ChatState>(); - if (!message->getBody().empty() || (chatState && chatState->getChatState() == ChatState::Composing)) { + if (!message->getBody().get_value_or("").empty() || (chatState && chatState->getChatState() == ChatState::Composing)) { setToJID(from); } } diff --git a/Swift/Controllers/Chat/ChatControllerBase.cpp b/Swift/Controllers/Chat/ChatControllerBase.cpp index 4a84a6e..fef3e7a 100644 --- a/Swift/Controllers/Chat/ChatControllerBase.cpp +++ b/Swift/Controllers/Chat/ChatControllerBase.cpp @@ -172,8 +172,8 @@ void ChatControllerBase::handleSendMessageRequest(const std::string &body, bool } message->setID(lastSentMessageStanzaID_ = idGenerator_.generateID()); stanzaChannel_->sendMessage(message); - postSendMessage(message->getBody(), boost::dynamic_pointer_cast<Stanza>(message)); - onActivity(message->getBody()); + postSendMessage(message->getBody().get(), boost::dynamic_pointer_cast<Stanza>(message)); + onActivity(message->getBody().get()); #ifdef SWIFT_EXPERIMENTAL_HISTORY logMessage(body, selfJID_, toJID_, now, false); @@ -237,7 +237,7 @@ void ChatControllerBase::handleIncomingMessage(boost::shared_ptr<MessageEvent> m } } boost::shared_ptr<Message> message = messageEvent->getStanza(); - std::string body = message->getBody(); + std::string body = message->getBody().get_value_or(""); HighlightAction highlight; if (message->isError()) { if (!message->getTo().getResource().empty()) { @@ -286,7 +286,7 @@ void ChatControllerBase::handleIncomingMessage(boost::shared_ptr<MessageEvent> m boost::shared_ptr<Replace> replace = message->getPayload<Replace>(); if (replace) { - std::string body = message->getBody(); + std::string body = message->getBody().get_value_or(""); // Should check if the user has a previous message std::map<JID, std::string>::iterator lastMessage; lastMessage = lastMessagesUIID_.find(from); diff --git a/Swift/Controllers/Chat/ChatsManager.cpp b/Swift/Controllers/Chat/ChatsManager.cpp index 1a69982..49caee4 100644 --- a/Swift/Controllers/Chat/ChatsManager.cpp +++ b/Swift/Controllers/Chat/ChatsManager.cpp @@ -917,7 +917,7 @@ void ChatsManager::handleIncomingMessage(boost::shared_ptr<Message> message) { // Do not bind a controller to a full JID, for delivery receipts or chat state notifications. bool bindControllerToJID = false; ChatState::ref chatState = message->getPayload<ChatState>(); - if (!message->getBody().empty() || (chatState && chatState->getChatState() == ChatState::Composing)) { + if (!message->getBody().get_value_or("").empty() || (chatState && chatState->getChatState() == ChatState::Composing)) { bindControllerToJID = true; } diff --git a/Swift/Controllers/Chat/MUCController.cpp b/Swift/Controllers/Chat/MUCController.cpp index e6c16b7..409fe1f 100644 --- a/Swift/Controllers/Chat/MUCController.cpp +++ b/Swift/Controllers/Chat/MUCController.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2015 Isode Limited. + * Copyright (c) 2010-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ @@ -22,6 +22,7 @@ #include <Swiften/Client/StanzaChannel.h> #include <Swiften/Disco/EntityCapsProvider.h> #include <Swiften/Elements/Delay.h> +#include <Swiften/Elements/Thread.h> #include <Swiften/MUC/MUC.h> #include <Swiften/MUC/MUCBookmark.h> #include <Swiften/MUC/MUCBookmarkManager.h> @@ -531,7 +532,7 @@ JID MUCController::nickToJID(const std::string& nick) { bool MUCController::messageTargetsMe(boost::shared_ptr<Message> message) { std::string stringRegexp(".*\\b" + boost::to_lower_copy(nick_) + "\\b.*"); boost::regex myRegexp(stringRegexp); - return boost::regex_match(boost::to_lower_copy(message->getBody()), myRegexp); + return boost::regex_match(boost::to_lower_copy(message->getBody().get_value_or("")), myRegexp); } void MUCController::preHandleIncomingMessage(boost::shared_ptr<MessageEvent> messageEvent) { @@ -559,7 +560,7 @@ void MUCController::preHandleIncomingMessage(boost::shared_ptr<MessageEvent> mes receivedActivity(); joined_ = true; - if (message->hasSubject() && message->getBody().empty()) { + if (message->hasSubject() && !message->getPayload<Body>() && !message->getPayload<Thread>()) { chatWindow_->addSystemMessage(chatMessageParser_->parseMessageBody(str(format(QT_TRANSLATE_NOOP("", "The room subject is now: %1%")) % message->getSubject())), ChatWindow::DefaultDirection); chatWindow_->setSubject(message->getSubject()); doneGettingHistory_ = true; @@ -1078,7 +1079,7 @@ void MUCController::addRecentLogs() { } void MUCController::checkDuplicates(boost::shared_ptr<Message> newMessage) { - std::string body = newMessage->getBody(); + std::string body = newMessage->getBody().get_value_or(""); JID jid = newMessage->getFrom(); boost::optional<boost::posix_time::ptime> time = newMessage->getTimestamp(); diff --git a/Swift/Controllers/Chat/UnitTest/MUCControllerTest.cpp b/Swift/Controllers/Chat/UnitTest/MUCControllerTest.cpp index bc6ada2..e8fc41d 100644 --- a/Swift/Controllers/Chat/UnitTest/MUCControllerTest.cpp +++ b/Swift/Controllers/Chat/UnitTest/MUCControllerTest.cpp @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2015 Isode Limited. + * Copyright (c) 2010-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ @@ -19,6 +19,7 @@ #include <Swiften/Crypto/PlatformCryptoProvider.h> #include <Swiften/Disco/DummyEntityCapsProvider.h> #include <Swiften/Elements/MUCUserPayload.h> +#include <Swiften/Elements/Thread.h> #include <Swiften/MUC/MUCBookmarkManager.h> #include <Swiften/MUC/UnitTest/MockMUC.h> #include <Swiften/Network/TimerFactory.h> @@ -58,6 +59,10 @@ class MUCControllerTest : public CppUnit::TestFixture { CPPUNIT_TEST(testMessageWithLabelItem); CPPUNIT_TEST(testCorrectMessageWithLabelItem); CPPUNIT_TEST(testRoleAffiliationStates); + CPPUNIT_TEST(testSubjectChangeCorrect); + CPPUNIT_TEST(testSubjectChangeIncorrectA); + CPPUNIT_TEST(testSubjectChangeIncorrectB); + CPPUNIT_TEST(testSubjectChangeIncorrectC); CPPUNIT_TEST_SUITE_END(); public: @@ -215,7 +220,7 @@ public: CPPUNIT_ASSERT(window_->labelsEnabled_); CPPUNIT_ASSERT(stanzaChannel_->isAvailable()); /* Otherwise will prevent sends. */ CPPUNIT_ASSERT(message); - CPPUNIT_ASSERT_EQUAL(messageBody, message->getBody()); + CPPUNIT_ASSERT_EQUAL(messageBody, message->getBody().get()); CPPUNIT_ASSERT(!message->getPayload<SecurityLabel>()); } @@ -242,7 +247,7 @@ public: CPPUNIT_ASSERT(window_->labelsEnabled_); CPPUNIT_ASSERT(stanzaChannel_->isAvailable()); /* Otherwise will prevent sends. */ CPPUNIT_ASSERT(message); - CPPUNIT_ASSERT_EQUAL(messageBody, message->getBody()); + CPPUNIT_ASSERT_EQUAL(messageBody, message->getBody().get()); CPPUNIT_ASSERT_EQUAL(label, message->getPayload<SecurityLabel>()); } @@ -274,13 +279,13 @@ public: CPPUNIT_ASSERT(window_->labelsEnabled_); CPPUNIT_ASSERT(stanzaChannel_->isAvailable()); /* Otherwise will prevent sends. */ CPPUNIT_ASSERT(message); - CPPUNIT_ASSERT_EQUAL(messageBody, message->getBody()); + CPPUNIT_ASSERT_EQUAL(messageBody, message->getBody().get()); CPPUNIT_ASSERT_EQUAL(label, message->getPayload<SecurityLabel>()); window_->label_ = labelItem2; window_->onSendMessageRequest(messageBody, true); rawStanza = stanzaChannel_->sentStanzas[stanzaChannel_->sentStanzas.size() - 1]; message = boost::dynamic_pointer_cast<Message>(rawStanza); - CPPUNIT_ASSERT_EQUAL(messageBody, message->getBody()); + CPPUNIT_ASSERT_EQUAL(messageBody, message->getBody().get()); CPPUNIT_ASSERT_EQUAL(label, message->getPayload<SecurityLabel>()); } @@ -398,6 +403,106 @@ public: } } + void testSubjectChangeCorrect() { + std::string messageBody("test message"); + window_->onSendMessageRequest(messageBody, false); + boost::shared_ptr<Stanza> rawStanza = stanzaChannel_->sentStanzas[stanzaChannel_->sentStanzas.size() - 1]; + Message::ref message = boost::dynamic_pointer_cast<Message>(rawStanza); + CPPUNIT_ASSERT(stanzaChannel_->isAvailable()); /* Otherwise will prevent sends. */ + CPPUNIT_ASSERT(message); + CPPUNIT_ASSERT_EQUAL(messageBody, message->getBody().get_value_or("")); + + { + Message::ref message = boost::make_shared<Message>(); + message->setType(Message::Groupchat); + message->setTo(self_); + message->setFrom(mucJID_.withResource("SomeNickname")); + message->setID(iqChannel_->getNewIQID()); + message->setSubject("New Room Subject"); + + controller_->handleIncomingMessage(boost::make_shared<MessageEvent>(message)); + CPPUNIT_ASSERT_EQUAL(std::string("The room subject is now: New Room Subject"), boost::dynamic_pointer_cast<ChatWindow::ChatTextMessagePart>(window_->lastAddedSystemMessage_.getParts()[0])->text); + } + } + + /* + * Test that message stanzas with subject element and non-empty body element do not cause a subject change. + */ + void testSubjectChangeIncorrectA() { + std::string messageBody("test message"); + window_->onSendMessageRequest(messageBody, false); + boost::shared_ptr<Stanza> rawStanza = stanzaChannel_->sentStanzas[stanzaChannel_->sentStanzas.size() - 1]; + Message::ref message = boost::dynamic_pointer_cast<Message>(rawStanza); + CPPUNIT_ASSERT(stanzaChannel_->isAvailable()); /* Otherwise will prevent sends. */ + CPPUNIT_ASSERT(message); + CPPUNIT_ASSERT_EQUAL(messageBody, message->getBody().get_value_or("")); + + { + Message::ref message = boost::make_shared<Message>(); + message->setType(Message::Groupchat); + message->setTo(self_); + message->setFrom(mucJID_.withResource("SomeNickname")); + message->setID(iqChannel_->getNewIQID()); + message->setSubject("New Room Subject"); + message->setBody("Some body text that prevents this stanza from being a subject change."); + + controller_->handleIncomingMessage(boost::make_shared<MessageEvent>(message)); + CPPUNIT_ASSERT_EQUAL(std::string("Trying to enter room teaparty@rooms.wonderland.lit"), boost::dynamic_pointer_cast<ChatWindow::ChatTextMessagePart>(window_->lastAddedSystemMessage_.getParts()[0])->text); + } + } + + /* + * Test that message stanzas with subject element and thread element do not cause a subject change. + */ + void testSubjectChangeIncorrectB() { + std::string messageBody("test message"); + window_->onSendMessageRequest(messageBody, false); + boost::shared_ptr<Stanza> rawStanza = stanzaChannel_->sentStanzas[stanzaChannel_->sentStanzas.size() - 1]; + Message::ref message = boost::dynamic_pointer_cast<Message>(rawStanza); + CPPUNIT_ASSERT(stanzaChannel_->isAvailable()); /* Otherwise will prevent sends. */ + CPPUNIT_ASSERT(message); + CPPUNIT_ASSERT_EQUAL(messageBody, message->getBody().get_value_or("")); + + { + Message::ref message = boost::make_shared<Message>(); + message->setType(Message::Groupchat); + message->setTo(self_); + message->setFrom(mucJID_.withResource("SomeNickname")); + message->setID(iqChannel_->getNewIQID()); + message->setSubject("New Room Subject"); + message->addPayload(boost::make_shared<Thread>("Thread that prevents the subject change.")); + + controller_->handleIncomingMessage(boost::make_shared<MessageEvent>(message)); + CPPUNIT_ASSERT_EQUAL(std::string("Trying to enter room teaparty@rooms.wonderland.lit"), boost::dynamic_pointer_cast<ChatWindow::ChatTextMessagePart>(window_->lastAddedSystemMessage_.getParts()[0])->text); + } + } + + /* + * Test that message stanzas with subject element and empty body element do not cause a subject change. + */ + void testSubjectChangeIncorrectC() { + std::string messageBody("test message"); + window_->onSendMessageRequest(messageBody, false); + boost::shared_ptr<Stanza> rawStanza = stanzaChannel_->sentStanzas[stanzaChannel_->sentStanzas.size() - 1]; + Message::ref message = boost::dynamic_pointer_cast<Message>(rawStanza); + CPPUNIT_ASSERT(stanzaChannel_->isAvailable()); /* Otherwise will prevent sends. */ + CPPUNIT_ASSERT(message); + CPPUNIT_ASSERT_EQUAL(messageBody, message->getBody().get_value_or("")); + + { + Message::ref message = boost::make_shared<Message>(); + message->setType(Message::Groupchat); + message->setTo(self_); + message->setFrom(mucJID_.withResource("SomeNickname")); + message->setID(iqChannel_->getNewIQID()); + message->setSubject("New Room Subject"); + message->setBody(""); + + controller_->handleIncomingMessage(boost::make_shared<MessageEvent>(message)); + CPPUNIT_ASSERT_EQUAL(std::string("Trying to enter room teaparty@rooms.wonderland.lit"), boost::dynamic_pointer_cast<ChatWindow::ChatTextMessagePart>(window_->lastAddedSystemMessage_.getParts()[0])->text); + } + } + void testRoleAffiliationStatesVerify(const std::map<std::string, MUCOccupant> &occupants) { /* verify that the roster is in sync */ GroupRosterItem* group = window_->getRosterModel()->getRoot(); |