From 703a1c28c3c87ac0fb365ff0683d7c64fcdd2210 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Remko=20Tron=C3=A7on?= Date: Tue, 20 Sep 2011 22:38:30 +0200 Subject: Added ClientBlockListManager. diff --git a/Swiften/Client/BlockList.cpp b/Swiften/Client/BlockList.cpp new file mode 100644 index 0000000..0b2fc12 --- /dev/null +++ b/Swiften/Client/BlockList.cpp @@ -0,0 +1,13 @@ +/* + * Copyright (c) 2011 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include + +using namespace Swift; + +BlockList::~BlockList() { + +} diff --git a/Swiften/Client/BlockList.h b/Swiften/Client/BlockList.h new file mode 100644 index 0000000..39a211d --- /dev/null +++ b/Swiften/Client/BlockList.h @@ -0,0 +1,33 @@ +/* + * Copyright (c) 2011 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include + +#include +#include + +namespace Swift { + class BlockList { + public: + enum State { + Requesting, + Available, + Error, + }; + virtual ~BlockList(); + + virtual State getState() const = 0; + + virtual const std::set& getItems() const = 0; + + public: + boost::signal onStateChanged; + boost::signal onItemAdded; + boost::signal onItemRemoved; + }; +} diff --git a/Swiften/Client/BlockListImpl.cpp b/Swiften/Client/BlockListImpl.cpp new file mode 100644 index 0000000..dfaaaf1 --- /dev/null +++ b/Swiften/Client/BlockListImpl.cpp @@ -0,0 +1,56 @@ +/* + * Copyright (c) 2011 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include + +#include + +using namespace Swift; + +BlockListImpl::BlockListImpl() { + +} + +void BlockListImpl::setItems(const std::vector& items) { + this->items = std::set(items.begin(), items.end()); +} + +void BlockListImpl::addItem(const JID& item) { + if (items.insert(item).second) { + onItemAdded(item); + } +} + +void BlockListImpl::removeItem(const JID& item) { + if (items.erase(item)) { + onItemRemoved(item); + } +} + +void BlockListImpl::setState(State state) { + if (this->state != state) { + onStateChanged(); + } +} + +void BlockListImpl::addItems(const std::vector& items) { + foreach (const JID& item, items) { + addItem(item); + } +} + +void BlockListImpl::removeItems(const std::vector& items) { + foreach (const JID& item, items) { + removeItem(item); + } +} + +void BlockListImpl::removeAllItems() { + foreach (const JID& item, items) { + removeItem(item); + } +} + diff --git a/Swiften/Client/BlockListImpl.h b/Swiften/Client/BlockListImpl.h new file mode 100644 index 0000000..ef08340 --- /dev/null +++ b/Swiften/Client/BlockListImpl.h @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2011 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include + +namespace Swift { + class BlockListImpl : public BlockList { + public: + BlockListImpl(); + + virtual State getState() const { + return state; + } + + void setState(State state); + + virtual const std::set& getItems() const { + return items; + } + + void setItems(const std::vector& items); + void addItem(const JID& item); + void removeItem(const JID& item); + void addItems(const std::vector& items); + void removeItems(const std::vector& items); + void removeAllItems(); + + private: + State state; + std::set items; + }; +} diff --git a/Swiften/Client/ClientBlockListManager.cpp b/Swiften/Client/ClientBlockListManager.cpp new file mode 100644 index 0000000..7222cea --- /dev/null +++ b/Swiften/Client/ClientBlockListManager.cpp @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2011 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#include + +#include +#include +#include + +#include + +using namespace Swift; + +namespace { + class BlockResponder : public SetResponder { + public: + BlockResponder(boost::shared_ptr blockList, IQRouter* iqRouter) : SetResponder(iqRouter), blockList(blockList) { + } + + virtual bool handleSetRequest(const JID& from, const JID&, const std::string& id, boost::shared_ptr payload) { + if (getIQRouter()->isAccountJID(from)) { + if (payload) { + blockList->addItems(payload->getItems()); + } + sendResponse(from, id, boost::shared_ptr()); + } + else { + sendError(from, id, ErrorPayload::NotAuthorized, ErrorPayload::Cancel); + } + return true; + } + + private: + boost::shared_ptr blockList; + }; + + class UnblockResponder : public SetResponder { + public: + UnblockResponder(boost::shared_ptr blockList, IQRouter* iqRouter) : SetResponder(iqRouter), blockList(blockList) { + } + + virtual bool handleSetRequest(const JID& from, const JID&, const std::string& id, boost::shared_ptr payload) { + if (getIQRouter()->isAccountJID(from)) { + if (payload) { + if (payload->getItems().empty()) { + blockList->removeAllItems(); + } + else { + blockList->removeItems(payload->getItems()); + } + } + sendResponse(from, id, boost::shared_ptr()); + } + else { + sendError(from, id, ErrorPayload::NotAuthorized, ErrorPayload::Cancel); + } + return true; + } + + private: + boost::shared_ptr blockList; + }; +} + +ClientBlockListManager::ClientBlockListManager(IQRouter* iqRouter) : iqRouter(iqRouter) { +} + +ClientBlockListManager::~ClientBlockListManager() { + unblockResponder->stop(); + blockResponder->stop(); + if (getRequest) { + getRequest->onResponse.disconnect(boost::bind(&ClientBlockListManager::handleBlockListReceived, this, _1, _2)); + } +} + +boost::shared_ptr ClientBlockListManager::getBlockList() { + if (!blockList) { + blockList = boost::make_shared(); + blockList->setState(BlockList::Requesting); + assert(!getRequest); + getRequest = boost::make_shared< GenericRequest >(IQ::Get, JID(), boost::make_shared(), iqRouter); + getRequest->onResponse.connect(boost::bind(&ClientBlockListManager::handleBlockListReceived, this, _1, _2)); + getRequest->send(); + } + return blockList; +} + +void ClientBlockListManager::handleBlockListReceived(boost::shared_ptr payload, ErrorPayload::ref error) { + if (error || !payload) { + blockList->setState(BlockList::Error); + } + else { + blockList->setState(BlockList::Available); + blockList->setItems(payload->getItems()); + blockResponder = boost::make_shared(blockList, iqRouter); + blockResponder->start(); + unblockResponder = boost::make_shared(blockList, iqRouter); + unblockResponder->start(); + } +} + diff --git a/Swiften/Client/ClientBlockListManager.h b/Swiften/Client/ClientBlockListManager.h new file mode 100644 index 0000000..21d35e3 --- /dev/null +++ b/Swiften/Client/ClientBlockListManager.h @@ -0,0 +1,46 @@ +/* + * Copyright (c) 2011 Remko Tronçon + * Licensed under the GNU General Public License v3. + * See Documentation/Licenses/GPLv3.txt for more information. + */ + +#pragma once + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace Swift { + class IQRouter; + + class ClientBlockListManager { + public: + ClientBlockListManager(IQRouter *iqRouter); + ~ClientBlockListManager(); + + bool isSupported() const; + + /** + * Returns the blocklist. + */ + boost::shared_ptr getBlockList(); + + private: + void handleBlockListReceived(boost::shared_ptr payload, ErrorPayload::ref); + + private: + IQRouter* iqRouter; + boost::shared_ptr > getRequest; + boost::shared_ptr > blockResponder; + boost::shared_ptr > unblockResponder; + boost::shared_ptr blockList; + }; +} + diff --git a/Swiften/Queries/IQRouter.h b/Swiften/Queries/IQRouter.h index 167cb8f..8dba334 100644 --- a/Swiften/Queries/IQRouter.h +++ b/Swiften/Queries/IQRouter.h @@ -63,6 +63,16 @@ namespace Swift { bool isAvailable(); + /** + * Checks whether the given jid is the account JID (i.e. it is either + * the bare JID, or it is the empty JID). + * Can be used to check whether a stanza is sent by the server on behalf + * of the user's account. + */ + bool isAccountJID(const JID& jid) { + return jid.isValid() ? jid_.toBare().equals(jid, JID::WithResource) : true; + } + private: void handleIQ(boost::shared_ptr iq); void processPendingRemoves(); diff --git a/Swiften/Queries/Request.cpp b/Swiften/Queries/Request.cpp index 0126d62..382e44c 100644 --- a/Swiften/Queries/Request.cpp +++ b/Swiften/Queries/Request.cpp @@ -67,16 +67,13 @@ bool Request::handleIQ(boost::shared_ptr iq) { } bool Request::isCorrectSender(const JID& jid) { - if (isAccountJID(receiver_)) { - return isAccountJID(jid); + if (router_->isAccountJID(receiver_)) { + return router_->isAccountJID(jid); } else { return jid.equals(receiver_, JID::WithResource); } } -bool Request::isAccountJID(const JID& jid) { - return jid.isValid() ? router_->getJID().toBare().equals(jid, JID::WithResource) : true; -} } diff --git a/Swiften/Queries/Request.h b/Swiften/Queries/Request.h index a7139cf..677a758 100644 --- a/Swiften/Queries/Request.h +++ b/Swiften/Queries/Request.h @@ -60,7 +60,6 @@ namespace Swift { private: bool handleIQ(boost::shared_ptr); bool isCorrectSender(const JID& jid); - bool isAccountJID(const JID& jid); private: IQRouter* router_; diff --git a/Swiften/Queries/Responder.h b/Swiften/Queries/Responder.h index a9aab17..2ba9c24 100644 --- a/Swiften/Queries/Responder.h +++ b/Swiften/Queries/Responder.h @@ -94,6 +94,10 @@ namespace Swift { router_->sendIQ(IQ::createError(to, from, id, condition, type)); } + IQRouter* getIQRouter() const { + return router_; + } + private: virtual bool handleIQ(boost::shared_ptr iq) { if (iq->getType() == IQ::Set || iq->getType() == IQ::Get) { diff --git a/Swiften/SConscript b/Swiften/SConscript index f55485a..0144ddb 100644 --- a/Swiften/SConscript +++ b/Swiften/SConscript @@ -79,6 +79,9 @@ if env["SCONS_STAGE"] == "build" : "Client/Client.cpp", "Client/ClientXMLTracer.cpp", "Client/ClientSession.cpp", + "Client/BlockList.cpp", + "Client/BlockListImpl.cpp", + "Client/ClientBlockListManager.cpp", "Client/MemoryStorages.cpp", "Client/NickResolver.cpp", "Client/NickManager.cpp", -- cgit v0.10.2-6-g49f6