From 3e972565e51f5b2fa7e9768d5d84a7d4b6dfc09b Mon Sep 17 00:00:00 2001 From: Kevin Smith Date: Wed, 5 Oct 2011 08:34:05 +0100 Subject: Allow joining passworded MUCs. Resolves: #991 diff --git a/.gitignore b/.gitignore index 6500850..928b15b 100644 --- a/.gitignore +++ b/.gitignore @@ -43,3 +43,4 @@ cppcheck.log /.settings/ /nbproject/private/ 3rdParty/LibMiniUPnPc/src/miniupnpc/miniupnpcstrings.h +*.sublime-workspace \ No newline at end of file diff --git a/Swift/Controllers/Chat/ChatsManager.cpp b/Swift/Controllers/Chat/ChatsManager.cpp index d3060b8..e6441e1 100644 --- a/Swift/Controllers/Chat/ChatsManager.cpp +++ b/Swift/Controllers/Chat/ChatsManager.cpp @@ -199,7 +199,7 @@ void ChatsManager::handleMUCBookmarkAdded(const MUCBookmark& bookmark) { std::map::iterator it = mucControllers_.find(bookmark.getRoom()); if (it == mucControllers_.end() && bookmark.getAutojoin()) { //FIXME: need vcard stuff here to get a nick - handleJoinMUCRequest(bookmark.getRoom(), bookmark.getNick(), false, false); + handleJoinMUCRequest(bookmark.getRoom(), bookmark.getPassword(), bookmark.getNick(), false, false); } chatListWindow_->addMUCBookmark(bookmark); } @@ -321,7 +321,7 @@ void ChatsManager::handleUIEvent(boost::shared_ptr event) { mucBookmarkManager_->replaceBookmark(editMUCBookmarkEvent->getOldBookmark(), editMUCBookmarkEvent->getNewBookmark()); } else if (JoinMUCUIEvent::ref joinEvent = boost::dynamic_pointer_cast(event)) { - handleJoinMUCRequest(joinEvent->getJID(), joinEvent->getNick(), joinEvent->getShouldJoinAutomatically(), joinEvent->getCreateAsReservedRoomIfNew()); + handleJoinMUCRequest(joinEvent->getJID(), joinEvent->getPassword(), joinEvent->getNick(), joinEvent->getShouldJoinAutomatically(), joinEvent->getCreateAsReservedRoomIfNew()); mucControllers_[joinEvent->getJID()]->activateChatWindow(); } else if (boost::shared_ptr joinEvent = boost::dynamic_pointer_cast(event)) { @@ -481,7 +481,7 @@ void ChatsManager::rebindControllerJID(const JID& from, const JID& to) { chatControllers_[to]->setToJID(to); } -void ChatsManager::handleJoinMUCRequest(const JID &mucJID, const boost::optional& nickMaybe, bool addAutoJoin, bool createAsReservedIfNew) { +void ChatsManager::handleJoinMUCRequest(const JID &mucJID, const boost::optional& password, const boost::optional& nickMaybe, bool addAutoJoin, bool createAsReservedIfNew) { if (addAutoJoin) { MUCBookmark bookmark(mucJID, mucJID.getNode()); bookmark.setAutojoin(true); @@ -500,7 +500,7 @@ void ChatsManager::handleJoinMUCRequest(const JID &mucJID, const boost::optional if (createAsReservedIfNew) { muc->setCreateAsReservedIfNew(); } - MUCController* controller = new MUCController(jid_, muc, nick, stanzaChannel_, iqRouter_, chatWindowFactory_, presenceOracle_, avatarManager_, uiEventStream_, false, timerFactory_, eventController_, entityCapsProvider_); + MUCController* controller = new MUCController(jid_, muc, password, nick, stanzaChannel_, iqRouter_, chatWindowFactory_, presenceOracle_, avatarManager_, uiEventStream_, false, timerFactory_, eventController_, entityCapsProvider_); mucControllers_[mucJID] = controller; controller->setAvailableServerFeatures(serverDiscoInfo_); controller->onUserLeft.connect(boost::bind(&ChatsManager::handleUserLeftMUC, this, controller)); @@ -549,7 +549,7 @@ void ChatsManager::handleMUCSelectedAfterSearch(const JID& muc) { } void ChatsManager::handleMUCBookmarkActivated(const MUCBookmark& mucBookmark) { - uiEventStream_->send(boost::make_shared(mucBookmark.getRoom(), mucBookmark.getNick())); + uiEventStream_->send(boost::make_shared(mucBookmark.getRoom(), mucBookmark.getPassword(), mucBookmark.getNick())); } void ChatsManager::handleNewFileTransferController(FileTransferController* ftc) { @@ -560,7 +560,8 @@ void ChatsManager::handleNewFileTransferController(FileTransferController* ftc) void ChatsManager::handleRecentActivated(const ChatListWindow::Chat& chat) { if (chat.isMUC) { - uiEventStream_->send(boost::make_shared(chat.jid, chat.nick)); + /* FIXME: This means that recents requiring passwords will just flat-out not work */ + uiEventStream_->send(boost::make_shared(chat.jid, boost::optional(), chat.nick)); } else { uiEventStream_->send(boost::make_shared(chat.jid)); diff --git a/Swift/Controllers/Chat/ChatsManager.h b/Swift/Controllers/Chat/ChatsManager.h index a82492c..8e94d9a 100644 --- a/Swift/Controllers/Chat/ChatsManager.h +++ b/Swift/Controllers/Chat/ChatsManager.h @@ -58,7 +58,7 @@ namespace Swift { private: ChatListWindow::Chat createChatListChatItem(const JID& jid, const std::string& activity); void handleChatRequest(const std::string& contact); - void handleJoinMUCRequest(const JID& muc, const boost::optional& nick, bool addAutoJoin, bool createAsReservedIfNew); + void handleJoinMUCRequest(const JID& muc, const boost::optional& password, const boost::optional& nick, bool addAutoJoin, bool createAsReservedIfNew); void handleSearchMUCRequest(); void handleMUCSelectedAfterSearch(const JID&); void rebindControllerJID(const JID& from, const JID& to); diff --git a/Swift/Controllers/Chat/MUCController.cpp b/Swift/Controllers/Chat/MUCController.cpp index d72c0f7..2b8a8b7 100644 --- a/Swift/Controllers/Chat/MUCController.cpp +++ b/Swift/Controllers/Chat/MUCController.cpp @@ -44,6 +44,7 @@ namespace Swift { MUCController::MUCController ( const JID& self, MUC::ref muc, + const boost::optional& password, const std::string &nick, StanzaChannel* stanzaChannel, IQRouter* iqRouter, @@ -55,7 +56,7 @@ MUCController::MUCController ( TimerFactory* timerFactory, EventController* eventController, EntityCapsProvider* entityCapsProvider) : - ChatControllerBase(self, stanzaChannel, iqRouter, chatWindowFactory, muc->getJID(), presenceOracle, avatarManager, useDelayForLatency, uiEventStream, eventController, timerFactory, entityCapsProvider), muc_(muc), nick_(nick), desiredNick_(nick) { + ChatControllerBase(self, stanzaChannel, iqRouter, chatWindowFactory, muc->getJID(), presenceOracle, avatarManager, useDelayForLatency, uiEventStream, eventController, timerFactory, entityCapsProvider), muc_(muc), nick_(nick), desiredNick_(nick), password_(password) { parting_ = true; joined_ = false; lastWasPresence_ = false; @@ -146,6 +147,9 @@ void MUCController::rejoin() { if (parting_) { joined_ = false; parting_ = false; + if (password_) { + muc_->setPassword(*password_); + } //FIXME: check for received activity if (lastActivity_ == boost::posix_time::not_a_date_time) { muc_->joinAs(nick_); diff --git a/Swift/Controllers/Chat/MUCController.h b/Swift/Controllers/Chat/MUCController.h index 17dbba4..d22d2ca 100644 --- a/Swift/Controllers/Chat/MUCController.h +++ b/Swift/Controllers/Chat/MUCController.h @@ -42,7 +42,7 @@ namespace Swift { class MUCController : public ChatControllerBase { public: - MUCController(const JID& self, MUC::ref muc, const std::string &nick, StanzaChannel* stanzaChannel, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, PresenceOracle* presenceOracle, AvatarManager* avatarManager, UIEventStream* events, bool useDelayForLatency, TimerFactory* timerFactory, EventController* eventController, EntityCapsProvider* entityCapsProvider); + MUCController(const JID& self, MUC::ref muc, const boost::optional& password, const std::string &nick, StanzaChannel* stanzaChannel, IQRouter* iqRouter, ChatWindowFactory* chatWindowFactory, PresenceOracle* presenceOracle, AvatarManager* avatarManager, UIEventStream* events, bool useDelayForLatency, TimerFactory* timerFactory, EventController* eventController, EntityCapsProvider* entityCapsProvider); ~MUCController(); boost::signal onUserLeft; boost::signal onUserJoined; @@ -112,6 +112,7 @@ namespace Swift { std::set currentOccupants_; std::vector joinParts_; boost::posix_time::ptime lastActivity_; + boost::optional password_; }; } diff --git a/Swift/Controllers/Chat/UnitTest/MUCControllerTest.cpp b/Swift/Controllers/Chat/UnitTest/MUCControllerTest.cpp index ad5ceac..16ad999 100644 --- a/Swift/Controllers/Chat/UnitTest/MUCControllerTest.cpp +++ b/Swift/Controllers/Chat/UnitTest/MUCControllerTest.cpp @@ -60,7 +60,7 @@ public: entityCapsProvider_ = new DummyEntityCapsProvider(); muc_ = MUC::ref(new MUC(stanzaChannel_, iqRouter_, directedPresenceSender_, JID("teaparty@rooms.wonderland.lit"), mucRegistry_)); mocks_->ExpectCall(chatWindowFactory_, ChatWindowFactory::createChatWindow).With(muc_->getJID(), uiEventStream_).Return(window_); - controller_ = new MUCController (self_, muc_, nick_, stanzaChannel_, iqRouter_, chatWindowFactory_, presenceOracle_, avatarManager_, uiEventStream_, false, timerFactory, eventController_, entityCapsProvider_); + controller_ = new MUCController (self_, muc_, boost::optional(), nick_, stanzaChannel_, iqRouter_, chatWindowFactory_, presenceOracle_, avatarManager_, uiEventStream_, false, timerFactory, eventController_, entityCapsProvider_); }; void tearDown() { diff --git a/Swift/Controllers/UIEvents/JoinMUCUIEvent.h b/Swift/Controllers/UIEvents/JoinMUCUIEvent.h index e1d65ad..b3ff8c7 100644 --- a/Swift/Controllers/UIEvents/JoinMUCUIEvent.h +++ b/Swift/Controllers/UIEvents/JoinMUCUIEvent.h @@ -12,21 +12,23 @@ #include -#include "Swift/Controllers/UIEvents/UIEvent.h" +#include namespace Swift { class JoinMUCUIEvent : public UIEvent { public: typedef boost::shared_ptr ref; - JoinMUCUIEvent(const JID& jid, const boost::optional& nick = boost::optional(), bool joinAutomaticallyInFuture = false, bool createAsReservedRoomIfNew = false) : jid_(jid), nick_(nick), joinAutomatically_(joinAutomaticallyInFuture), createAsReservedRoomIfNew_(createAsReservedRoomIfNew) {}; - boost::optional getNick() {return nick_;}; - JID getJID() {return jid_;}; - bool getShouldJoinAutomatically() {return joinAutomatically_;} - bool getCreateAsReservedRoomIfNew() {return createAsReservedRoomIfNew_;} + JoinMUCUIEvent(const JID& jid, const boost::optional& password = boost::optional(), const boost::optional& nick = boost::optional(), bool joinAutomaticallyInFuture = false, bool createAsReservedRoomIfNew = false) : jid_(jid), nick_(nick), joinAutomatically_(joinAutomaticallyInFuture), createAsReservedRoomIfNew_(createAsReservedRoomIfNew), password_(password) {}; + const boost::optional& getNick() const {return nick_;} + const JID& getJID() const {return jid_;} + bool getShouldJoinAutomatically() const {return joinAutomatically_;} + bool getCreateAsReservedRoomIfNew() const {return createAsReservedRoomIfNew_;} + const boost::optional& getPassword() const {return password_;} private: JID jid_; boost::optional nick_; bool joinAutomatically_; bool createAsReservedRoomIfNew_; + boost::optional password_; }; } diff --git a/Swift/QtUI/QtJoinMUCWindow.cpp b/Swift/QtUI/QtJoinMUCWindow.cpp index fec3c4d..14777bd 100644 --- a/Swift/QtUI/QtJoinMUCWindow.cpp +++ b/Swift/QtUI/QtJoinMUCWindow.cpp @@ -38,8 +38,9 @@ void QtJoinMUCWindow::handleJoin() { } lastSetNick = Q2PSTRING(ui.nickName->text()); + std::string password = Q2PSTRING(ui.password->text()); JID room(Q2PSTRING(ui.room->text())); - uiEventStream->send(boost::make_shared(room, lastSetNick, ui.joinAutomatically->isChecked(), !ui.instantRoom->isChecked())); + uiEventStream->send(boost::make_shared(room, password, lastSetNick, ui.joinAutomatically->isChecked(), !ui.instantRoom->isChecked())); hide(); } @@ -59,6 +60,7 @@ void QtJoinMUCWindow::setMUC(const std::string& nick) { void QtJoinMUCWindow::show() { QWidget::show(); QWidget::activateWindow(); + ui.password->setText(""); } } diff --git a/Swift/QtUI/QtJoinMUCWindow.ui b/Swift/QtUI/QtJoinMUCWindow.ui index 74fe513..4c4935a 100644 --- a/Swift/QtUI/QtJoinMUCWindow.ui +++ b/Swift/QtUI/QtJoinMUCWindow.ui @@ -7,7 +7,7 @@ 0 0 410 - 212 + 224 @@ -53,6 +53,16 @@ + + + + Password: + + + + + + diff --git a/Swiften/Elements/MUCPayload.h b/Swiften/Elements/MUCPayload.h index 3b99111..29cab8d 100644 --- a/Swiften/Elements/MUCPayload.h +++ b/Swiften/Elements/MUCPayload.h @@ -40,6 +40,10 @@ namespace Swift { since_ = since; } + void setPassword(const std::string& password) { + password_ = password; + } + int getMaxChars() const{ return maxChars_; } @@ -52,6 +56,10 @@ namespace Swift { return seconds_; } + const boost::optional& getPassword() const { + return password_; + } + const boost::posix_time::ptime& getSince() const { return since_; } @@ -61,5 +69,6 @@ namespace Swift { int maxStanzas_; int seconds_; boost::posix_time::ptime since_; + boost::optional password_; }; } diff --git a/Swiften/Elements/Storage.h b/Swiften/Elements/Storage.h index 8118b3b..03c958c 100644 --- a/Swiften/Elements/Storage.h +++ b/Swiften/Elements/Storage.h @@ -8,9 +8,12 @@ #include +#include + #include #include #include +#include namespace Swift { class Storage : public Payload { @@ -22,7 +25,7 @@ namespace Swift { JID jid; bool autoJoin; std::string nick; - std::string password; + boost::optional password; }; struct URL { diff --git a/Swiften/MUC/MUC.cpp b/Swiften/MUC/MUC.cpp index 08391b4..15355ad 100644 --- a/Swiften/MUC/MUC.cpp +++ b/Swiften/MUC/MUC.cpp @@ -44,6 +44,13 @@ void MUC::joinAs(const std::string &nick) { } /** + * Set the password used for entering the room. + */ +void MUC::setPassword(const boost::optional& newPassword) { + password = newPassword; +} + +/** * Join the MUC with context since date. */ void MUC::joinWithContextSince(const std::string &nick, const boost::posix_time::ptime& since) { @@ -68,6 +75,9 @@ void MUC::internalJoin(const std::string &nick) { if (joinSince_ != boost::posix_time::not_a_date_time) { mucPayload->setSince(joinSince_); } + if (password) { + mucPayload->setPassword(*password); + } joinPresence->addPayload(mucPayload); presenceSender->sendPresence(joinPresence); diff --git a/Swiften/MUC/MUC.h b/Swiften/MUC/MUC.h index adc5707..a9b42b8 100644 --- a/Swiften/MUC/MUC.h +++ b/Swiften/MUC/MUC.h @@ -65,6 +65,7 @@ namespace Swift { /** Send an invite for the person to join the MUC */ void invitePerson(const JID& person, const std::string& reason = ""); void setCreateAsReservedIfNew() {createAsReservedIfNew = true;} + void setPassword(const boost::optional& password); public: boost::signal onJoinComplete; boost::signal onJoinFailed; @@ -110,5 +111,6 @@ namespace Swift { boost::posix_time::ptime joinSince_; bool createAsReservedIfNew; bool unlocking; + boost::optional password; }; } diff --git a/Swiften/MUC/MUCBookmark.h b/Swiften/MUC/MUCBookmark.h index 3f612c4..3c28bdb 100644 --- a/Swiften/MUC/MUCBookmark.h +++ b/Swiften/MUC/MUCBookmark.h @@ -59,7 +59,8 @@ namespace Swift { } bool operator==(const MUCBookmark& rhs) const { - return rhs.room_ == room_ && rhs.name_ == name_ && rhs.nick_ == nick_ && rhs.password_ == password_ && rhs.autojoin_ == autojoin_; + /* FIXME: not checking passwords for equality - which might make sense, perhaps */ + return rhs.room_ == room_ && rhs.name_ == name_ && rhs.nick_ == nick_ /*&& rhs.password_ == password_*/ && rhs.autojoin_ == autojoin_; } Storage::Room toStorage() const { diff --git a/Swiften/Parser/PayloadParsers/UnitTest/StorageParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/StorageParserTest.cpp index 4fd8ae5..a378d0b 100644 --- a/Swiften/Parser/PayloadParsers/UnitTest/StorageParserTest.cpp +++ b/Swiften/Parser/PayloadParsers/UnitTest/StorageParserTest.cpp @@ -42,7 +42,7 @@ class StorageParserTest : public CppUnit::TestFixture { CPPUNIT_ASSERT_EQUAL(JID("council@conference.underhill.org"), rooms[0].jid); CPPUNIT_ASSERT(rooms[0].autoJoin); CPPUNIT_ASSERT_EQUAL(std::string("Puck"), rooms[0].nick); - CPPUNIT_ASSERT_EQUAL(std::string("MyPass"), rooms[0].password); + CPPUNIT_ASSERT_EQUAL(std::string("MyPass"), *rooms[0].password); } void testParse_MultipleRooms() { diff --git a/Swiften/Serializer/PayloadSerializers/MUCPayloadSerializer.cpp b/Swiften/Serializer/PayloadSerializers/MUCPayloadSerializer.cpp index 7080e14..58f78b8 100644 --- a/Swiften/Serializer/PayloadSerializers/MUCPayloadSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/MUCPayloadSerializer.cpp @@ -7,9 +7,11 @@ #include #include +#include #include #include +#include #include namespace Swift { @@ -40,6 +42,12 @@ std::string MUCPayloadSerializer::serializePayload(boost::shared_ptr historyElement->setAttribute("since", sinceString); history = true; } + if (muc->getPassword()) { + std::string password = *muc->getPassword(); + boost::shared_ptr passwordElement(new XMLElement("password")); + passwordElement->addNode(boost::make_shared(password)); + mucElement.addNode(passwordElement); + } if (history) { mucElement.addNode(historyElement); } diff --git a/Swiften/Serializer/PayloadSerializers/StorageSerializer.cpp b/Swiften/Serializer/PayloadSerializers/StorageSerializer.cpp index 30adf26..77fb3c0 100644 --- a/Swiften/Serializer/PayloadSerializers/StorageSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/StorageSerializer.cpp @@ -30,9 +30,9 @@ std::string StorageSerializer::serializePayload(boost::shared_ptr stora nickElement->addNode(boost::shared_ptr(new XMLTextNode(room.nick))); conferenceElement->addNode(nickElement); } - if (!room.password.empty()) { + if (room.password) { boost::shared_ptr passwordElement(new XMLElement("password")); - passwordElement->addNode(boost::shared_ptr(new XMLTextNode(room.password))); + passwordElement->addNode(boost::shared_ptr(new XMLTextNode(*room.password))); conferenceElement->addNode(passwordElement); } storageElement.addNode(conferenceElement); -- cgit v0.10.2-6-g49f6