summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKevin Smith <git@kismith.co.uk>2011-09-21 12:25:27 (GMT)
committerKevin Smith <git@kismith.co.uk>2011-09-23 16:47:57 (GMT)
commitf9c432ca127d6e7d87b49d2fbf6aace34bea0e06 (patch)
treed7f069d3c48cc3d768e770df614fe87ade6f3902 /Swiften
parent20d3385909a2f9d886e7e0781357b23474e9f8dc (diff)
downloadswift-contrib-f9c432ca127d6e7d87b49d2fbf6aace34bea0e06.zip
swift-contrib-f9c432ca127d6e7d87b49d2fbf6aace34bea0e06.tar.bz2
Add support for kicking people from MUCs.
This also introduces a new DOM-like parser structure, used for the MUC parsers. Partially Resolves: #689
Diffstat (limited to 'Swiften')
-rw-r--r--Swiften/Elements/MUCAdminPayload.h35
-rw-r--r--Swiften/Elements/MUCItem.h21
-rw-r--r--Swiften/Elements/MUCUserPayload.h15
-rw-r--r--Swiften/MUC/MUC.cpp22
-rw-r--r--Swiften/MUC/MUC.h4
-rw-r--r--Swiften/Parser/GenericPayloadTreeParser.cpp8
-rw-r--r--Swiften/Parser/GenericPayloadTreeParser.h58
-rw-r--r--Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp2
-rw-r--r--Swiften/Parser/PayloadParsers/MUCAdminPayloadParser.cpp23
-rw-r--r--Swiften/Parser/PayloadParsers/MUCAdminPayloadParser.h20
-rw-r--r--Swiften/Parser/PayloadParsers/MUCItemParser.cpp82
-rw-r--r--Swiften/Parser/PayloadParsers/MUCItemParser.h20
-rw-r--r--Swiften/Parser/PayloadParsers/MUCUserPayloadParser.cpp87
-rw-r--r--Swiften/Parser/PayloadParsers/MUCUserPayloadParser.h19
-rw-r--r--Swiften/Parser/PayloadParsers/UnitTest/MUCAdminPayloadParserTest.cpp41
-rw-r--r--Swiften/Parser/SConscript4
-rw-r--r--Swiften/Parser/Tree/NullParserElement.h19
-rw-r--r--Swiften/Parser/Tree/ParserElement.cpp72
-rw-r--r--Swiften/Parser/Tree/ParserElement.h41
-rw-r--r--Swiften/Parser/UnitTest/GenericPayloadTreeParserTest.cpp58
-rw-r--r--Swiften/SConscript4
-rw-r--r--Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.cpp2
-rw-r--r--Swiften/Serializer/PayloadSerializers/MUCAdminPayloadSerializer.cpp34
-rw-r--r--Swiften/Serializer/PayloadSerializers/MUCAdminPayloadSerializer.h22
-rw-r--r--Swiften/Serializer/PayloadSerializers/MUCItemSerializer.h69
-rw-r--r--Swiften/Serializer/PayloadSerializers/MUCUserPayloadSerializer.cpp39
-rw-r--r--Swiften/Serializer/PayloadSerializers/MUCUserPayloadSerializer.h2
-rw-r--r--Swiften/Serializer/PayloadSerializers/UnitTest/MUCAdminPayloadSerializerTest.cpp39
28 files changed, 721 insertions, 141 deletions
diff --git a/Swiften/Elements/MUCAdminPayload.h b/Swiften/Elements/MUCAdminPayload.h
new file mode 100644
index 0000000..7b3da20
--- /dev/null
+++ b/Swiften/Elements/MUCAdminPayload.h
@@ -0,0 +1,35 @@
+/*
+ * Copyright (c) 2010 Kevin Smith
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#pragma once
+
+#include <boost/optional.hpp>
+#include <boost/shared_ptr.hpp>
+#include <string>
+#include <vector>
+
+#include <Swiften/JID/JID.h>
+#include <Swiften/Elements/Payload.h>
+#include <Swiften/Elements/MUCOccupant.h>
+#include <Swiften/Elements/MUCItem.h>
+
+namespace Swift {
+ class MUCAdminPayload : public Payload {
+ public:
+ typedef boost::shared_ptr<MUCAdminPayload> ref;
+
+
+ MUCAdminPayload() {
+ }
+
+ void addItem(MUCItem item) {items_.push_back(item);}
+
+ const std::vector<MUCItem>& getItems() const {return items_;}
+
+ private:
+ std::vector<MUCItem> items_;
+ };
+}
diff --git a/Swiften/Elements/MUCItem.h b/Swiften/Elements/MUCItem.h
new file mode 100644
index 0000000..86217ec
--- /dev/null
+++ b/Swiften/Elements/MUCItem.h
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2011 Kevin Smith
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#pragma once
+
+#include <Swiften/Elements/MUCOccupant.h>
+#include <Swiften/JID/JID.h>
+namespace Swift {
+struct MUCItem {
+ MUCItem() {}
+ boost::optional<JID> realJID;
+ boost::optional<std::string> nick;
+ boost::optional<MUCOccupant::Affiliation> affiliation;
+ boost::optional<MUCOccupant::Role> role;
+ boost::optional<JID> actor;
+ boost::optional<std::string> reason;
+};
+}
diff --git a/Swiften/Elements/MUCUserPayload.h b/Swiften/Elements/MUCUserPayload.h
index 0276964..de9f1e5 100644
--- a/Swiften/Elements/MUCUserPayload.h
+++ b/Swiften/Elements/MUCUserPayload.h
@@ -8,32 +8,25 @@
#include <boost/optional.hpp>
#include <boost/shared_ptr.hpp>
#include <string>
#include <vector>
#include <Swiften/JID/JID.h>
#include <Swiften/Elements/Payload.h>
#include <Swiften/Elements/MUCOccupant.h>
+#include <Swiften/Elements/MUCItem.h>
namespace Swift {
class MUCUserPayload : public Payload {
public:
typedef boost::shared_ptr<MUCUserPayload> ref;
- struct Item {
- Item(MUCOccupant::Affiliation affiliation = MUCOccupant::NoAffiliation, MUCOccupant::Role role = MUCOccupant::NoRole) : affiliation(affiliation), role(role) {}
- boost::optional<JID> realJID;
- boost::optional<std::string> nick;
- MUCOccupant::Affiliation affiliation;
- MUCOccupant::Role role;
- };
-
struct StatusCode {
StatusCode() : code(0) {}
int code;
};
// struct Password {
// }
@@ -42,22 +35,22 @@ namespace Swift {
// }
// struct Invite {
// }
MUCUserPayload() {
}
- void addItem(Item item) {items_.push_back(item);}
+ void addItem(MUCItem item) {items_.push_back(item);}
void addStatusCode(StatusCode code) {statusCodes_.push_back(code);}
- const std::vector<Item>& getItems() const {return items_;}
+ const std::vector<MUCItem>& getItems() const {return items_;}
const std::vector<StatusCode>& getStatusCodes() const {return statusCodes_;}
private:
- std::vector<Item> items_;
+ std::vector<MUCItem> items_;
std::vector<StatusCode> statusCodes_;
};
}
diff --git a/Swiften/MUC/MUC.cpp b/Swiften/MUC/MUC.cpp
index 1ade7e3..4b3960f 100644
--- a/Swiften/MUC/MUC.cpp
+++ b/Swiften/MUC/MUC.cpp
@@ -11,18 +11,19 @@
#include <boost/smart_ptr/make_shared.hpp>
#include <Swiften/Base/foreach.h>
#include <Swiften/Presence/DirectedPresenceSender.h>
#include <Swiften/Client/StanzaChannel.h>
#include <Swiften/Queries/IQRouter.h>
#include <Swiften/Elements/Form.h>
#include <Swiften/Elements/IQ.h>
#include <Swiften/Elements/MUCUserPayload.h>
+#include <Swiften/Elements/MUCAdminPayload.h>
#include <Swiften/Elements/MUCPayload.h>
#include <Swiften/MUC/MUCRegistry.h>
#include <Swiften/Queries/GenericRequest.h>
namespace Swift {
typedef std::pair<std::string, MUCOccupant> StringMUCOccupantPair;
MUC::MUC(StanzaChannel* stanzaChannel, IQRouter* iqRouter, DirectedPresenceSender* presenceSender, const JID &muc, MUCRegistry* mucRegistry) : ownMUCJID(muc), stanzaChannel(stanzaChannel), iqRouter_(iqRouter), presenceSender(presenceSender), mucRegistry(mucRegistry) {
@@ -115,20 +116,20 @@ void MUC::handleIncomingPresence(Presence::ref presence) {
std::string nick = presence->getFrom().getResource();
if (nick.empty()) {
return;
}
MUCOccupant::Role role(MUCOccupant::NoRole);
MUCOccupant::Affiliation affiliation(MUCOccupant::NoAffiliation);
boost::optional<JID> realJID;
if (mucPayload && mucPayload->getItems().size() > 0) {
- role = mucPayload->getItems()[0].role;
- affiliation = mucPayload->getItems()[0].affiliation;
+ role = mucPayload->getItems()[0].role ? mucPayload->getItems()[0].role.get() : MUCOccupant::NoRole;
+ affiliation = mucPayload->getItems()[0].affiliation ? mucPayload->getItems()[0].affiliation.get() : MUCOccupant::NoAffiliation;
realJID = mucPayload->getItems()[0].realJID;
}
//100 is non-anonymous
//TODO: 100 may also be specified in a <message/>
//170 is room logging to http
//TODO: Nick changes
if (presence->getType() == Presence::Unavailable) {
if (presence->getFrom() == ownMUCJID) {
@@ -211,18 +212,35 @@ void MUC::handleCreationConfigResponse(MUCOwnerPayload::ref /*unused*/, ErrorPay
bool MUC::hasOccupant(const std::string& nick) {
return occupants.find(nick) != occupants.end();
}
MUCOccupant MUC::getOccupant(const std::string& nick) {
return occupants.find(nick)->second;
}
+void MUC::kickUser(const JID& jid) {
+ MUCAdminPayload::ref mucPayload = boost::make_shared<MUCAdminPayload>();
+ MUCItem item;
+ item.role = MUCOccupant::NoRole;
+ item.nick = jid.getResource();
+ mucPayload->addItem(item);
+ GenericRequest<MUCAdminPayload>* request = new GenericRequest<MUCAdminPayload>(IQ::Set, getJID(), mucPayload, iqRouter_);
+ request->onResponse.connect(boost::bind(&MUC::handleKickResponse, this, _1, _2, jid));
+ request->send();
+}
+
+void MUC::handleKickResponse(MUCAdminPayload::ref /*unused*/, ErrorPayload::ref error, const JID& jid) {
+ if (error) {
+ onKickFailed(error, jid);
+ }
+}
+
//FIXME: Recognise Topic changes
//TODO: Invites(direct/mediated)
//TODO: requesting membership
//TODO: get member list
//TODO: request voice
diff --git a/Swiften/MUC/MUC.h b/Swiften/MUC/MUC.h
index 828a36f..41dbc4a 100644
--- a/Swiften/MUC/MUC.h
+++ b/Swiften/MUC/MUC.h
@@ -7,18 +7,19 @@
#pragma once
#include <Swiften/JID/JID.h>
#include <string>
#include <Swiften/Elements/Message.h>
#include <Swiften/Elements/Presence.h>
#include <Swiften/Elements/MUCOccupant.h>
#include <Swiften/MUC/MUCRegistry.h>
#include <Swiften/Elements/MUCOwnerPayload.h>
+#include <Swiften/Elements/MUCAdminPayload.h>
#include <boost/shared_ptr.hpp>
#include <Swiften/Base/boost_bsignals.h>
#include <boost/signals/connection.hpp>
#include <map>
namespace Swift {
class StanzaChannel;
@@ -48,21 +49,23 @@ namespace Swift {
/*void queryRoomItems(); */
std::string getCurrentNick();
void part();
void handleIncomingMessage(Message::ref message);
/** Expose public so it can be called when e.g. user goes offline */
void handleUserLeft(LeavingType);
/** Get occupant information*/
MUCOccupant getOccupant(const std::string& nick);
bool hasOccupant(const std::string& nick);
+ void kickUser(const JID& jid);
public:
boost::signal<void (const std::string& /*nick*/)> onJoinComplete;
boost::signal<void (ErrorPayload::ref)> onJoinFailed;
+ boost::signal<void (ErrorPayload::ref, const JID&)> onKickFailed;
boost::signal<void (Presence::ref)> onOccupantPresenceChange;
boost::signal<void (const std::string&, const MUCOccupant& /*now*/, const MUCOccupant::Role& /*old*/)> onOccupantRoleChanged;
boost::signal<void (const std::string&, const MUCOccupant::Affiliation& /*new*/, const MUCOccupant::Affiliation& /*old*/)> onOccupantAffiliationChanged;
boost::signal<void (const MUCOccupant&)> onOccupantJoined;
boost::signal<void (const MUCOccupant&, LeavingType, const std::string& /*reason*/)> onOccupantLeft;
/* boost::signal<void (const MUCInfo&)> onInfoResult; */
/* boost::signal<void (const blah&)> onItemsResult; */
@@ -73,18 +76,19 @@ namespace Swift {
const std::string& getOwnNick() const {
return ownMUCJID.getResource();
}
private:
void handleIncomingPresence(Presence::ref presence);
void internalJoin(const std::string& nick);
void handleCreationConfigResponse(MUCOwnerPayload::ref, ErrorPayload::ref);
+ void handleKickResponse(MUCAdminPayload::ref, ErrorPayload::ref, const JID&);
private:
JID ownMUCJID;
StanzaChannel* stanzaChannel;
IQRouter* iqRouter_;
DirectedPresenceSender* presenceSender;
MUCRegistry* mucRegistry;
std::map<std::string, MUCOccupant> occupants;
bool joinSucceeded_;
diff --git a/Swiften/Parser/GenericPayloadTreeParser.cpp b/Swiften/Parser/GenericPayloadTreeParser.cpp
new file mode 100644
index 0000000..0e25cbc
--- /dev/null
+++ b/Swiften/Parser/GenericPayloadTreeParser.cpp
@@ -0,0 +1,8 @@
+/*
+ * Copyright (c) 2011 Kevin Smith
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <Swiften/Parser/GenericPayloadTreeParser.h>
+
diff --git a/Swiften/Parser/GenericPayloadTreeParser.h b/Swiften/Parser/GenericPayloadTreeParser.h
new file mode 100644
index 0000000..0030af7
--- /dev/null
+++ b/Swiften/Parser/GenericPayloadTreeParser.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2011 Kevin Smith
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#pragma once
+
+#include <deque>
+
+#include <boost/shared_ptr.hpp>
+#include <boost/smart_ptr/make_shared.hpp>
+
+#include <Swiften/Parser/GenericPayloadParser.h>
+#include <Swiften/Parser/Tree/ParserElement.h>
+#include <Swiften/Parser/Tree/NullParserElement.h>
+
+#include <iostream>
+
+namespace Swift {
+
+
+ /**
+ * Generic parser offering something a bit like a DOM to work with.
+ */
+ template<typename PAYLOAD_TYPE>
+ class GenericPayloadTreeParser : public GenericPayloadParser<PAYLOAD_TYPE> {
+ public:
+ virtual void handleStartElement(const std::string& element, const std::string& xmlns, const AttributeMap& attributes) {
+ //std::cerr << element << ", " << xmlns << ", " << attributes.getEntries().size();
+ if (!root_) {
+ root_ = boost::make_shared<ParserElement>(element, xmlns, attributes);
+ elementStack_.push_back(root_);
+ } else {
+ ParserElement::ref current = *elementStack_.rbegin();
+ elementStack_.push_back(current->addChild(element, xmlns, attributes));
+ }
+ }
+
+ virtual void handleEndElement(const std::string& /*element*/, const std::string&) {
+ elementStack_.pop_back();
+ if (elementStack_.empty()) {
+ handleTree(root_);
+ }
+ }
+
+ virtual void handleCharacterData(const std::string& data) {
+ ParserElement::ref current = *elementStack_.rbegin();
+ current->appendCharacterData(data);
+ }
+
+ virtual void handleTree(ParserElement::ref root) = 0;
+
+ private:
+ std::deque<ParserElement::ref> elementStack_;
+ ParserElement::ref root_;
+ };
+}
diff --git a/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp b/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp
index e9c49ee..1b59f6f 100644
--- a/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp
+++ b/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp
@@ -38,18 +38,19 @@
#include <Swiften/Parser/PayloadParsers/StreamInitiationParserFactory.h>
#include <Swiften/Parser/PayloadParsers/BytestreamsParserFactory.h>
#include <Swiften/Parser/PayloadParsers/IBBParser.h>
#include <Swiften/Parser/PayloadParsers/VCardUpdateParserFactory.h>
#include <Swiften/Parser/PayloadParsers/VCardParserFactory.h>
#include <Swiften/Parser/PayloadParsers/RawXMLPayloadParserFactory.h>
#include <Swiften/Parser/PayloadParsers/PrivateStorageParserFactory.h>
#include <Swiften/Parser/PayloadParsers/DelayParser.h>
#include <Swiften/Parser/PayloadParsers/MUCUserPayloadParserFactory.h>
+#include <Swiften/Parser/PayloadParsers/MUCAdminPayloadParser.h>
#include <Swiften/Parser/PayloadParsers/NicknameParserFactory.h>
#include <Swiften/Parser/PayloadParsers/ReplaceParser.h>
#include <Swiften/Parser/PayloadParsers/LastParser.h>
using namespace boost;
namespace Swift {
FullPayloadParserFactoryCollection::FullPayloadParserFactoryCollection() {
@@ -82,18 +83,19 @@ FullPayloadParserFactoryCollection::FullPayloadParserFactoryCollection() {
factories_.push_back(shared_ptr<PayloadParserFactory>(new InBandRegistrationPayloadParserFactory()));
factories_.push_back(shared_ptr<PayloadParserFactory>(new SearchPayloadParserFactory()));
factories_.push_back(shared_ptr<PayloadParserFactory>(new StreamInitiationParserFactory()));
factories_.push_back(shared_ptr<PayloadParserFactory>(new BytestreamsParserFactory()));
factories_.push_back(shared_ptr<PayloadParserFactory>(new VCardUpdateParserFactory()));
factories_.push_back(shared_ptr<PayloadParserFactory>(new VCardParserFactory()));
factories_.push_back(shared_ptr<PayloadParserFactory>(new PrivateStorageParserFactory(this)));
factories_.push_back(shared_ptr<PayloadParserFactory>(new ChatStateParserFactory()));
factories_.push_back(shared_ptr<PayloadParserFactory>(new MUCUserPayloadParserFactory()));
+ factories_.push_back(shared_ptr<PayloadParserFactory>(new GenericPayloadParserFactory<MUCAdminPayloadParser>("query", "http://jabber.org/protocol/muc#admin")));
factories_.push_back(shared_ptr<PayloadParserFactory>(new NicknameParserFactory()));
foreach(shared_ptr<PayloadParserFactory> factory, factories_) {
addFactory(factory.get());
}
defaultFactory_ = new RawXMLPayloadParserFactory();
setDefaultFactory(defaultFactory_);
}
FullPayloadParserFactoryCollection::~FullPayloadParserFactoryCollection() {
diff --git a/Swiften/Parser/PayloadParsers/MUCAdminPayloadParser.cpp b/Swiften/Parser/PayloadParsers/MUCAdminPayloadParser.cpp
new file mode 100644
index 0000000..137ead4
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/MUCAdminPayloadParser.cpp
@@ -0,0 +1,23 @@
+/*
+ * Copyright (c) 2011 Kevin Smith
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <Swiften/Parser/PayloadParsers/MUCAdminPayloadParser.h>
+
+#include <boost/lexical_cast.hpp>
+
+#include <Swiften/Base/foreach.h>
+#include <Swiften/Elements/MUCOccupant.h>
+
+namespace Swift {
+
+void MUCAdminPayloadParser::handleTree(ParserElement::ref root) {
+ foreach (ParserElement::ref itemElement, root->getChildren("item", "http://jabber.org/protocol/muc#admin")) {
+ MUCItem item = MUCItemParser::itemFromTree(itemElement);
+ getPayloadInternal()->addItem(item);
+ }
+}
+
+}
diff --git a/Swiften/Parser/PayloadParsers/MUCAdminPayloadParser.h b/Swiften/Parser/PayloadParsers/MUCAdminPayloadParser.h
new file mode 100644
index 0000000..dfa26da
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/MUCAdminPayloadParser.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2011 Kevin Smith
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#pragma once
+
+#include <boost/optional.hpp>
+
+#include <Swiften/Elements/MUCAdminPayload.h>
+#include <Swiften/Parser/GenericPayloadTreeParser.h>
+#include <Swiften/Parser/PayloadParsers/MUCItemParser.h>
+
+namespace Swift {
+ class MUCAdminPayloadParser : public GenericPayloadTreeParser<MUCAdminPayload> {
+ public:
+ virtual void handleTree(ParserElement::ref root);
+ };
+}
diff --git a/Swiften/Parser/PayloadParsers/MUCItemParser.cpp b/Swiften/Parser/PayloadParsers/MUCItemParser.cpp
new file mode 100644
index 0000000..2eb9997
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/MUCItemParser.cpp
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2011 Kevin Smith
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <Swiften/Parser/PayloadParsers/MUCItemParser.h>
+
+#include <boost/lexical_cast.hpp>
+
+#include <Swiften/Elements/MUCOccupant.h>
+
+#include <cassert>
+#include <iostream>
+
+namespace Swift {
+
+MUCItem MUCItemParser::itemFromTree(ParserElement::ref root) {
+ MUCItem item;
+ std::string affiliation = root->getAttributes().getAttribute("affiliation");
+ std::string role = root->getAttributes().getAttribute("role");
+ std::string nick = root->getAttributes().getAttribute("nick");
+ std::string jid = root->getAttributes().getAttribute("jid");
+ item.affiliation = parseAffiliation(affiliation);
+ item.role = parseRole(role);
+ if (!jid.empty()) {
+ item.realJID = JID(jid);
+ }
+ if (!nick.empty()) {
+ item.nick = nick;
+ }
+ std::string xmlns = root->getNamespace();
+ std::string reason = root->getChild("reason", xmlns)->getText();
+ std::string actor = root->getChild("actor", xmlns)->getAttributes().getAttribute("jid");
+ if (!reason.empty()) {
+ item.reason = reason;
+ }
+ if (!actor.empty()) {
+ item.actor = JID(actor);
+ }
+
+ return item;
+}
+
+boost::optional<MUCOccupant::Role> MUCItemParser::parseRole(const std::string& roleString) {
+ if (roleString == "moderator") {
+ return MUCOccupant::Moderator;
+ }
+ if (roleString == "participant") {
+ return MUCOccupant::Participant;
+ }
+ if (roleString == "visitor") {
+ return MUCOccupant::Visitor;
+ }
+ if (roleString == "none") {
+ return MUCOccupant::NoRole;
+ }
+ return boost::optional<MUCOccupant::Role>();
+}
+
+boost::optional<MUCOccupant::Affiliation> MUCItemParser::parseAffiliation(const std::string& affiliationString) {
+ if (affiliationString == "owner") {
+ return MUCOccupant::Owner;
+ }
+ if (affiliationString == "admin") {
+ return MUCOccupant::Admin;
+ }
+ if (affiliationString == "member") {
+ return MUCOccupant::Member;
+ }
+ if (affiliationString == "outcast") {
+ return MUCOccupant::Outcast;
+ }
+ if (affiliationString == "none") {
+ return MUCOccupant::NoAffiliation;
+ }
+ return boost::optional<MUCOccupant::Affiliation>();
+}
+
+}
+
+
diff --git a/Swiften/Parser/PayloadParsers/MUCItemParser.h b/Swiften/Parser/PayloadParsers/MUCItemParser.h
new file mode 100644
index 0000000..a0ea060
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/MUCItemParser.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (c) 2011 Kevin Smith
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#pragma once
+
+#include <Swiften/Elements/MUCItem.h>
+#include <Swiften/Parser/GenericPayloadTreeParser.h>
+
+namespace Swift {
+ class MUCItemParser {
+ public:
+ static MUCItem itemFromTree(ParserElement::ref root);
+ private:
+ static boost::optional<MUCOccupant::Role> parseRole(const std::string& itemString);
+ static boost::optional<MUCOccupant::Affiliation> parseAffiliation(const std::string& statusString);
+ };
+}
diff --git a/Swiften/Parser/PayloadParsers/MUCUserPayloadParser.cpp b/Swiften/Parser/PayloadParsers/MUCUserPayloadParser.cpp
index bd81b88..71ae571 100644
--- a/Swiften/Parser/PayloadParsers/MUCUserPayloadParser.cpp
+++ b/Swiften/Parser/PayloadParsers/MUCUserPayloadParser.cpp
@@ -2,93 +2,30 @@
* Copyright (c) 2010 Kevin Smith
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#include <Swiften/Parser/PayloadParsers/MUCUserPayloadParser.h>
#include <boost/lexical_cast.hpp>
+#include <Swiften/Base/foreach.h>
#include <Swiften/Elements/MUCOccupant.h>
-#include <cassert>
-#include <iostream>
-
namespace Swift {
-MUCUserPayloadParser::MUCUserPayloadParser() : level(TopLevel) {
-}
-
-void MUCUserPayloadParser::handleStartElement(const std::string& element, const std::string&, const AttributeMap& attributes) {
- if (level == ItemLevel) {
- if (element == "item") {
- MUCUserPayload::Item item;
- std::string affiliation = attributes.getAttribute("affiliation");
- std::string role = attributes.getAttribute("role");
- std::string nick = attributes.getAttribute("nick");
- std::string jid = attributes.getAttribute("jid");
- item.affiliation = parseAffiliation(affiliation);
- item.role = parseRole(role);
- if (!jid.empty()) {
- item.realJID = JID(jid);
- }
- if (!nick.empty()) {
- item.nick = nick;
- }
- getPayloadInternal()->addItem(item);
- } else if (element == "status") {
- MUCUserPayload::StatusCode status;
- try {
- status.code = boost::lexical_cast<int>(attributes.getAttribute("code").c_str());
- getPayloadInternal()->addStatusCode(status);
- } catch (boost::bad_lexical_cast&) {
- }
+void MUCUserPayloadParser::handleTree(ParserElement::ref root) {
+ foreach (ParserElement::ref itemElement, root->getChildren("item", "http://jabber.org/protocol/muc#user")) {
+ MUCItem item = MUCItemParser::itemFromTree(itemElement);
+ getPayloadInternal()->addItem(item);
+ }
+ foreach (ParserElement::ref statusElement, root->getChildren("item", "http://jabber.org/protocol/muc#user")) {
+ MUCUserPayload::StatusCode status;
+ try {
+ status.code = boost::lexical_cast<int>(statusElement->getAttributes().getAttribute("code").c_str());
+ getPayloadInternal()->addStatusCode(status);
+ } catch (boost::bad_lexical_cast&) {
}
}
- ++level;
-}
-
-MUCOccupant::Role MUCUserPayloadParser::parseRole(const std::string& roleString) const {
- if (roleString == "moderator") {
- return MUCOccupant::Moderator;
- }
- if (roleString == "participant") {
- return MUCOccupant::Participant;
- }
- if (roleString == "visitor") {
- return MUCOccupant::Visitor;
- }
- if (roleString == "none") {
- return MUCOccupant::NoRole;
- }
- return MUCOccupant::NoRole;
-}
-
-MUCOccupant::Affiliation MUCUserPayloadParser::parseAffiliation(const std::string& affiliationString) const {
- if (affiliationString == "owner") {
- return MUCOccupant::Owner;
- }
- if (affiliationString == "admin") {
- return MUCOccupant::Admin;
- }
- if (affiliationString == "member") {
- return MUCOccupant::Member;
- }
- if (affiliationString == "outcast") {
- return MUCOccupant::Outcast;
- }
- if (affiliationString == "none") {
- return MUCOccupant::NoAffiliation;
- }
- return MUCOccupant::NoAffiliation;
-}
-
-
-void MUCUserPayloadParser::handleEndElement(const std::string& /*element*/, const std::string&) {
- --level;
-}
-
-void MUCUserPayloadParser::handleCharacterData(const std::string& /*data*/) {
-
}
}
diff --git a/Swiften/Parser/PayloadParsers/MUCUserPayloadParser.h b/Swiften/Parser/PayloadParsers/MUCUserPayloadParser.h
index b819905..e020127 100644
--- a/Swiften/Parser/PayloadParsers/MUCUserPayloadParser.h
+++ b/Swiften/Parser/PayloadParsers/MUCUserPayloadParser.h
@@ -3,29 +3,18 @@
* Licensed under the GNU General Public License v3.
* See Documentation/Licenses/GPLv3.txt for more information.
*/
#pragma once
#include <boost/optional.hpp>
#include <Swiften/Elements/MUCUserPayload.h>
-#include <Swiften/Parser/GenericPayloadParser.h>
+#include <Swiften/Parser/GenericPayloadTreeParser.h>
+#include <Swiften/Parser/PayloadParsers/MUCItemParser.h>
namespace Swift {
- class MUCUserPayloadParser : public GenericPayloadParser<MUCUserPayload> {
+ class MUCUserPayloadParser : public GenericPayloadTreeParser<MUCUserPayload> {
public:
- MUCUserPayloadParser();
-
- 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);
- MUCOccupant::Role parseRole(const std::string& itemString) const;
- MUCOccupant::Affiliation parseAffiliation(const std::string& statusString) const;
- private:
- enum Level {
- TopLevel = 0,
- ItemLevel = 1
- };
- int level;
+ virtual void handleTree(ParserElement::ref root);
};
}
diff --git a/Swiften/Parser/PayloadParsers/UnitTest/MUCAdminPayloadParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/MUCAdminPayloadParserTest.cpp
new file mode 100644
index 0000000..0648f58
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/UnitTest/MUCAdminPayloadParserTest.cpp
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2011 Kevin Smith
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/extensions/TestFactoryRegistry.h>
+
+#include <Swiften/Parser/PayloadParsers/MUCAdminPayloadParser.h>
+#include <Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h>
+
+using namespace Swift;
+
+class MUCAdminPayloadParserTest : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(MUCAdminPayloadParserTest);
+ CPPUNIT_TEST(testParse);
+ CPPUNIT_TEST_SUITE_END();
+
+ public:
+ MUCAdminPayloadParserTest() {}
+
+ void testParse() {
+ PayloadsParserTester parser;
+
+ CPPUNIT_ASSERT(parser.parse("<query xmlns=\"http://jabber.org/protocol/muc#admin\"><item affiliation=\"owner\" role=\"visitor\"><actor jid=\"kev@tester.lit\"/><reason>malice</reason></item></query>"));
+
+ MUCAdminPayload::ref payload = boost::dynamic_pointer_cast<MUCAdminPayload>(parser.getPayload());
+ MUCItem item = payload->getItems()[0];
+ CPPUNIT_ASSERT_EQUAL(MUCOccupant::Owner, item.affiliation.get());
+ CPPUNIT_ASSERT_EQUAL(MUCOccupant::Visitor, item.role.get());
+ CPPUNIT_ASSERT_EQUAL(JID("kev@tester.lit"), item.actor.get());
+ CPPUNIT_ASSERT_EQUAL(std::string("malice"), item.reason.get());
+ }
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(MUCAdminPayloadParserTest);
+
+
+
diff --git a/Swiften/Parser/SConscript b/Swiften/Parser/SConscript
index 17505f1..b9fcebb 100644
--- a/Swiften/Parser/SConscript
+++ b/Swiften/Parser/SConscript
@@ -8,18 +8,19 @@ myenv.MergeFlags(swiften_env.get("EXPAT_FLAGS", ""))
sources = [
"AttributeMap.cpp",
"AuthRequestParser.cpp",
"AuthChallengeParser.cpp",
"AuthSuccessParser.cpp",
"AuthResponseParser.cpp",
"CompressParser.cpp",
"ElementParser.cpp",
"IQParser.cpp",
+ "GenericPayloadTreeParser.cpp",
"MessageParser.cpp",
"PayloadParser.cpp",
"StanzaAckParser.cpp",
"ComponentHandshakeParser.cpp",
"PayloadParserFactory.cpp",
"PayloadParserFactoryCollection.cpp",
"PayloadParsers/BodyParser.cpp",
"PayloadParsers/SubjectParser.cpp",
"PayloadParsers/ChatStateParser.cpp",
@@ -45,30 +46,33 @@ sources = [
"PayloadParsers/StorageParser.cpp",
"PayloadParsers/StatusParser.cpp",
"PayloadParsers/StatusShowParser.cpp",
"PayloadParsers/StreamInitiationParser.cpp",
"PayloadParsers/BytestreamsParser.cpp",
"PayloadParsers/VCardParser.cpp",
"PayloadParsers/VCardUpdateParser.cpp",
"PayloadParsers/DelayParser.cpp",
"PayloadParsers/MUCUserPayloadParser.cpp",
+ "PayloadParsers/MUCAdminPayloadParser.cpp",
+ "PayloadParsers/MUCItemParser.cpp",
"PayloadParsers/NicknameParser.cpp",
"PayloadParsers/ReplaceParser.cpp",
"PayloadParsers/LastParser.cpp",
"PlatformXMLParserFactory.cpp",
"PresenceParser.cpp",
"SerializingParser.cpp",
"StanzaParser.cpp",
"StreamErrorParser.cpp",
"StreamFeaturesParser.cpp",
"StreamManagementEnabledParser.cpp",
"StreamResumeParser.cpp",
"StreamResumedParser.cpp",
+ "Tree/ParserElement.cpp",
"XMLParser.cpp",
"XMLParserClient.cpp",
"XMLParserFactory.cpp",
"XMPPParser.cpp",
"XMPPParserClient.cpp",
]
if myenv.get("HAVE_EXPAT", 0) :
myenv.Append(CPPDEFINES = "HAVE_EXPAT")
diff --git a/Swiften/Parser/Tree/NullParserElement.h b/Swiften/Parser/Tree/NullParserElement.h
new file mode 100644
index 0000000..93c0662
--- /dev/null
+++ b/Swiften/Parser/Tree/NullParserElement.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2011 Kevin Smith
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#pragma once
+
+#include <string>
+#include <Swiften/Parser/Tree/ParserElement.h>
+
+namespace Swift {
+
+ class NullParserElement : public ParserElement {
+ public:
+ NullParserElement() : ParserElement("", "", AttributeMap()) {}
+ virtual operator bool() {return false;};
+ };
+}
diff --git a/Swiften/Parser/Tree/ParserElement.cpp b/Swiften/Parser/Tree/ParserElement.cpp
new file mode 100644
index 0000000..c851b41
--- /dev/null
+++ b/Swiften/Parser/Tree/ParserElement.cpp
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2011 Kevin Smith
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+
+#include <Swiften/Parser/Tree/ParserElement.h>
+#include <Swiften/Parser/Tree/NullParserElement.h>
+
+#include <iostream>
+
+namespace Swift{
+
+ParserElement::ParserElement(const std::string& name, const std::string& xmlns, const AttributeMap& attributes) : name_(name), xmlns_(xmlns), attributes_(attributes) {
+
+}
+
+ParserElement::~ParserElement() {
+
+}
+
+ParserElement::operator bool() {
+ return true;
+}
+
+ParserElement::ref ParserElement::addChild(const std::string& name, const std::string& xmlns, const AttributeMap& attributes) {
+ ParserElement::ref child = boost::make_shared<ParserElement>(name, xmlns, attributes);
+ children_.push_back(child);
+ return child;
+}
+
+void ParserElement::appendCharacterData(const std::string& data) {
+ text_ += data;
+}
+
+std::string ParserElement::getText() {
+ return text_;
+}
+
+std::string ParserElement::getName() {
+ return name_;
+}
+
+std::string ParserElement::getNamespace() {
+ return xmlns_;
+}
+
+struct DoesntMatch {
+ public:
+ DoesntMatch(const std::string& tagName, const std::string& ns) : tagName(tagName), ns(ns) {}
+ bool operator()(ParserElement::ref element) { return element->getName() != tagName || element->getNamespace() != ns; }
+ private:
+ std::string tagName;
+ std::string ns;
+};
+
+
+std::vector<ParserElement::ref> ParserElement::getChildren(const std::string& name, const std::string& xmlns) {
+ std::vector<ParserElement::ref> result;
+ std::remove_copy_if(children_.begin(), children_.end(), std::back_inserter(result), DoesntMatch(name, xmlns));
+ return result;
+}
+
+ParserElement::ref ParserElement::getChild(const std::string& name, const std::string& xmlns) {
+ std::vector<ParserElement::ref> results = getChildren(name, xmlns);
+ boost::shared_ptr<NullParserElement> nullParser = boost::make_shared<NullParserElement>();
+ ParserElement::ref result = results.empty() ? boost::dynamic_pointer_cast<ParserElement>(nullParser) : results[0];
+ return result;
+}
+
+}
diff --git a/Swiften/Parser/Tree/ParserElement.h b/Swiften/Parser/Tree/ParserElement.h
new file mode 100644
index 0000000..ddf67fa
--- /dev/null
+++ b/Swiften/Parser/Tree/ParserElement.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (c) 2011 Kevin Smith
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+
+#pragma once
+
+#include <string>
+#include <vector>
+#include <Swiften/Base/boost_bsignals.h>
+#include <Swiften/Parser/AttributeMap.h>
+#include <boost/shared_ptr.hpp>
+#include <boost/smart_ptr/make_shared.hpp>
+
+namespace Swift {
+class ParserElement {
+ public:
+ typedef boost::shared_ptr<ParserElement> ref;
+ ParserElement(const std::string& name, const std::string& xmlns, const AttributeMap& attributes);
+ virtual ~ParserElement();
+ virtual operator bool();
+ ParserElement::ref addChild(const std::string& name, const std::string& xmlns, const AttributeMap& attributes);
+ void appendCharacterData(const std::string& data);
+ std::string getText();
+ std::string getName();
+ std::string getNamespace();
+ std::vector<ParserElement::ref> getChildren(const std::string& name, const std::string& xmlns);
+ ParserElement::ref getChild(const std::string& name, const std::string& xmlns);
+ const AttributeMap& getAttributes() const {return attributes_;}
+ private:
+ std::vector<ParserElement::ref> children_;
+ std::string name_;
+ std::string xmlns_;
+ AttributeMap attributes_;
+ std::string text_;
+
+};
+
+}
diff --git a/Swiften/Parser/UnitTest/GenericPayloadTreeParserTest.cpp b/Swiften/Parser/UnitTest/GenericPayloadTreeParserTest.cpp
new file mode 100644
index 0000000..d095afc
--- /dev/null
+++ b/Swiften/Parser/UnitTest/GenericPayloadTreeParserTest.cpp
@@ -0,0 +1,58 @@
+/*
+ * Copyright (c) 2011 Kevin Smith
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/extensions/TestFactoryRegistry.h>
+
+#include <Swiften/Parser/GenericPayloadTreeParser.h>
+#include <Swiften/Parser/PayloadParsers/UnitTest/PayloadParserTester.h>
+#include <Swiften/Elements/RawXMLPayload.h>
+
+using namespace Swift;
+
+class GenericPayloadTreeParserTest : public CppUnit::TestFixture {
+ CPPUNIT_TEST_SUITE(GenericPayloadTreeParserTest);
+ CPPUNIT_TEST(testTree);
+ CPPUNIT_TEST_SUITE_END();
+
+ public:
+ void testTree() {
+ MyParser testling;
+
+ std::string data = "<topLevel xmlns='urn:test:top'><firstLevelInheritedEmpty/><firstLevelInherited><secondLevelMultiChildren num='1'/><secondLevelMultiChildren num='2'/></firstLevelInherited><firstLevelNS xmlns='urn:test:first'/></topLevel>";
+
+ PayloadParserTester tester(&testling);
+ tester.parse(data);
+
+ ParserElement::ref tree = testling.tree;
+
+ CPPUNIT_ASSERT_EQUAL(std::string("topLevel"), tree->getName());
+ CPPUNIT_ASSERT_EQUAL(std::string("urn:test:top"), tree->getNamespace());
+ CPPUNIT_ASSERT(tree->getChild("firstLevelInheritedEmpty", "urn:test:top"));
+ CPPUNIT_ASSERT(!*tree->getChild("firstLevelInheritedEmpty", ""));
+ CPPUNIT_ASSERT(tree->getChild("firstLevelInherited", "urn:test:top"));
+ CPPUNIT_ASSERT_EQUAL(static_cast<size_t>(2), tree->getChild("firstLevelInherited", "urn:test:top")->getChildren("secondLevelMultiChildren", "urn:test:top").size());
+ CPPUNIT_ASSERT_EQUAL(std::string("1"), tree->getChild("firstLevelInherited", "urn:test:top")->getChildren("secondLevelMultiChildren", "urn:test:top")[0]->getAttributes().getAttribute("num"));
+ CPPUNIT_ASSERT_EQUAL(std::string("2"), tree->getChild("firstLevelInherited", "urn:test:top")->getChildren("secondLevelMultiChildren", "urn:test:top")[1]->getAttributes().getAttribute("num"));
+ CPPUNIT_ASSERT(tree->getChild("firstLevelNS", "urn:test:first"));
+ }
+
+ private:
+
+
+ class MyParser : public GenericPayloadTreeParser<RawXMLPayload>
+ {
+ public:
+ virtual ~MyParser() {}
+ virtual void handleTree(ParserElement::ref root) {
+ tree = root;
+ }
+ ParserElement::ref tree;
+ };
+
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(GenericPayloadTreeParserTest);
diff --git a/Swiften/SConscript b/Swiften/SConscript
index 0144ddb..e20e5e6 100644
--- a/Swiften/SConscript
+++ b/Swiften/SConscript
@@ -140,18 +140,19 @@ if env["SCONS_STAGE"] == "build" :
"Serializer/PayloadSerializers/IBBSerializer.cpp",
"Serializer/PayloadSerializers/CapsInfoSerializer.cpp",
"Serializer/PayloadSerializers/ChatStateSerializer.cpp",
"Serializer/PayloadSerializers/DiscoInfoSerializer.cpp",
"Serializer/PayloadSerializers/DiscoItemsSerializer.cpp",
"Serializer/PayloadSerializers/ErrorSerializer.cpp",
"Serializer/PayloadSerializers/FullPayloadSerializerCollection.cpp",
"Serializer/PayloadSerializers/MUCPayloadSerializer.cpp",
"Serializer/PayloadSerializers/MUCUserPayloadSerializer.cpp",
+ "Serializer/PayloadSerializers/MUCAdminPayloadSerializer.cpp",
"Serializer/PayloadSerializers/MUCOwnerPayloadSerializer.cpp",
"Serializer/PayloadSerializers/ResourceBindSerializer.cpp",
"Serializer/PayloadSerializers/RosterItemExchangeSerializer.cpp",
"Serializer/PayloadSerializers/RosterSerializer.cpp",
"Serializer/PayloadSerializers/SecurityLabelSerializer.cpp",
"Serializer/PayloadSerializers/SecurityLabelsCatalogSerializer.cpp",
"Serializer/PayloadSerializers/SoftwareVersionSerializer.cpp",
"Serializer/PayloadSerializers/StreamInitiationSerializer.cpp",
"Serializer/PayloadSerializers/BytestreamsSerializer.cpp",
@@ -286,20 +287,22 @@ if env["SCONS_STAGE"] == "build" :
File("Parser/PayloadParsers/UnitTest/SoftwareVersionParserTest.cpp"),
File("Parser/PayloadParsers/UnitTest/StatusParserTest.cpp"),
File("Parser/PayloadParsers/UnitTest/StatusShowParserTest.cpp"),
File("Parser/PayloadParsers/UnitTest/StreamInitiationParserTest.cpp"),
File("Parser/PayloadParsers/UnitTest/VCardParserTest.cpp"),
File("Parser/PayloadParsers/UnitTest/StorageParserTest.cpp"),
File("Parser/PayloadParsers/UnitTest/PrivateStorageParserTest.cpp"),
File("Parser/PayloadParsers/UnitTest/VCardUpdateParserTest.cpp"),
File("Parser/PayloadParsers/UnitTest/ReplaceTest.cpp"),
+ File("Parser/PayloadParsers/UnitTest/MUCAdminPayloadParserTest.cpp"),
File("Parser/UnitTest/AttributeMapTest.cpp"),
File("Parser/UnitTest/IQParserTest.cpp"),
+ File("Parser/UnitTest/GenericPayloadTreeParserTest.cpp"),
File("Parser/UnitTest/MessageParserTest.cpp"),
File("Parser/UnitTest/PayloadParserFactoryCollectionTest.cpp"),
File("Parser/UnitTest/PresenceParserTest.cpp"),
File("Parser/UnitTest/StanzaAckParserTest.cpp"),
File("Parser/UnitTest/SerializingParserTest.cpp"),
File("Parser/UnitTest/StanzaParserTest.cpp"),
File("Parser/UnitTest/StreamFeaturesParserTest.cpp"),
File("Parser/UnitTest/StreamManagementEnabledParserTest.cpp"),
File("Parser/UnitTest/XMLParserTest.cpp"),
@@ -330,18 +333,19 @@ if env["SCONS_STAGE"] == "build" :
File("Serializer/PayloadSerializers/UnitTest/StatusSerializerTest.cpp"),
File("Serializer/PayloadSerializers/UnitTest/StatusShowSerializerTest.cpp"),
File("Serializer/PayloadSerializers/UnitTest/StreamInitiationSerializerTest.cpp"),
File("Serializer/PayloadSerializers/UnitTest/InBandRegistrationPayloadSerializerTest.cpp"),
File("Serializer/PayloadSerializers/UnitTest/VCardUpdateSerializerTest.cpp"),
File("Serializer/PayloadSerializers/UnitTest/VCardSerializerTest.cpp"),
File("Serializer/PayloadSerializers/UnitTest/StorageSerializerTest.cpp"),
File("Serializer/PayloadSerializers/UnitTest/PrivateStorageSerializerTest.cpp"),
File("Serializer/PayloadSerializers/UnitTest/ReplaceSerializerTest.cpp"),
+ File("Serializer/PayloadSerializers/UnitTest/MUCAdminPayloadSerializerTest.cpp"),
File("Serializer/UnitTest/StreamFeaturesSerializerTest.cpp"),
File("Serializer/UnitTest/AuthSuccessSerializerTest.cpp"),
File("Serializer/UnitTest/AuthChallengeSerializerTest.cpp"),
File("Serializer/UnitTest/AuthRequestSerializerTest.cpp"),
File("Serializer/UnitTest/AuthResponseSerializerTest.cpp"),
File("Serializer/UnitTest/XMPPSerializerTest.cpp"),
File("Serializer/XML/UnitTest/XMLElementTest.cpp"),
File("StreamManagement/UnitTest/StanzaAckRequesterTest.cpp"),
File("StreamManagement/UnitTest/StanzaAckResponderTest.cpp"),
diff --git a/Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.cpp b/Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.cpp
index 0746c37..0ddd445 100644
--- a/Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.cpp
+++ b/Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.cpp
@@ -15,18 +15,19 @@
#include <Swiften/Serializer/PayloadSerializers/BlockSerializer.h>
#include <Swiften/Serializer/PayloadSerializers/SubjectSerializer.h>
#include <Swiften/Serializer/PayloadSerializers/ChatStateSerializer.h>
#include <Swiften/Serializer/PayloadSerializers/PrioritySerializer.h>
#include <Swiften/Serializer/PayloadSerializers/ErrorSerializer.h>
#include <Swiften/Serializer/PayloadSerializers/RosterSerializer.h>
#include <Swiften/Serializer/PayloadSerializers/RosterItemExchangeSerializer.h>
#include <Swiften/Serializer/PayloadSerializers/MUCPayloadSerializer.h>
#include <Swiften/Serializer/PayloadSerializers/MUCUserPayloadSerializer.h>
+#include <Swiften/Serializer/PayloadSerializers/MUCAdminPayloadSerializer.h>
#include <Swiften/Serializer/PayloadSerializers/MUCOwnerPayloadSerializer.h>
#include <Swiften/Serializer/PayloadSerializers/SoftwareVersionSerializer.h>
#include <Swiften/Serializer/PayloadSerializers/StatusSerializer.h>
#include <Swiften/Serializer/PayloadSerializers/StatusShowSerializer.h>
#include <Swiften/Serializer/PayloadSerializers/DiscoInfoSerializer.h>
#include <Swiften/Serializer/PayloadSerializers/DiscoItemsSerializer.h>
#include <Swiften/Serializer/PayloadSerializers/CapsInfoSerializer.h>
#include <Swiften/Serializer/PayloadSerializers/ResourceBindSerializer.h>
#include <Swiften/Serializer/PayloadSerializers/StartSessionSerializer.h>
@@ -55,18 +56,19 @@ FullPayloadSerializerCollection::FullPayloadSerializerCollection() {
serializers_.push_back(new BodySerializer());
serializers_.push_back(new SubjectSerializer());
serializers_.push_back(new ChatStateSerializer());
serializers_.push_back(new PrioritySerializer());
serializers_.push_back(new ErrorSerializer());
serializers_.push_back(new RosterSerializer());
serializers_.push_back(new RosterItemExchangeSerializer());
serializers_.push_back(new MUCPayloadSerializer());
serializers_.push_back(new MUCUserPayloadSerializer());
+ serializers_.push_back(new MUCAdminPayloadSerializer());
serializers_.push_back(new MUCOwnerPayloadSerializer(this));
serializers_.push_back(new SoftwareVersionSerializer());
serializers_.push_back(new StatusSerializer());
serializers_.push_back(new StatusShowSerializer());
serializers_.push_back(new DiscoInfoSerializer());
serializers_.push_back(new DiscoItemsSerializer());
serializers_.push_back(new CapsInfoSerializer());
serializers_.push_back(new BlockSerializer<BlockPayload>("block"));
serializers_.push_back(new BlockSerializer<UnblockPayload>("unblock"));
diff --git a/Swiften/Serializer/PayloadSerializers/MUCAdminPayloadSerializer.cpp b/Swiften/Serializer/PayloadSerializers/MUCAdminPayloadSerializer.cpp
new file mode 100644
index 0000000..552f7f1
--- /dev/null
+++ b/Swiften/Serializer/PayloadSerializers/MUCAdminPayloadSerializer.cpp
@@ -0,0 +1,34 @@
+/*
+ * Copyright (c) 2011 Kevin Smith
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <Swiften/Serializer/PayloadSerializers/MUCAdminPayloadSerializer.h>
+
+#include <sstream>
+
+#include <boost/shared_ptr.hpp>
+#include <boost/smart_ptr/make_shared.hpp>
+
+#include <Swiften/Base/foreach.h>
+#include <Swiften/Serializer/XML/XMLElement.h>
+#include <Swiften/Serializer/XML/XMLTextNode.h>
+#include <Swiften/Serializer/PayloadSerializers/MUCItemSerializer.h>
+
+
+namespace Swift {
+
+MUCAdminPayloadSerializer::MUCAdminPayloadSerializer() : GenericPayloadSerializer<MUCAdminPayload>() {
+}
+
+std::string MUCAdminPayloadSerializer::serializePayload(boost::shared_ptr<MUCAdminPayload> payload) const {
+ XMLElement mucElement("query", "http://jabber.org/protocol/muc#admin");
+ foreach (const MUCItem item, payload->getItems()) {
+ mucElement.addNode(MUCItemSerializer::itemToElement(item));
+ }
+ return mucElement.serialize();
+}
+
+
+}
diff --git a/Swiften/Serializer/PayloadSerializers/MUCAdminPayloadSerializer.h b/Swiften/Serializer/PayloadSerializers/MUCAdminPayloadSerializer.h
new file mode 100644
index 0000000..e288cd7
--- /dev/null
+++ b/Swiften/Serializer/PayloadSerializers/MUCAdminPayloadSerializer.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2011 Kevin Smith
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#pragma once
+
+#include <Swiften/Serializer/GenericPayloadSerializer.h>
+#include <Swiften/Elements/MUCAdminPayload.h>
+
+namespace Swift {
+ class MUCAdminPayloadSerializer : public GenericPayloadSerializer<MUCAdminPayload> {
+ public:
+ MUCAdminPayloadSerializer();
+ std::string affiliationToString(MUCOccupant::Affiliation affiliation) const;
+ std::string roleToString(MUCOccupant::Role role) const;
+
+ virtual std::string serializePayload(boost::shared_ptr<MUCAdminPayload> version) const;
+ };
+}
+
diff --git a/Swiften/Serializer/PayloadSerializers/MUCItemSerializer.h b/Swiften/Serializer/PayloadSerializers/MUCItemSerializer.h
new file mode 100644
index 0000000..7cb662c
--- /dev/null
+++ b/Swiften/Serializer/PayloadSerializers/MUCItemSerializer.h
@@ -0,0 +1,69 @@
+/*
+ * Copyright (c) 2011 Kevin Smith
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#pragma once
+
+#include <Swiften/Serializer/GenericPayloadSerializer.h>
+#include <Swiften/Elements/MUCItem.h>
+#include <boost/smart_ptr/make_shared.hpp>
+
+namespace Swift {
+ class MUCItemSerializer {
+ public:
+ static std::string affiliationToString(MUCOccupant::Affiliation affiliation) {
+ std::string result;
+ switch (affiliation) {
+ case MUCOccupant::Owner: result = "owner"; break;
+ case MUCOccupant::Admin: result = "admin"; break;
+ case MUCOccupant::Member: result = "member"; break;
+ case MUCOccupant::Outcast: result = "outcast"; break;
+ case MUCOccupant::NoAffiliation: result = "none"; break;
+ default: assert(false);
+ }
+ return result;
+ }
+
+ static std::string roleToString(MUCOccupant::Role role) {
+ std::string result;
+ switch (role) {
+ case MUCOccupant::Moderator: result = "moderator"; break;
+ case MUCOccupant::NoRole: result = "none"; break;
+ case MUCOccupant::Participant: result = "participant"; break;
+ case MUCOccupant::Visitor: result = "visitor"; break;
+ default: assert(false);
+ }
+ return result;
+
+ }
+
+ static boost::shared_ptr<XMLElement> itemToElement(const MUCItem& item) {
+ boost::shared_ptr<XMLElement> itemElement(new XMLElement("item"));
+ if (item.affiliation) {
+ itemElement->setAttribute("affiliation", affiliationToString(item.affiliation.get()));
+ }
+ if (item.role) {
+ itemElement->setAttribute("role", roleToString(item.role.get()));
+ }
+ if (item.realJID) {
+ itemElement->setAttribute("jid", item.realJID.get());
+ }
+ if (item.nick) {
+ itemElement->setAttribute("nick", item.nick.get());
+ }
+ if (item.actor) {
+ boost::shared_ptr<XMLElement> actorElement(new XMLElement("actor"));
+ actorElement->setAttribute("jid", item.actor->toString());
+ itemElement->addNode(actorElement);
+ }
+ if (item.reason) {
+ boost::shared_ptr<XMLElement> reasonElement(new XMLElement("reason"));
+ reasonElement->addNode(boost::make_shared<XMLTextNode>(*item.reason));
+ itemElement->addNode(reasonElement);
+ }
+ return itemElement;
+ }
+ };
+}
diff --git a/Swiften/Serializer/PayloadSerializers/MUCUserPayloadSerializer.cpp b/Swiften/Serializer/PayloadSerializers/MUCUserPayloadSerializer.cpp
index 44aa506..0a8153d 100644
--- a/Swiften/Serializer/PayloadSerializers/MUCUserPayloadSerializer.cpp
+++ b/Swiften/Serializer/PayloadSerializers/MUCUserPayloadSerializer.cpp
@@ -7,68 +7,35 @@
#include <Swiften/Serializer/PayloadSerializers/MUCUserPayloadSerializer.h>
#include <sstream>
#include <boost/shared_ptr.hpp>
#include <Swiften/Base/foreach.h>
#include <Swiften/Serializer/XML/XMLElement.h>
#include <Swiften/Serializer/XML/XMLTextNode.h>
-
+#include <Swiften/Serializer/PayloadSerializers/MUCItemSerializer.h>
namespace Swift {
MUCUserPayloadSerializer::MUCUserPayloadSerializer() : GenericPayloadSerializer<MUCUserPayload>() {
}
std::string MUCUserPayloadSerializer::serializePayload(boost::shared_ptr<MUCUserPayload> payload) const {
XMLElement mucElement("x", "http://jabber.org/protocol/muc#user");
foreach (const MUCUserPayload::StatusCode statusCode, payload->getStatusCodes()) {
boost::shared_ptr<XMLElement> statusElement(new XMLElement("status"));
std::ostringstream code;
code << statusCode.code;
statusElement->setAttribute("code", code.str());
mucElement.addNode(statusElement);
}
- foreach (const MUCUserPayload::Item item, payload->getItems()) {
- boost::shared_ptr<XMLElement> itemElement(new XMLElement("item"));
- itemElement->setAttribute("affiliation", affiliationToString(item.affiliation));
- itemElement->setAttribute("role", roleToString(item.role));
- if (item.realJID) {
- itemElement->setAttribute("jid", item.realJID.get());
- }
- if (item.nick) {
- itemElement->setAttribute("nick", item.nick.get());
- }
- mucElement.addNode(itemElement);
+ foreach (const MUCItem item, payload->getItems()) {
+ mucElement.addNode(MUCItemSerializer::itemToElement(item));
}
return mucElement.serialize();
}
-std::string MUCUserPayloadSerializer::affiliationToString(MUCOccupant::Affiliation affiliation) const {
- std::string result;
- switch (affiliation) {
- case MUCOccupant::Owner: result = "owner"; break;
- case MUCOccupant::Admin: result = "admin"; break;
- case MUCOccupant::Member: result = "member"; break;
- case MUCOccupant::Outcast: result = "outcast"; break;
- case MUCOccupant::NoAffiliation: result = "none"; break;
- default: assert(false);
- }
- return result;
-}
-
-std::string MUCUserPayloadSerializer::roleToString(MUCOccupant::Role role) const {
- std::string result;
- switch (role) {
- case MUCOccupant::Moderator: result = "moderator"; break;
- case MUCOccupant::NoRole: result = "none"; break;
- case MUCOccupant::Participant: result = "participant"; break;
- case MUCOccupant::Visitor: result = "visitor"; break;
- default: assert(false);
- }
- return result;
-}
}
diff --git a/Swiften/Serializer/PayloadSerializers/MUCUserPayloadSerializer.h b/Swiften/Serializer/PayloadSerializers/MUCUserPayloadSerializer.h
index 634ce22..84c4a96 100644
--- a/Swiften/Serializer/PayloadSerializers/MUCUserPayloadSerializer.h
+++ b/Swiften/Serializer/PayloadSerializers/MUCUserPayloadSerializer.h
@@ -7,16 +7,14 @@
#pragma once
#include <Swiften/Serializer/GenericPayloadSerializer.h>
#include <Swiften/Elements/MUCUserPayload.h>
namespace Swift {
class MUCUserPayloadSerializer : public GenericPayloadSerializer<MUCUserPayload> {
public:
MUCUserPayloadSerializer();
- std::string affiliationToString(MUCOccupant::Affiliation affiliation) const;
- std::string roleToString(MUCOccupant::Role role) const;
virtual std::string serializePayload(boost::shared_ptr<MUCUserPayload> version) const;
};
}
diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/MUCAdminPayloadSerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/MUCAdminPayloadSerializerTest.cpp
new file mode 100644
index 0000000..a8acf80
--- /dev/null
+++ b/Swiften/Serializer/PayloadSerializers/UnitTest/MUCAdminPayloadSerializerTest.cpp
@@ -0,0 +1,39 @@
+/*
+ * Copyright (c) 2011 Kevin Smith
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include <cppunit/extensions/HelperMacros.h>
+#include <cppunit/extensions/TestFactoryRegistry.h>
+
+#include <boost/smart_ptr/make_shared.hpp>
+
+#include <Swiften/Serializer/PayloadSerializers/MUCAdminPayloadSerializer.h>
+
+using namespace Swift;
+
+class MUCAdminPayloadSerializerTest : public CppUnit::TestFixture
+{
+ CPPUNIT_TEST_SUITE(MUCAdminPayloadSerializerTest);
+ CPPUNIT_TEST(testSerialize);
+ CPPUNIT_TEST_SUITE_END();
+
+ public:
+ MUCAdminPayloadSerializerTest() {}
+
+ void testSerialize() {
+ MUCAdminPayloadSerializer testling;
+ boost::shared_ptr<MUCAdminPayload> admin = boost::make_shared<MUCAdminPayload>();
+ MUCItem item;
+ item.affiliation = MUCOccupant::Owner;
+ item.role = MUCOccupant::Visitor;
+ item.reason = "malice";
+ item.actor = JID("kev@tester.lit");
+ admin->addItem(item);
+
+ CPPUNIT_ASSERT_EQUAL(std::string("<query xmlns=\"http://jabber.org/protocol/muc#admin\"><item affiliation=\"owner\" role=\"visitor\"><actor jid=\"kev@tester.lit\"/><reason>malice</reason></item></query>"), testling.serialize(admin));
+ }
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(MUCAdminPayloadSerializerTest);