summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
Diffstat (limited to 'Swiften')
-rw-r--r--Swiften/Elements/VCard.h193
-rw-r--r--Swiften/Parser/PayloadParsers/UnitTest/VCardParserTest.cpp73
-rw-r--r--Swiften/Parser/PayloadParsers/VCardParser.cpp166
-rw-r--r--Swiften/Parser/PayloadParsers/VCardParser.h4
-rw-r--r--Swiften/Serializer/PayloadSerializers/UnitTest/VCardSerializerTest.cpp80
-rw-r--r--Swiften/Serializer/PayloadSerializers/VCardSerializer.cpp172
6 files changed, 677 insertions, 11 deletions
diff --git a/Swiften/Elements/VCard.h b/Swiften/Elements/VCard.h
index f9822c9..41f2623 100644
--- a/Swiften/Elements/VCard.h
+++ b/Swiften/Elements/VCard.h
@@ -7,8 +7,10 @@
#pragma once
#include <boost/shared_ptr.hpp>
+#include <boost/date_time/posix_time/ptime.hpp>
#include <string>
+#include <Swiften/JID/JID.h>
#include <Swiften/Base/ByteArray.h>
#include <Swiften/Elements/Payload.h>
@@ -29,6 +31,71 @@ namespace Swift {
std::string address;
};
+ struct Telephone {
+ Telephone() : isHome(false), isWork(false), isVoice(false), isFax(false), isPager(false), isMSG(false), isCell(false),
+ isVideo(false), isBBS(false), isModem(false), isISDN(false), isPCS(false), isPreferred(false) {
+ }
+
+ bool isHome;
+ bool isWork;
+ bool isVoice;
+ bool isFax;
+ bool isPager;
+ bool isMSG;
+ bool isCell;
+ bool isVideo;
+ bool isBBS;
+ bool isModem;
+ bool isISDN;
+ bool isPCS;
+ bool isPreferred;
+ std::string number;
+ };
+
+ enum DeliveryType {
+ DomesticDelivery,
+ InternationalDelivery,
+ None
+ };
+
+ struct Address {
+ Address() : isHome(false), isWork(false), isPostal(false), isParcel(false), deliveryType(None), isPreferred(false) {
+ }
+
+ bool isHome;
+ bool isWork;
+ bool isPostal;
+ bool isParcel;
+ DeliveryType deliveryType;
+ bool isPreferred;
+
+ std::string POBox;
+ std::string addressExtension;
+ std::string street;
+ std::string locality;
+ std::string region;
+ std::string postalCode;
+ std::string country;
+ };
+
+ struct AddressLabel {
+ AddressLabel() : isHome(false), isWork(false), isPostal(false), isParcel(false), deliveryType(None), isPreferred(false) {
+ }
+
+ bool isHome;
+ bool isWork;
+ bool isPostal;
+ bool isParcel;
+ DeliveryType deliveryType;
+ bool isPreferred;
+ std::vector<std::string> lines;
+ };
+
+ struct Organization {
+ std::string name;
+ std::vector<std::string> units;
+ };
+
VCard() {}
void setVersion(const std::string& version) { version_ = version; }
@@ -78,8 +145,124 @@ namespace Swift {
emailAddresses_.push_back(email);
}
+ void clearEMailAddresses() {
+ emailAddresses_.clear();
+ }
+
EMailAddress getPreferredEMailAddress() const;
+ void setBirthday(const boost::posix_time::ptime& birthday) {
+ birthday_ = birthday;
+ }
+
+ const boost::posix_time::ptime& getBirthday() const {
+ return birthday_;
+ }
+
+ const std::vector<Telephone>& getTelephones() const {
+ return telephones_;
+ }
+
+ void addTelephone(const Telephone& phone) {
+ telephones_.push_back(phone);
+ }
+
+ void clearTelephones() {
+ telephones_.clear();
+ }
+
+ const std::vector<Address>& getAddresses() const {
+ return addresses_;
+ }
+
+ void addAddress(const Address& address) {
+ addresses_.push_back(address);
+ }
+
+ void clearAddresses() {
+ addresses_.clear();
+ }
+
+ const std::vector<AddressLabel>& getAddressLabels() const {
+ return addressLabels_;
+ }
+
+ void addAddressLabel(const AddressLabel& addressLabel) {
+ addressLabels_.push_back(addressLabel);
+ }
+
+ void clearAddressLabels() {
+ addressLabels_.clear();
+ }
+
+ const std::vector<JID>& getJIDs() const {
+ return jids_;
+ }
+
+ void addJID(const JID& jid) {
+ jids_.push_back(jid);
+ }
+
+ void clearJIDs() {
+ jids_.clear();
+ }
+
+ const std::string& getDescription() const {
+ return description_;
+ }
+
+ void setDescription(const std::string& description) {
+ this->description_ = description;
+ }
+
+ const std::vector<Organization>& getOrganizations() const {
+ return organizations_;
+ }
+
+ void addOrganization(const Organization& organization) {
+ organizations_.push_back(organization);
+ }
+
+ void clearOrganizations() {
+ organizations_.clear();
+ }
+
+ const std::vector<std::string>& getTitles() const {
+ return titles_;
+ }
+
+ void addTitle(const std::string& title) {
+ titles_.push_back(title);
+ }
+
+ void clearTitles() {
+ titles_.clear();
+ }
+
+ const std::vector<std::string>& getRoles() const {
+ return roles_;
+ }
+
+ void addRole(const std::string& role) {
+ roles_.push_back(role);
+ }
+
+ void clearRoles() {
+ roles_.clear();
+ }
+
+ const std::vector<std::string>& getURLs() const {
+ return urls_;
+ }
+
+ void addURL(const std::string& url) {
+ urls_.push_back(url);
+ }
+
+ void clearURLs() {
+ urls_.clear();
+ }
+
private:
std::string version_;
std::string fullName_;
@@ -92,7 +275,17 @@ namespace Swift {
ByteArray photo_;
std::string photoType_;
std::string nick_;
+ boost::posix_time::ptime birthday_;
std::string unknownContent_;
std::vector<EMailAddress> emailAddresses_;
+ std::vector<Telephone> telephones_;
+ std::vector<Address> addresses_;
+ std::vector<AddressLabel> addressLabels_;
+ std::vector<JID> jids_;
+ std::string description_;
+ std::vector<Organization> organizations_;
+ std::vector<std::string> titles_;
+ std::vector<std::string> roles_;
+ std::vector<std::string> urls_;
};
}
diff --git a/Swiften/Parser/PayloadParsers/UnitTest/VCardParserTest.cpp b/Swiften/Parser/PayloadParsers/UnitTest/VCardParserTest.cpp
index f1e6635..eda2547 100644
--- a/Swiften/Parser/PayloadParsers/UnitTest/VCardParserTest.cpp
+++ b/Swiften/Parser/PayloadParsers/UnitTest/VCardParserTest.cpp
@@ -7,6 +7,8 @@
#include <Swiften/Base/ByteArray.h>
#include <QA/Checker/IO.h>
+#include <boost/date_time/posix_time/posix_time.hpp>
+
#include <cppunit/extensions/HelperMacros.h>
#include <cppunit/extensions/TestFactoryRegistry.h>
@@ -48,8 +50,36 @@ class VCardParserTest : public CppUnit::TestFixture {
"<WORK/>"
"<X400/>"
"</EMAIL>"
+ "<TEL>"
+ "<NUMBER>555-6273</NUMBER>"
+ "<HOME/>"
+ "<VOICE/>"
+ "</TEL>"
+ "<ADR>"
+ "<LOCALITY>Any Town</LOCALITY>"
+ "<STREET>Fake Street 123</STREET>"
+ "<PCODE>12345</PCODE>"
+ "<CTRY>USA</CTRY>"
+ "<HOME/>"
+ "</ADR>"
+ "<LABEL>"
+ "<LINE>Fake Street 123</LINE>"
+ "<LINE>12345 Any Town</LINE>"
+ "<LINE>USA</LINE>"
+ "<HOME/>"
+ "</LABEL>"
"<NICKNAME>DreamGirl</NICKNAME>"
- "<BDAY>1234</BDAY>"
+ "<BDAY>1865-05-04</BDAY>"
+ "<JID>alice@teaparty.lit</JID>"
+ "<JID>alice@wonderland.lit</JID>"
+ "<DESC>I once fell down a rabbit hole.</DESC>"
+ "<ORG>"
+ "<ORGNAME>Alice In Wonderland Inc.</ORGNAME>"
+ "</ORG>"
+ "<TITLE>Some Title</TITLE>"
+ "<ROLE>Main Character</ROLE>"
+ "<URL>http://wonderland.lit/~alice</URL>"
+ "<URL>http://teaparty.lit/~alice2</URL>"
"<MAILER>mutt</MAILER>"
"</vCard>"));
@@ -62,7 +92,7 @@ class VCardParserTest : public CppUnit::TestFixture {
CPPUNIT_ASSERT_EQUAL(std::string("Mrs"), payload->getPrefix());
CPPUNIT_ASSERT_EQUAL(std::string("PhD"), payload->getSuffix());
CPPUNIT_ASSERT_EQUAL(std::string("DreamGirl"), payload->getNickname());
- CPPUNIT_ASSERT_EQUAL(std::string("<BDAY xmlns=\"vcard-temp\">1234</BDAY><MAILER xmlns=\"vcard-temp\">mutt</MAILER>"), payload->getUnknownContent());
+ CPPUNIT_ASSERT_EQUAL(boost::posix_time::ptime(boost::gregorian::date(1865, 5, 4)), payload->getBirthday());
CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(payload->getEMailAddresses().size()));
CPPUNIT_ASSERT_EQUAL(std::string("alice@wonderland.lit"), payload->getEMailAddresses()[0].address);
CPPUNIT_ASSERT(payload->getEMailAddresses()[0].isHome);
@@ -76,6 +106,45 @@ class VCardParserTest : public CppUnit::TestFixture {
CPPUNIT_ASSERT(!payload->getEMailAddresses()[1].isPreferred);
CPPUNIT_ASSERT(payload->getEMailAddresses()[1].isWork);
CPPUNIT_ASSERT(payload->getEMailAddresses()[1].isX400);
+
+ CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(payload->getTelephones().size()));
+ CPPUNIT_ASSERT_EQUAL(std::string("555-6273"), payload->getTelephones()[0].number);
+ CPPUNIT_ASSERT(payload->getTelephones()[0].isHome);
+ CPPUNIT_ASSERT(payload->getTelephones()[0].isVoice);
+ CPPUNIT_ASSERT(!payload->getTelephones()[0].isPreferred);
+
+ CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(payload->getAddresses().size()));
+ CPPUNIT_ASSERT_EQUAL(std::string("Any Town"), payload->getAddresses()[0].locality);
+ CPPUNIT_ASSERT_EQUAL(std::string("Fake Street 123"), payload->getAddresses()[0].street);
+ CPPUNIT_ASSERT_EQUAL(std::string("12345"), payload->getAddresses()[0].postalCode);
+ CPPUNIT_ASSERT_EQUAL(std::string("USA"), payload->getAddresses()[0].country);
+ CPPUNIT_ASSERT(payload->getAddresses()[0].isHome);
+
+ CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(payload->getAddressLabels().size()));
+ CPPUNIT_ASSERT_EQUAL(std::string("Fake Street 123"), payload->getAddressLabels()[0].lines[0]);
+ CPPUNIT_ASSERT_EQUAL(std::string("12345 Any Town"), payload->getAddressLabels()[0].lines[1]);
+ CPPUNIT_ASSERT_EQUAL(std::string("USA"), payload->getAddressLabels()[0].lines[2]);
+ CPPUNIT_ASSERT(payload->getAddressLabels()[0].isHome);
+
+ CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(payload->getJIDs().size()));
+ CPPUNIT_ASSERT_EQUAL(JID("alice@teaparty.lit"), payload->getJIDs()[0]);
+ CPPUNIT_ASSERT_EQUAL(JID("alice@wonderland.lit"), payload->getJIDs()[1]);
+
+ CPPUNIT_ASSERT_EQUAL(std::string("I once fell down a rabbit hole."), payload->getDescription());
+
+ CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(payload->getOrganizations().size()));
+ CPPUNIT_ASSERT_EQUAL(std::string("Alice In Wonderland Inc."), payload->getOrganizations()[0].name);
+ CPPUNIT_ASSERT_EQUAL(0, static_cast<int>(payload->getOrganizations()[0].units.size()));
+
+ CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(payload->getTitles().size()));
+ CPPUNIT_ASSERT_EQUAL(std::string("Some Title"), payload->getTitles()[0]);
+ CPPUNIT_ASSERT_EQUAL(1, static_cast<int>(payload->getRoles().size()));
+ CPPUNIT_ASSERT_EQUAL(std::string("Main Character"), payload->getRoles()[0]);
+ CPPUNIT_ASSERT_EQUAL(2, static_cast<int>(payload->getURLs().size()));
+ CPPUNIT_ASSERT_EQUAL(std::string("http://wonderland.lit/~alice"), payload->getURLs()[0]);
+ CPPUNIT_ASSERT_EQUAL(std::string("http://teaparty.lit/~alice2"), payload->getURLs()[1]);
+
+ CPPUNIT_ASSERT_EQUAL(std::string("<MAILER xmlns=\"vcard-temp\">mutt</MAILER>"), payload->getUnknownContent());
}
void testParse_Photo() {
diff --git a/Swiften/Parser/PayloadParsers/VCardParser.cpp b/Swiften/Parser/PayloadParsers/VCardParser.cpp
index 553d26a..9640787 100644
--- a/Swiften/Parser/PayloadParsers/VCardParser.cpp
+++ b/Swiften/Parser/PayloadParsers/VCardParser.cpp
@@ -6,6 +6,7 @@
#include <Swiften/Parser/PayloadParsers/VCardParser.h>
#include <Swiften/Base/foreach.h>
+#include <Swiften/Base/DateTime.h>
#include <Swiften/StringCodecs/Base64.h>
#include <Swiften/Parser/SerializingParser.h>
@@ -20,6 +21,18 @@ void VCardParser::handleStartElement(const std::string& element, const std::stri
if (elementHierarchy == "/vCard/EMAIL") {
currentEMailAddress_ = VCard::EMailAddress();
}
+ if (elementHierarchy == "/vCard/TEL") {
+ currentTelephone_ = VCard::Telephone();
+ }
+ if (elementHierarchy == "/vCard/ADR") {
+ currentAddress_ = VCard::Address();
+ }
+ if (elementHierarchy == "/vCard/LABEL") {
+ currentAddressLabel_ = VCard::AddressLabel();
+ }
+ if (elementHierarchy == "/vCard/ORG") {
+ currentOrganization_ = VCard::Organization();
+ }
if (elementStack_.size() == 2) {
assert(!unknownContentParser_);
unknownContentParser_ = new SerializingParser();
@@ -90,9 +103,160 @@ void VCardParser::handleEndElement(const std::string& element, const std::string
else if (elementHierarchy == "/vCard/EMAIL/PREF") {
currentEMailAddress_.isPreferred = true;
}
- else if (elementHierarchy == "/vCard/EMAIL") {
+ else if (elementHierarchy == "/vCard/EMAIL" && !currentEMailAddress_.address.empty()) {
getPayloadInternal()->addEMailAddress(currentEMailAddress_);
}
+ else if (elementHierarchy == "/vCard/BDAY" && !currentText_.empty()) {
+ getPayloadInternal()->setBirthday(stringToDateTime(currentText_));
+ }
+ else if (elementHierarchy == "/vCard/TEL/NUMBER") {
+ currentTelephone_.number = currentText_;
+ }
+ else if (elementHierarchy == "/vCard/TEL/HOME") {
+ currentTelephone_.isHome = true;
+ }
+ else if (elementHierarchy == "/vCard/TEL/WORK") {
+ currentTelephone_.isWork = true;
+ }
+ else if (elementHierarchy == "/vCard/TEL/VOICE") {
+ currentTelephone_.isVoice = true;
+ }
+ else if (elementHierarchy == "/vCard/TEL/FAX") {
+ currentTelephone_.isFax = true;
+ }
+ else if (elementHierarchy == "/vCard/TEL/PAGER") {
+ currentTelephone_.isPager = true;
+ }
+ else if (elementHierarchy == "/vCard/TEL/MSG") {
+ currentTelephone_.isMSG = true;
+ }
+ else if (elementHierarchy == "/vCard/TEL/CELL") {
+ currentTelephone_.isCell = true;
+ }
+ else if (elementHierarchy == "/vCard/TEL/VIDEO") {
+ currentTelephone_.isVideo = true;
+ }
+ else if (elementHierarchy == "/vCard/TEL/BBS") {
+ currentTelephone_.isBBS = true;
+ }
+ else if (elementHierarchy == "/vCard/TEL/MODEM") {
+ currentTelephone_.isModem = true;
+ }
+ else if (elementHierarchy == "/vCard/TEL/ISDN") {
+ currentTelephone_.isISDN = true;
+ }
+ else if (elementHierarchy == "/vCard/TEL/PCS") {
+ currentTelephone_.isPCS = true;
+ }
+ else if (elementHierarchy == "/vCard/TEL/PREF") {
+ currentTelephone_.isPreferred = true;
+ }
+ else if (elementHierarchy == "/vCard/TEL" && !currentTelephone_.number.empty()) {
+ getPayloadInternal()->addTelephone(currentTelephone_);
+ }
+ else if (elementHierarchy == "/vCard/ADR/HOME") {
+ currentAddress_.isHome = true;
+ }
+ else if (elementHierarchy == "/vCard/ADR/WORK") {
+ currentAddress_.isWork = true;
+ }
+ else if (elementHierarchy == "/vCard/ADR/POSTAL") {
+ currentAddress_.isPostal = true;
+ }
+ else if (elementHierarchy == "/vCard/ADR/PARCEL") {
+ currentAddress_.isParcel = true;
+ }
+ else if (elementHierarchy == "/vCard/ADR/DOM") {
+ currentAddress_.deliveryType = VCard::DomesticDelivery;
+ }
+ else if (elementHierarchy == "/vCard/ADR/INTL") {
+ currentAddress_.deliveryType = VCard::InternationalDelivery;
+ }
+ else if (elementHierarchy == "/vCard/ADR/PREF") {
+ currentAddress_.isPreferred = true;
+ }
+ else if (elementHierarchy == "/vCard/ADR/POBOX") {
+ currentAddress_.POBox = currentText_;
+ }
+ else if (elementHierarchy == "/vCard/ADR/EXTADD") {
+ currentAddress_.addressExtension = currentText_;
+ }
+ else if (elementHierarchy == "/vCard/ADR/STREET") {
+ currentAddress_.street = currentText_;
+ }
+ else if (elementHierarchy == "/vCard/ADR/LOCALITY") {
+ currentAddress_.locality = currentText_;
+ }
+ else if (elementHierarchy == "/vCard/ADR/REGION") {
+ currentAddress_.region = currentText_;
+ }
+ else if (elementHierarchy == "/vCard/ADR/PCODE") {
+ currentAddress_.postalCode = currentText_;
+ }
+ else if (elementHierarchy == "/vCard/ADR/CTRY") {
+ currentAddress_.country = currentText_;
+ }
+ else if (elementHierarchy == "/vCard/ADR") {
+ if (!currentAddress_.POBox.empty() || !currentAddress_.addressExtension.empty() ||
+ !currentAddress_.street.empty() || !currentAddress_.locality.empty() ||
+ !currentAddress_.region.empty() || !currentAddress_.region.empty() ||
+ !currentAddress_.postalCode.empty() || !currentAddress_.country.empty()) {
+ getPayloadInternal()->addAddress(currentAddress_);
+ }
+ }
+ else if (elementHierarchy == "/vCard/LABEL/HOME") {
+ currentAddressLabel_.isHome = true;
+ }
+ else if (elementHierarchy == "/vCard/LABEL/WORK") {
+ currentAddressLabel_.isWork = true;
+ }
+ else if (elementHierarchy == "/vCard/LABEL/POSTAL") {
+ currentAddressLabel_.isPostal = true;
+ }
+ else if (elementHierarchy == "/vCard/LABEL/PARCEL") {
+ currentAddressLabel_.isParcel = true;
+ }
+ else if (elementHierarchy == "/vCard/LABEL/DOM") {
+ currentAddressLabel_.deliveryType = VCard::DomesticDelivery;
+ }
+ else if (elementHierarchy == "/vCard/LABEL/INTL") {
+ currentAddressLabel_.deliveryType = VCard::InternationalDelivery;
+ }
+ else if (elementHierarchy == "/vCard/LABEL/PREF") {
+ currentAddressLabel_.isPreferred = true;
+ }
+ else if (elementHierarchy == "/vCard/LABEL/LINE") {
+ currentAddressLabel_.lines.push_back(currentText_);
+ }
+ else if (elementHierarchy == "/vCard/LABEL") {
+ getPayloadInternal()->addAddressLabel(currentAddressLabel_);
+ }
+ else if (elementHierarchy == "/vCard/JID" && !currentText_.empty()) {
+ getPayloadInternal()->addJID(JID(currentText_));
+ }
+ else if (elementHierarchy == "/vCard/DESC") {
+ getPayloadInternal()->setDescription(currentText_);
+ }
+ else if (elementHierarchy == "/vCard/ORG/ORGNAME") {
+ currentOrganization_.name = currentText_;
+ }
+ else if (elementHierarchy == "/vCard/ORG/ORGUNIT" && !currentText_.empty()) {
+ currentOrganization_.units.push_back(currentText_);
+ }
+ else if (elementHierarchy == "/vCard/ORG") {
+ if (!currentOrganization_.name.empty() || !currentOrganization_.units.empty()) {
+ getPayloadInternal()->addOrganization(currentOrganization_);
+ }
+ }
+ else if (elementHierarchy == "/vCard/TITLE" && !currentText_.empty()) {
+ getPayloadInternal()->addTitle(currentText_);
+ }
+ else if (elementHierarchy == "/vCard/ROLE" && !currentText_.empty()) {
+ getPayloadInternal()->addRole(currentText_);
+ }
+ else if (elementHierarchy == "/vCard/URL" && !currentText_.empty()) {
+ getPayloadInternal()->addURL(currentText_);
+ }
else if (elementStack_.size() == 2 && unknownContentParser_) {
getPayloadInternal()->addUnknownContent(unknownContentParser_->getResult());
}
diff --git a/Swiften/Parser/PayloadParsers/VCardParser.h b/Swiften/Parser/PayloadParsers/VCardParser.h
index b1c47a3..f10d639 100644
--- a/Swiften/Parser/PayloadParsers/VCardParser.h
+++ b/Swiften/Parser/PayloadParsers/VCardParser.h
@@ -28,6 +28,10 @@ namespace Swift {
private:
std::vector<std::string> elementStack_;
VCard::EMailAddress currentEMailAddress_;
+ VCard::Telephone currentTelephone_;
+ VCard::Address currentAddress_;
+ VCard::AddressLabel currentAddressLabel_;
+ VCard::Organization currentOrganization_;
SerializingParser* unknownContentParser_;
std::string currentText_;
};
diff --git a/Swiften/Serializer/PayloadSerializers/UnitTest/VCardSerializerTest.cpp b/Swiften/Serializer/PayloadSerializers/UnitTest/VCardSerializerTest.cpp
index 3ac1d77..01c8e77 100644
--- a/Swiften/Serializer/PayloadSerializers/UnitTest/VCardSerializerTest.cpp
+++ b/Swiften/Serializer/PayloadSerializers/UnitTest/VCardSerializerTest.cpp
@@ -31,14 +31,15 @@ class VCardSerializerTest : public CppUnit::TestFixture
vcard->setNickname("DreamGirl");
vcard->setPhoto(createByteArray("abcdef"));
vcard->setPhotoType("image/png");
- vcard->addUnknownContent("<BDAY>1234</BDAY><MAILER>mutt</MAILER>");
+ vcard->setBirthday(boost::posix_time::ptime(boost::gregorian::date(1865, 5, 4)));
+ vcard->addUnknownContent("<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 emailAddress1;
+ emailAddress1.address = "alice@wonderland.lit";
+ emailAddress1.isHome = true;
+ emailAddress1.isPreferred = true;
+ emailAddress1.isInternet = true;
+ vcard->addEMailAddress(emailAddress1);
VCard::EMailAddress address2;
address2.address = "alice@teaparty.lit";
@@ -46,6 +47,41 @@ class VCardSerializerTest : public CppUnit::TestFixture
address2.isX400 = true;
vcard->addEMailAddress(address2);
+ VCard::Telephone telephone1;
+ telephone1.number = "555-6273";
+ telephone1.isHome = true;
+ telephone1.isVoice = true;
+ vcard->addTelephone(telephone1);
+
+ VCard::Address address1;
+ address1.locality = "Any Town";
+ address1.street = "Fake Street 123";
+ address1.postalCode = "12345";
+ address1.country = "USA";
+ address1.isHome = true;
+ vcard->addAddress(address1);
+
+ VCard::AddressLabel label1;
+ label1.lines.push_back("Fake Street 123");
+ label1.lines.push_back("12345 Any Town");
+ label1.lines.push_back("USA");
+ label1.isHome = true;
+ vcard->addAddressLabel(label1);
+
+ vcard->addJID(JID("alice@teaparty.lit"));
+ vcard->addJID(JID("alice@wonderland.lit"));
+
+ vcard->setDescription("I once fell down a rabbit hole.");
+
+ VCard::Organization org1;
+ org1.name = "Alice In Wonderland Inc.";
+ vcard->addOrganization(org1);
+
+ vcard->addTitle("Some Title");
+ vcard->addRole("Main Character");
+ vcard->addURL("http://wonderland.lit/~alice");
+ vcard->addURL("http://teaparty.lit/~alice2");
+
std::string expectedResult =
"<vCard xmlns=\"vcard-temp\">"
"<VERSION>2.0</VERSION>"
@@ -73,7 +109,35 @@ class VCardSerializerTest : public CppUnit::TestFixture
"<TYPE>image/png</TYPE>"
"<BINVAL>YWJjZGVm</BINVAL>"
"</PHOTO>"
- "<BDAY>1234</BDAY>"
+ "<BDAY>1865-05-04T00:00:00Z</BDAY>"
+ "<TEL>"
+ "<NUMBER>555-6273</NUMBER>"
+ "<HOME/>"
+ "<VOICE/>"
+ "</TEL>"
+ "<ADR>"
+ "<STREET>Fake Street 123</STREET>"
+ "<LOCALITY>Any Town</LOCALITY>"
+ "<PCODE>12345</PCODE>"
+ "<CTRY>USA</CTRY>"
+ "<HOME/>"
+ "</ADR>"
+ "<LABEL>"
+ "<LINE>Fake Street 123</LINE>"
+ "<LINE>12345 Any Town</LINE>"
+ "<LINE>USA</LINE>"
+ "<HOME/>"
+ "</LABEL>"
+ "<JID>alice@teaparty.lit</JID>"
+ "<JID>alice@wonderland.lit</JID>"
+ "<DESC>I once fell down a rabbit hole.</DESC>"
+ "<ORG>"
+ "<ORGNAME>Alice In Wonderland Inc.</ORGNAME>"
+ "</ORG>"
+ "<TITLE>Some Title</TITLE>"
+ "<ROLE>Main Character</ROLE>"
+ "<URL>http://wonderland.lit/~alice</URL>"
+ "<URL>http://teaparty.lit/~alice2</URL>"
"<MAILER>mutt</MAILER>"
"</vCard>";
diff --git a/Swiften/Serializer/PayloadSerializers/VCardSerializer.cpp b/Swiften/Serializer/PayloadSerializers/VCardSerializer.cpp
index 1512c6c..2676a02 100644
--- a/Swiften/Serializer/PayloadSerializers/VCardSerializer.cpp
+++ b/Swiften/Serializer/PayloadSerializers/VCardSerializer.cpp
@@ -13,10 +13,17 @@
#include <Swiften/Serializer/XML/XMLTextNode.h>
#include <Swiften/Serializer/XML/XMLRawTextNode.h>
#include <Swiften/StringCodecs/Base64.h>
+#include <Swiften/Base/DateTime.h>
#include <Swiften/Base/foreach.h>
namespace Swift {
+boost::shared_ptr<XMLElement> createTextElement(const std::string& elementName, const std::string& text) {
+ boost::shared_ptr<XMLElement> element = boost::make_shared<XMLElement>(elementName);
+ element->addNode(boost::make_shared<XMLTextNode>(text));
+ return element;
+}
+
VCardSerializer::VCardSerializer() : GenericPayloadSerializer<VCard>() {
}
@@ -102,6 +109,171 @@ std::string VCardSerializer::serializePayload(boost::shared_ptr<VCard> vcard) c
}
queryElement.addNode(photoElement);
}
+ if (!vcard->getBirthday().is_not_a_date_time()) {
+ XMLElement::ref bdayElement(new XMLElement("BDAY"));
+ bdayElement->addNode(boost::shared_ptr<XMLTextNode>(new XMLTextNode(dateTimeToString(vcard->getBirthday()))));
+ queryElement.addNode(bdayElement);
+ }
+
+ foreach(const VCard::Telephone& telephone, vcard->getTelephones()) {
+ boost::shared_ptr<XMLElement> telElement(new XMLElement("TEL"));
+ boost::shared_ptr<XMLElement> numberElement(new XMLElement("NUMBER"));
+ numberElement->addNode(boost::shared_ptr<XMLTextNode>(new XMLTextNode(telephone.number)));
+ telElement->addNode(numberElement);
+ if (telephone.isHome) {
+ telElement->addNode(boost::shared_ptr<XMLElement>(new XMLElement("HOME")));
+ }
+ if (telephone.isWork) {
+ telElement->addNode(boost::shared_ptr<XMLElement>(new XMLElement("WORK")));
+ }
+ if (telephone.isVoice) {
+ telElement->addNode(boost::shared_ptr<XMLElement>(new XMLElement("VOICE")));
+ }
+ if (telephone.isFax) {
+ telElement->addNode(boost::shared_ptr<XMLElement>(new XMLElement("FAX")));
+ }
+ if (telephone.isPager) {
+ telElement->addNode(boost::shared_ptr<XMLElement>(new XMLElement("PAGER")));
+ }
+ if (telephone.isMSG) {
+ telElement->addNode(boost::shared_ptr<XMLElement>(new XMLElement("MSG")));
+ }
+ if (telephone.isCell) {
+ telElement->addNode(boost::shared_ptr<XMLElement>(new XMLElement("CELL")));
+ }
+ if (telephone.isVideo) {
+ telElement->addNode(boost::shared_ptr<XMLElement>(new XMLElement("VIDEO")));
+ }
+ if (telephone.isBBS) {
+ telElement->addNode(boost::shared_ptr<XMLElement>(new XMLElement("BBS")));
+ }
+ if (telephone.isModem) {
+ telElement->addNode(boost::shared_ptr<XMLElement>(new XMLElement("MODEM")));
+ }
+ if (telephone.isISDN) {
+ telElement->addNode(boost::shared_ptr<XMLElement>(new XMLElement("ISDN")));
+ }
+ if (telephone.isPCS) {
+ telElement->addNode(boost::shared_ptr<XMLElement>(new XMLElement("PCS")));
+ }
+ if (telephone.isPreferred) {
+ telElement->addNode(boost::shared_ptr<XMLElement>(new XMLElement("PREF")));
+ }
+ queryElement.addNode(telElement);
+ }
+
+ foreach(const VCard::Address& address, vcard->getAddresses()) {
+ boost::shared_ptr<XMLElement> adrElement(new XMLElement("ADR"));
+ if (!address.POBox.empty()) {
+ adrElement->addNode(createTextElement("POBOX", address.POBox));
+ }
+ if (!address.addressExtension.empty()) {
+ adrElement->addNode(createTextElement("EXTADD", address.addressExtension));
+ }
+ if (!address.street.empty()) {
+ adrElement->addNode(createTextElement("STREET", address.street));
+ }
+ if (!address.locality.empty()) {
+ adrElement->addNode(createTextElement("LOCALITY", address.locality));
+ }
+ if (!address.region.empty()) {
+ adrElement->addNode(createTextElement("REGION", address.region));
+ }
+ if (!address.postalCode.empty()) {
+ adrElement->addNode(createTextElement("PCODE", address.postalCode));
+ }
+ if (!address.country.empty()) {
+ adrElement->addNode(createTextElement("CTRY", address.country));
+ }
+
+ if (address.isHome) {
+ adrElement->addNode(boost::make_shared<XMLElement>("HOME"));
+ }
+ if (address.isWork) {
+ adrElement->addNode(boost::make_shared<XMLElement>("WORK"));
+ }
+ if (address.isPostal) {
+ adrElement->addNode(boost::make_shared<XMLElement>("POSTAL"));
+ }
+ if (address.isParcel) {
+ adrElement->addNode(boost::make_shared<XMLElement>("PARCEL"));
+ }
+ if (address.deliveryType == VCard::DomesticDelivery) {
+ adrElement->addNode(boost::make_shared<XMLElement>("DOM"));
+ }
+ if (address.deliveryType == VCard::InternationalDelivery) {
+ adrElement->addNode(boost::make_shared<XMLElement>("INTL"));
+ }
+ if (address.isPreferred) {
+ adrElement->addNode(boost::make_shared<XMLElement>("PREF"));
+ }
+ queryElement.addNode(adrElement);
+ }
+
+ foreach(const VCard::AddressLabel& addressLabel, vcard->getAddressLabels()) {
+ boost::shared_ptr<XMLElement> labelElement(new XMLElement("LABEL"));
+
+ foreach(const std::string& line, addressLabel.lines) {
+ labelElement->addNode(createTextElement("LINE", line));
+ }
+
+ if (addressLabel.isHome) {
+ labelElement->addNode(boost::make_shared<XMLElement>("HOME"));
+ }
+ if (addressLabel.isWork) {
+ labelElement->addNode(boost::make_shared<XMLElement>("WORK"));
+ }
+ if (addressLabel.isPostal) {
+ labelElement->addNode(boost::make_shared<XMLElement>("POSTAL"));
+ }
+ if (addressLabel.isParcel) {
+ labelElement->addNode(boost::make_shared<XMLElement>("PARCEL"));
+ }
+ if (addressLabel.deliveryType == VCard::DomesticDelivery) {
+ labelElement->addNode(boost::make_shared<XMLElement>("DOM"));
+ }
+ if (addressLabel.deliveryType == VCard::InternationalDelivery) {
+ labelElement->addNode(boost::make_shared<XMLElement>("INTL"));
+ }
+ if (addressLabel.isPreferred) {
+ labelElement->addNode(boost::make_shared<XMLElement>("PREF"));
+ }
+ queryElement.addNode(labelElement);
+ }
+
+ foreach(const JID& jid, vcard->getJIDs()) {
+ queryElement.addNode(createTextElement("JID", jid.toString()));
+ }
+
+ if (!vcard->getDescription().empty()) {
+ queryElement.addNode(createTextElement("DESC", vcard->getDescription()));
+ }
+
+ foreach(const VCard::Organization& org, vcard->getOrganizations()) {
+ boost::shared_ptr<XMLElement> orgElement(new XMLElement("ORG"));
+ if (!org.name.empty()) {
+ orgElement->addNode(createTextElement("ORGNAME", org.name));
+ }
+ if (!org.units.empty()) {
+ foreach(const std::string& unit, org.units) {
+ orgElement->addNode(createTextElement("ORGUNIT", unit));
+ }
+ }
+ queryElement.addNode(orgElement);
+ }
+
+ foreach(const std::string& title, vcard->getTitles()) {
+ queryElement.addNode(createTextElement("TITLE", title));
+ }
+
+ foreach(const std::string& role, vcard->getRoles()) {
+ queryElement.addNode(createTextElement("ROLE", role));
+ }
+
+ foreach(const std::string& url, vcard->getURLs()) {
+ queryElement.addNode(createTextElement("URL", url));
+ }
+
if (!vcard->getUnknownContent().empty()) {
queryElement.addNode(boost::make_shared<XMLRawTextNode>(vcard->getUnknownContent()));
}