From 2fec654b2345ba974b843a0868d580f9c12fdfea Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be>
Date: Wed, 10 Nov 2010 23:02:28 +0100
Subject: Added InBandRegistration classes.


diff --git a/Swiften/Elements/InBandRegistrationPayload.h b/Swiften/Elements/InBandRegistrationPayload.h
new file mode 100644
index 0000000..6dafa04
--- /dev/null
+++ b/Swiften/Elements/InBandRegistrationPayload.h
@@ -0,0 +1,201 @@
+/*
+ * Copyright (c) 2010 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#pragma once
+
+#include <boost/shared_ptr.hpp>
+#include <boost/optional.hpp>
+
+#include "Swiften/Elements/Payload.h"
+#include "Swiften/Elements/Form.h"
+#include "Swiften/Base/String.h"
+
+namespace Swift {
+	class InBandRegistrationPayload : public Payload {
+		public:
+			typedef boost::shared_ptr<InBandRegistrationPayload> ref;
+
+			InBandRegistrationPayload() : registered(false) {}
+
+			Form::ref getForm() const { return form; }
+			void setForm(Form::ref f) { form = f; }
+
+			bool isRegistered() const {
+				return registered;
+			}
+
+			void setRegistered(bool b) {
+				registered = b;
+			}
+
+			const boost::optional<String>& getInstructions() const {
+				return instructions;
+			}
+
+			const boost::optional<String>& getUsername() const {
+				return username;
+			}
+
+			const boost::optional<String>& getNick() const {
+				return nick;
+			}
+
+			const boost::optional<String>& getPassword() const {
+				return password;
+			}
+
+			const boost::optional<String>& getName() const {
+				return name;
+			}
+
+			const boost::optional<String>& getFirst() const {
+				return first;
+			}
+
+			const boost::optional<String>& getLast() const {
+				return last;
+			}
+
+			const boost::optional<String>& getEMail() const {
+				return email;
+			}
+
+			const boost::optional<String>& getAddress() const {
+				return address;
+			}
+
+			const boost::optional<String>& getCity() const {
+				return city;
+			}
+
+			const boost::optional<String>& getState() const {
+				return state;
+			}
+
+			const boost::optional<String>& getZip() const {
+				return zip;
+			}
+
+			const boost::optional<String>& getPhone() const {
+				return phone;
+			}
+
+			const boost::optional<String>& getURL() const {
+				return url;
+			}
+
+			const boost::optional<String>& getDate() const {
+				return date;
+			}
+
+			const boost::optional<String>& getMisc() const {
+				return misc;
+			}
+
+			const boost::optional<String>& getText() const {
+				return text;
+			}
+
+			const boost::optional<String>& getKey() const {
+				return key;
+			}
+
+			void setInstructions(const String& v) {
+				this->instructions = v;
+			}
+
+			void setUsername(const String& v) {
+				this->username = v;
+			}
+
+			void setNick(const String& v) {
+				this->nick = v;
+			}
+
+			void setPassword(const String& v) {
+				this->password = v;
+			}
+
+			void setName(const String& v) {
+				this->name = v;
+			}
+
+			void setFirst(const String& v) {
+				this->first = v;
+			}
+
+			void setLast(const String& v) {
+				this->last = v;
+			}
+
+			void setEMail(const String& v) {
+				this->email = v;
+			}
+
+			void setAddress(const String& v) {
+				this->address = v;
+			}
+
+			void setCity(const String& v) {
+				this->city = v;
+			}
+
+			void setState(const String& v) {
+				this->state = v;
+			}
+
+			void setZip(const String& v) {
+				this->zip = v;
+			}
+
+			void setPhone(const String& v) {
+				this->phone = v;
+			}
+
+			void setURL(const String& v) {
+				this->url = v;
+			}
+
+			void setDate(const String& v) {
+				this->date = v;
+			}
+
+			void setMisc(const String& v) {
+				this->misc = v;
+			}
+
+			void setText(const String& v) {
+				this->text = v;
+			}
+
+			void setKey(const String& v) {
+				this->key = v;
+			}
+
+
+		private:
+			Form::ref form;
+			bool registered;
+			boost::optional<String> instructions;
+			boost::optional<String> username;
+			boost::optional<String> nick;
+			boost::optional<String> password;
+			boost::optional<String> name;
+			boost::optional<String> first;
+			boost::optional<String> last;
+			boost::optional<String> email;
+			boost::optional<String> address;
+			boost::optional<String> city;
+			boost::optional<String> state;
+			boost::optional<String> zip;
+			boost::optional<String> phone;
+			boost::optional<String> url;
+			boost::optional<String> date;
+			boost::optional<String> misc;
+			boost::optional<String> text;
+			boost::optional<String> key;
+	};
+}
diff --git a/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp b/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp
index 90e9038..41bba11 100644
--- a/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp
+++ b/Swiften/Parser/PayloadParsers/FullPayloadParserFactoryCollection.cpp
@@ -27,6 +27,7 @@
 #include "Swiften/Parser/PayloadParsers/SecurityLabelsCatalogParserFactory.h"
 #include "Swiften/Parser/PayloadParsers/FormParserFactory.h"
 #include "Swiften/Parser/PayloadParsers/CommandParserFactory.h"
+#include "Swiften/Parser/PayloadParsers/InBandRegistrationPayloadParserFactory.h"
 #include "Swiften/Parser/PayloadParsers/StreamInitiationParserFactory.h"
 #include "Swiften/Parser/PayloadParsers/BytestreamsParserFactory.h"
 #include "Swiften/Parser/PayloadParsers/IBBParserFactory.h"
@@ -62,6 +63,7 @@ FullPayloadParserFactoryCollection::FullPayloadParserFactoryCollection() {
 	factories_.push_back(shared_ptr<PayloadParserFactory>(new SecurityLabelsCatalogParserFactory()));
 	factories_.push_back(shared_ptr<PayloadParserFactory>(new FormParserFactory()));
 	factories_.push_back(shared_ptr<PayloadParserFactory>(new CommandParserFactory()));
+	factories_.push_back(shared_ptr<PayloadParserFactory>(new InBandRegistrationPayloadParserFactory()));
 	factories_.push_back(shared_ptr<PayloadParserFactory>(new StreamInitiationParserFactory()));
 	factories_.push_back(shared_ptr<PayloadParserFactory>(new BytestreamsParserFactory()));
 	factories_.push_back(shared_ptr<PayloadParserFactory>(new VCardUpdateParserFactory()));
diff --git a/Swiften/Parser/PayloadParsers/InBandRegistrationPayloadParser.cpp b/Swiften/Parser/PayloadParsers/InBandRegistrationPayloadParser.cpp
new file mode 100644
index 0000000..0e1b593
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/InBandRegistrationPayloadParser.cpp
@@ -0,0 +1,125 @@
+/*
+ * Copyright (c) 2010 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include "Swiften/Parser/PayloadParsers/InBandRegistrationPayloadParser.h"
+#include "Swiften/Parser/PayloadParsers/FormParserFactory.h"
+#include "Swiften/Parser/PayloadParsers/FormParser.h"
+
+namespace Swift {
+
+InBandRegistrationPayloadParser::InBandRegistrationPayloadParser() : level(TopLevel), formParser(NULL)  {
+	formParserFactory = new FormParserFactory();
+}
+
+InBandRegistrationPayloadParser::~InBandRegistrationPayloadParser() {
+	delete formParserFactory;
+}
+
+void InBandRegistrationPayloadParser::handleStartElement(const String& element, const String& ns, const AttributeMap& attributes) {
+	if (level == TopLevel) {
+	}
+	else if (level == PayloadLevel) {
+		if (element == "x" && ns == "jabber:x:data") {
+			assert(!formParser);
+			formParser = dynamic_cast<FormParser*>(formParserFactory->createPayloadParser());
+		}
+		else {
+			currentText.clear();
+		}
+	}
+
+	if (formParser) {
+		formParser->handleStartElement(element, ns, attributes);
+	}
+
+	++level;
+}
+
+void InBandRegistrationPayloadParser::handleEndElement(const String& element, const String& ns) {
+	--level;
+
+	if (formParser) {
+		formParser->handleEndElement(element, ns);
+	}
+
+	if (level == TopLevel) {
+	}
+	else if (level == PayloadLevel) {
+		if (formParser) {
+			getPayloadInternal()->setForm(formParser->getPayloadInternal());
+			delete formParser;
+			formParser = NULL;
+		}
+		else if (element == "registered") {
+			getPayloadInternal()->setRegistered(true);
+		}
+		else if (element == "instructions") {
+			getPayloadInternal()->setInstructions(currentText);
+		}
+		else if (element == "username") {
+			getPayloadInternal()->setUsername(currentText);
+		}
+		else if (element == "nick") {
+			getPayloadInternal()->setNick(currentText);
+		}
+		else if (element == "password") {
+			getPayloadInternal()->setPassword(currentText);
+		}
+		else if (element == "name") {
+			getPayloadInternal()->setName(currentText);
+		}
+		else if (element == "first") {
+			getPayloadInternal()->setFirst(currentText);
+		}
+		else if (element == "last") {
+			getPayloadInternal()->setLast(currentText);
+		}
+		else if (element == "email") {
+			getPayloadInternal()->setEMail(currentText);
+		}
+		else if (element == "address") {
+			getPayloadInternal()->setAddress(currentText);
+		}
+		else if (element == "city") {
+			getPayloadInternal()->setCity(currentText);
+		}
+		else if (element == "state") {
+			getPayloadInternal()->setState(currentText);
+		}
+		else if (element == "zip") {
+			getPayloadInternal()->setZip(currentText);
+		}
+		else if (element == "phone") {
+			getPayloadInternal()->setPhone(currentText);
+		}
+		else if (element == "url") {
+			getPayloadInternal()->setURL(currentText);
+		}
+		else if (element == "date") {
+			getPayloadInternal()->setDate(currentText);
+		}
+		else if (element == "misc") {
+			getPayloadInternal()->setMisc(currentText);
+		}
+		else if (element == "text") {
+			getPayloadInternal()->setText(currentText);
+		}
+		else if (element == "key") {
+			getPayloadInternal()->setKey(currentText);
+		}
+	}
+}
+
+void InBandRegistrationPayloadParser::handleCharacterData(const String& data) {
+	if (formParser) {
+		formParser->handleCharacterData(data);
+	}
+	else {
+		currentText += data;
+	}
+}
+
+}
diff --git a/Swiften/Parser/PayloadParsers/InBandRegistrationPayloadParser.h b/Swiften/Parser/PayloadParsers/InBandRegistrationPayloadParser.h
new file mode 100644
index 0000000..d616e70
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/InBandRegistrationPayloadParser.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (c) 2010 Remko Tronçon
+ * 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/InBandRegistrationPayload.h"
+#include "Swiften/Parser/GenericPayloadParser.h"
+
+namespace Swift {
+	class FormParserFactory;
+	class FormParser;
+
+	class InBandRegistrationPayloadParser : public GenericPayloadParser<InBandRegistrationPayload> {
+		public:
+			InBandRegistrationPayloadParser();
+			~InBandRegistrationPayloadParser();
+
+			virtual void handleStartElement(const String& element, const String&, const AttributeMap& attributes);
+			virtual void handleEndElement(const String& element, const String&);
+			virtual void handleCharacterData(const String& data);
+
+		private:
+			enum Level { 
+				TopLevel = 0, 
+				PayloadLevel = 1,
+			};
+			int level;
+			FormParserFactory* formParserFactory;
+			FormParser* formParser;
+			String currentText;
+	};
+}
diff --git a/Swiften/Parser/PayloadParsers/InBandRegistrationPayloadParserFactory.h b/Swiften/Parser/PayloadParsers/InBandRegistrationPayloadParserFactory.h
new file mode 100644
index 0000000..0417174
--- /dev/null
+++ b/Swiften/Parser/PayloadParsers/InBandRegistrationPayloadParserFactory.h
@@ -0,0 +1,17 @@
+/*
+ * Copyright (c) 2010 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#pragma once
+
+#include "Swiften/Parser/GenericPayloadParserFactory.h"
+#include "Swiften/Parser/PayloadParsers/InBandRegistrationPayloadParser.h"
+
+namespace Swift {
+	class InBandRegistrationPayloadParserFactory : public GenericPayloadParserFactory<InBandRegistrationPayloadParser> {
+		public:
+			InBandRegistrationPayloadParserFactory() : GenericPayloadParserFactory<InBandRegistrationPayloadParser>("query", "jabber:iq:register") {}
+	};
+}
diff --git a/Swiften/Parser/SConscript b/Swiften/Parser/SConscript
index 1eeb266..92d5aa9 100644
--- a/Swiften/Parser/SConscript
+++ b/Swiften/Parser/SConscript
@@ -29,6 +29,7 @@ sources = [
 		"PayloadParsers/FormParser.cpp",
 		"PayloadParsers/IBBParser.cpp",
 		"PayloadParsers/CommandParser.cpp",
+		"PayloadParsers/InBandRegistrationPayloadParser.cpp",
 		"PayloadParsers/FullPayloadParserFactoryCollection.cpp",
 		"PayloadParsers/PriorityParser.cpp",
 		"PayloadParsers/PrivateStorageParser.cpp",
diff --git a/Swiften/Queries/Requests/GetInBandRegistrationFormRequest.cpp b/Swiften/Queries/Requests/GetInBandRegistrationFormRequest.cpp
new file mode 100644
index 0000000..5f6be03
--- /dev/null
+++ b/Swiften/Queries/Requests/GetInBandRegistrationFormRequest.cpp
@@ -0,0 +1,7 @@
+/*
+ * Copyright (c) 2010 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include "Swiften/Queries/Requests/GetInBandRegistrationFormRequest.h"
diff --git a/Swiften/Queries/Requests/GetInBandRegistrationFormRequest.h b/Swiften/Queries/Requests/GetInBandRegistrationFormRequest.h
new file mode 100644
index 0000000..33bc156
--- /dev/null
+++ b/Swiften/Queries/Requests/GetInBandRegistrationFormRequest.h
@@ -0,0 +1,26 @@
+/*
+ * Copyright (c) 2010 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#pragma once
+
+#include "Swiften/Queries/GenericRequest.h"
+#include "Swiften/Elements/InBandRegistrationPayload.h"
+
+
+namespace Swift {
+	class GetInBandRegistrationFormRequest : public GenericRequest<InBandRegistrationPayload> {
+		public:
+			typedef boost::shared_ptr<GetInBandRegistrationFormRequest> ref;
+
+			static ref create(IQRouter* router) {
+				return ref(new GetInBandRegistrationFormRequest(router));
+			}
+
+		private:
+			GetInBandRegistrationFormRequest(IQRouter* router) : GenericRequest<InBandRegistrationPayload>(IQ::Get, JID(), InBandRegistrationPayload::ref(new InBandRegistrationPayload()), router) {
+			}
+	};
+}
diff --git a/Swiften/Queries/Requests/SubmitInBandRegistrationFormRequest.cpp b/Swiften/Queries/Requests/SubmitInBandRegistrationFormRequest.cpp
new file mode 100644
index 0000000..f28c878
--- /dev/null
+++ b/Swiften/Queries/Requests/SubmitInBandRegistrationFormRequest.cpp
@@ -0,0 +1,7 @@
+/*
+ * Copyright (c) 2010 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include "Swiften/Queries/Requests/SubmitInBandRegistrationFormRequest.h"
diff --git a/Swiften/Queries/Requests/SubmitInBandRegistrationFormRequest.h b/Swiften/Queries/Requests/SubmitInBandRegistrationFormRequest.h
new file mode 100644
index 0000000..3ed14bb
--- /dev/null
+++ b/Swiften/Queries/Requests/SubmitInBandRegistrationFormRequest.h
@@ -0,0 +1,36 @@
+/*
+ * Copyright (c) 2010 Kevin Smith
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#pragma once
+
+#include "Swiften/Base/boost_bsignals.h"
+#include <boost/shared_ptr.hpp>
+
+#include "Swiften/Queries/Request.h"
+#include "Swiften/Elements/InBandRegistrationPayload.h"
+
+
+namespace Swift {
+	class SetInBandRegistrationRequest : public Request {
+		public:
+			typedef boost::shared_ptr<SetInBandRegistrationRequest> ref;
+
+			static ref create(InBandRegistrationPayload::ref payload, IQRouter* router) {
+				return ref(new SetInBandRegistrationRequest(payload, router));
+			}
+
+		private:
+			SetInBandRegistrationRequest(InBandRegistrationPayload::ref payload, IQRouter* router) : Request(IQ::Set, JID(), InBandRegistrationPayload::ref(payload), router) {
+			}
+
+			virtual void handleResponse(Payload::ref payload, boost::optional<ErrorPayload> error) {
+				onResponse(payload, error);
+			}
+
+		public:
+			boost::signal<void (Payload::ref, const boost::optional<ErrorPayload>&)> onResponse;
+	};
+}
diff --git a/Swiften/SConscript b/Swiften/SConscript
index 28db30d..df34e8b 100644
--- a/Swiften/SConscript
+++ b/Swiften/SConscript
@@ -54,6 +54,8 @@ if env["SCONS_STAGE"] == "build" :
 			"Queries/IQHandler.cpp",
 			"Queries/IQRouter.cpp",
 			"Queries/Request.cpp",
+			"Queries/Requests/GetInBandRegistrationFormRequest.cpp",
+			"Queries/Requests/SubmitInBandRegistrationFormRequest.cpp",
 			"Queries/Responders/SoftwareVersionResponder.cpp",
 			"Roster/ContactRosterItem.cpp",
 			"Roster/GroupRosterItem.cpp",
@@ -95,6 +97,7 @@ if env["SCONS_STAGE"] == "build" :
 			"Serializer/PayloadSerializers/PrivateStorageSerializer.cpp",
 			"Serializer/PayloadSerializers/DelaySerializer.cpp",
 			"Serializer/PayloadSerializers/CommandSerializer.cpp",
+			"Serializer/PayloadSerializers/InBandRegistrationPayloadSerializer.cpp",
 			"Serializer/PayloadSerializers/FormSerializer.cpp",
 			"Serializer/PayloadSerializers/NicknameSerializer.cpp",
 			"Serializer/PresenceSerializer.cpp",
@@ -241,6 +244,7 @@ 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"),
diff --git a/Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.cpp b/Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.cpp
index 0dc4b2d..f57411b 100644
--- a/Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.cpp
+++ b/Swiften/Serializer/PayloadSerializers/FullPayloadSerializerCollection.cpp
@@ -37,6 +37,7 @@
 #include "Swiften/Serializer/PayloadSerializers/DelaySerializer.h"
 #include "Swiften/Serializer/PayloadSerializers/FormSerializer.h"
 #include "Swiften/Serializer/PayloadSerializers/CommandSerializer.h"
+#include "Swiften/Serializer/PayloadSerializers/InBandRegistrationPayloadSerializer.h"
 #include "Swiften/Serializer/PayloadSerializers/NicknameSerializer.h"
 
 namespace Swift {
@@ -72,6 +73,7 @@ FullPayloadSerializerCollection::FullPayloadSerializerCollection() {
 	serializers_.push_back(new FormSerializer());
 	serializers_.push_back(new PrivateStorageSerializer(this));
 	serializers_.push_back(new CommandSerializer());
+	serializers_.push_back(new InBandRegistrationPayloadSerializer());
 	serializers_.push_back(new NicknameSerializer());
 	foreach(PayloadSerializer* serializer, serializers_) {
 		addSerializer(serializer);
diff --git a/Swiften/Serializer/PayloadSerializers/InBandRegistrationPayloadSerializer.cpp b/Swiften/Serializer/PayloadSerializers/InBandRegistrationPayloadSerializer.cpp
new file mode 100644
index 0000000..8e8bcf2
--- /dev/null
+++ b/Swiften/Serializer/PayloadSerializers/InBandRegistrationPayloadSerializer.cpp
@@ -0,0 +1,108 @@
+/*
+ * Copyright (c) 2010 Remko Tronçon
+ * Licensed under the GNU General Public License v3.
+ * See Documentation/Licenses/GPLv3.txt for more information.
+ */
+
+#include "Swiften/Serializer/PayloadSerializers/InBandRegistrationPayloadSerializer.h"
+
+#include <boost/shared_ptr.hpp>
+
+#include "Swiften/Base/foreach.h"
+#include "Swiften/Serializer/XML/XMLElement.h"
+#include "Swiften/Serializer/XML/XMLRawTextNode.h"
+#include "Swiften/Serializer/PayloadSerializers/FormSerializer.h"
+
+namespace Swift {
+
+InBandRegistrationPayloadSerializer::InBandRegistrationPayloadSerializer() {
+}
+
+String InBandRegistrationPayloadSerializer::serializePayload(boost::shared_ptr<InBandRegistrationPayload> registration)	const {
+	XMLElement registerElement("query", "jabber:iq:register");
+
+	if (registration->isRegistered()) {
+		registerElement.addNode(XMLElement::ref(new XMLElement("registered")));
+	}
+
+	if (registration->getInstructions()) {
+		registerElement.addNode(XMLElement::ref(new XMLElement("instructions", "", *registration->getInstructions())));
+	}
+
+
+	if (registration->getUsername()) {
+		registerElement.addNode(XMLElement::ref(new XMLElement("username", "", *registration->getUsername())));
+	}
+
+	if (registration->getNick()) {
+		registerElement.addNode(XMLElement::ref(new XMLElement("nick", "", *registration->getNick())));
+	}
+
+	if (registration->getPassword()) {
+		registerElement.addNode(XMLElement::ref(new XMLElement("password", "", *registration->getPassword())));
+	}
+
+	if (registration->getName()) {
+		registerElement.addNode(XMLElement::ref(new XMLElement("name", "", *registration->getName())));
+	}
+
+	if (registration->getFirst()) {
+		registerElement.addNode(XMLElement::ref(new XMLElement("first", "", *registration->getFirst())));
+	}
+
+	if (registration->getLast()) {
+		registerElement.addNode(XMLElement::ref(new XMLElement("last", "", *registration->getLast())));
+	}
+
+	if (registration->getEMail()) {
+		registerElement.addNode(XMLElement::ref(new XMLElement("email", "", *registration->getEMail())));
+	}
+
+	if (registration->getAddress()) {
+		registerElement.addNode(XMLElement::ref(new XMLElement("address", "", *registration->getAddress())));
+	}
+
+	if (registration->getCity()) {
+		registerElement.addNode(XMLElement::ref(new XMLElement("city", "", *registration->getCity())));
+	}
+
+	if (registration->getState()) {
+		registerElement.addNode(XMLElement::ref(new XMLElement("state", "", *registration->getState())));
+	}
+
+	if (registration->getZip()) {
+		registerElement.addNode(XMLElement::ref(new XMLElement("zip", "", *registration->getZip())));
+	}
+
+	if (registration->getPhone()) {
+		registerElement.addNode(XMLElement::ref(new XMLElement("phone", "", *registration->getPhone())));
+	}
+
+	if (registration->getURL()) {
+		registerElement.addNode(XMLElement::ref(new XMLElement("url", "", *registration->getURL())));
+	}
+
+	if (registration->getDate()) {
+		registerElement.addNode(XMLElement::ref(new XMLElement("date", "", *registration->getDate())));
+	}
+
+	if (registration->getMisc()) {
+		registerElement.addNode(XMLElement::ref(new XMLElement("misc", "", *registration->getMisc())));
+	}
+
+	if (registration->getText()) {
+		registerElement.addNode(XMLElement::ref(new XMLElement("text", "", *registration->getText())));
+	}
+
+	if (registration->getKey()) {
+		registerElement.addNode(XMLElement::ref(new XMLElement("key", "", *registration->getKey())));
+	}
+
+	if (Form::ref form = registration->getForm()) {
+		registerElement.addNode(boost::shared_ptr<XMLRawTextNode>(new XMLRawTextNode(FormSerializer().serialize(form))));
+	}
+
+	return registerElement.serialize();
+}
+
+}
diff --git a/Swiften/Serializer/PayloadSerializers/InBandRegistrationPayloadSerializer.h b/Swiften/Serializer/PayloadSerializers/InBandRegistrationPayloadSerializer.h
new file mode 100644
index 0000000..168aa3a
--- /dev/null
+++ b/Swiften/Serializer/PayloadSerializers/InBandRegistrationPayloadSerializer.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (c) 2010 Remko Tronçon
+ * 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/InBandRegistrationPayload.h"
+
+namespace Swift {
+	class PayloadSerializerCollection;
+
+	class InBandRegistrationPayloadSerializer : public GenericPayloadSerializer<InBandRegistrationPayload> {
+		public:
+			InBandRegistrationPayloadSerializer();
+
+			virtual String serializePayload(boost::shared_ptr<InBandRegistrationPayload>)  const;
+	};
+}
diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/InBandRegistrationPayloadSerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/InBandRegistrationPayloadSerializerTest.cpp
new file mode 100644
index 0000000..1654abc
--- /dev/null
+++ b/Swiften/Serializer/PayloadSerializers/UnitTest/InBandRegistrationPayloadSerializerTest.cpp
@@ -0,0 +1,61 @@
+/*
+ * Copyright (c) 2010 Remko Tronçon
+ * 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/Serializer/PayloadSerializers/InBandRegistrationPayloadSerializer.h"
+
+using namespace Swift;
+
+class InBandRegistrationPayloadSerializerTest : public CppUnit::TestFixture {
+		CPPUNIT_TEST_SUITE(InBandRegistrationPayloadSerializerTest);
+		CPPUNIT_TEST(testSerialize);
+		CPPUNIT_TEST(testSerialize_Form);
+		CPPUNIT_TEST_SUITE_END();
+
+	public:
+		void testSerialize() {
+			InBandRegistrationPayloadSerializer testling;
+			boost::shared_ptr<InBandRegistrationPayload> registration(new InBandRegistrationPayload());
+			registration->setRegistered(true);
+
+			String expectedResult = 
+				"<query xmlns=\"jabber:iq:register\">"
+					"<registered/>"
+				"</query>";
+
+			CPPUNIT_ASSERT_EQUAL(expectedResult, testling.serialize(registration));
+		}
+		void testSerialize_Form() {
+			InBandRegistrationPayloadSerializer testling;
+			boost::shared_ptr<InBandRegistrationPayload> registration(new InBandRegistrationPayload());
+			registration->setInstructions("Use the enclosed form to register.");
+
+			boost::shared_ptr<Form> form(new Form(Form::FormType));
+			form->setTitle("Contest Registration");
+
+			FormField::ref field = HiddenFormField::create("jabber:iq:register");
+			field->setName("FORM_TYPE");
+			form->addField(field);
+			registration->setForm(form);
+
+			String expectedResult = 
+				"<query xmlns=\"jabber:iq:register\">"
+					"<instructions>Use the enclosed form to register.</instructions>"
+					"<x type=\"form\" xmlns=\"jabber:x:data\">"
+						"<title>Contest Registration</title>"
+						"<field type=\"hidden\" var=\"FORM_TYPE\">"
+							"<value>jabber:iq:register</value>"
+						"</field>"
+					"</x>"
+				"</query>";
+
+			CPPUNIT_ASSERT_EQUAL(expectedResult, testling.serialize(registration));
+		}
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(InBandRegistrationPayloadSerializerTest);
diff --git a/Swiften/Serializer/XML/XMLElement.cpp b/Swiften/Serializer/XML/XMLElement.cpp
index d88ff08..289ce31 100644
--- a/Swiften/Serializer/XML/XMLElement.cpp
+++ b/Swiften/Serializer/XML/XMLElement.cpp
@@ -7,14 +7,17 @@
 #include "Swiften/Serializer/XML/XMLElement.h"
 
 #include "Swiften/Base/foreach.h"
+#include "Swiften/Serializer/XML/XMLTextNode.h"
 
 namespace Swift {
 
-XMLElement::XMLElement(const String& tag, const String& xmlns) : 
-		tag_(tag) {
+XMLElement::XMLElement(const String& tag, const String& xmlns, const String& text) : tag_(tag) {
 	if (!xmlns.isEmpty()) {
 		setAttribute("xmlns", xmlns);
 	}
+	if (!text.isEmpty()) {
+		addNode(XMLTextNode::ref(new XMLTextNode(text)));
+	}
 }
 
 String XMLElement::serialize() {
diff --git a/Swiften/Serializer/XML/XMLElement.h b/Swiften/Serializer/XML/XMLElement.h
index cac29f1..b350344 100644
--- a/Swiften/Serializer/XML/XMLElement.h
+++ b/Swiften/Serializer/XML/XMLElement.h
@@ -19,7 +19,7 @@ namespace Swift {
 		public:
 			typedef boost::shared_ptr<XMLElement> ref;
 
-			XMLElement(const String& tag, const String& xmlns = "");
+			XMLElement(const String& tag, const String& xmlns = "", const String& text = "");
 
 			void setAttribute(const String& attribute, const String& value);
 			void addNode(boost::shared_ptr<XMLNode> node);
-- 
cgit v0.10.2-6-g49f6