diff options
author | Kevin Smith <git@kismith.co.uk> | 2011-09-28 16:45:00 (GMT) |
---|---|---|
committer | Kevin Smith <git@kismith.co.uk> | 2011-09-28 16:45:00 (GMT) |
commit | 1daf22de85758cfd035f1fcf6a70007315db4f28 (patch) | |
tree | ae822e3db619af06ec1b26fd342165b24fe89543 | |
parent | 5c544f02222a3318b8581f68071b6a6b66b1d4c0 (diff) | |
download | swift-contrib-1daf22de85758cfd035f1fcf6a70007315db4f28.zip swift-contrib-1daf22de85758cfd035f1fcf6a70007315db4f28.tar.bz2 |
Destroy rooms.
Resolves: #990
24 files changed, 272 insertions, 16 deletions
diff --git a/Swift/Controllers/Chat/MUCController.cpp b/Swift/Controllers/Chat/MUCController.cpp index 56cc639..e1d02ae 100644 --- a/Swift/Controllers/Chat/MUCController.cpp +++ b/Swift/Controllers/Chat/MUCController.cpp @@ -67,18 +67,19 @@ MUCController::MUCController ( completer_ = new TabComplete(); chatWindow_->setRosterModel(roster_); chatWindow_->setTabComplete(completer_); chatWindow_->setName(muc->getJID().getNode()); chatWindow_->onClosed.connect(boost::bind(&MUCController::handleWindowClosed, this)); chatWindow_->onOccupantSelectionChanged.connect(boost::bind(&MUCController::handleWindowOccupantSelectionChanged, this, _1)); chatWindow_->onOccupantActionSelected.connect(boost::bind(&MUCController::handleActionRequestedOnOccupant, this, _1, _2)); chatWindow_->onChangeSubjectRequest.connect(boost::bind(&MUCController::handleChangeSubjectRequest, this, _1)); chatWindow_->onConfigureRequest.connect(boost::bind(&MUCController::handleConfigureRequest, this, _1)); + chatWindow_->onDestroyRequest.connect(boost::bind(&MUCController::handleDestroyRoomRequest, this)); muc_->onJoinComplete.connect(boost::bind(&MUCController::handleJoinComplete, this, _1)); muc_->onJoinFailed.connect(boost::bind(&MUCController::handleJoinFailed, this, _1)); muc_->onOccupantJoined.connect(boost::bind(&MUCController::handleOccupantJoined, this, _1)); muc_->onOccupantPresenceChange.connect(boost::bind(&MUCController::handleOccupantPresenceChange, this, _1)); muc_->onOccupantLeft.connect(boost::bind(&MUCController::handleOccupantLeft, this, _1, _2, _3)); muc_->onOccupantRoleChanged.connect(boost::bind(&MUCController::handleOccupantRoleChanged, this, _1, _2, _3)); muc_->onConfigurationFailed.connect(boost::bind(&MUCController::handleConfigurationFailed, this, _1)); muc_->onConfigurationFormReceived.connect(boost::bind(&MUCController::handleConfigurationFormReceived, this, _1)); if (timerFactory) { @@ -592,10 +593,14 @@ void MUCController::handleConfigurationFailed(ErrorPayload::ref error) { std::string errorMessage = getErrorMessage(error); errorMessage = str(format(QT_TRANSLATE_NOOP("", "Room configuration failed: %1%.")) % errorMessage); chatWindow_->addErrorMessage(errorMessage); } void MUCController::handleConfigurationFormReceived(Form::ref form) { chatWindow_->showRoomConfigurationForm(form); } +void MUCController::handleDestroyRoomRequest() { + muc_->destroyRoom(); +} + } diff --git a/Swift/Controllers/Chat/MUCController.h b/Swift/Controllers/Chat/MUCController.h index 4be1488..7a7461b 100644 --- a/Swift/Controllers/Chat/MUCController.h +++ b/Swift/Controllers/Chat/MUCController.h @@ -85,18 +85,19 @@ namespace Swift { bool messageTargetsMe(boost::shared_ptr<Message> message); void updateJoinParts(); bool shouldUpdateJoinParts(); void dayTicked() {lastWasPresence_ = false;} void processUserPart(); void handleBareJIDCapsChanged(const JID& jid); void handleConfigureRequest(Form::ref); void handleConfigurationFailed(ErrorPayload::ref); void handleConfigurationFormReceived(Form::ref); + void handleDestroyRoomRequest(); private: MUC::ref muc_; UIEventStream* events_; std::string nick_; std::string desiredNick_; Roster* roster_; TabComplete* completer_; bool parting_; diff --git a/Swift/Controllers/UIInterfaces/ChatWindow.h b/Swift/Controllers/UIInterfaces/ChatWindow.h index 75c92d3..df57d80 100644 --- a/Swift/Controllers/UIInterfaces/ChatWindow.h +++ b/Swift/Controllers/UIInterfaces/ChatWindow.h @@ -96,18 +96,19 @@ namespace Swift { boost::signal<void (const std::string&, bool isCorrection)> onSendMessageRequest; boost::signal<void ()> onSendCorrectionMessageRequest; boost::signal<void ()> onUserTyping; boost::signal<void ()> onUserCancelsTyping; boost::signal<void ()> onAlertButtonClicked; boost::signal<void (ContactRosterItem*)> onOccupantSelectionChanged; boost::signal<void (ChatWindow::OccupantAction, ContactRosterItem*)> onOccupantActionSelected; boost::signal<void (const std::string&)> onChangeSubjectRequest; boost::signal<void (Form::ref)> onConfigureRequest; + boost::signal<void ()> onDestroyRequest; // File transfer related boost::signal<void (std::string /* id */)> onFileTransferCancel; boost::signal<void (std::string /* id */, std::string /* description */)> onFileTransferStart; boost::signal<void (std::string /* id */, std::string /* path */)> onFileTransferAccept; boost::signal<void (std::string /* path */)> onSendFileRequest; }; } #endif diff --git a/Swift/QtUI/QtChatWindow.cpp b/Swift/QtUI/QtChatWindow.cpp index 1576880..496c42c 100644 --- a/Swift/QtUI/QtChatWindow.cpp +++ b/Swift/QtUI/QtChatWindow.cpp @@ -694,29 +694,33 @@ void QtChatWindow::setAvailableOccupantActions(const std::vector<OccupantAction> void QtChatWindow::setSubject(const std::string& subject) { //subject_->setVisible(!subject.empty()); subject_->setText(P2QSTRING(subject)); } void QtChatWindow::handleActionButtonClicked() { QMenu contextMenu; QAction* changeSubject = contextMenu.addAction(tr("Change subject")); QAction* configure = contextMenu.addAction(tr("Configure room")); + QAction* destroy = contextMenu.addAction(tr("Destroy room")); QAction* result = contextMenu.exec(QCursor::pos()); if (result == changeSubject) { bool ok; QString subject = QInputDialog::getText(this, tr("Change room subject"), tr("New subject:"), QLineEdit::Normal, subject_->text(), &ok); if (ok) { onChangeSubjectRequest(Q2PSTRING(subject)); } } else if (result == configure) { onConfigureRequest(Form::ref()); } + else if (result == destroy) { + onDestroyRequest(); + } } void QtChatWindow::showRoomConfigurationForm(Form::ref form) { if (mucConfigurationWindow) { delete mucConfigurationWindow.data(); } mucConfigurationWindow = new QtMUCConfigurationWindow(form); mucConfigurationWindow->onFormComplete.connect(boost::bind(boost::ref(onConfigureRequest), _1)); } diff --git a/Swiften/Elements/MUCUserPayload.h b/Swiften/Elements/MUCUserPayload.h index 699badd..c9ea62c 100644 --- a/Swiften/Elements/MUCUserPayload.h +++ b/Swiften/Elements/MUCUserPayload.h @@ -44,14 +44,23 @@ namespace Swift { void addItem(const MUCItem& item) {items_.push_back(item);} void addStatusCode(StatusCode code) {statusCodes_.push_back(code);} const std::vector<MUCItem>& getItems() const {return items_;} const std::vector<StatusCode>& getStatusCodes() const {return statusCodes_;} + boost::shared_ptr<Payload> getPayload() const { + return payload_; + } + + void setPayload(boost::shared_ptr<Payload> p) { + payload_ = p; + } + private: std::vector<MUCItem> items_; std::vector<StatusCode> statusCodes_; + boost::shared_ptr<Payload> payload_; }; } diff --git a/Swiften/MUC/MUC.cpp b/Swiften/MUC/MUC.cpp index c450c6d..6fe8f19 100644 --- a/Swiften/MUC/MUC.cpp +++ b/Swiften/MUC/MUC.cpp @@ -14,18 +14,19 @@ #include <Swiften/Presence/DirectedPresenceSender.h> #include <Swiften/Client/StanzaChannel.h> #include <Swiften/Queries/IQRouter.h> #include <Swiften/Elements/Form.h> #include <Swiften/Elements/Message.h> #include <Swiften/Elements/IQ.h> #include <Swiften/Elements/MUCUserPayload.h> #include <Swiften/Elements/MUCAdminPayload.h> #include <Swiften/Elements/MUCPayload.h> +#include <Swiften/Elements/MUCDestroyPayload.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) { scopedConnection_ = stanzaChannel->onPresenceReceived.connect(boost::bind(&MUC::handleIncomingPresence, this, _1)); @@ -270,18 +271,27 @@ void MUC::handleConfigurationResultReceived(MUCOwnerPayload::ref /*payload*/, Er void MUC::configureRoom(Form::ref form) { MUCOwnerPayload::ref mucPayload(new MUCOwnerPayload()); mucPayload->setPayload(form); GenericRequest<MUCOwnerPayload>* request = new GenericRequest<MUCOwnerPayload>(IQ::Set, getJID(), mucPayload, iqRouter_); request->onResponse.connect(boost::bind(&MUC::handleConfigurationResultReceived, this, _1, _2)); request->send(); } +void MUC::destroyRoom() { + MUCOwnerPayload::ref mucPayload = boost::make_shared<MUCOwnerPayload>(); + MUCDestroyPayload::ref mucDestroyPayload = boost::make_shared<MUCDestroyPayload>(); + mucPayload->setPayload(mucDestroyPayload); + GenericRequest<MUCOwnerPayload>* request = new GenericRequest<MUCOwnerPayload>(IQ::Set, getJID(), mucPayload, iqRouter_); + request->onResponse.connect(boost::bind(&MUC::handleConfigurationResultReceived, this, _1, _2)); + request->send(); +} + //TODO: Invites(direct/mediated) //TODO: requesting membership //TODO: get member list //TODO: request voice //TODO: moderator use cases diff --git a/Swiften/MUC/MUC.h b/Swiften/MUC/MUC.h index 4017c97..b99c4b4 100644 --- a/Swiften/MUC/MUC.h +++ b/Swiften/MUC/MUC.h @@ -54,18 +54,19 @@ namespace Swift { /** 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); void changeSubject(const std::string& subject); void requestConfigurationForm(); void configureRoom(Form::ref); + void destroyRoom(); 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 (ErrorPayload::ref)> onConfigurationFailed; 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; diff --git a/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp b/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp index 3d56f61..ebb0f3e 100644 --- a/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp +++ b/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp @@ -40,18 +40,19 @@ #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/MUCOwnerPayloadParser.h> +#include <Swiften/Parser/PayloadParsers/MUCDestroyPayloadParser.h> #include <Swiften/Parser/PayloadParsers/MUCOwnerPayloadParserFactory.h> #include <Swiften/Parser/PayloadParsers/NicknameParserFactory.h> #include <Swiften/Parser/PayloadParsers/ReplaceParser.h> #include <Swiften/Parser/PayloadParsers/LastParser.h> #include <Swiften/Parser/PayloadParsers/JingleParserFactory.h> #include <Swiften/Parser/PayloadParsers/JingleReasonParser.h> #include <Swiften/Parser/PayloadParsers/JingleContentPayloadParserFactory.h> #include <Swiften/Parser/PayloadParsers/JingleIBBTransportMethodPayloadParser.h> #include <Swiften/Parser/PayloadParsers/JingleS5BTransportMethodPayloadParser.h> @@ -97,21 +98,23 @@ FullPayloadParserFactoryCollection::FullPayloadParserFactoryCollection() { factories_.push_back(shared_ptr<PayloadParserFactory>(new CommandParserFactory())); 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 MUCUserPayloadParserFactory(this))); factories_.push_back(shared_ptr<PayloadParserFactory>(new MUCOwnerPayloadParserFactory(this))); factories_.push_back(shared_ptr<PayloadParserFactory>(new GenericPayloadParserFactory<MUCAdminPayloadParser>("query", "http://jabber.org/protocol/muc#admin"))); + factories_.push_back(shared_ptr<PayloadParserFactory>(new GenericPayloadParserFactory<MUCDestroyPayloadParser>("destroy", "http://jabber.org/protocol/muc#user"))); + factories_.push_back(shared_ptr<PayloadParserFactory>(new GenericPayloadParserFactory<MUCDestroyPayloadParser>("destroy", "http://jabber.org/protocol/muc#owner"))); factories_.push_back(shared_ptr<PayloadParserFactory>(new NicknameParserFactory())); factories_.push_back(shared_ptr<PayloadParserFactory>(new JingleParserFactory(this))); factories_.push_back(shared_ptr<PayloadParserFactory>(new GenericPayloadParserFactory<JingleReasonParser>("reason", "urn:xmpp:jingle:1"))); factories_.push_back(shared_ptr<PayloadParserFactory>(new JingleContentPayloadParserFactory(this))); factories_.push_back(shared_ptr<PayloadParserFactory>(new GenericPayloadParserFactory<JingleIBBTransportMethodPayloadParser>("transport", "urn:xmpp:jingle:transports:ibb:1"))); factories_.push_back(shared_ptr<PayloadParserFactory>(new GenericPayloadParserFactory<JingleS5BTransportMethodPayloadParser>("transport", "urn:xmpp:jingle:transports:s5b:1"))); factories_.push_back(shared_ptr<PayloadParserFactory>(new JingleFileTransferDescriptionParserFactory(this))); factories_.push_back(shared_ptr<PayloadParserFactory>(new GenericPayloadParserFactory<StreamInitiationFileInfoParser>("file", "http://jabber.org/protocol/si/profile/file-transfer"))); factories_.push_back(shared_ptr<PayloadParserFactory>(new GenericPayloadParserFactory<JingleFileTransferReceivedParser>("received", "urn:xmpp:jingle:apps:file-transfer:3"))); diff --git a/Swiften/Parser/PayloadParsers/MUCDestroyPayloadParser.cpp b/Swiften/Parser/PayloadParsers/MUCDestroyPayloadParser.cpp new file mode 100644 index 0000000..a8d29d0 --- /dev/null +++ b/Swiften/Parser/PayloadParsers/MUCDestroyPayloadParser.cpp @@ -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. + */ + +#include <Swiften/Parser/PayloadParsers/MUCDestroyPayloadParser.h> + +#include <Swiften/Base/foreach.h> + +namespace Swift { + +void MUCDestroyPayloadParser::handleTree(ParserElement::ref root) { + std::string ns = root->getNamespace(); + std::string jid = root->getAttributes().getAttribute("jid"); + if (!jid.empty()) { + getPayloadInternal()->setNewVenue(JID(jid)); + } + getPayloadInternal()->setReason(root->getChild("reason", ns)->getText()); +} + +} diff --git a/Swiften/Parser/PayloadParsers/MUCDestroyPayloadParser.h b/Swiften/Parser/PayloadParsers/MUCDestroyPayloadParser.h new file mode 100644 index 0000000..714651f --- /dev/null +++ b/Swiften/Parser/PayloadParsers/MUCDestroyPayloadParser.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 <boost/optional.hpp> + +#include <Swiften/Elements/MUCDestroyPayload.h> +#include <Swiften/Parser/GenericPayloadTreeParser.h> + +namespace Swift { + class MUCDestroyPayloadParser : public GenericPayloadTreeParser<MUCDestroyPayload> { + public: + virtual void handleTree(ParserElement::ref root); + }; +} diff --git a/Swiften/Parser/PayloadParsers/MUCUserPayloadParser.cpp b/Swiften/Parser/PayloadParsers/MUCUserPayloadParser.cpp index e6ccbbe..2da8b35 100644 --- a/Swiften/Parser/PayloadParsers/MUCUserPayloadParser.cpp +++ b/Swiften/Parser/PayloadParsers/MUCUserPayloadParser.cpp @@ -2,30 +2,38 @@ * 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/Parser/PayloadParserFactoryCollection.h> +#include <Swiften/Parser/PayloadParserFactory.h> #include <Swiften/Base/foreach.h> #include <Swiften/Elements/MUCOccupant.h> +#include <Swiften/Parser/Tree/TreeReparser.h> namespace Swift { 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("status", "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&) { + foreach (ParserElement::ref child, root->getAllChildren()) { + if (child->getName() == "item" && child->getNamespace() == root->getNamespace()) { + MUCItem item = MUCItemParser::itemFromTree(child); + getPayloadInternal()->addItem(item); + } + else if (child->getName() == "status" && child->getNamespace() == root->getNamespace()) { + MUCUserPayload::StatusCode status; + try { + status.code = boost::lexical_cast<int>(child->getAttributes().getAttribute("code").c_str()); + getPayloadInternal()->addStatusCode(status); + } catch (boost::bad_lexical_cast&) { + } + } + else { + getPayloadInternal()->setPayload(TreeReparser::parseTree(child, factories)); } } } } diff --git a/Swiften/Parser/PayloadParsers/MUCUserPayloadParser.h b/Swiften/Parser/PayloadParsers/MUCUserPayloadParser.h index e020127..66e63a8 100644 --- a/Swiften/Parser/PayloadParsers/MUCUserPayloadParser.h +++ b/Swiften/Parser/PayloadParsers/MUCUserPayloadParser.h @@ -7,14 +7,18 @@ #pragma once #include <boost/optional.hpp> #include <Swiften/Elements/MUCUserPayload.h> #include <Swiften/Parser/GenericPayloadTreeParser.h> #include <Swiften/Parser/PayloadParsers/MUCItemParser.h> namespace Swift { + class PayloadParserFactoryCollection; class MUCUserPayloadParser : public GenericPayloadTreeParser<MUCUserPayload> { public: + MUCUserPayloadParser(PayloadParserFactoryCollection* collection) : factories(collection) {} virtual void handleTree(ParserElement::ref root); + private: + PayloadParserFactoryCollection* factories; }; } diff --git a/Swiften/Parser/PayloadParsers/MUCUserPayloadParserFactory.h b/Swiften/Parser/PayloadParsers/MUCUserPayloadParserFactory.h index e6c8863..2c1c915 100644 --- a/Swiften/Parser/PayloadParsers/MUCUserPayloadParserFactory.h +++ b/Swiften/Parser/PayloadParsers/MUCUserPayloadParserFactory.h @@ -4,14 +4,26 @@ * See Documentation/Licenses/GPLv3.txt for more information. */ #pragma once #include <Swiften/Parser/GenericPayloadParserFactory.h> #include <Swiften/Parser/PayloadParsers/MUCUserPayloadParser.h> namespace Swift { - class MUCUserPayloadParserFactory : public GenericPayloadParserFactory<MUCUserPayloadParser> { + class MUCUserPayloadParserFactory : public PayloadParserFactory { public: - MUCUserPayloadParserFactory() : GenericPayloadParserFactory<MUCUserPayloadParser>("x", "http://jabber.org/protocol/muc#user") {} + MUCUserPayloadParserFactory(PayloadParserFactoryCollection* factories) : factories(factories) { + } + + virtual bool canParse(const std::string& element, const std::string& ns, const AttributeMap&) const { + return element == "x" && ns == "http://jabber.org/protocol/muc#user"; + } + + virtual PayloadParser* createPayloadParser() { + return new MUCUserPayloadParser(factories); + } + + private: + PayloadParserFactoryCollection* factories; }; } diff --git a/Swiften/Parser/PayloadParsers/UnitTest/MUCUserPayloadParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/MUCUserPayloadParserTest.cpp index cc2463d..45862e2 100644 --- a/Swiften/Parser/PayloadParsers/UnitTest/MUCUserPayloadParserTest.cpp +++ b/Swiften/Parser/PayloadParsers/UnitTest/MUCUserPayloadParserTest.cpp @@ -3,27 +3,29 @@ * 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/Base/foreach.h> #include <Swiften/Parser/PayloadParsers/MUCUserPayloadParser.h> +#include <Swiften/Elements/MUCDestroyPayload.h> #include <Swiften/Parser/PayloadParsers/UnitTest/PayloadsParserTester.h> using namespace Swift; class MUCUserPayloadParserTest : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(MUCUserPayloadParserTest); CPPUNIT_TEST(testParseEmpty); CPPUNIT_TEST(testParse); + CPPUNIT_TEST(testParseDestroy); CPPUNIT_TEST_SUITE_END(); public: MUCUserPayloadParserTest() {} void testParse() { PayloadsParserTester parser; CPPUNIT_ASSERT(parser.parse("<x xmlns=\"http://jabber.org/protocol/muc#user\"><status code='110'/><item affiliation=\"owner\" role=\"visitor\"><actor jid=\"kev@tester.lit\"/><reason>malice</reason></item><status code='210'/></x>")); @@ -50,12 +52,25 @@ class MUCUserPayloadParserTest : public CppUnit::TestFixture void testParseEmpty() { PayloadsParserTester parser; CPPUNIT_ASSERT(parser.parse("<x xmlns=\"http://jabber.org/protocol/muc#user\"/>")); MUCUserPayload::ref payload = boost::dynamic_pointer_cast<MUCUserPayload>(parser.getPayload()); CPPUNIT_ASSERT(payload); CPPUNIT_ASSERT(payload->getItems().empty()); } + + void testParseDestroy() { + PayloadsParserTester parser; + + CPPUNIT_ASSERT(parser.parse("<x xmlns=\"http://jabber.org/protocol/muc#user\"><destroy jid='alice@wonderland.lit'><reason>bert</reason></destroy></x>")); + + MUCUserPayload::ref payload = boost::dynamic_pointer_cast<MUCUserPayload>(parser.getPayload()); + CPPUNIT_ASSERT(payload); + MUCDestroyPayload::ref destroy = boost::dynamic_pointer_cast<MUCDestroyPayload>(payload->getPayload()); + CPPUNIT_ASSERT(destroy); + CPPUNIT_ASSERT_EQUAL(std::string("bert"), destroy->getReason()); + CPPUNIT_ASSERT_EQUAL(JID("alice@wonderland.lit"), destroy->getNewVenue()); + } }; CPPUNIT_TEST_SUITE_REGISTRATION(MUCUserPayloadParserTest); diff --git a/Swiften/Parser/SConscript b/Swiften/Parser/SConscript index 67f706d..2a5d2ee 100644 --- a/Swiften/Parser/SConscript +++ b/Swiften/Parser/SConscript @@ -56,34 +56,36 @@ sources = [ "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/MUCOwnerPayloadParser.cpp", + "PayloadParsers/MUCDestroyPayloadParser.cpp", "PayloadParsers/MUCItemParser.cpp", "PayloadParsers/NicknameParser.cpp", "PayloadParsers/ReplaceParser.cpp", "PayloadParsers/LastParser.cpp", "PayloadParsers/S5BProxyRequestParser.cpp", "PlatformXMLParserFactory.cpp", "PresenceParser.cpp", "SerializingParser.cpp", "StanzaParser.cpp", "StreamErrorParser.cpp", "StreamFeaturesParser.cpp", "StreamManagementEnabledParser.cpp", "StreamResumeParser.cpp", "StreamResumedParser.cpp", "Tree/ParserElement.cpp", "Tree/NullParserElement.cpp", + "Tree/TreeReparser.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/ParserElement.h b/Swiften/Parser/Tree/ParserElement.h index b3ad785..b268c76 100644 --- a/Swiften/Parser/Tree/ParserElement.h +++ b/Swiften/Parser/Tree/ParserElement.h @@ -25,18 +25,19 @@ namespace Swift { const std::string& getText() const { return text_; } const std::string& getName() const { return name_; } const std::string& getNamespace() const { return xmlns_; } const AttributeMap& getAttributes() const { return attributes_; } ParserElement::ref addChild(const std::string& name, const std::string& xmlns, const AttributeMap& attributes); void appendCharacterData(const std::string& data); std::vector<ParserElement::ref> getChildren(const std::string& name, const std::string& xmlns) const; + const std::vector<ParserElement::ref>& getAllChildren() const {return children_;} ParserElement::ref getChild(const std::string& name, const std::string& xmlns) const; virtual operator bool() { return true; } private: std::vector<ParserElement::ref> children_; std::string name_; diff --git a/Swiften/Parser/Tree/TreeReparser.cpp b/Swiften/Parser/Tree/TreeReparser.cpp new file mode 100644 index 0000000..9d09831 --- /dev/null +++ b/Swiften/Parser/Tree/TreeReparser.cpp @@ -0,0 +1,48 @@ +/* + * 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/TreeReparser.h> + +#include <boost/lexical_cast.hpp> +#include <utility> +#include <deque> + +#include <Swiften/Parser/PayloadParserFactoryCollection.h> +#include <Swiften/Parser/PayloadParserFactory.h> +#include <Swiften/Parser/PayloadParser.h> +#include <Swiften/Base/foreach.h> +#include <Swiften/Elements/MUCOccupant.h> + +namespace Swift { + +typedef std::pair<ParserElement::ref, bool> ElementState; + +boost::shared_ptr<Payload> TreeReparser::parseTree(ParserElement::ref root, PayloadParserFactoryCollection* collection) { + PayloadParser* parser = collection->getPayloadParserFactory(root->getName(), root->getNamespace(), root->getAttributes())->createPayloadParser(); + std::deque<ElementState > stack; + stack.push_back(ElementState(root, true)); + while (!stack.empty()) { + ElementState current = stack.back(); + stack.pop_back(); + if (current.second) { + stack.push_back(ElementState(current.first, false)); + parser->handleStartElement(current.first->getName(), current.first->getNamespace(), current.first->getAttributes()); + foreach(ParserElement::ref child, current.first->getAllChildren()) { + stack.push_back(ElementState(child, true)); + } + } else { + parser->handleCharacterData(current.first->getText()); + parser->handleEndElement(current.first->getName(), current.first->getNamespace()); + } + + } + + boost::shared_ptr<Payload> payload = parser->getPayload(); + delete parser; + return payload; +} + +} diff --git a/Swiften/Parser/Tree/TreeReparser.h b/Swiften/Parser/Tree/TreeReparser.h new file mode 100644 index 0000000..212c518 --- /dev/null +++ b/Swiften/Parser/Tree/TreeReparser.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 <Swiften/Parser/GenericPayloadTreeParser.h> +#include <Swiften/Parser/PayloadParsers/MUCItemParser.h> + +namespace Swift { + class PayloadParserFactoryCollection; + class TreeReparser { + public: + static boost::shared_ptr<Payload> parseTree(ParserElement::ref root, PayloadParserFactoryCollection* collection); + + }; +} diff --git a/Swiften/SConscript b/Swiften/SConscript index 0dda91f..fce110a 100644 --- a/Swiften/SConscript +++ b/Swiften/SConscript @@ -144,18 +144,19 @@ if env["SCONS_STAGE"] == "build" : "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/MUCDestroyPayloadSerializer.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", "Serializer/PayloadSerializers/VCardSerializer.cpp", diff --git a/Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.cpp b/Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.cpp index 55c39c7..f3e22d2 100644 --- a/Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.cpp +++ b/Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.cpp @@ -17,18 +17,19 @@ #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/MUCDestroyPayloadSerializer.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> #include <Swiften/Serializer/PayloadSerializers/SecurityLabelSerializer.h> @@ -65,21 +66,22 @@ FullPayloadSerializerCollection::FullPayloadSerializerCollection() { serializers_.push_back(new IBBSerializer()); 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 MUCDestroyPayloadSerializer()); serializers_.push_back(new MUCAdminPayloadSerializer()); serializers_.push_back(new MUCOwnerPayloadSerializer(this)); + serializers_.push_back(new MUCUserPayloadSerializer(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")); serializers_.push_back(new BlockSerializer<BlockListPayload>("blocklist")); diff --git a/Swiften/Serializer/PayloadSerializers/MUCDestroyPayloadSerializer.cpp b/Swiften/Serializer/PayloadSerializers/MUCDestroyPayloadSerializer.cpp new file mode 100644 index 0000000..e78a381 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/MUCDestroyPayloadSerializer.cpp @@ -0,0 +1,37 @@ +/* + * 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/MUCDestroyPayloadSerializer.h> + +#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> + +namespace Swift { + +MUCDestroyPayloadSerializer::MUCDestroyPayloadSerializer() : GenericPayloadSerializer<MUCDestroyPayload>() { +} + +std::string MUCDestroyPayloadSerializer::serializePayload(boost::shared_ptr<MUCDestroyPayload> payload) const { + XMLElement mucElement("destroy", ""); + if (!payload->getReason().empty()) { + XMLElement::ref reason = boost::make_shared<XMLElement>("reason", ""); + reason->addNode(boost::make_shared<XMLTextNode>(payload->getReason())); + mucElement.addNode(reason); + } + if (payload->getNewVenue().isValid()) { + mucElement.setAttribute("jid", payload->getNewVenue().toString()); + } + return mucElement.serialize(); +} + + + + +} diff --git a/Swiften/Serializer/PayloadSerializers/MUCDestroyPayloadSerializer.h b/Swiften/Serializer/PayloadSerializers/MUCDestroyPayloadSerializer.h new file mode 100644 index 0000000..419a683 --- /dev/null +++ b/Swiften/Serializer/PayloadSerializers/MUCDestroyPayloadSerializer.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/Serializer/GenericPayloadSerializer.h> +#include <Swiften/Elements/MUCDestroyPayload.h> + +namespace Swift { + class PayloadSerializerCollection; + class MUCDestroyPayloadSerializer : public GenericPayloadSerializer<MUCDestroyPayload> { + public: + MUCDestroyPayloadSerializer(); + virtual std::string serializePayload(boost::shared_ptr<MUCDestroyPayload> version) const; + }; +} + diff --git a/Swiften/Serializer/PayloadSerializers/MUCUserPayloadSerializer.cpp b/Swiften/Serializer/PayloadSerializers/MUCUserPayloadSerializer.cpp index 0a8153d..68662b1 100644 --- a/Swiften/Serializer/PayloadSerializers/MUCUserPayloadSerializer.cpp +++ b/Swiften/Serializer/PayloadSerializers/MUCUserPayloadSerializer.cpp @@ -7,35 +7,44 @@ #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/XML/XMLRawTextNode.h> #include <Swiften/Serializer/PayloadSerializers/MUCItemSerializer.h> +#include <Swiften/Serializer/PayloadSerializerCollection.h> namespace Swift { -MUCUserPayloadSerializer::MUCUserPayloadSerializer() : GenericPayloadSerializer<MUCUserPayload>() { +MUCUserPayloadSerializer::MUCUserPayloadSerializer(PayloadSerializerCollection* serializers) : GenericPayloadSerializer<MUCUserPayload>(), serializers(serializers) { } 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 MUCItem item, payload->getItems()) { mucElement.addNode(MUCItemSerializer::itemToElement(item)); } + boost::shared_ptr<Payload> childPayload = payload->getPayload(); + if (childPayload) { + PayloadSerializer* serializer = serializers->getPayloadSerializer(childPayload); + if (serializer) { + mucElement.addNode(boost::shared_ptr<XMLRawTextNode>(new XMLRawTextNode(serializer->serialize(childPayload)))); + } + } return mucElement.serialize(); } } diff --git a/Swiften/Serializer/PayloadSerializers/MUCUserPayloadSerializer.h b/Swiften/Serializer/PayloadSerializers/MUCUserPayloadSerializer.h index 84c4a96..8c237e0 100644 --- a/Swiften/Serializer/PayloadSerializers/MUCUserPayloadSerializer.h +++ b/Swiften/Serializer/PayloadSerializers/MUCUserPayloadSerializer.h @@ -4,17 +4,20 @@ * See Documentation/Licenses/GPLv3.txt for more information. */ #pragma once #include <Swiften/Serializer/GenericPayloadSerializer.h> #include <Swiften/Elements/MUCUserPayload.h> namespace Swift { + class PayloadSerializerCollection; class MUCUserPayloadSerializer : public GenericPayloadSerializer<MUCUserPayload> { public: - MUCUserPayloadSerializer(); + MUCUserPayloadSerializer(PayloadSerializerCollection* serializers); virtual std::string serializePayload(boost::shared_ptr<MUCUserPayload> version) const; + private: + PayloadSerializerCollection* serializers; }; } |