diff options
Diffstat (limited to 'Swift/Controllers/Chat')
-rw-r--r-- | Swift/Controllers/Chat/MUCController.cpp | 32 | ||||
-rw-r--r-- | Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp | 14 | ||||
-rw-r--r-- | Swift/Controllers/Chat/UnitTest/MUCControllerTest.cpp | 10 | ||||
-rw-r--r-- | Swift/Controllers/Chat/UserSearchController.cpp | 16 |
4 files changed, 33 insertions, 39 deletions
diff --git a/Swift/Controllers/Chat/MUCController.cpp b/Swift/Controllers/Chat/MUCController.cpp index 9ae3845..349bf8a 100644 --- a/Swift/Controllers/Chat/MUCController.cpp +++ b/Swift/Controllers/Chat/MUCController.cpp @@ -1,47 +1,47 @@ /* * Copyright (c) 2010-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #include <Swift/Controllers/Chat/MUCController.h> #include <algorithm> #include <boost/bind.hpp> #include <boost/regex.hpp> #include <boost/algorithm/string.hpp> +#include <boost/range/adaptor/reversed.hpp> #include <Swiften/Avatars/AvatarManager.h> #include <Swiften/Base/Log.h> -#include <Swiften/Base/foreach.h> #include <Swiften/Base/format.h> #include <Swiften/Base/Tristate.h> #include <Swiften/Client/BlockList.h> #include <Swiften/Client/ClientBlockListManager.h> #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> #include <Swiften/Network/Timer.h> #include <Swiften/Network/TimerFactory.h> #include <Swiften/Roster/XMPPRoster.h> #include <SwifTools/TabComplete.h> #include <Swift/Controllers/Chat/ChatMessageParser.h> #include <Swift/Controllers/Highlighter.h> #include <Swift/Controllers/Intl.h> #include <Swift/Controllers/Roster/ContactRosterItem.h> #include <Swift/Controllers/Roster/GroupRosterItem.h> #include <Swift/Controllers/Roster/ItemOperations/SetAvatar.h> #include <Swift/Controllers/Roster/ItemOperations/SetMUC.h> #include <Swift/Controllers/Roster/ItemOperations/SetPresence.h> #include <Swift/Controllers/Roster/Roster.h> #include <Swift/Controllers/Roster/RosterVCardProvider.h> #include <Swift/Controllers/UIEvents/InviteToMUCUIEvent.h> #include <Swift/Controllers/UIEvents/RequestAddUserDialogUIEvent.h> #include <Swift/Controllers/UIEvents/RequestChangeBlockStateUIEvent.h> @@ -211,129 +211,128 @@ void MUCController::handleWindowOccupantSelectionChanged(ContactRosterItem* item // Add contact is available only if the real JID is also available if (muc_->getOccupant(item->getJID().getResource()).getRealJID()) { actions.push_back(ChatWindow::AddContact); } actions.push_back(ChatWindow::ShowProfile); } chatWindow_->setAvailableOccupantActions(actions); } void MUCController::handleActionRequestedOnOccupant(ChatWindow::OccupantAction action, ContactRosterItem* item) { JID mucJID = item->getJID(); MUCOccupant occupant = muc_->getOccupant(mucJID.getResource()); JID realJID; if (occupant.getRealJID()) { realJID = occupant.getRealJID().get(); } switch (action) { case ChatWindow::Kick: muc_->kickOccupant(mucJID);break; case ChatWindow::Ban: muc_->changeAffiliation(realJID, MUCOccupant::Outcast);break; case ChatWindow::MakeModerator: muc_->changeOccupantRole(mucJID, MUCOccupant::Moderator);break; case ChatWindow::MakeParticipant: muc_->changeOccupantRole(mucJID, MUCOccupant::Participant);break; case ChatWindow::MakeVisitor: muc_->changeOccupantRole(mucJID, MUCOccupant::Visitor);break; case ChatWindow::AddContact: if (occupant.getRealJID()) events_->send(std::make_shared<RequestAddUserDialogUIEvent>(realJID, occupant.getNick()));break; case ChatWindow::ShowProfile: events_->send(std::make_shared<ShowProfileForRosterItemUIEvent>(mucJID));break; } } void MUCController::handleBareJIDCapsChanged(const JID& /*jid*/) { Tristate support = Yes; bool any = false; - foreach (const std::string& nick, currentOccupants_) { + for (const auto& nick : currentOccupants_) { DiscoInfo::ref disco = entityCapsProvider_->getCaps(toJID_.toBare().toString() + "/" + nick); if (disco && disco->hasFeature(DiscoInfo::MessageCorrectionFeature)) { any = true; } else { support = Maybe; } } if (!any) { support = No; } chatWindow_->setCorrectionEnabled(support); } /** * Join the MUC if not already in it. */ void MUCController::rejoin() { if (parting_) { joined_ = false; parting_ = false; if (password_) { muc_->setPassword(*password_); } //FIXME: check for received activity #ifdef SWIFT_EXPERIMENTAL_HISTORY if (lastActivity_ == boost::posix_time::not_a_date_time && historyController_) { lastActivity_ = historyController_->getLastTimeStampFromMUC(selfJID_, toJID_); } #endif if (lastActivity_ == boost::posix_time::not_a_date_time) { muc_->joinAs(nick_); } else { muc_->joinWithContextSince(nick_, lastActivity_); } } } bool MUCController::isJoined() { return joined_; } const std::string& MUCController::getNick() { return nick_; } const boost::optional<std::string> MUCController::getPassword() const { return password_; } bool MUCController::isImpromptu() const { return isImpromptu_; } std::map<std::string, JID> MUCController::getParticipantJIDs() const { std::map<std::string, JID> participants; - typedef std::pair<std::string, MUCOccupant> MUCOccupantPair; std::map<std::string, MUCOccupant> occupants = muc_->getOccupants(); - foreach(const MUCOccupantPair& occupant, occupants) { + for (const auto& occupant : occupants) { if (occupant.first != nick_) { participants[occupant.first] = occupant.second.getRealJID().is_initialized() ? occupant.second.getRealJID().get().toBare() : JID(); } } return participants; } void MUCController::sendInvites(const std::vector<JID>& jids, const std::string& reason) const { - foreach (const JID& jid, jids) { + for (const auto& jid : jids) { muc_->invitePerson(jid, reason, isImpromptu_); } } void MUCController::handleJoinTimeoutTick() { receivedActivity(); chatWindow_->addSystemMessage(chatMessageParser_->parseMessageBody(str(format(QT_TRANSLATE_NOOP("", "Room %1% is not responding. This operation may never complete.")) % toJID_.toString())), ChatWindow::DefaultDirection); } void MUCController::receivedActivity() { if (loginCheckTimer_) { loginCheckTimer_->stop(); } } #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wswitch-enum" void MUCController::handleJoinFailed(std::shared_ptr<ErrorPayload> error) { receivedActivity(); std::string errorMessage = QT_TRANSLATE_NOOP("", "Unable to enter this room"); std::string rejoinNick; if (error) { switch (error->getCondition()) { case ErrorPayload::Conflict: rejoinNick = nick_ + "_"; errorMessage = str(format(QT_TRANSLATE_NOOP("", "Unable to enter this room as %1%, retrying as %2%")) % nick_ % rejoinNick); break; case ErrorPayload::JIDMalformed: errorMessage += ": "; @@ -832,61 +831,61 @@ void MUCController::appendToJoinParts(std::vector<NickJoinPart>& joinParts, cons case JoinThenPart: break; } (*it).type = type; break; } } if (!matched) { joinParts.push_back(newEvent); } } std::string MUCController::concatenateListOfNames(const std::vector<NickJoinPart>& joinParts) { std::string result; for (size_t i = 0; i < joinParts.size(); i++) { if (i > 0) { if (i < joinParts.size() - 1) { result += ", "; } else { result += QT_TRANSLATE_NOOP("", " and "); } } NickJoinPart event = joinParts[i]; result += event.nick; } return result; } std::string MUCController::generateJoinPartString(const std::vector<NickJoinPart>& joinParts, bool isImpromptu) { std::vector<NickJoinPart> sorted[4]; std::string eventStrings[4]; - foreach (NickJoinPart event, joinParts) { + for (const auto& event : joinParts) { sorted[event.type].push_back(event); } std::string result; std::vector<JoinPart> populatedEvents; for (size_t i = 0; i < 4; i++) { std::string names = concatenateListOfNames(sorted[i]); if (!names.empty()) { std::string eventString; switch (i) { case Join: if (sorted[i].size() > 1) { eventString = (isImpromptu ? QT_TRANSLATE_NOOP("", "%1% have joined the chat") : QT_TRANSLATE_NOOP("", "%1% have entered the room")); } else { eventString = (isImpromptu ? QT_TRANSLATE_NOOP("", "%1% has joined the chat") : QT_TRANSLATE_NOOP("", "%1% has entered the room")); } break; case Part: if (sorted[i].size() > 1) { eventString = (isImpromptu ? QT_TRANSLATE_NOOP("", "%1% have left the chat") : QT_TRANSLATE_NOOP("", "%1% have left the room")); } else { eventString = (isImpromptu ? QT_TRANSLATE_NOOP("", "%1% have left the chat") : QT_TRANSLATE_NOOP("", "%1% has left the room")); } break; case JoinThenPart: if (sorted[i].size() > 1) { eventString = (isImpromptu ? QT_TRANSLATE_NOOP("", "%1% have joined then left the chat") : QT_TRANSLATE_NOOP("", "%1% have entered then left the room")); } else { @@ -910,61 +909,61 @@ std::string MUCController::generateJoinPartString(const std::vector<NickJoinPart if (i > 0) { if (i < populatedEvents.size() - 1) { result += ", "; } else { result += QT_TRANSLATE_NOOP("", " and "); } } result += eventStrings[populatedEvents[i]]; } return result; } std::string MUCController::generateNicknameChangeString(const std::string& oldNickname, const std::string& newNickname) { return str(boost::format(QT_TRANSLATE_NOOP("", "%1% is now known as %2%.")) % oldNickname % newNickname); } void MUCController::handleChangeSubjectRequest(const std::string& subject) { muc_->changeSubject(subject); } void MUCController::handleBookmarkRequest() { const JID jid = muc_->getJID(); // Prepare new bookmark for this room. MUCBookmark roomBookmark(jid, jid.toBare().toString()); roomBookmark.setPassword(password_); roomBookmark.setNick(nick_); // Check for existing bookmark for this room and, if it exists, use it instead. std::vector<MUCBookmark> bookmarks = mucBookmarkManager_->getBookmarks(); - foreach (const MUCBookmark& bookmark, bookmarks) { + for (const auto& bookmark : bookmarks) { if (bookmark.getRoom() == jid.toBare()) { roomBookmark = bookmark; break; } } chatWindow_->showBookmarkWindow(roomBookmark); } void MUCController::handleConfigureRequest(Form::ref form) { if (form) { muc_->configureRoom(form); } else { muc_->requestConfigurationForm(); } } void MUCController::handleConfigurationFailed(ErrorPayload::ref error) { std::string errorMessage = getErrorMessage(error); errorMessage = str(format(QT_TRANSLATE_NOOP("", "Room configuration failed: %1%.")) % errorMessage); chatWindow_->addErrorMessage(chatMessageParser_->parseMessageBody(errorMessage)); } void MUCController::handleOccupantRoleChangeFailed(ErrorPayload::ref error, const JID&, MUCOccupant::Role) { std::string errorMessage = getErrorMessage(error); errorMessage = str(format(QT_TRANSLATE_NOOP("", "Occupant role change failed: %1%.")) % errorMessage); chatWindow_->addErrorMessage(chatMessageParser_->parseMessageBody(errorMessage)); } @@ -974,216 +973,213 @@ void MUCController::configureAsImpromptuRoom(Form::ref form) { onImpromptuConfigCompleted(); } void MUCController::handleConfigurationFormReceived(Form::ref form) { if (isImpromptu_) { if (!isImpromptuAlreadyConfigured_) { configureAsImpromptuRoom(form); } } else { chatWindow_->showRoomConfigurationForm(form); } } void MUCController::handleConfigurationCancelled() { muc_->cancelConfigureRoom(); } void MUCController::handleDestroyRoomRequest() { muc_->destroyRoom(); } void MUCController::handleInvitePersonToThisMUCRequest(const std::vector<JID>& jidsToInvite) { RequestInviteToMUCUIEvent::ImpromptuMode mode = isImpromptu_ ? RequestInviteToMUCUIEvent::Impromptu : RequestInviteToMUCUIEvent::NotImpromptu; std::shared_ptr<UIEvent> event(new RequestInviteToMUCUIEvent(muc_->getJID(), jidsToInvite, mode)); eventStream_->send(event); } void MUCController::handleUIEvent(std::shared_ptr<UIEvent> event) { std::shared_ptr<InviteToMUCUIEvent> inviteEvent = std::dynamic_pointer_cast<InviteToMUCUIEvent>(event); if (inviteEvent && inviteEvent->getRoom() == muc_->getJID()) { - foreach (const JID& jid, inviteEvent->getInvites()) { + for (const auto& jid : inviteEvent->getInvites()) { muc_->invitePerson(jid, inviteEvent->getReason(), isImpromptu_); } } } void MUCController::handleGetAffiliationsRequest() { muc_->requestAffiliationList(MUCOccupant::Owner); muc_->requestAffiliationList(MUCOccupant::Admin); muc_->requestAffiliationList(MUCOccupant::Member); muc_->requestAffiliationList(MUCOccupant::Outcast); } -typedef std::pair<MUCOccupant::Affiliation, JID> AffiliationChangePair; - void MUCController::handleChangeAffiliationsRequest(const std::vector<std::pair<MUCOccupant::Affiliation, JID> >& changes) { std::set<JID> addedJIDs; - foreach (const AffiliationChangePair& change, changes) { + for (const auto& change : changes) { if (change.first != MUCOccupant::NoAffiliation) { addedJIDs.insert(change.second); } } - foreach (const AffiliationChangePair& change, changes) { + for (const auto& change : changes) { if (change.first != MUCOccupant::NoAffiliation || addedJIDs.find(change.second) == addedJIDs.end()) { muc_->changeAffiliation(change.second, change.first); } } } void MUCController::handleUnblockUserRequest() { eventStream_->send(std::make_shared<RequestChangeBlockStateUIEvent>(RequestChangeBlockStateUIEvent::Unblocked, muc_->getJID())); } void MUCController::handleBlockingStateChanged() { std::shared_ptr<BlockList> blockList = clientBlockListManager_->getBlockList(); if (blockList->getState() == BlockList::Available) { if (blockList->isBlocked(toJID_)) { if (!blockedContactAlert_) { blockedContactAlert_ = chatWindow_->addAlert(QT_TRANSLATE_NOOP("", "You've blocked this room. To enter the room, first unblock it using the cog menu and try again")); } chatWindow_->setBlockingState(ChatWindow::IsBlocked); } else { if (blockedContactAlert_) { chatWindow_->removeAlert(*blockedContactAlert_); blockedContactAlert_.reset(); } chatWindow_->setBlockingState(ChatWindow::IsUnblocked); } } } void MUCController::handleAffiliationListReceived(MUCOccupant::Affiliation affiliation, const std::vector<JID>& jids) { chatWindow_->setAffiliations(affiliation, jids); } void MUCController::logMessage(const std::string& message, const JID& fromJID, const JID& toJID, const boost::posix_time::ptime& timeStamp, bool isIncoming) { // log only incoming messages if (isIncoming && historyController_) { historyController_->addMessage(message, fromJID, toJID, HistoryMessage::Groupchat, timeStamp); } } void MUCController::addRecentLogs() { if (!historyController_) { return; } joinContext_ = historyController_->getMUCContext(selfJID_, toJID_, lastActivity_); - foreach (const HistoryMessage& message, joinContext_) { + for (const auto& message : joinContext_) { bool senderIsSelf = nick_ == message.getFromJID().getResource(); // the chatWindow uses utc timestamps addMessage(chatMessageParser_->parseMessageBody(message.getMessage()), senderDisplayNameFromMessage(message.getFromJID()), senderIsSelf, std::make_shared<SecurityLabel>(), avatarManager_->getAvatarPath(message.getFromJID()), message.getTime() - boost::posix_time::hours(message.getOffset())); } } void MUCController::checkDuplicates(std::shared_ptr<Message> newMessage) { std::string body = newMessage->getBody().get_value_or(""); JID jid = newMessage->getFrom(); boost::optional<boost::posix_time::ptime> time = newMessage->getTimestamp(); - reverse_foreach (const HistoryMessage& message, joinContext_) { + for (const auto& message : boost::adaptors::reverse(joinContext_)) { boost::posix_time::ptime messageTime = message.getTime() - boost::posix_time::hours(message.getOffset()); if (time && time < messageTime) { break; } if (time && time != messageTime) { continue; } if (message.getFromJID() != jid) { continue; } if (message.getMessage() != body) { continue; } // Mark the message as unreadable newMessage->setBody(""); } } void MUCController::setNick(const std::string& nick) { nick_ = nick; highlighter_->setNick(nick_); } Form::ref MUCController::buildImpromptuRoomConfiguration(Form::ref roomConfigurationForm) { Form::ref result = std::make_shared<Form>(Form::SubmitType); std::string impromptuConfigs[] = { "muc#roomconfig_enablelogging", "muc#roomconfig_persistentroom", "muc#roomconfig_publicroom", "muc#roomconfig_whois"}; std::set<std::string> impromptuConfigsMissing(impromptuConfigs, impromptuConfigs + 4); - foreach (std::shared_ptr<FormField> field, roomConfigurationForm->getFields()) { + for (const auto& field : roomConfigurationForm->getFields()) { std::shared_ptr<FormField> resultField; if (field->getName() == "muc#roomconfig_enablelogging") { resultField = std::make_shared<FormField>(FormField::BooleanType, "0"); } if (field->getName() == "muc#roomconfig_persistentroom") { resultField = std::make_shared<FormField>(FormField::BooleanType, "0"); } if (field->getName() == "muc#roomconfig_publicroom") { resultField = std::make_shared<FormField>(FormField::BooleanType, "0"); } if (field->getName() == "muc#roomconfig_whois") { resultField = std::make_shared<FormField>(FormField::ListSingleType, "anyone"); } if (field->getName() == "FORM_TYPE") { resultField = std::make_shared<FormField>(FormField::HiddenType, "http://jabber.org/protocol/muc#roomconfig"); } if (resultField) { impromptuConfigsMissing.erase(field->getName()); resultField->setName(field->getName()); result->addField(resultField); } } - foreach (const std::string& config, impromptuConfigsMissing) { + for (const auto& config : impromptuConfigsMissing) { if (config == "muc#roomconfig_publicroom") { chatWindow_->addSystemMessage(chatMessageParser_->parseMessageBody(QT_TRANSLATE_NOOP("", "This server doesn't support hiding your chat from other users.")), ChatWindow::DefaultDirection); } else if (config == "muc#roomconfig_whois") { chatWindow_->addSystemMessage(chatMessageParser_->parseMessageBody(QT_TRANSLATE_NOOP("", "This server doesn't support sharing people's real identity in this chat.")), ChatWindow::DefaultDirection); } } return result; } void MUCController::setImpromptuWindowTitle() { std::string title; - typedef std::pair<std::string, MUCOccupant> StringMUCOccupantPair; std::map<std::string, MUCOccupant> occupants = muc_->getOccupants(); if (occupants.size() <= 1) { title = QT_TRANSLATE_NOOP("", "Empty Chat"); } else { - foreach (StringMUCOccupantPair pair, occupants) { + for (const auto& pair : occupants) { if (pair.first != nick_) { title += (title.empty() ? "" : ", ") + pair.first; } } } chatWindow_->setName(title); } void MUCController::handleRoomUnlocked() { // Handle buggy MUC implementations where the joined room already exists and is unlocked. // Configure the room again in this case. if (!isImpromptuAlreadyConfigured_) { if (isImpromptu_ && (muc_->getOccupant(nick_).getAffiliation() == MUCOccupant::Owner)) { muc_->requestConfigurationForm(); } else if (isImpromptu_) { onImpromptuConfigCompleted(); } } } void MUCController::setAvailableServerFeatures(std::shared_ptr<DiscoInfo> info) { ChatControllerBase::setAvailableServerFeatures(info); if (iqRouter_->isAvailable() && info->hasFeature(DiscoInfo::BlockingCommandFeature)) { std::shared_ptr<BlockList> blockList = clientBlockListManager_->getBlockList(); blockingOnStateChangedConnection_ = blockList->onStateChanged.connect(boost::bind(&MUCController::handleBlockingStateChanged, this)); blockingOnItemAddedConnection_ = blockList->onItemAdded.connect(boost::bind(&MUCController::handleBlockingStateChanged, this)); blockingOnItemRemovedConnection_ = blockList->onItemRemoved.connect(boost::bind(&MUCController::handleBlockingStateChanged, this)); handleBlockingStateChanged(); diff --git a/Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp b/Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp index 31c9be9..a5e68cf 100644 --- a/Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp +++ b/Swift/Controllers/Chat/UnitTest/ChatsManagerTest.cpp @@ -62,61 +62,61 @@ #include <Swift/Controllers/UnitTest/MockChatWindow.h> #include <Swift/Controllers/WhiteboardManager.h> #include <Swift/Controllers/XMPPEvents/EventController.h> using namespace Swift; class ChatsManagerTest : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(ChatsManagerTest); CPPUNIT_TEST(testFirstOpenWindowIncoming); CPPUNIT_TEST(testSecondOpenWindowIncoming); CPPUNIT_TEST(testFirstOpenWindowOutgoing); CPPUNIT_TEST(testFirstOpenWindowBareToFull); CPPUNIT_TEST(testSecondWindow); CPPUNIT_TEST(testUnbindRebind); CPPUNIT_TEST(testNoDuplicateUnbind); CPPUNIT_TEST(testThreeMUCWindows); CPPUNIT_TEST(testChatControllerPresenceAccessUpdatedOnRemoveFromRoster); CPPUNIT_TEST(testChatControllerPresenceAccessUpdatedOnAddToRoster); CPPUNIT_TEST(testChatControllerPresenceAccessUpdatedOnSubscriptionChangeToBoth); CPPUNIT_TEST(testChatControllerPresenceAccessUpdatedOnSubscriptionChangeToFrom); CPPUNIT_TEST(testChatControllerFullJIDBindingOnMessageAndNotReceipt); CPPUNIT_TEST(testChatControllerFullJIDBindingOnTypingAndNotActive); CPPUNIT_TEST(testChatControllerPMPresenceHandling); CPPUNIT_TEST(testLocalMUCServiceDiscoveryResetOnDisconnect); CPPUNIT_TEST(testPresenceChangeDoesNotReplaceMUCInvite); // Highlighting tests CPPUNIT_TEST(testChatControllerHighlightingNotificationTesting); CPPUNIT_TEST(testChatControllerHighlightingNotificationDeduplicateSounds); CPPUNIT_TEST(testChatControllerMeMessageHandling); - CPPUNIT_TEST(testRestartingMUCComponentCrash); + CPPUNIT_TEST(testRestartingMUCComponentCrash); CPPUNIT_TEST(testChatControllerMeMessageHandlingInMUC); // Carbons tests CPPUNIT_TEST(testCarbonsForwardedIncomingMessageToSecondResource); CPPUNIT_TEST(testCarbonsForwardedOutgoingMessageFromSecondResource); CPPUNIT_TEST_SUITE_END(); public: void setUp() { mocks_ = new MockRepository(); jid_ = JID("test@test.com/resource"); stanzaChannel_ = new DummyStanzaChannel(); iqRouter_ = new IQRouter(stanzaChannel_); eventController_ = new EventController(); chatWindowFactory_ = mocks_->InterfaceMock<ChatWindowFactory>(); joinMUCWindowFactory_ = mocks_->InterfaceMock<JoinMUCWindowFactory>(); xmppRoster_ = new XMPPRosterImpl(); mucRegistry_ = new MUCRegistry(); nickResolver_ = new NickResolver(jid_.toBare(), xmppRoster_, nullptr, mucRegistry_); presenceOracle_ = new PresenceOracle(stanzaChannel_, xmppRoster_); serverDiscoInfo_ = std::make_shared<DiscoInfo>(); presenceSender_ = new StanzaChannelPresenceSender(stanzaChannel_); directedPresenceSender_ = new DirectedPresenceSender(presenceSender_); mucManager_ = new MUCManager(stanzaChannel_, iqRouter_, directedPresenceSender_, mucRegistry_); uiEventStream_ = new UIEventStream(); entityCapsProvider_ = new DummyEntityCapsProvider(); chatListWindowFactory_ = mocks_->InterfaceMock<ChatListWindowFactory>(); mucSearchWindowFactory_ = mocks_->InterfaceMock<MUCSearchWindowFactory>(); settings_ = new DummySettingsProvider(); @@ -428,103 +428,103 @@ public: /** * Test that ChatController sends receipts if requested after change from subscription state To to subscription state Both. */ void testChatControllerPresenceAccessUpdatedOnSubscriptionChangeToBoth() { testhelperChatControllerPresenceAccessUpdatedOnSubscriptionChangeReceiptsAllowed(RosterItemPayload::To, RosterItemPayload::Both); } /** * Test that ChatController sends receipts if requested after change from subscription state To to subscription state From. */ void testChatControllerPresenceAccessUpdatedOnSubscriptionChangeToFrom() { testhelperChatControllerPresenceAccessUpdatedOnSubscriptionChangeReceiptsAllowed(RosterItemPayload::To, RosterItemPayload::From); } void testChatControllerFullJIDBindingOnMessageAndNotReceipt() { JID ownJID("test@test.com/resource"); JID sender("foo@test.com"); std::vector<JID> senderResource; senderResource.push_back(sender.withResource("resourceA")); senderResource.push_back(sender.withResource("resourceB")); // We support delivery receipts. settings_->storeSetting(SettingConstants::REQUEST_DELIVERYRECEIPTS, true); // Open chat window to a sender. MockChatWindow* window = new MockChatWindow(); mocks_->ExpectCall(chatWindowFactory_, ChatWindowFactory::createChatWindow).With(sender, uiEventStream_).Return(window); uiEventStream_->send(std::make_shared<RequestChatUIEvent>(sender)); - foreach(const JID& senderJID, senderResource) { + for (const auto& senderJID : senderResource) { // The sender supports delivery receipts. DiscoInfo::ref disco = std::make_shared<DiscoInfo>(); disco->addFeature(DiscoInfo::MessageDeliveryReceiptsFeature); entityCapsProvider_->caps[senderJID] = disco; // The sender is online. Presence::ref senderPresence = std::make_shared<Presence>(); senderPresence->setFrom(senderJID); senderPresence->setTo(ownJID); stanzaChannel_->onPresenceReceived(senderPresence); entityCapsProvider_->onCapsChanged(senderJID); } // Send first message. window->onSendMessageRequest("hello there", false); // A bare message is send because no resources is bound. CPPUNIT_ASSERT_EQUAL(sender, stanzaChannel_->getStanzaAtIndex<Message>(1)->getTo()); CPPUNIT_ASSERT(stanzaChannel_->getStanzaAtIndex<Message>(1)->getPayload<DeliveryReceiptRequest>()); // Two resources respond with message receipts. - foreach(const JID& senderJID, senderResource) { + for (const auto& senderJID : senderResource) { Message::ref receiptReply = std::make_shared<Message>(); receiptReply->setFrom(senderJID); receiptReply->setTo(ownJID); std::shared_ptr<DeliveryReceipt> receipt = std::make_shared<DeliveryReceipt>(); receipt->setReceivedID(stanzaChannel_->getStanzaAtIndex<Message>(1)->getID()); receiptReply->addPayload(receipt); manager_->handleIncomingMessage(receiptReply); } // Send second message. window->onSendMessageRequest("how are you?", false); // A bare message is send because no resources is bound. CPPUNIT_ASSERT_EQUAL(sender, stanzaChannel_->getStanzaAtIndex<Message>(1)->getTo()); CPPUNIT_ASSERT(stanzaChannel_->getStanzaAtIndex<Message>(1)->getPayload<DeliveryReceiptRequest>()); // Two resources respond with message receipts. - foreach(const JID& senderJID, senderResource) { + for (const auto& senderJID : senderResource) { Message::ref receiptReply = std::make_shared<Message>(); receiptReply->setFrom(senderJID); receiptReply->setTo(ownJID); std::shared_ptr<DeliveryReceipt> receipt = std::make_shared<DeliveryReceipt>(); receipt->setReceivedID(stanzaChannel_->getStanzaAtIndex<Message>(1)->getID()); receiptReply->addPayload(receipt); manager_->handleIncomingMessage(receiptReply); } // Reply with a message including a body text. Message::ref reply = std::make_shared<Message>(); reply->setFrom(senderResource[0]); reply->setTo(ownJID); reply->setBody("fine."); manager_->handleIncomingMessage(reply); // Send third message. window->onSendMessageRequest("great to hear.", false); // The chat session is bound to the full JID of the first resource. CPPUNIT_ASSERT_EQUAL(senderResource[0], stanzaChannel_->getStanzaAtIndex<Message>(3)->getTo()); CPPUNIT_ASSERT(stanzaChannel_->getStanzaAtIndex<Message>(2)->getPayload<DeliveryReceiptRequest>()); // Receive random receipt from second sender resource. reply = std::make_shared<Message>(); reply->setFrom(senderResource[1]); reply->setTo(ownJID); std::shared_ptr<DeliveryReceipt> receipt = std::make_shared<DeliveryReceipt>(); @@ -543,103 +543,103 @@ public: reply = std::make_shared<Message>(); reply->setFrom(senderResource[1]); reply->setTo(ownJID); reply->setBody("nothing."); manager_->handleIncomingMessage(reply); // Send fifth message. window->onSendMessageRequest("okay", false); // The chat session is now bound to the full JID of the second resource. CPPUNIT_ASSERT_EQUAL(senderResource[1], stanzaChannel_->getStanzaAtIndex<Message>(5)->getTo()); CPPUNIT_ASSERT(stanzaChannel_->getStanzaAtIndex<Message>(5)->getPayload<DeliveryReceiptRequest>()); } void testChatControllerFullJIDBindingOnTypingAndNotActive() { JID ownJID("test@test.com/resource"); JID sender("foo@test.com"); std::vector<JID> senderResource; senderResource.push_back(sender.withResource("resourceA")); senderResource.push_back(sender.withResource("resourceB")); // We support delivery receipts. settings_->storeSetting(SettingConstants::REQUEST_DELIVERYRECEIPTS, true); // Open chat window to a sender. MockChatWindow* window = new MockChatWindow(); mocks_->ExpectCall(chatWindowFactory_, ChatWindowFactory::createChatWindow).With(sender, uiEventStream_).Return(window); uiEventStream_->send(std::make_shared<RequestChatUIEvent>(sender)); - foreach(const JID& senderJID, senderResource) { + for (const auto& senderJID : senderResource) { // The sender supports delivery receipts. DiscoInfo::ref disco = std::make_shared<DiscoInfo>(); disco->addFeature(DiscoInfo::MessageDeliveryReceiptsFeature); entityCapsProvider_->caps[senderJID] = disco; // The sender is online. Presence::ref senderPresence = std::make_shared<Presence>(); senderPresence->setFrom(senderJID); senderPresence->setTo(ownJID); stanzaChannel_->onPresenceReceived(senderPresence); entityCapsProvider_->onCapsChanged(senderJID); } // Send first message. window->onSendMessageRequest("hello there", false); // A bare message is send because no resources is bound. CPPUNIT_ASSERT_EQUAL(sender, stanzaChannel_->getStanzaAtIndex<Message>(1)->getTo()); CPPUNIT_ASSERT(stanzaChannel_->getStanzaAtIndex<Message>(1)->getPayload<DeliveryReceiptRequest>()); // Two resources respond with message receipts. - foreach(const JID& senderJID, senderResource) { + for (const auto& senderJID : senderResource) { Message::ref reply = std::make_shared<Message>(); reply->setFrom(senderJID); reply->setTo(ownJID); std::shared_ptr<ChatState> csn = std::make_shared<ChatState>(); csn->setChatState(ChatState::Active); reply->addPayload(csn); manager_->handleIncomingMessage(reply); } // Send second message. window->onSendMessageRequest("how are you?", false); // A bare message is send because no resources is bound. CPPUNIT_ASSERT_EQUAL(sender, stanzaChannel_->getStanzaAtIndex<Message>(1)->getTo()); CPPUNIT_ASSERT(stanzaChannel_->getStanzaAtIndex<Message>(1)->getPayload<DeliveryReceiptRequest>()); // Two resources respond with message receipts. - foreach(const JID& senderJID, senderResource) { + for (const auto& senderJID : senderResource) { Message::ref receiptReply = std::make_shared<Message>(); receiptReply->setFrom(senderJID); receiptReply->setTo(ownJID); std::shared_ptr<DeliveryReceipt> receipt = std::make_shared<DeliveryReceipt>(); receipt->setReceivedID(stanzaChannel_->getStanzaAtIndex<Message>(1)->getID()); receiptReply->addPayload(receipt); manager_->handleIncomingMessage(receiptReply); } // Reply with a message including a CSN. Message::ref reply = std::make_shared<Message>(); reply->setFrom(senderResource[0]); reply->setTo(ownJID); std::shared_ptr<ChatState> csn = std::make_shared<ChatState>(); csn->setChatState(ChatState::Composing); reply->addPayload(csn); manager_->handleIncomingMessage(reply); // Send third message. window->onSendMessageRequest("great to hear.", false); // The chat session is now bound to the full JID of the first resource due to its recent composing message. CPPUNIT_ASSERT_EQUAL(senderResource[0], stanzaChannel_->getStanzaAtIndex<Message>(3)->getTo()); CPPUNIT_ASSERT(stanzaChannel_->getStanzaAtIndex<Message>(3)->getPayload<DeliveryReceiptRequest>()); // Reply with a message including a CSN from the other resource. reply = std::make_shared<Message>(); reply->setFrom(senderResource[1]); diff --git a/Swift/Controllers/Chat/UnitTest/MUCControllerTest.cpp b/Swift/Controllers/Chat/UnitTest/MUCControllerTest.cpp index 1142c98..32639f6 100644 --- a/Swift/Controllers/Chat/UnitTest/MUCControllerTest.cpp +++ b/Swift/Controllers/Chat/UnitTest/MUCControllerTest.cpp @@ -1,44 +1,43 @@ /* * Copyright (c) 2010-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #include <boost/algorithm/string.hpp> #include <cppunit/extensions/HelperMacros.h> #include <cppunit/extensions/TestFactoryRegistry.h> #include <hippomocks.h> #include <Swiften/Avatars/NullAvatarManager.h> -#include <Swiften/Base/foreach.h> #include <Swiften/Client/ClientBlockListManager.h> #include <Swiften/Client/DummyStanzaChannel.h> #include <Swiften/Client/NickResolver.h> #include <Swiften/Crypto/CryptoProvider.h> #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> #include <Swiften/Presence/DirectedPresenceSender.h> #include <Swiften/Presence/PresenceOracle.h> #include <Swiften/Presence/StanzaChannelPresenceSender.h> #include <Swiften/Queries/DummyIQChannel.h> #include <Swiften/Roster/XMPPRoster.h> #include <Swiften/Roster/XMPPRosterImpl.h> #include <Swiften/VCards/VCardManager.h> #include <Swiften/VCards/VCardMemoryStorage.h> #include <Swift/Controllers/Chat/ChatMessageParser.h> #include <Swift/Controllers/Chat/MUCController.h> #include <Swift/Controllers/Chat/UserSearchController.h> #include <Swift/Controllers/Roster/GroupRosterItem.h> #include <Swift/Controllers/Roster/Roster.h> #include <Swift/Controllers/Settings/DummySettingsProvider.h> #include <Swift/Controllers/UIEvents/UIEventStream.h> #include <Swift/Controllers/UIInterfaces/ChatWindow.h> #include <Swift/Controllers/UIInterfaces/ChatWindowFactory.h> #include <Swift/Controllers/UIInterfaces/UserSearchWindowFactory.h> @@ -344,77 +343,76 @@ public: list.push_back(NickJoinPart("Ernie", Join)); CPPUNIT_ASSERT_EQUAL(std::string("Kev, Bert and Ernie have entered the room and Remko has left the room"), MUCController::generateJoinPartString(list, false)); } void testJoinPartStringContructionMixed() { std::vector<NickJoinPart> list; list.push_back(NickJoinPart("Kev", JoinThenPart)); CPPUNIT_ASSERT_EQUAL(std::string("Kev has entered then left the room"), MUCController::generateJoinPartString(list, false)); list.push_back(NickJoinPart("Remko", Part)); CPPUNIT_ASSERT_EQUAL(std::string("Remko has left the room and Kev has entered then left the room"), MUCController::generateJoinPartString(list, false)); list.push_back(NickJoinPart("Bert", PartThenJoin)); CPPUNIT_ASSERT_EQUAL(std::string("Remko has left the room, Kev has entered then left the room and Bert has left then returned to the room"), MUCController::generateJoinPartString(list, false)); list.push_back(NickJoinPart("Ernie", JoinThenPart)); CPPUNIT_ASSERT_EQUAL(std::string("Remko has left the room, Kev and Ernie have entered then left the room and Bert has left then returned to the room"), MUCController::generateJoinPartString(list, false)); } JID jidFromOccupant(const MUCOccupant& occupant) { return JID(mucJID_.toString()+"/"+occupant.getNick()); } void testRoleAffiliationStates() { typedef std::map<std::string, MUCOccupant> occupant_map; occupant_map occupants; occupants.insert(occupant_map::value_type("Kev", MUCOccupant("Kev", MUCOccupant::Participant, MUCOccupant::Owner))); occupants.insert(occupant_map::value_type("Remko", MUCOccupant("Remko", MUCOccupant::Participant, MUCOccupant::Owner))); occupants.insert(occupant_map::value_type("Bert", MUCOccupant("Bert", MUCOccupant::Participant, MUCOccupant::Owner))); occupants.insert(occupant_map::value_type("Ernie", MUCOccupant("Ernie", MUCOccupant::Participant, MUCOccupant::Owner))); /* populate the MUC with fake users */ - typedef const std::pair<std::string,MUCOccupant> occupantIterator; - foreach(occupantIterator &occupant, occupants) { + for (auto&& occupant : occupants) { muc_->insertOccupant(occupant.second); } std::vector<MUCOccupant> alterations; alterations.push_back(MUCOccupant("Kev", MUCOccupant::Visitor, MUCOccupant::Admin)); alterations.push_back(MUCOccupant("Remko", MUCOccupant::Moderator, MUCOccupant::Member)); alterations.push_back(MUCOccupant("Bert", MUCOccupant::Visitor, MUCOccupant::Outcast)); alterations.push_back(MUCOccupant("Ernie", MUCOccupant::NoRole, MUCOccupant::Member)); alterations.push_back(MUCOccupant("Bert", MUCOccupant::Moderator, MUCOccupant::Owner)); alterations.push_back(MUCOccupant("Kev", MUCOccupant::Participant, MUCOccupant::Outcast)); alterations.push_back(MUCOccupant("Bert", MUCOccupant::Visitor, MUCOccupant::NoAffiliation)); alterations.push_back(MUCOccupant("Remko", MUCOccupant::NoRole, MUCOccupant::NoAffiliation)); alterations.push_back(MUCOccupant("Ernie", MUCOccupant::Visitor, MUCOccupant::Outcast)); - foreach(const MUCOccupant& alteration, alterations) { + for (const auto& alteration : alterations) { /* perform an alteration to a user's role and affiliation */ occupant_map::iterator occupant = occupants.find(alteration.getNick()); CPPUNIT_ASSERT(occupant != occupants.end()); const JID jid = jidFromOccupant(occupant->second); /* change the affiliation, leave the role in place */ muc_->changeAffiliation(jid, alteration.getAffiliation()); occupant->second = MUCOccupant(occupant->first, occupant->second.getRole(), alteration.getAffiliation()); testRoleAffiliationStatesVerify(occupants); /* change the role, leave the affiliation in place */ muc_->changeOccupantRole(jid, alteration.getRole()); occupant->second = MUCOccupant(occupant->first, alteration.getRole(), occupant->second.getAffiliation()); testRoleAffiliationStatesVerify(occupants); } } void testSubjectChangeCorrect() { std::string messageBody("test message"); window_->onSendMessageRequest(messageBody, false); std::shared_ptr<Stanza> rawStanza = stanzaChannel_->sentStanzas[stanzaChannel_->sentStanzas.size() - 1]; Message::ref message = std::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 = std::make_shared<Message>(); message->setType(Message::Groupchat); message->setTo(self_); message->setFrom(mucJID_.withResource("SomeNickname")); message->setID(iqChannel_->getNewIQID()); @@ -479,64 +477,64 @@ public: /* * 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); std::shared_ptr<Stanza> rawStanza = stanzaChannel_->sentStanzas[stanzaChannel_->sentStanzas.size() - 1]; Message::ref message = std::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 = std::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(std::make_shared<MessageEvent>(message)); CPPUNIT_ASSERT_EQUAL(std::string("Trying to enter room teaparty@rooms.wonderland.lit"), std::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(); - foreach(RosterItem* rosterItem, group->getChildren()) { + for (auto rosterItem : group->getChildren()) { GroupRosterItem* child = dynamic_cast<GroupRosterItem*>(rosterItem); CPPUNIT_ASSERT(child); - foreach(RosterItem* childItem, child->getChildren()) { + for (auto childItem : child->getChildren()) { ContactRosterItem* item = dynamic_cast<ContactRosterItem*>(childItem); CPPUNIT_ASSERT(item); std::map<std::string, MUCOccupant>::const_iterator occupant = occupants.find(item->getJID().getResource()); CPPUNIT_ASSERT(occupant != occupants.end()); CPPUNIT_ASSERT(item->getMUCRole() == occupant->second.getRole()); CPPUNIT_ASSERT(item->getMUCAffiliation() == occupant->second.getAffiliation()); } } } private: JID self_; JID mucJID_; MockMUC::ref muc_; std::string nick_; DummyStanzaChannel* stanzaChannel_; DummyIQChannel* iqChannel_; IQRouter* iqRouter_; EventController* eventController_; ChatWindowFactory* chatWindowFactory_; UserSearchWindowFactory* userSearchWindowFactory_; MUCController* controller_; // NickResolver* nickResolver_; PresenceOracle* presenceOracle_; AvatarManager* avatarManager_; StanzaChannelPresenceSender* presenceSender_; DirectedPresenceSender* directedPresenceSender_; MockRepository* mocks_; UIEventStream* uiEventStream_; MockChatWindow* window_; diff --git a/Swift/Controllers/Chat/UserSearchController.cpp b/Swift/Controllers/Chat/UserSearchController.cpp index 305049f..91e0dea 100644 --- a/Swift/Controllers/Chat/UserSearchController.cpp +++ b/Swift/Controllers/Chat/UserSearchController.cpp @@ -1,45 +1,44 @@ /* * Copyright (c) 2010-2016 Isode Limited. * All rights reserved. * See the COPYING file for more information. */ #include <Swift/Controllers/Chat/UserSearchController.h> #include <memory> #include <boost/bind.hpp> #include <Swiften/Avatars/AvatarManager.h> #include <Swiften/Base/String.h> -#include <Swiften/Base/foreach.h> #include <Swiften/Disco/DiscoServiceWalker.h> #include <Swiften/Disco/GetDiscoInfoRequest.h> #include <Swiften/Disco/GetDiscoItemsRequest.h> #include <Swiften/Presence/PresenceOracle.h> #include <Swiften/VCards/VCardManager.h> #include <Swift/Controllers/ContactEditController.h> #include <Swift/Controllers/ContactSuggester.h> #include <Swift/Controllers/Intl.h> #include <Swift/Controllers/ProfileSettingsProvider.h> #include <Swift/Controllers/Roster/RosterController.h> #include <Swift/Controllers/UIEvents/RequestAddUserDialogUIEvent.h> #include <Swift/Controllers/UIEvents/RequestChatWithUserDialogUIEvent.h> #include <Swift/Controllers/UIEvents/RequestInviteToMUCUIEvent.h> #include <Swift/Controllers/UIEvents/UIEventStream.h> #include <Swift/Controllers/UIInterfaces/UserSearchWindow.h> #include <Swift/Controllers/UIInterfaces/UserSearchWindowFactory.h> namespace Swift { static const std::string SEARCHED_DIRECTORIES = "searchedDirectories"; UserSearchController::UserSearchController(Type type, const JID& jid, UIEventStream* uiEventStream, VCardManager* vcardManager, UserSearchWindowFactory* factory, IQRouter* iqRouter, RosterController* rosterController, ContactSuggester* contactSuggester, AvatarManager* avatarManager, PresenceOracle* presenceOracle, ProfileSettingsProvider* settings) : type_(type), jid_(jid), uiEventStream_(uiEventStream), vcardManager_(vcardManager), factory_(factory), iqRouter_(iqRouter), rosterController_(rosterController), contactSuggester_(contactSuggester), avatarManager_(avatarManager), presenceOracle_(presenceOracle), settings_(settings) { uiEventStream_->onUIEvent.connect(boost::bind(&UserSearchController::handleUIEvent, this, _1)); vcardManager_->onVCardChanged.connect(boost::bind(&UserSearchController::handleVCardChanged, this, _1, _2)); avatarManager_->onAvatarChanged.connect(boost::bind(&UserSearchController::handleAvatarChanged, this, _1)); presenceOracle_->onPresenceChange.connect(boost::bind(&UserSearchController::handlePresenceChanged, this, _1)); window_ = nullptr; discoWalker_ = nullptr; loadSavedDirectories(); @@ -116,201 +115,202 @@ void UserSearchController::handleUIEvent(std::shared_ptr<UIEvent> event) { window_->setRoomJID(inviteToMUCRequest->getRoom()); } return; } } void UserSearchController::handleFormRequested(const JID& service) { window_->setSearchError(false); window_->setServerSupportsSearch(true); //Abort a previous search if is active endDiscoWalker(); delete discoWalker_; discoWalker_ = new DiscoServiceWalker(service, iqRouter_); discoWalker_->onServiceFound.connect(boost::bind(&UserSearchController::handleDiscoServiceFound, this, _1, _2)); discoWalker_->onWalkComplete.connect(boost::bind(&UserSearchController::handleDiscoWalkFinished, this)); discoWalker_->beginWalk(); } void UserSearchController::endDiscoWalker() { if (discoWalker_) { discoWalker_->endWalk(); discoWalker_->onServiceFound.disconnect(boost::bind(&UserSearchController::handleDiscoServiceFound, this, _1, _2)); discoWalker_->onWalkComplete.disconnect(boost::bind(&UserSearchController::handleDiscoWalkFinished, this)); } } void UserSearchController::handleDiscoServiceFound(const JID& jid, std::shared_ptr<DiscoInfo> info) { //bool isUserDirectory = false; bool supports55 = false; - foreach (DiscoInfo::Identity identity, info->getIdentities()) { + // TODO: Cleanup code + for (const auto& identity : info->getIdentities()) { if ((identity.getCategory() == "directory" && identity.getType() == "user")) { //isUserDirectory = true; } } std::vector<std::string> features = info->getFeatures(); supports55 = std::find(features.begin(), features.end(), DiscoInfo::JabberSearchFeature) != features.end(); if (/*isUserDirectory && */supports55) { //FIXME: once M-Link correctly advertises directoryness. /* Abort further searches.*/ endDiscoWalker(); std::shared_ptr<GenericRequest<SearchPayload> > searchRequest(new GenericRequest<SearchPayload>(IQ::Get, jid, std::make_shared<SearchPayload>(), iqRouter_)); searchRequest->onResponse.connect(boost::bind(&UserSearchController::handleFormResponse, this, _1, _2)); searchRequest->send(); } } void UserSearchController::handleFormResponse(std::shared_ptr<SearchPayload> fields, ErrorPayload::ref error) { if (error || !fields) { window_->setServerSupportsSearch(false); return; } window_->setSearchFields(fields); } void UserSearchController::handleSearch(std::shared_ptr<SearchPayload> fields, const JID& jid) { addToSavedDirectories(jid); std::shared_ptr<GenericRequest<SearchPayload> > searchRequest(new GenericRequest<SearchPayload>(IQ::Set, jid, fields, iqRouter_)); searchRequest->onResponse.connect(boost::bind(&UserSearchController::handleSearchResponse, this, _1, _2)); searchRequest->send(); } void UserSearchController::handleSearchResponse(std::shared_ptr<SearchPayload> resultsPayload, ErrorPayload::ref error) { if (error || !resultsPayload) { window_->setSearchError(true); return; } std::vector<UserSearchResult> results; if (resultsPayload->getForm()) { window_->setResultsForm(resultsPayload->getForm()); } else { - foreach (SearchPayload::Item item, resultsPayload->getItems()) { + for (auto&& item : resultsPayload->getItems()) { JID jid(item.jid); std::map<std::string, std::string> fields; fields["first"] = item.first; fields["last"] = item.last; fields["nick"] = item.nick; fields["email"] = item.email; UserSearchResult result(jid, fields); results.push_back(result); } window_->setResults(results); } } void UserSearchController::handleNameSuggestionRequest(const JID &jid) { suggestionsJID_= jid; VCard::ref vcard = vcardManager_->getVCardAndRequestWhenNeeded(jid); if (vcard) { handleVCardChanged(jid, vcard); } } void UserSearchController::handleJIDEditingFinished(const JID& jid) { if (jid.isValid()) { if (rosterController_->getItem(jid)) { window_->setWarning(QT_TRANSLATE_NOOP("", "This contact is already on your contact list.")); } else if (jid.getNode().empty()) { window_->setWarning(QT_TRANSLATE_NOOP("", "Part of the address you have entered is missing. An address has a structure of 'user@example.com'.")); } else { window_->setWarning(boost::optional<std::string>()); } } else { window_->setWarning(QT_TRANSLATE_NOOP("", "The address you have entered is invalid.")); } } void UserSearchController::handleContactSuggestionsRequested(std::string text) { const std::vector<JID> existingJIDs = window_->getJIDs(); std::vector<Contact::ref> suggestions = contactSuggester_->getSuggestions(text, false); /* do not suggest contacts that have already been added to the chat list */ std::vector<Contact::ref>::iterator i = suggestions.begin(); while (i != suggestions.end()) { bool found = false; - foreach (const JID& jid, existingJIDs) { + for (const auto& jid : existingJIDs) { if ((*i)->jid == jid) { found = true; break; } } // remove contact suggestions which are already on the contact list in add-contact-mode if (type_ == AddContact) { if (!found && !!rosterController_->getItem((*i)->jid)) { found = true; } } if (found) { i = suggestions.erase(i); } else { i++; } } window_->setContactSuggestions(suggestions); } void UserSearchController::handleVCardChanged(const JID& jid, VCard::ref vcard) { if (jid == suggestionsJID_) { window_->setNameSuggestions(ContactEditController::nameSuggestionsFromVCard(vcard)); suggestionsJID_ = JID(); } handleJIDUpdateRequested(std::vector<JID>(1, jid)); } void UserSearchController::handleAvatarChanged(const JID& jid) { handleJIDUpdateRequested(std::vector<JID>(1, jid)); } void UserSearchController::handlePresenceChanged(Presence::ref presence) { handleJIDUpdateRequested(std::vector<JID>(1, presence->getFrom().toBare())); } void UserSearchController::handleJIDUpdateRequested(const std::vector<JID>& jids) { if (window_) { std::vector<Contact::ref> updates; - foreach(const JID& jid, jids) { + for (const auto& jid : jids) { updates.push_back(convertJIDtoContact(jid)); } window_->updateContacts(updates); } } void UserSearchController::handleJIDAddRequested(const std::vector<JID>& jids) { std::vector<Contact::ref> contacts; - foreach(const JID& jid, jids) { + for (const auto& jid : jids) { contacts.push_back(convertJIDtoContact(jid)); } window_->addContacts(contacts); } Contact::ref UserSearchController::convertJIDtoContact(const JID& jid) { Contact::ref contact = std::make_shared<Contact>(); contact->jid = jid; // name lookup boost::optional<XMPPRosterItem> rosterItem = rosterController_->getItem(jid); if (rosterItem && !rosterItem->getName().empty()) { contact->name = rosterItem->getName(); } else { VCard::ref vcard = vcardManager_->getVCard(jid); if (vcard && !vcard->getFullName().empty()) { contact->name = vcard->getFullName(); } else { contact->name = jid.toString(); } } // presence lookup Presence::ref presence = presenceOracle_->getAccountPresence(jid); if (presence) { contact->statusType = presence->getShow(); } else { contact->statusType = StatusShow::None; } @@ -331,62 +331,62 @@ void UserSearchController::initializeUserWindow() { case AddContact: windowType = UserSearchWindow::AddContact; break; case StartChat: windowType = UserSearchWindow::ChatToContact; break; case InviteToChat: windowType = UserSearchWindow::InviteToChat; break; } window_ = factory_->createUserSearchWindow(windowType, uiEventStream_, rosterController_->getGroups()); if (!window_) { // UI Doesn't support user search return; } window_->onNameSuggestionRequested.connect(boost::bind(&UserSearchController::handleNameSuggestionRequest, this, _1)); window_->onFormRequested.connect(boost::bind(&UserSearchController::handleFormRequested, this, _1)); window_->onSearchRequested.connect(boost::bind(&UserSearchController::handleSearch, this, _1, _2)); window_->onContactSuggestionsRequested.connect(boost::bind(&UserSearchController::handleContactSuggestionsRequested, this, _1)); window_->onJIDUpdateRequested.connect(boost::bind(&UserSearchController::handleJIDUpdateRequested, this, _1)); window_->onJIDAddRequested.connect(boost::bind(&UserSearchController::handleJIDAddRequested, this, _1)); window_->onJIDEditFieldChanged.connect(boost::bind(&UserSearchController::handleJIDEditingFinished, this, _1)); window_->setSelectedService(JID(jid_.getDomain())); window_->clear(); } } void UserSearchController::loadSavedDirectories() { savedDirectories_.clear(); - foreach (std::string stringItem, String::split(settings_->getStringSetting(SEARCHED_DIRECTORIES), '\n')) { + for (auto&& stringItem : String::split(settings_->getStringSetting(SEARCHED_DIRECTORIES), '\n')) { if(!stringItem.empty()) { savedDirectories_.push_back(JID(stringItem)); } } } void UserSearchController::addToSavedDirectories(const JID& jid) { if (!jid.isValid()) { return; } savedDirectories_.erase(std::remove(savedDirectories_.begin(), savedDirectories_.end(), jid), savedDirectories_.end()); savedDirectories_.insert(savedDirectories_.begin(), jid); std::string collapsed; int i = 0; - foreach (JID jidItem, savedDirectories_) { + for (const auto& jidItem : savedDirectories_) { if (i >= 15) { break; } if (!collapsed.empty()) { collapsed += "\n"; } collapsed += jidItem.toString(); ++i; } settings_->storeString(SEARCHED_DIRECTORIES, collapsed); window_->addSavedServices(savedDirectories_); } } |