diff --git a/backends/libpurple/main.cpp b/backends/libpurple/main.cpp index 56dbdb33..b3c208e8 100644 --- a/backends/libpurple/main.cpp +++ b/backends/libpurple/main.cpp @@ -485,6 +485,16 @@ class SpectrumNetworkPlugin : public NetworkPlugin { } } + void handleBuddyBlockToggled(const std::string &user, const std::string &buddyName, bool blocked) { + PurpleAccount *account = m_sessions[user]; + if (account) { + if (blocked) + purple_privacy_deny(account, buddyName.c_str(), FALSE, FALSE); + else + purple_privacy_allow(account, buddyName.c_str(), FALSE, FALSE); + } + } + void handleTypingRequest(const std::string &user, const std::string &buddyName) { PurpleAccount *account = m_sessions[user]; if (account) { @@ -657,7 +667,8 @@ static void buddyListUpdate(PurpleBuddyList *list, PurpleBlistNode *node) { std::string message; getStatus(buddy, status, message); - np->handleBuddyChanged(np->m_accounts[account], purple_buddy_get_name(buddy), getAlias(buddy), getGroups(buddy)[0], (int) status.getType(), message, getIconHash(buddy)); + np->handleBuddyChanged(np->m_accounts[account], purple_buddy_get_name(buddy), getAlias(buddy), getGroups(buddy)[0], (int) status.getType(), message, getIconHash(buddy), + purple_privacy_check(account, purple_buddy_get_name(buddy)) == false); } static void NodeRemoved(PurpleBlistNode *node, void *data) { diff --git a/include/Swiften/Elements/BlockPayload.cpp b/include/Swiften/Elements/BlockPayload.cpp new file mode 100644 index 00000000..8031c17f --- /dev/null +++ b/include/Swiften/Elements/BlockPayload.cpp @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2011 Jan Kaluza + * Licensed under the Simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include + +namespace Swift { + +// This payload is NOT part of ANY XEP and it is only +// libtransport related extension. +BlockPayload::BlockPayload() { + +} + +} diff --git a/include/Swiften/Elements/BlockPayload.h b/include/Swiften/Elements/BlockPayload.h new file mode 100644 index 00000000..10ddf15b --- /dev/null +++ b/include/Swiften/Elements/BlockPayload.h @@ -0,0 +1,25 @@ +/* + * Copyright (c) 2011 Jan Kaluza + * Licensed under the Simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include +#include +#include + +#include + +// This payload is NOT part of ANY XEP and it is only +// libtransport related extension. +namespace Swift { + class BlockPayload : public Payload { + public: + typedef boost::shared_ptr ref; + + public: + BlockPayload(); + }; +} diff --git a/include/Swiften/Parser/PayloadParsers/BlockParser.cpp b/include/Swiften/Parser/PayloadParsers/BlockParser.cpp new file mode 100644 index 00000000..660d8320 --- /dev/null +++ b/include/Swiften/Parser/PayloadParsers/BlockParser.cpp @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2011 Jan Kaluza + * Licensed under the Simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include + +namespace Swift { + +// This payload is NOT part of ANY XEP and it is only +// libtransport related extension. +BlockParser::BlockParser() /*: level_(0)*/ { +} + +void BlockParser::handleStartElement(const std::string& /*element*/, const std::string& /*ns*/, const AttributeMap& /*attributes*/) { +} + +void BlockParser::handleEndElement(const std::string&, const std::string&) { +} + +void BlockParser::handleCharacterData(const std::string&) { + +} + +} diff --git a/include/Swiften/Parser/PayloadParsers/BlockParser.h b/include/Swiften/Parser/PayloadParsers/BlockParser.h new file mode 100644 index 00000000..f170047a --- /dev/null +++ b/include/Swiften/Parser/PayloadParsers/BlockParser.h @@ -0,0 +1,26 @@ +/* + * Copyright (c) 2011 Jan Kaluza + * Licensed under the Simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include +#include + +// This payload is NOT part of ANY XEP and it is only +// libtransport related extension. +namespace Swift { + class BlockParser : public GenericPayloadParser { + public: + BlockParser(); + + virtual void handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes); + virtual void handleEndElement(const std::string& element, const std::string&); + virtual void handleCharacterData(const std::string& data); + +// private: +// int level_; + }; +} diff --git a/include/Swiften/Serializer/PayloadSerializers/BlockSerializer.cpp b/include/Swiften/Serializer/PayloadSerializers/BlockSerializer.cpp new file mode 100644 index 00000000..05e42847 --- /dev/null +++ b/include/Swiften/Serializer/PayloadSerializers/BlockSerializer.cpp @@ -0,0 +1,28 @@ +/* + * Copyright (c) 2011 Jan Kaluza + * Licensed under the Simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#include + +#include + +#include +#include +#include + +namespace Swift { + +// This payload is NOT part of ANY XEP and it is only +// libtransport related extension. +BlockSerializer::BlockSerializer() : GenericPayloadSerializer() { +} + +std::string BlockSerializer::serializePayload(boost::shared_ptr attention) const { + XMLElement attentionElement("block", "urn:xmpp:block:0"); + + return attentionElement.serialize(); +} + +} diff --git a/include/Swiften/Serializer/PayloadSerializers/BlockSerializer.h b/include/Swiften/Serializer/PayloadSerializers/BlockSerializer.h new file mode 100644 index 00000000..b6583f02 --- /dev/null +++ b/include/Swiften/Serializer/PayloadSerializers/BlockSerializer.h @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2011 Jan Kaluza + * Licensed under the Simplified BSD license. + * See Documentation/Licenses/BSD-simplified.txt for more information. + */ + +#pragma once + +#include +#include + +// This payload is NOT part of ANY XEP and it is only +// libtransport related extension. +namespace Swift { + class BlockSerializer : public GenericPayloadSerializer { + public: + BlockSerializer(); + + virtual std::string serializePayload(boost::shared_ptr) const; + }; +} diff --git a/include/transport/buddy.h b/include/transport/buddy.h index adbe9a38..7bfed9a3 100644 --- a/include/transport/buddy.h +++ b/include/transport/buddy.h @@ -84,6 +84,14 @@ class Buddy { /// Marks this buddy as offline. void setOffline(); + void setBlocked(bool block) { + m_blocked = block; + } + + bool isBlocked() { + return m_blocked; + } + /// Returns true if this buddy is marked as available/online. /// \return true if this buddy is marked as available/online. @@ -170,6 +178,7 @@ class Buddy { long m_id; bool m_online; + bool m_blocked; std::string m_subscription; Swift::Presence::ref m_lastPresence; Swift::JID m_jid; diff --git a/include/transport/networkplugin.h b/include/transport/networkplugin.h index 983c28f9..81325602 100644 --- a/include/transport/networkplugin.h +++ b/include/transport/networkplugin.h @@ -41,7 +41,8 @@ class NetworkPlugin { virtual ~NetworkPlugin(); void handleBuddyChanged(const std::string &user, const std::string &buddyName, const std::string &alias, - const std::string &groups, int status, const std::string &statusMessage = "", const std::string &iconHash = "" + const std::string &groups, int status, const std::string &statusMessage = "", const std::string &iconHash = "", + bool blocked = false ); void handleParticipantChanged(const std::string &user, const std::string &nickname, const std::string &room, int flags, int status = Swift::StatusShow::None, const std::string &statusMessage = "", const std::string &newname = ""); @@ -78,6 +79,7 @@ class NetworkPlugin { virtual void handleStatusChangeRequest(const std::string &/*user*/, int status, const std::string &statusMessage) {} virtual void handleBuddyUpdatedRequest(const std::string &/*user*/, const std::string &/*buddyName*/, const std::string &/*alias*/, const std::string &/*groups*/) {} virtual void handleBuddyRemovedRequest(const std::string &/*user*/, const std::string &/*buddyName*/, const std::string &/*groups*/) {} + virtual void handleBuddyBlockToggled(const std::string &/*user*/, const std::string &/*buddyName*/, bool /*blocked*/) {} virtual void handleTypingRequest(const std::string &/*user*/, const std::string &/*buddyName*/) {} virtual void handleTypedRequest(const std::string &/*user*/, const std::string &/*buddyName*/) {} diff --git a/include/transport/networkpluginserver.h b/include/transport/networkpluginserver.h index 6c2ca240..239bff24 100644 --- a/include/transport/networkpluginserver.h +++ b/include/transport/networkpluginserver.h @@ -39,6 +39,7 @@ class Config; class NetworkConversation; class VCardResponder; class RosterResponder; +class BlockResponder; class NetworkPluginServer { public: @@ -95,6 +96,8 @@ class NetworkPluginServer { void handleBuddyRemoved(Buddy *buddy); void handleBuddyAdded(Buddy *buddy, const Swift::RosterItemPayload &item); + void handleBlockToggled(Buddy *buddy); + void handleVCardUpdated(User *user, boost::shared_ptr vcard); void handleVCardRequired(User *user, const std::string &name, unsigned int id); @@ -107,6 +110,7 @@ class NetworkPluginServer { UserManager *m_userManager; VCardResponder *m_vcardResponder; RosterResponder *m_rosterResponder; + BlockResponder *m_blockResponder; Config *m_config; boost::shared_ptr m_server; std::list m_clients; diff --git a/src/blockresponder.cpp b/src/blockresponder.cpp new file mode 100644 index 00000000..7710fcc6 --- /dev/null +++ b/src/blockresponder.cpp @@ -0,0 +1,69 @@ +/** + * XMPP - libpurple transport + * + * Copyright (C) 2009, Jan Kaluza + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ + +#include "blockresponder.h" + +#include +#include +#include "Swiften/Queries/IQRouter.h" +#include "Swiften/Elements/BlockPayload.h" +#include "Swiften/Swiften.h" +#include "transport/usermanager.h" +#include "transport/user.h" +#include "transport/buddy.h" +#include "transport/rostermanager.h" +#include "log4cxx/logger.h" + +using namespace log4cxx; + +using namespace Swift; +using namespace boost; + +namespace Transport { + +static LoggerPtr logger = Logger::getLogger("BlockResponder"); + +BlockResponder::BlockResponder(Swift::IQRouter *router, UserManager *userManager) : Swift::SetResponder(router) { + m_userManager = userManager; +} + +BlockResponder::~BlockResponder() { + +} + +bool BlockResponder::handleSetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr info) { + User *user = m_userManager->getUser(from.toBare().toString()); + if (!user) { + LOG4CXX_WARN(logger, from.toBare().toString() << ": User is not logged in"); + return true; + } + + Buddy *buddy = user->getRosterManager()->getBuddy(Buddy::JIDToLegacyName(to)); + if (buddy) { + LOG4CXX_WARN(logger, from.toBare().toString() << ": Buddy " << Buddy::JIDToLegacyName(to) << " does not exist"); + return true; + } + + onBlockToggled(buddy); + + return true; +} + +} diff --git a/src/blockresponder.h b/src/blockresponder.h new file mode 100644 index 00000000..37ecbd4e --- /dev/null +++ b/src/blockresponder.h @@ -0,0 +1,46 @@ +/** + * libtransport -- C++ library for easy XMPP Transports development + * + * Copyright (C) 2011, Jan Kaluza + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA + */ + +#pragma once + +#include +#include "Swiften/Swiften.h" +#include "Swiften/Queries/SetResponder.h" +#include "Swiften/Elements/BlockPayload.h" + +namespace Transport { + +class UserManager; +class Buddy; + +class BlockResponder : public Swift::SetResponder { + public: + BlockResponder(Swift::IQRouter *router, UserManager *userManager); + ~BlockResponder(); + + boost::signal onBlockToggled; + + private: + virtual bool handleSetRequest(const Swift::JID& from, const Swift::JID& to, const std::string& id, boost::shared_ptr payload); + + UserManager *m_userManager; +}; + +} \ No newline at end of file diff --git a/src/buddy.cpp b/src/buddy.cpp index 725b969c..b22c4d1b 100644 --- a/src/buddy.cpp +++ b/src/buddy.cpp @@ -22,10 +22,11 @@ #include "transport/rostermanager.h" #include "transport/user.h" #include "transport/transport.h" +#include "Swiften/Elements/BlockPayload.h" namespace Transport { -Buddy::Buddy(RosterManager *rosterManager, long id) : m_id(id), m_online(false), m_subscription("ask"), m_flags(BUDDY_NO_FLAG), m_rosterManager(rosterManager){ +Buddy::Buddy(RosterManager *rosterManager, long id) : m_id(id), m_online(false), m_blocked(false), m_subscription("ask"), m_flags(BUDDY_NO_FLAG), m_rosterManager(rosterManager){ // m_rosterManager->setBuddy(this); } @@ -112,6 +113,9 @@ Swift::Presence::ref Buddy::generatePresenceStanza(int features, bool only_new) // if (features & 0/*TRANSPORT_FEATURE_AVATARS*/) { presence->addPayload(boost::shared_ptr(new Swift::VCardUpdate (getIconHash()))); // } + if (m_blocked) { + presence->addPayload(boost::shared_ptr(new Swift::BlockPayload ())); + } } if (only_new) { diff --git a/src/networkplugin.cpp b/src/networkplugin.cpp index cddd7a4b..12abf827 100644 --- a/src/networkplugin.cpp +++ b/src/networkplugin.cpp @@ -130,7 +130,7 @@ void NetworkPlugin::handleSubject(const std::string &user, const std::string &le } void NetworkPlugin::handleBuddyChanged(const std::string &user, const std::string &buddyName, const std::string &alias, - const std::string &groups, int status, const std::string &statusMessage, const std::string &iconHash) { + const std::string &groups, int status, const std::string &statusMessage, const std::string &iconHash, bool blocked) { pbnetwork::Buddy buddy; buddy.set_username(user); buddy.set_buddyname(buddyName); @@ -139,6 +139,7 @@ void NetworkPlugin::handleBuddyChanged(const std::string &user, const std::strin buddy.set_status(status); buddy.set_statusmessage(statusMessage); buddy.set_iconhash(iconHash); + buddy.set_blocked(blocked); std::string message; buddy.SerializeToString(&message); @@ -373,8 +374,12 @@ void NetworkPlugin::handleBuddyChangedPayload(const std::string &data) { // TODO: ERROR return; } - - handleBuddyUpdatedRequest(payload.username(), payload.buddyname(), payload.alias(), payload.groups()); + if (payload.has_blocked()) { + handleBuddyBlockToggled(payload.username(), payload.buddyname(), payload.blocked()); + } + else { + handleBuddyUpdatedRequest(payload.username(), payload.buddyname(), payload.alias(), payload.groups()); + } } void NetworkPlugin::handleBuddyRemovedPayload(const std::string &data) { diff --git a/src/networkpluginserver.cpp b/src/networkpluginserver.cpp index d39d6b99..0c032f18 100644 --- a/src/networkpluginserver.cpp +++ b/src/networkpluginserver.cpp @@ -30,6 +30,7 @@ #include "transport/conversation.h" #include "transport/vcardresponder.h" #include "transport/rosterresponder.h" +#include "blockresponder.h" #include "Swiften/Swiften.h" #include "Swiften/Server/ServerStanzaChannel.h" #include "Swiften/Elements/StreamError.h" @@ -130,6 +131,7 @@ static void handleBuddyPayload(LocalBuddy *buddy, const pbnetwork::Buddy &payloa buddy->setGroups(groups); buddy->setStatus(Swift::StatusShow((Swift::StatusShow::Type) payload.status()), payload.statusmessage()); buddy->setIconHash(payload.iconhash()); + buddy->setBlocked(payload.blocked()); } NetworkPluginServer::NetworkPluginServer(Component *component, Config *config, UserManager *userManager) { @@ -155,6 +157,10 @@ NetworkPluginServer::NetworkPluginServer(Component *component, Config *config, U m_rosterResponder->onBuddyUpdated.connect(boost::bind(&NetworkPluginServer::handleBuddyUpdated, this, _1, _2)); m_rosterResponder->start(); + m_blockResponder = new BlockResponder(component->getIQRouter(), userManager); + m_blockResponder->onBlockToggled.connect(boost::bind(&NetworkPluginServer::handleBlockToggled, this, _1)); + m_blockResponder->start(); + m_server = Swift::BoostConnectionServer::create(Swift::HostAddress(CONFIG_STRING(m_config, "service.backend_host")), boost::lexical_cast(CONFIG_STRING(m_config, "service.backend_port")), component->getNetworkFactories()->getIOServiceThread()->getIOService(), component->m_loop); m_server->onNewConnection.connect(boost::bind(&NetworkPluginServer::handleNewClientConnection, this, _1)); m_server->start(); @@ -173,6 +179,7 @@ NetworkPluginServer::~NetworkPluginServer() { delete m_component->m_factory; delete m_vcardResponder; delete m_rosterResponder; + delete m_blockResponder; } void NetworkPluginServer::handleNewClientConnection(boost::shared_ptr c) { @@ -857,6 +864,30 @@ void NetworkPluginServer::handleBuddyAdded(Buddy *buddy, const Swift::RosterItem handleBuddyUpdated(buddy, item); } +void NetworkPluginServer::handleBlockToggled(Buddy *b) { + User *user = b->getRosterManager()->getUser(); + + pbnetwork::Buddy buddy; + buddy.set_username(user->getJID().toBare()); + buddy.set_buddyname(b->getName()); + buddy.set_alias(b->getAlias()); + buddy.set_groups(b->getGroups().size() == 0 ? "" : b->getGroups()[0]); + buddy.set_status(Swift::StatusShow::None); + buddy.set_blocked(not b->isBlocked()); + + std::string message; + buddy.SerializeToString(&message); + + WRAP(message, pbnetwork::WrapperMessage_Type_TYPE_BUDDY_CHANGED); + + Backend *c = (Backend *) user->getData(); + if (!c) { + return; + } + send(c->connection, message); +} + + void NetworkPluginServer::handleVCardUpdated(User *user, boost::shared_ptr v) { pbnetwork::VCard vcard; vcard.set_username(user->getJID().toBare()); diff --git a/src/pbnetwork.proto b/src/pbnetwork.proto index 77e95303..1f1ef413 100644 --- a/src/pbnetwork.proto +++ b/src/pbnetwork.proto @@ -30,6 +30,7 @@ message Buddy { optional int32 status = 5; optional string statusMessage = 6; optional string iconHash = 7; + optional bool blocked = 8; } message ConversationMessage { diff --git a/src/transport.cpp b/src/transport.cpp index 2cb8042b..b752b7bd 100644 --- a/src/transport.cpp +++ b/src/transport.cpp @@ -33,6 +33,8 @@ #include "Swiften/Serializer/PayloadSerializers/AttentionSerializer.h" #include "Swiften/Parser/PayloadParsers/XHTMLIMParser.h" #include "Swiften/Serializer/PayloadSerializers/XHTMLIMSerializer.h" +#include "Swiften/Parser/PayloadParsers/BlockParser.h" +#include "Swiften/Serializer/PayloadSerializers/BlockSerializer.h" #include "log4cxx/logger.h" #include "log4cxx/consoleappender.h" #include "log4cxx/patternlayout.h" @@ -90,9 +92,11 @@ Component::Component(Swift::EventLoop *loop, Config *config, Factory *factory, T m_server->addPayloadParserFactory(new GenericPayloadParserFactory("private", "jabber:iq:private")); m_server->addPayloadParserFactory(new GenericPayloadParserFactory("attention", "urn:xmpp:attention:0")); m_server->addPayloadParserFactory(new GenericPayloadParserFactory("html", "http://jabber.org/protocol/xhtml-im")); + m_server->addPayloadParserFactory(new GenericPayloadParserFactory("block", "urn:xmpp:block:0")); m_server->addPayloadSerializer(new Swift::AttentionSerializer()); m_server->addPayloadSerializer(new Swift::XHTMLIMSerializer()); + m_server->addPayloadSerializer(new Swift::BlockSerializer()); m_server->onDataRead.connect(bind(&Component::handleDataRead, this, _1)); m_server->onDataWritten.connect(bind(&Component::handleDataWritten, this, _1));