From 1e2c3461458f4274d539daf51507ce81d845cce0 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Remko=20Tron=C3=A7on?= <git@el-tramo.be>
Date: Mon, 6 Sep 2010 11:19:02 +0200
Subject: Partial VCard support without losing unknown data.


diff --git a/Slimber/Server.cpp b/Slimber/Server.cpp
index 7ec3b66..734f3b8 100644
--- a/Slimber/Server.cpp
+++ b/Slimber/Server.cpp
@@ -407,8 +407,8 @@ LinkLocalServiceInfo Server::getLinkLocalServiceInfo(boost::shared_ptr<Presence>
 	if (!vcard->getNickname().isEmpty()) {
 		info.setNick(vcard->getNickname());
 	}
-	if (!vcard->getEMail().isEmpty()) {
-		info.setEMail(vcard->getEMail());
+	if (!vcard->getPreferredEMailAddress().address.isEmpty()) {
+		info.setEMail(vcard->getPreferredEMailAddress().address);
 	}
 	info.setMessage(presence->getStatus());
 	switch (presence->getShow()) {
diff --git a/Swiften/Elements/VCard.cpp b/Swiften/Elements/VCard.cpp
new file mode 100644
index 0000000..8262e07
--- /dev/null
+++ b/Swiften/Elements/VCard.cpp
@@ -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.
+ */
+
+#include "Swiften/Elements/VCard.h"
+
+#include "Swiften/Base/foreach.h"
+
+namespace Swift {
+
+VCard::EMailAddress VCard::getPreferredEMailAddress() const {
+	foreach(const EMailAddress& address, emailAddresses_) {
+		if (address.isPreferred) {
+			return address;
+		}
+	}
+	if (emailAddresses_.size() > 0) {
+		return emailAddresses_[0];
+	}
+	return EMailAddress();
+}
+
+
+}
diff --git a/Swiften/Elements/VCard.h b/Swiften/Elements/VCard.h
index 60f94b1..15173f1 100644
--- a/Swiften/Elements/VCard.h
+++ b/Swiften/Elements/VCard.h
@@ -14,8 +14,23 @@
 namespace Swift {
 	class VCard : public Payload, public Shared<VCard> {
 		public:
+			struct EMailAddress {
+				EMailAddress() : isHome(false), isWork(false), isInternet(false), isPreferred(false), isX400(false) {
+				}
+
+				bool isHome;
+				bool isWork;
+				bool isInternet;
+				bool isPreferred;
+				bool isX400;
+				String address;
+			};
+
 			VCard() {}
 
+			void setVersion(const String& version) { version_ = version; }
+			const String& getVersion() const { return version_; }
+
 			void setFullName(const String& fullName) { fullName_ = fullName; }
 			const String& getFullName() const { return fullName_; }
 
@@ -25,8 +40,18 @@ namespace Swift {
 			void setGivenName(const String& givenName) { givenName_ = givenName; }
 			const String& getGivenName() const { return givenName_; }
 
-			void setEMail(const String& email) { email_ = email; }
-			const String& getEMail() const { return email_; }
+			void setMiddleName(const String& middleName) { middleName_ = middleName; }
+			const String& getMiddleName() const { return middleName_; }
+
+			void setPrefix(const String& prefix) { prefix_ = prefix; }
+			const String& getPrefix() const { return prefix_; }
+
+			void setSuffix(const String& suffix) { suffix_ = suffix; }
+			const String& getSuffix() const { return suffix_; }
+
+
+			//void setEMailAddress(const String& email) { email_ = email; }
+			//const String& getEMailAddress() const { return email_; }
 
 			void setNickname(const String& nick) { nick_ = nick; }
 			const String& getNickname() const { return nick_; }
@@ -37,13 +62,34 @@ namespace Swift {
 			void setPhotoType(const String& photoType) { photoType_ = photoType; }
 			const String& getPhotoType() { return photoType_; }
 
+			const String& getUnknownContent() const { return unknownContent_; }
+			void addUnknownContent(const String& c) { 
+				unknownContent_ += c;
+			}
+
+			const std::vector<EMailAddress> getEMailAddresses() const {
+				return emailAddresses_;
+			}
+
+			void addEMailAddress(const EMailAddress& email) {
+				emailAddresses_.push_back(email);
+			}
+
+			EMailAddress getPreferredEMailAddress() const;
+
 		private:
+			String version_;
 			String fullName_;
 			String familyName_;
 			String givenName_;
-			String email_;
+			String middleName_;
+			String prefix_;
+			String suffix_;
+			//String email_;
 			ByteArray photo_;
 			String photoType_;
 			String nick_;
+			String unknownContent_;
+			std::vector<EMailAddress> emailAddresses_;
 	};
 }
diff --git a/Swiften/Parser/PayloadParsers/RosterParser.cpp b/Swiften/Parser/PayloadParsers/RosterParser.cpp
index c3a35b6..6db2b30 100644
--- a/Swiften/Parser/PayloadParsers/RosterParser.cpp
+++ b/Swiften/Parser/PayloadParsers/RosterParser.cpp
@@ -71,6 +71,7 @@ void RosterParser::handleEndElement(const String& element, const String& ns) {
 		if (unknownContentParser_) {
 			unknownContentParser_->handleEndElement(element, ns);
 			currentItem_.addUnknownContent(unknownContentParser_->getResult());
+			delete unknownContentParser_;
 			unknownContentParser_ = NULL;
 		}
 		else if (element == "group") {
diff --git a/Swiften/Parser/PayloadParsers/UnitTest/VCardParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/VCardParserTest.cpp
index 999eb34..dfcc0ec 100644
--- a/Swiften/Parser/PayloadParsers/UnitTest/VCardParserTest.cpp
+++ b/Swiften/Parser/PayloadParsers/UnitTest/VCardParserTest.cpp
@@ -12,15 +12,68 @@
 
 using namespace Swift;
 
-class VCardParserTest : public CppUnit::TestFixture
-{
+class VCardParserTest : public CppUnit::TestFixture {
 		CPPUNIT_TEST_SUITE(VCardParserTest);
+		CPPUNIT_TEST(testParse);
 		CPPUNIT_TEST(testParse_Photo);
 		CPPUNIT_TEST(testParse_Nickname);
 		CPPUNIT_TEST_SUITE_END();
 
 	public:
-		VCardParserTest() {}
+		void testParse() {
+			PayloadsParserTester parser;
+
+			CPPUNIT_ASSERT(parser.parse(
+				"<vCard xmlns=\"vcard-temp\">"
+					"<VERSION>2.0</VERSION>"
+					"<FN>Alice In Wonderland</FN>"
+					"<N>"
+						"<FAMILY>Wonderland</FAMILY>"
+						"<GIVEN>Alice</GIVEN>"
+						"<MIDDLE>In</MIDDLE>"
+						"<PREFIX>Mrs</PREFIX>"
+						"<SUFFIX>PhD</SUFFIX>"
+					"</N>"
+					"<EMAIL>"
+						"<USERID>alice@wonderland.lit</USERID>"
+						"<HOME/>"
+						"<INTERNET/>"
+						"<PREF/>"
+					"</EMAIL>"
+					"<EMAIL>"
+						"<USERID>alice@teaparty.lit</USERID>"
+						"<WORK/>"
+						"<X400/>"
+					"</EMAIL>"
+					"<NICKNAME>DreamGirl</NICKNAME>"
+					"<BDAY>1234</BDAY>"
+					"<MAILER>mutt</MAILER>"
+				"</vCard>"));
+
+			boost::shared_ptr<VCard> payload = boost::dynamic_pointer_cast<VCard>(parser.getPayload());
+			CPPUNIT_ASSERT_EQUAL(String("2.0"), payload->getVersion());
+			CPPUNIT_ASSERT_EQUAL(String("Alice In Wonderland"), payload->getFullName());
+			CPPUNIT_ASSERT_EQUAL(String("Alice"), payload->getGivenName());
+			CPPUNIT_ASSERT_EQUAL(String("In"), payload->getMiddleName());
+			CPPUNIT_ASSERT_EQUAL(String("Wonderland"), payload->getFamilyName());
+			CPPUNIT_ASSERT_EQUAL(String("Mrs"), payload->getPrefix());
+			CPPUNIT_ASSERT_EQUAL(String("PhD"), payload->getSuffix());
+			CPPUNIT_ASSERT_EQUAL(String("DreamGirl"), payload->getNickname());
+			CPPUNIT_ASSERT_EQUAL(String("<BDAY xmlns=\"vcard-temp\">1234</BDAY><MAILER xmlns=\"vcard-temp\">mutt</MAILER>"), payload->getUnknownContent());
+			CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(payload->getEMailAddresses().size()));
+			CPPUNIT_ASSERT_EQUAL(String("alice@wonderland.lit"), payload->getEMailAddresses()[0].address);
+			CPPUNIT_ASSERT(payload->getEMailAddresses()[0].isHome);
+			CPPUNIT_ASSERT(payload->getEMailAddresses()[0].isInternet);
+			CPPUNIT_ASSERT(payload->getEMailAddresses()[0].isPreferred);
+			CPPUNIT_ASSERT(!payload->getEMailAddresses()[0].isWork);
+			CPPUNIT_ASSERT(!payload->getEMailAddresses()[0].isX400);
+			CPPUNIT_ASSERT_EQUAL(String("alice@teaparty.lit"), payload->getEMailAddresses()[1].address);
+			CPPUNIT_ASSERT(!payload->getEMailAddresses()[1].isHome);
+			CPPUNIT_ASSERT(!payload->getEMailAddresses()[1].isInternet);
+			CPPUNIT_ASSERT(!payload->getEMailAddresses()[1].isPreferred);
+			CPPUNIT_ASSERT(payload->getEMailAddresses()[1].isWork);
+			CPPUNIT_ASSERT(payload->getEMailAddresses()[1].isX400);
+		}
 
 		void testParse_Photo() {
 			PayloadsParserTester parser;
diff --git a/Swiften/Parser/PayloadParsers/VCardParser.cpp b/Swiften/Parser/PayloadParsers/VCardParser.cpp
index 338efc6..2f1f8dc 100644
--- a/Swiften/Parser/PayloadParsers/VCardParser.cpp
+++ b/Swiften/Parser/PayloadParsers/VCardParser.cpp
@@ -7,27 +7,39 @@
 #include "Swiften/Parser/PayloadParsers/VCardParser.h"
 #include "Swiften/Base/foreach.h"
 #include "Swiften/StringCodecs/Base64.h"
+#include "Swiften/Parser/SerializingParser.h"
 
 namespace Swift {
 
-VCardParser::VCardParser() {
+VCardParser::VCardParser() : unknownContentParser_(NULL) {
 }
 
-void VCardParser::handleStartElement(const String& element, const String&, const AttributeMap&) {
+void VCardParser::handleStartElement(const String& element, const String& ns, const AttributeMap& attributes) {
 	elementStack_.push_back(element);
+	String elementHierarchy = getElementHierarchy();
+	if (elementHierarchy == "/vCard/EMAIL") {
+		currentEMailAddress_ = VCard::EMailAddress();
+	}
+	if (elementStack_.size() == 2) {
+		assert(!unknownContentParser_);
+		unknownContentParser_ = new SerializingParser();
+		unknownContentParser_->handleStartElement(element, ns, attributes);
+	}
+	else if (unknownContentParser_) {
+		unknownContentParser_->handleStartElement(element, ns, attributes);
+	}
+
 	currentText_ = "";
 }
 
-void VCardParser::handleEndElement(const String&, const String&) {
-	String elementHierarchy = getElementHierarchy();
-	if (elementHierarchy == "/vCard/PHOTO/TYPE") {
-		getPayloadInternal()->setPhotoType(currentText_);
-	}
-	else if (elementHierarchy == "/vCard/PHOTO/BINVAL") {
-		getPayloadInternal()->setPhoto(Base64::decode(currentText_));
+void VCardParser::handleEndElement(const String& element, const String& ns) {
+	if (unknownContentParser_) {
+		unknownContentParser_->handleEndElement(element, ns);
 	}
-	else if (elementHierarchy == "/vCard/NICKNAME") {
-		getPayloadInternal()->setNickname(currentText_);
+
+	String elementHierarchy = getElementHierarchy();
+	if (elementHierarchy == "/vCard/VERSION") {
+		getPayloadInternal()->setVersion(currentText_);
 	}
 	else if (elementHierarchy == "/vCard/FN") {
 		getPayloadInternal()->setFullName(currentText_);
@@ -38,13 +50,64 @@ void VCardParser::handleEndElement(const String&, const String&) {
 	else if (elementHierarchy == "/vCard/N/GIVEN") {
 		getPayloadInternal()->setGivenName(currentText_);
 	}
+	else if (elementHierarchy == "/vCard/N/MIDDLE") {
+		getPayloadInternal()->setMiddleName(currentText_);
+	}
+	else if (elementHierarchy == "/vCard/N/PREFIX") {
+		getPayloadInternal()->setPrefix(currentText_);
+	}
+	else if (elementHierarchy == "/vCard/N/SUFFIX") {
+		getPayloadInternal()->setSuffix(currentText_);
+	}
+	else if (elementHierarchy == "/vCard/N") {
+	}
+	else if (elementHierarchy == "/vCard/NICKNAME") {
+		getPayloadInternal()->setNickname(currentText_);
+	}
+	else if (elementHierarchy == "/vCard/PHOTO/TYPE") {
+		getPayloadInternal()->setPhotoType(currentText_);
+	}
+	else if (elementHierarchy == "/vCard/PHOTO/BINVAL") {
+		getPayloadInternal()->setPhoto(Base64::decode(currentText_));
+	}
+	else if (elementHierarchy == "/vCard/PHOTO") {
+	}
 	else if (elementHierarchy == "/vCard/EMAIL/USERID") {
-		getPayloadInternal()->setEMail(currentText_);
+		currentEMailAddress_.address = currentText_;
+	}
+	else if (elementHierarchy == "/vCard/EMAIL/HOME") {
+		currentEMailAddress_.isHome = true;
+	}
+	else if (elementHierarchy == "/vCard/EMAIL/WORK") {
+		currentEMailAddress_.isWork = true;
+	}
+	else if (elementHierarchy == "/vCard/EMAIL/INTERNET") {
+		currentEMailAddress_.isInternet = true;
+	}
+	else if (elementHierarchy == "/vCard/EMAIL/X400") {
+		currentEMailAddress_.isX400 = true;
+	}
+	else if (elementHierarchy == "/vCard/EMAIL/PREF") {
+		currentEMailAddress_.isPreferred = true;
+	}
+	else if (elementHierarchy == "/vCard/EMAIL") {
+		getPayloadInternal()->addEMailAddress(currentEMailAddress_);
+	}
+	else if (elementStack_.size() == 2 && unknownContentParser_) {
+		getPayloadInternal()->addUnknownContent(unknownContentParser_->getResult());
+	}
+
+	if (elementStack_.size() == 2 && unknownContentParser_) {
+		delete unknownContentParser_;
+		unknownContentParser_ = NULL;
 	}
 	elementStack_.pop_back();
 }
 
 void VCardParser::handleCharacterData(const String& text) {
+	if (unknownContentParser_) {
+		unknownContentParser_->handleCharacterData(text);
+	}
 	currentText_ += text;
 }
 
diff --git a/Swiften/Parser/PayloadParsers/VCardParser.h b/Swiften/Parser/PayloadParsers/VCardParser.h
index d22f8f5..f912ff1 100644
--- a/Swiften/Parser/PayloadParsers/VCardParser.h
+++ b/Swiften/Parser/PayloadParsers/VCardParser.h
@@ -25,6 +25,8 @@ namespace Swift {
 
 		private:
 			std::vector<String> elementStack_;
+			VCard::EMailAddress currentEMailAddress_;
+			SerializingParser* unknownContentParser_;
 			String currentText_;
 	};
 }
diff --git a/Swiften/SConscript b/Swiften/SConscript
index a23efa0..3d82cfa 100644
--- a/Swiften/SConscript
+++ b/Swiften/SConscript
@@ -43,6 +43,7 @@ if env["SCONS_STAGE"] == "build" :
 			"Elements/Payload.cpp",
 			"Elements/RosterPayload.cpp",
 			"Elements/Stanza.cpp",
+			"Elements/VCard.cpp",
 			"MUC/MUC.cpp",
 			"MUC/MUCOccupant.cpp",
 			"MUC/MUCRegistry.cpp",
@@ -218,6 +219,7 @@ if env["SCONS_STAGE"] == "build" :
 			File("Serializer/PayloadSerializers/UnitTest/StatusSerializerTest.cpp"),
 			File("Serializer/PayloadSerializers/UnitTest/StatusShowSerializerTest.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/UnitTest/StreamFeaturesSerializerTest.cpp"),
diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/VCardSerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/VCardSerializerTest.cpp
new file mode 100644
index 0000000..11b24dc
--- /dev/null
+++ b/Swiften/Serializer/PayloadSerializers/UnitTest/VCardSerializerTest.cpp
@@ -0,0 +1,84 @@
+/*
+ * 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/VCardSerializer.h"
+
+using namespace Swift;
+
+class VCardSerializerTest : public CppUnit::TestFixture
+{
+		CPPUNIT_TEST_SUITE(VCardSerializerTest);
+		CPPUNIT_TEST(testSerialize);
+		CPPUNIT_TEST_SUITE_END();
+
+	public:
+		void testSerialize() {
+			VCardSerializer testling;
+			boost::shared_ptr<VCard> vcard(new VCard());
+			vcard->setVersion("2.0");
+			vcard->setFullName("Alice In Wonderland");
+			vcard->setPrefix("Mrs");
+			vcard->setGivenName("Alice");
+			vcard->setMiddleName("In");
+			vcard->setFamilyName("Wonderland");
+			vcard->setSuffix("PhD");
+			vcard->setNickname("DreamGirl");
+			vcard->setPhoto("abcdef");
+			vcard->setPhotoType("image/png");
+			vcard->addUnknownContent("<BDAY>1234</BDAY><MAILER>mutt</MAILER>");
+
+			VCard::EMailAddress address1;
+			address1.address = "alice@wonderland.lit";
+			address1.isHome = true;
+			address1.isPreferred = true;
+			address1.isInternet = true;
+			vcard->addEMailAddress(address1);
+
+			VCard::EMailAddress address2;
+			address2.address = "alice@teaparty.lit";
+			address2.isWork = true;
+			address2.isX400 = true;
+			vcard->addEMailAddress(address2);
+
+			String expectedResult = 
+				"<vCard xmlns=\"vcard-temp\">"
+					"<VERSION>2.0</VERSION>"
+					"<FN>Alice In Wonderland</FN>"
+					"<N>"
+						"<FAMILY>Wonderland</FAMILY>"
+						"<GIVEN>Alice</GIVEN>"
+						"<MIDDLE>In</MIDDLE>"
+						"<PREFIX>Mrs</PREFIX>"
+						"<SUFFIX>PhD</SUFFIX>"
+					"</N>"
+					"<EMAIL>"
+						"<USERID>alice@wonderland.lit</USERID>"
+						"<HOME/>"
+						"<INTERNET/>"
+						"<PREF/>"
+					"</EMAIL>"
+					"<EMAIL>"
+						"<USERID>alice@teaparty.lit</USERID>"
+						"<WORK/>"
+						"<X400/>"
+					"</EMAIL>"
+					"<NICKNAME>DreamGirl</NICKNAME>"
+					"<PHOTO>"
+						"<TYPE>image/png</TYPE>"
+						"<BINVAL>616263646566</BINVAL>"
+					"</PHOTO>"
+					"<BDAY>1234</BDAY>"
+					"<MAILER>mutt</MAILER>"
+				"</vCard>";
+
+			CPPUNIT_ASSERT_EQUAL(expectedResult, testling.serialize(vcard));
+		}
+};
+
+CPPUNIT_TEST_SUITE_REGISTRATION(VCardSerializerTest);
diff --git a/Swiften/Serializer/PayloadSerializers/VCardSerializer.cpp b/Swiften/Serializer/PayloadSerializers/VCardSerializer.cpp
index 8975818..5953ef6 100644
--- a/Swiften/Serializer/PayloadSerializers/VCardSerializer.cpp
+++ b/Swiften/Serializer/PayloadSerializers/VCardSerializer.cpp
@@ -10,7 +10,9 @@
 
 #include "Swiften/Serializer/XML/XMLElement.h"
 #include "Swiften/Serializer/XML/XMLTextNode.h"
+#include "Swiften/Serializer/XML/XMLRawTextNode.h"
 #include "Swiften/StringCodecs/Hexify.h"
+#include "Swiften/Base/foreach.h"
 
 namespace Swift {
 
@@ -19,12 +21,17 @@ VCardSerializer::VCardSerializer() : GenericPayloadSerializer<VCard>() {
 
 String VCardSerializer::serializePayload(boost::shared_ptr<VCard> vcard)  const {
 	XMLElement queryElement("vCard", "vcard-temp");
+	if (!vcard->getVersion().isEmpty()) {
+		boost::shared_ptr<XMLElement> versionElement(new XMLElement("VERSION"));
+		versionElement->addNode(boost::shared_ptr<XMLTextNode>(new XMLTextNode(vcard->getVersion())));
+		queryElement.addNode(versionElement);
+	}
 	if (!vcard->getFullName().isEmpty()) {
 		boost::shared_ptr<XMLElement> fullNameElement(new XMLElement("FN"));
 		fullNameElement->addNode(boost::shared_ptr<XMLTextNode>(new XMLTextNode(vcard->getFullName())));
 		queryElement.addNode(fullNameElement);
 	}
-	if (!vcard->getGivenName().isEmpty() || !vcard->getFamilyName().isEmpty()) {
+	if (!vcard->getGivenName().isEmpty() || !vcard->getFamilyName().isEmpty() || !vcard->getMiddleName().isEmpty() || !vcard->getPrefix().isEmpty() || !vcard->getSuffix().isEmpty()) {
 		boost::shared_ptr<XMLElement> nameElement(new XMLElement("N"));
 		if (!vcard->getFamilyName().isEmpty()) {
 			boost::shared_ptr<XMLElement> familyNameElement(new XMLElement("FAMILY"));
@@ -36,13 +43,43 @@ String VCardSerializer::serializePayload(boost::shared_ptr<VCard> vcard)  const
 			givenNameElement->addNode(boost::shared_ptr<XMLTextNode>(new XMLTextNode(vcard->getGivenName())));
 			nameElement->addNode(givenNameElement);
 		}
+		if (!vcard->getMiddleName().isEmpty()) {
+			boost::shared_ptr<XMLElement> middleNameElement(new XMLElement("MIDDLE"));
+			middleNameElement->addNode(boost::shared_ptr<XMLTextNode>(new XMLTextNode(vcard->getMiddleName())));
+			nameElement->addNode(middleNameElement);
+		}
+		if (!vcard->getPrefix().isEmpty()) {
+			boost::shared_ptr<XMLElement> prefixElement(new XMLElement("PREFIX"));
+			prefixElement->addNode(boost::shared_ptr<XMLTextNode>(new XMLTextNode(vcard->getPrefix())));
+			nameElement->addNode(prefixElement);
+		}
+		if (!vcard->getSuffix().isEmpty()) {
+			boost::shared_ptr<XMLElement> suffixElement(new XMLElement("SUFFIX"));
+			suffixElement->addNode(boost::shared_ptr<XMLTextNode>(new XMLTextNode(vcard->getSuffix())));
+			nameElement->addNode(suffixElement);
+		}
 		queryElement.addNode(nameElement);
 	}
-	if (!vcard->getEMail().isEmpty()) {
+	foreach(const VCard::EMailAddress& emailAddress, vcard->getEMailAddresses()) {
 		boost::shared_ptr<XMLElement> emailElement(new XMLElement("EMAIL"));
 		boost::shared_ptr<XMLElement> userIDElement(new XMLElement("USERID"));
-		userIDElement->addNode(boost::shared_ptr<XMLTextNode>(new XMLTextNode(vcard->getEMail())));
+		userIDElement->addNode(boost::shared_ptr<XMLTextNode>(new XMLTextNode(emailAddress.address)));
 		emailElement->addNode(userIDElement);
+		if (emailAddress.isHome) {
+			emailElement->addNode(boost::shared_ptr<XMLElement>(new XMLElement("HOME")));
+		}
+		if (emailAddress.isWork) {
+			emailElement->addNode(boost::shared_ptr<XMLElement>(new XMLElement("WORK")));
+		}
+		if (emailAddress.isInternet) {
+			emailElement->addNode(boost::shared_ptr<XMLElement>(new XMLElement("INTERNET")));
+		}
+		if (emailAddress.isPreferred) {
+			emailElement->addNode(boost::shared_ptr<XMLElement>(new XMLElement("PREF")));
+		}
+		if (emailAddress.isX400) {
+			emailElement->addNode(boost::shared_ptr<XMLElement>(new XMLElement("X400")));
+		}
 		queryElement.addNode(emailElement);
 	}
 	if (!vcard->getNickname().isEmpty()) {
@@ -64,6 +101,9 @@ String VCardSerializer::serializePayload(boost::shared_ptr<VCard> vcard)  const
 		}
 		queryElement.addNode(photoElement);
 	}
+	if (!vcard->getUnknownContent().isEmpty()) {
+		queryElement.addNode(boost::shared_ptr<XMLRawTextNode>(new XMLRawTextNode(vcard->getUnknownContent())));
+	}
 	return queryElement.serialize();
 }
 
-- 
cgit v0.10.2-6-g49f6