From becafc386f14967df87659cd408b5cee5835227d Mon Sep 17 00:00:00 2001 From: Jeremy Lainé Date: Fri, 3 Aug 2012 15:46:40 +0200 Subject: add support for phone numbers to vCards --- CHANGELOG | 1 + src/base/QXmppVCardIq.cpp | 154 ++++++++++++++++++++++++++++++++++++++++++++-- src/base/QXmppVCardIq.h | 49 +++++++++++++++ tests/vcard.cpp | 56 +++++++++++++++-- tests/vcard.h | 2 + 5 files changed, 253 insertions(+), 9 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 5cb6538c..ccd566a0 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -3,6 +3,7 @@ QXmpp 0.6.4 (UNRELEASED) - Improve vCard support: * Make it possible to have several e-mail addresses. + * Make it possible to have several phone numbers. - Make it possible to set the client's extended information form (XEP-0128). - Fix XEP-0115 verification strings (remove duplicate features, sort form values) - Fix issues: diff --git a/src/base/QXmppVCardIq.cpp b/src/base/QXmppVCardIq.cpp index 7fb88a3a..a961c63d 100644 --- a/src/base/QXmppVCardIq.cpp +++ b/src/base/QXmppVCardIq.cpp @@ -56,7 +56,7 @@ public: QXmppVCardEmail::Type type; }; -/// Constructs an empty vCard e-mail address. +/// Constructs an empty e-mail address. QXmppVCardEmail::QXmppVCardEmail() : d(new QXmppVCardEmailPrivate) @@ -74,7 +74,7 @@ QXmppVCardEmail::~QXmppVCardEmail() { } -/// Assigns \a other to this vCard e-mail address. +/// Assigns \a other to this e-mail address. QXmppVCardEmail& QXmppVCardEmail::operator=(const QXmppVCardEmail &other) { @@ -142,6 +142,132 @@ void QXmppVCardEmail::toXml(QXmlStreamWriter *writer) const writer->writeEndElement(); } +class QXmppVCardPhonePrivate : public QSharedData +{ +public: + QXmppVCardPhonePrivate() : type(QXmppVCardPhone::None) {}; + QString number; + QXmppVCardPhone::Type type; +}; + +/// Constructs an empty phone number. + +QXmppVCardPhone::QXmppVCardPhone() + : d(new QXmppVCardPhonePrivate) +{ +} + +/// Constructs a copy of \a other. + +QXmppVCardPhone::QXmppVCardPhone(const QXmppVCardPhone &other) + : d(other.d) +{ +} + +QXmppVCardPhone::~QXmppVCardPhone() +{ +} + +/// Assigns \a other to this phone number. + +QXmppVCardPhone& QXmppVCardPhone::operator=(const QXmppVCardPhone &other) +{ + d = other.d; + return *this; +} + +/// Returns the phone number. + +QString QXmppVCardPhone::number() const +{ + return d->number; +} + +/// Sets the phone \a number. + +void QXmppVCardPhone::setNumber(const QString &number) +{ + d->number = number; +} + +/// Returns the e-mail type, which is a combination of TypeFlag. + +QXmppVCardPhone::Type QXmppVCardPhone::type() const +{ + return d->type; +} + +/// Sets the e-mail \a type, which is a combination of TypeFlag. + +void QXmppVCardPhone::setType(QXmppVCardPhone::Type type) +{ + d->type = type; +} + +void QXmppVCardPhone::parse(const QDomElement &element) +{ + if (!element.firstChildElement("HOME").isNull()) + d->type |= Home; + if (!element.firstChildElement("WORK").isNull()) + d->type |= Work; + if (!element.firstChildElement("VOICE").isNull()) + d->type |= Voice; + if (!element.firstChildElement("FAX").isNull()) + d->type |= Fax; + if (!element.firstChildElement("PAGER").isNull()) + d->type |= Pager; + if (!element.firstChildElement("MSG").isNull()) + d->type |= Messaging; + if (!element.firstChildElement("CELL").isNull()) + d->type |= Cell; + if (!element.firstChildElement("VIDEO").isNull()) + d->type |= Video; + if (!element.firstChildElement("BBS").isNull()) + d->type |= BBS; + if (!element.firstChildElement("MODEM").isNull()) + d->type |= Modem; + if (!element.firstChildElement("ISDN").isNull()) + d->type |= ISDN; + if (!element.firstChildElement("PCS").isNull()) + d->type |= PCS; + if (!element.firstChildElement("PREF").isNull()) + d->type |= Preferred; + d->number = element.firstChildElement("NUMBER").text(); +} + +void QXmppVCardPhone::toXml(QXmlStreamWriter *writer) const +{ + writer->writeStartElement("PHONE"); + if (d->type & Home) + writer->writeEmptyElement("HOME"); + if (d->type & Work) + writer->writeEmptyElement("WORK"); + if (d->type & Voice) + writer->writeEmptyElement("VOICE"); + if (d->type & Fax) + writer->writeEmptyElement("FAX"); + if (d->type & Pager) + writer->writeEmptyElement("PAGER"); + if (d->type & Messaging) + writer->writeEmptyElement("MSG"); + if (d->type & Cell) + writer->writeEmptyElement("CELL"); + if (d->type & Video) + writer->writeEmptyElement("VIDEO"); + if (d->type & BBS) + writer->writeEmptyElement("BBS"); + if (d->type & Modem) + writer->writeEmptyElement("MODEM"); + if (d->type & ISDN) + writer->writeEmptyElement("ISDN"); + if (d->type & PCS) + writer->writeEmptyElement("PCS"); + if (d->type & Preferred) + writer->writeEmptyElement("PREF"); + writer->writeTextElement("NUMBER", d->number); + writer->writeEndElement(); +} + class QXmppVCardIqPrivate : public QSharedData { public: @@ -158,6 +284,7 @@ public: QString photoType; QList emails; + QList phones; }; /// Constructs a QXmppVCardIq for the specified recipient. @@ -390,6 +517,19 @@ void QXmppVCardIq::setEmails(const QList &emails) d->emails = emails; } +/// Returns the phone numbers. + +QList QXmppVCardIq::phones() const +{ + return d->phones; +} + +/// Sets the phone numbers. + +void QXmppVCardIq::setPhones(const QList &phones) +{ + d->phones = phones; +} /// \cond bool QXmppVCardIq::isVCard(const QDomElement &nodeRecv) { @@ -420,6 +560,10 @@ void QXmppVCardIq::parseElementFromChild(const QDomElement& nodeRecv) QXmppVCardEmail email; email.parse(child); d->emails << email; + } else if (child.tagName() == "PHONE") { + QXmppVCardPhone phone; + phone.parse(child); + d->phones << phone; } child = child.nextSiblingElement(); } @@ -450,9 +594,9 @@ void QXmppVCardIq::toXmlElementFromChild(QXmlStreamWriter *writer) const helperToXmlAddTextElement(writer, "MIDDLE", d->middleName); writer->writeEndElement(); } - if (!d->url.isEmpty()) - helperToXmlAddTextElement(writer, "URL", d->url); + foreach (const QXmppVCardPhone &phone, d->phones) + phone.toXml(writer); if(!photo().isEmpty()) { writer->writeStartElement("PHOTO"); @@ -463,6 +607,8 @@ void QXmppVCardIq::toXmlElementFromChild(QXmlStreamWriter *writer) const helperToXmlAddTextElement(writer, "BINVAL", d->photo.toBase64()); writer->writeEndElement(); } + if (!d->url.isEmpty()) + helperToXmlAddTextElement(writer, "URL", d->url); writer->writeEndElement(); } diff --git a/src/base/QXmppVCardIq.h b/src/base/QXmppVCardIq.h index b32cc5f6..0e9a9862 100644 --- a/src/base/QXmppVCardIq.h +++ b/src/base/QXmppVCardIq.h @@ -31,6 +31,7 @@ #include class QXmppVCardEmailPrivate; +class QXmppVCardPhonePrivate; class QXmppVCardIqPrivate; /// \brief Represents a vCard e-mail address. @@ -70,6 +71,51 @@ private: QSharedDataPointer d; }; +/// \brief Represents a vCard phone number. + +class QXmppVCardPhone +{ +public: + /// \brief Describes phone number types. + enum TypeFlag { + None = 0x0, + Home = 0x1, + Work = 0x2, + Voice = 0x4, + Fax = 0x8, + Pager = 0x10, + Messaging = 0x20, + Cell = 0x40, + Video = 0x80, + BBS = 0x100, + Modem = 0x200, + ISDN = 0x400, + PCS = 0x800, + Preferred = 0x1000 + }; + Q_DECLARE_FLAGS(Type, TypeFlag); + + QXmppVCardPhone(); + QXmppVCardPhone(const QXmppVCardPhone &other); + ~QXmppVCardPhone(); + + QXmppVCardPhone& operator=(const QXmppVCardPhone &other); + + QString number() const; + void setNumber(const QString &number); + + Type type() const; + void setType(Type type); + + /// \cond + void parse(const QDomElement &element); + void toXml(QXmlStreamWriter *stream) const; + /// \endcond + +private: + QSharedDataPointer d; +}; + /// \brief Represents the XMPP vCard. /// /// The functions names are self explanatory. @@ -121,6 +167,9 @@ public: QList emails() const; void setEmails(const QList &emails); + + QList phones() const; + void setPhones(const QList &phones); /// \cond static bool isVCard(const QDomElement &element); diff --git a/tests/vcard.cpp b/tests/vcard.cpp index 89f8b46a..b92b269b 100644 --- a/tests/vcard.cpp +++ b/tests/vcard.cpp @@ -32,8 +32,11 @@ void tst_QXmppVCardIq::testEmail_data() QTest::addColumn("type"); QTest::newRow("none") << QByteArray("foo.bar@example.com") << int(QXmppVCardEmail::None); - QTest::newRow("internet") << QByteArray("foo.bar@example.com") << int(QXmppVCardEmail::Internet); - QTest::newRow("x400") << QByteArray("foo.bar@example.com") << int(QXmppVCardEmail::X400); + QTest::newRow("HOME") << QByteArray("foo.bar@example.com") << int(QXmppVCardEmail::Home); + QTest::newRow("WORK") << QByteArray("foo.bar@example.com") << int(QXmppVCardEmail::Work); + QTest::newRow("INTERNET") << QByteArray("foo.bar@example.com") << int(QXmppVCardEmail::Internet); + QTest::newRow("X400") << QByteArray("foo.bar@example.com") << int(QXmppVCardEmail::X400); + QTest::newRow("PREF") << QByteArray("foo.bar@example.com") << int(QXmppVCardEmail::Preferred); QTest::newRow("all") << QByteArray("foo.bar@example.com") << int(QXmppVCardEmail::Home | QXmppVCardEmail::Work | QXmppVCardEmail::Internet | QXmppVCardEmail::Preferred | QXmppVCardEmail::X400); } @@ -49,6 +52,40 @@ void tst_QXmppVCardIq::testEmail() serializePacket(email, xml); } +void tst_QXmppVCardIq::testPhone_data() +{ + QTest::addColumn("xml"); + QTest::addColumn("type"); + + QTest::newRow("none") << QByteArray("12345") << int(QXmppVCardPhone::None); + QTest::newRow("HOME") << QByteArray("12345") << int(QXmppVCardPhone::Home); + QTest::newRow("WORK") << QByteArray("12345") << int(QXmppVCardPhone::Work); + QTest::newRow("VOICE") << QByteArray("12345") << int(QXmppVCardPhone::Voice); + QTest::newRow("FAX") << QByteArray("12345") << int(QXmppVCardPhone::Fax); + QTest::newRow("PAGER") << QByteArray("12345") << int(QXmppVCardPhone::Pager); + QTest::newRow("MSG") << QByteArray("12345") << int(QXmppVCardPhone::Messaging); + QTest::newRow("CELL") << QByteArray("12345") << int(QXmppVCardPhone::Cell); + QTest::newRow("VIDEO") << QByteArray("") << int(QXmppVCardPhone::Video); + QTest::newRow("BBS") << QByteArray("12345") << int(QXmppVCardPhone::BBS); + QTest::newRow("MODEM") << QByteArray("12345") << int(QXmppVCardPhone::Modem); + QTest::newRow("IDSN") << QByteArray("12345") << int(QXmppVCardPhone::ISDN); + QTest::newRow("PCS") << QByteArray("12345") << int(QXmppVCardPhone::PCS); + QTest::newRow("PREF") << QByteArray("12345") << int(QXmppVCardPhone::Preferred); +} + +void tst_QXmppVCardIq::testPhone() +{ + QFETCH(QByteArray, xml); + QFETCH(int, type); + + QXmppVCardPhone phone; + parsePacket(phone, xml); + QCOMPARE(phone.number(), QLatin1String("12345")); + QCOMPARE(int(phone.type()), type); + serializePacket(phone, xml); +} + + void tst_QXmppVCardIq::testVCard() { const QByteArray xml( @@ -59,6 +96,8 @@ void tst_QXmppVCardIq::testVCard() "Foo Bar!" "FooBar" "FooWizBaz" + "12345" + "67890" "" "image/png" "" @@ -67,6 +106,7 @@ void tst_QXmppVCardIq::testVCard() "WfgYGBiQEHGJwSAK2BBQ1f3uvpAAAAAElFTkSuQmCC" "" "" + "http://code.google.com/p/qxmpp/" "" ""); @@ -74,18 +114,24 @@ void tst_QXmppVCardIq::testVCard() parsePacket(vcard, xml); QCOMPARE(vcard.birthday(), QDate(1983, 9, 14)); QCOMPARE(vcard.email(), QLatin1String("foo.bar@example.com")); + QCOMPARE(vcard.emails().size(), 1); + QCOMPARE(vcard.emails()[0].address(), QLatin1String("foo.bar@example.com")); + QCOMPARE(int(vcard.emails()[0].type()), int(QXmppVCardEmail::Internet)); QCOMPARE(vcard.nickName(), QLatin1String("FooBar")); QCOMPARE(vcard.fullName(), QLatin1String("Foo Bar!")); QCOMPARE(vcard.firstName(), QLatin1String("Foo")); QCOMPARE(vcard.middleName(), QLatin1String("Baz")); QCOMPARE(vcard.lastName(), QLatin1String("Wiz")); + QCOMPARE(vcard.phones().size(), 2); + QCOMPARE(vcard.phones()[0].number(), QLatin1String("12345")); + QCOMPARE(int(vcard.phones()[0].type()), int(QXmppVCardEmail::Home)); + QCOMPARE(vcard.phones()[1].number(), QLatin1String("67890")); + QCOMPARE(int(vcard.phones()[1].type()), int(QXmppVCardEmail::Work)); QCOMPARE(vcard.photo(), QByteArray::fromBase64( "iVBORw0KGgoAAAANSUhEUgAAAAgAAAAICAIAAABLbSncAAAAAXNSR0IArs4c6QAAAAlwSFlzAAA" "UIgAAFCIBjw1HyAAAAAd0SU1FB9oIHQInNvuJovgAAAAiSURBVAjXY2TQ+s/AwMDAwPD/GiMDlP" "WfgYGBiQEHGJwSAK2BBQ1f3uvpAAAAAElFTkSuQmCC")); QCOMPARE(vcard.photoType(), QLatin1String("image/png")); - QCOMPARE(vcard.emails().size(), 1); - QCOMPARE(vcard.emails()[0].address(), QLatin1String("foo.bar@example.com")); - QCOMPARE(int(vcard.emails()[0].type()), int(QXmppVCardEmail::Internet)); + QCOMPARE(vcard.url(), QLatin1String("http://code.google.com/p/qxmpp/")); serializePacket(vcard, xml); } diff --git a/tests/vcard.h b/tests/vcard.h index 5f0d6677..cc1527c1 100644 --- a/tests/vcard.h +++ b/tests/vcard.h @@ -30,5 +30,7 @@ class tst_QXmppVCardIq : public QObject private slots: void testEmail_data(); void testEmail(); + void testPhone_data(); + void testPhone(); void testVCard(); }; -- cgit v1.2.3