From 1daf22de85758cfd035f1fcf6a70007315db4f28 Mon Sep 17 00:00:00 2001
From: Kevin Smith <git@kismith.co.uk>
Date: Wed, 28 Sep 2011 17:45:00 +0100
Subject: Destroy rooms.

Resolves: #990

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
@@ -73,6 +73,7 @@ MUCController::MUCController (
 	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));
@@ -598,4 +599,8 @@ 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
@@ -91,6 +91,7 @@ namespace Swift {
 			void handleConfigureRequest(Form::ref);
 			void handleConfigurationFailed(ErrorPayload::ref);
 			void handleConfigurationFormReceived(Form::ref);
+			void handleDestroyRoomRequest();
 
 		private:
 			MUC::ref muc_;
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
@@ -102,6 +102,7 @@ namespace Swift {
 			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;
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
@@ -700,6 +700,7 @@ 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;
@@ -711,6 +712,9 @@ void QtChatWindow::handleActionButtonClicked() {
 	else if (result == configure) {
 		onConfigureRequest(Form::ref());
 	}
+	else if (result == destroy) {
+		onDestroyRequest();
+	}
 }
 
 void QtChatWindow::showRoomConfigurationForm(Form::ref form) {
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
@@ -50,8 +50,17 @@ namespace Swift {
 
 			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
@@ -20,6 +20,7 @@
 #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>
 
@@ -276,6 +277,15 @@ void MUC::configureRoom(Form::ref form) {
 	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
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
@@ -60,6 +60,7 @@ namespace Swift {
 			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;
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
@@ -46,6 +46,7 @@
 #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>
@@ -103,9 +104,11 @@ FullPayloadParserFactoryCollection::FullPayloadParserFactoryCollection() {
 	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")));
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
@@ -8,22 +8,30 @@
 
 #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
@@ -13,8 +13,12 @@
 #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
@@ -10,8 +10,20 @@
 #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
@@ -9,6 +9,7 @@
 
 #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;
@@ -18,6 +19,7 @@ class MUCUserPayloadParserTest : public CppUnit::TestFixture
 		CPPUNIT_TEST_SUITE(MUCUserPayloadParserTest);
 		CPPUNIT_TEST(testParseEmpty);
 		CPPUNIT_TEST(testParse);
+		CPPUNIT_TEST(testParseDestroy);
 		CPPUNIT_TEST_SUITE_END();
 
 	public:
@@ -56,6 +58,19 @@ class MUCUserPayloadParserTest : public CppUnit::TestFixture
 			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
@@ -62,6 +62,7 @@ sources = [
 		"PayloadParsers/MUCUserPayloadParser.cpp",
 		"PayloadParsers/MUCAdminPayloadParser.cpp",
 		"PayloadParsers/MUCOwnerPayloadParser.cpp",
+		"PayloadParsers/MUCDestroyPayloadParser.cpp",
 		"PayloadParsers/MUCItemParser.cpp",
 		"PayloadParsers/NicknameParser.cpp",
 		"PayloadParsers/ReplaceParser.cpp",
@@ -78,6 +79,7 @@ sources = [
 		"StreamResumedParser.cpp",
 		"Tree/ParserElement.cpp",
 		"Tree/NullParserElement.cpp",
+		"Tree/TreeReparser.cpp",
 		"XMLParser.cpp",
 		"XMLParserClient.cpp",
 		"XMLParserFactory.cpp",
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
@@ -31,6 +31,7 @@ namespace Swift {
 			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() {
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
@@ -150,6 +150,7 @@ if env["SCONS_STAGE"] == "build" :
 			"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",
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
@@ -23,6 +23,7 @@
 #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>
@@ -71,9 +72,10 @@ FullPayloadSerializerCollection::FullPayloadSerializerCollection() {
 	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());
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
@@ -13,11 +13,13 @@
 #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 {
@@ -32,6 +34,13 @@ std::string MUCUserPayloadSerializer::serializePayload(boost::shared_ptr<MUCUser
 	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
@@ -10,11 +10,14 @@
 #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;
 	};
 }
 
-- 
cgit v0.10.2-6-g49f6