Skip to content

Commit df3de9b

Browse files
committed
xep-0292: cover all possible types for bday/anniversary
1 parent 8a07305 commit df3de9b

File tree

2 files changed

+107
-72
lines changed

2 files changed

+107
-72
lines changed

src/xmpp/xmpp-im/xmpp_vcard4.cpp

Lines changed: 96 additions & 62 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,33 @@ namespace {
7171
return result;
7272
}
7373

74+
static void serialize(QDomElement parent, const PHistorical &historical, const char *tagName)
75+
{
76+
std::visit(
77+
[&](auto const &v) mutable {
78+
if (v.isNull()) {
79+
return;
80+
}
81+
auto doc = parent.ownerDocument();
82+
auto bday = parent.appendChild(doc.createElement(QLatin1String(tagName))).toElement();
83+
historical.first.addTo(bday);
84+
using Tv = std::decay_t<decltype(v)>;
85+
if constexpr (std::is_same_v<Tv, QString>) {
86+
VCardHelper::addTextElement(doc, bday, QLatin1String("text"), QStringList { v });
87+
} else if constexpr (std::is_same_v<Tv, QDate>) {
88+
VCardHelper::addTextElement(doc, bday, QLatin1String("date"),
89+
QStringList { v.toString(Qt::ISODate) });
90+
} else if constexpr (std::is_same_v<Tv, QDateTime>) {
91+
VCardHelper::addTextElement(doc, bday, QLatin1String("date-time"),
92+
QStringList { v.toString(Qt::ISODate) });
93+
} else if constexpr (std::is_same_v<Tv, QTime>) {
94+
VCardHelper::addTextElement(doc, bday, QLatin1String("time"),
95+
QStringList { v.toString(Qt::ISODate) });
96+
}
97+
},
98+
historical.second);
99+
}
100+
74101
template <typename ListType>
75102
static void addTextElement(QDomDocument &document, QDomElement &parent, const QString &tagName,
76103
const ListType &texts)
@@ -86,10 +113,10 @@ namespace {
86113
}
87114

88115
template <typename T>
89-
static void serializeList(QDomDocument &document, QDomElement &parent,
90-
const QList<std::pair<Parameters, T>> &list, const QString &tagName,
91-
const QString &innerTagName = QLatin1String("text"))
116+
static void serializeList(QDomElement &parent, const QList<std::pair<Parameters, T>> &list,
117+
const QString &tagName, const QString &innerTagName = QLatin1String("text"))
92118
{
119+
auto document = parent.ownerDocument();
93120
for (const auto &entry : list) {
94121
QDomElement element = document.createElement(tagName);
95122
entry.first.addTo(element);
@@ -219,6 +246,36 @@ namespace {
219246
}
220247
}
221248
};
249+
250+
static void unserialize(const QDomElement &parent, const char *tagName, PHistorical &to)
251+
{
252+
QDomElement source = parent.firstChildElement(QLatin1String(tagName));
253+
if (source.isNull()) {
254+
return;
255+
}
256+
to.first = Parameters(source.firstChildElement(QLatin1String("parameters")));
257+
auto v = VCardHelper::extractText(source, "date");
258+
if (v.isNull()) {
259+
v = VCardHelper::extractText(source, "date-time");
260+
if (v.isNull()) {
261+
v = VCardHelper::extractText(source, "time");
262+
if (v.isNull()) {
263+
to.second = VCardHelper::extractText(source, "text");
264+
} else {
265+
to.second = QTime::fromString(v, Qt::ISODate);
266+
}
267+
} else {
268+
to.second = QDateTime::fromString(v, Qt::ISODate);
269+
}
270+
} else {
271+
to.second = QDate::fromString(v, Qt::ISODate);
272+
}
273+
}
274+
275+
static bool isNull(const PHistorical &h)
276+
{
277+
return std::visit([](auto const &v) { return v.isNull(); }, h.second);
278+
}
222279
};
223280

224281
} // namespace
@@ -417,8 +474,8 @@ class VCard::VCardData : public QSharedData {
417474
PNames names; // at most 1
418475
PStringLists nickname;
419476
PAdvUris photo;
420-
PDate bday; // at most 1
421-
PDate anniversary; // at most 1
477+
PHistorical bday; // at most 1
478+
PHistorical anniversary; // at most 1
422479
VCard4::Gender gender;
423480
QString genderComment;
424481

@@ -495,17 +552,8 @@ class VCard::VCardData : public QSharedData {
495552
VCardHelper::fillContainer(element, "email", emails);
496553
VCardHelper::fillContainer(element, "key", key);
497554

498-
QDomElement bdayElement = element.firstChildElement(QLatin1String("bday"));
499-
if (!bdayElement.isNull()) {
500-
bday.first = Parameters(bdayElement.firstChildElement(QLatin1String("parameters")));
501-
bday.second = QDate::fromString(VCardHelper::extractText(bdayElement, "date"), Qt::ISODate);
502-
}
503-
504-
QDomElement anniversaryElement = element.firstChildElement(QLatin1String("anniversary"));
505-
if (!anniversaryElement.isNull()) {
506-
anniversary.first = Parameters(anniversaryElement.firstChildElement(QLatin1String("parameters")));
507-
anniversary.second = QDate::fromString(VCardHelper::extractText(anniversaryElement, "date"), Qt::ISODate);
508-
}
555+
VCardHelper::unserialize(element, "bday", bday);
556+
VCardHelper::unserialize(element, "anniversary", anniversary);
509557

510558
QDomElement genderElement = element.firstChildElement(QLatin1String("sex"));
511559
if (!genderElement.isNull()) {
@@ -559,7 +607,7 @@ class VCard::VCardData : public QSharedData {
559607
{
560608
return fullName.isEmpty() && names.second.isEmpty() && nickname.isEmpty() && emails.isEmpty() && tels.isEmpty()
561609
&& org.isEmpty() && title.isEmpty() && role.isEmpty() && note.isEmpty() && urls.isEmpty()
562-
&& bday.second.isNull() && anniversary.second.isNull() && gender == VCard4::Gender::Undefined
610+
&& VCardHelper::isNull(bday) && VCardHelper::isNull(anniversary) && gender == VCard4::Gender::Undefined
563611
&& uid.isEmpty() && kind.isEmpty() && categories.isEmpty() && busyTimeUrl.isEmpty()
564612
&& calendarRequestUri.isEmpty() && calendarUri.isEmpty() && clientPidMap.isEmpty() && geo.isEmpty()
565613
&& impp.isEmpty() && key.isEmpty() && lang.isEmpty() && logo.isEmpty() && member.isEmpty()
@@ -591,34 +639,22 @@ QDomElement VCard::toXmlElement(QDomDocument &document) const
591639

592640
QDomElement vCardElement = document.createElement(QLatin1String("vcard"));
593641

594-
VCardHelper::serializeList(document, vCardElement, d->fullName, QLatin1String("fn"));
642+
VCardHelper::serializeList(vCardElement, d->fullName, QLatin1String("fn"));
595643
if (!d->names.second.isEmpty()) {
596644
auto e = vCardElement.appendChild(d->names.second.toXmlElement(document)).toElement();
597645
d->names.first.addTo(e);
598646
}
599-
VCardHelper::serializeList(document, vCardElement, d->nickname, QLatin1String("nickname"), QLatin1String("text"));
600-
VCardHelper::serializeList(document, vCardElement, d->emails, QLatin1String("email"), QLatin1String("text"));
601-
VCardHelper::serializeList(document, vCardElement, d->tels, QLatin1String("tel"), QLatin1String("uri"));
602-
VCardHelper::serializeList(document, vCardElement, d->org, QLatin1String("org"), QLatin1String("text"));
603-
VCardHelper::serializeList(document, vCardElement, d->title, QLatin1String("title"), QLatin1String("text"));
604-
VCardHelper::serializeList(document, vCardElement, d->role, QLatin1String("role"), QLatin1String("text"));
605-
VCardHelper::serializeList(document, vCardElement, d->note, QLatin1String("note"), QLatin1String("text"));
606-
VCardHelper::serializeList(document, vCardElement, d->urls, QLatin1String("url"), QLatin1String("uri"));
607-
608-
if (!d->bday.second.isNull()) {
609-
QDomElement bdayElement = document.createElement(QLatin1String("bday"));
610-
d->bday.first.addTo(bdayElement);
611-
VCardHelper::addTextElement(document, bdayElement, QLatin1String("date"), d->bday.second.toString(Qt::ISODate));
612-
vCardElement.appendChild(bdayElement);
613-
}
614-
615-
if (!d->anniversary.second.isNull()) {
616-
QDomElement anniversaryElement = document.createElement(QLatin1String("anniversary"));
617-
d->anniversary.first.addTo(anniversaryElement);
618-
VCardHelper::addTextElement(document, anniversaryElement, QLatin1String("date"),
619-
d->anniversary.second.toString(Qt::ISODate));
620-
vCardElement.appendChild(anniversaryElement);
621-
}
647+
VCardHelper::serializeList(vCardElement, d->nickname, QLatin1String("nickname"), QLatin1String("text"));
648+
VCardHelper::serializeList(vCardElement, d->emails, QLatin1String("email"), QLatin1String("text"));
649+
VCardHelper::serializeList(vCardElement, d->tels, QLatin1String("tel"), QLatin1String("uri"));
650+
VCardHelper::serializeList(vCardElement, d->org, QLatin1String("org"), QLatin1String("text"));
651+
VCardHelper::serializeList(vCardElement, d->title, QLatin1String("title"), QLatin1String("text"));
652+
VCardHelper::serializeList(vCardElement, d->role, QLatin1String("role"), QLatin1String("text"));
653+
VCardHelper::serializeList(vCardElement, d->note, QLatin1String("note"), QLatin1String("text"));
654+
VCardHelper::serializeList(vCardElement, d->urls, QLatin1String("url"), QLatin1String("uri"));
655+
656+
VCardHelper::serialize(vCardElement, d->bday, "bday");
657+
VCardHelper::serialize(vCardElement, d->bday, "anniversary");
622658

623659
if (d->gender != VCard4::Gender::Undefined) {
624660
QDomElement genderElement = document.createElement(QLatin1String("gender"));
@@ -629,29 +665,27 @@ QDomElement VCard::toXmlElement(QDomDocument &document) const
629665
vCardElement.appendChild(genderElement);
630666
}
631667

632-
VCardHelper::serializeList(document, vCardElement, d->categories, QLatin1String("categories"),
633-
QLatin1String("text"));
634-
VCardHelper::serializeList(document, vCardElement, d->busyTimeUrl, QLatin1String("fburl"), QLatin1String("uri"));
635-
VCardHelper::serializeList(document, vCardElement, d->calendarRequestUri, QLatin1String("caladruri"),
636-
QLatin1String("uri"));
637-
VCardHelper::serializeList(document, vCardElement, d->calendarUri, QLatin1String("caluri"), QLatin1String("uri"));
668+
VCardHelper::serializeList(vCardElement, d->categories, QLatin1String("categories"), QLatin1String("text"));
669+
VCardHelper::serializeList(vCardElement, d->busyTimeUrl, QLatin1String("fburl"), QLatin1String("uri"));
670+
VCardHelper::serializeList(vCardElement, d->calendarRequestUri, QLatin1String("caladruri"), QLatin1String("uri"));
671+
VCardHelper::serializeList(vCardElement, d->calendarUri, QLatin1String("caluri"), QLatin1String("uri"));
638672
for (auto it = d->clientPidMap.cbegin(); it != d->clientPidMap.cend(); ++it) {
639673
auto m = vCardElement.appendChild(document.createElement(QLatin1String("clientpidmap")));
640674
m.appendChild(document.createElement(QLatin1String("sourceid")))
641675
.appendChild(document.createTextNode(QString::number(it.key())));
642676
m.appendChild(document.createElement(QLatin1String("uri"))).appendChild(document.createTextNode(it.value()));
643677
}
644-
VCardHelper::serializeList(document, vCardElement, d->geo, QLatin1String("geo"), QLatin1String("uri"));
645-
VCardHelper::serializeList(document, vCardElement, d->impp, QLatin1String("impp"), QLatin1String("uri"));
646-
VCardHelper::serializeList(document, vCardElement, d->key, QLatin1String("key"), QLatin1String("uri"));
647-
VCardHelper::serializeList(document, vCardElement, d->lang, QLatin1String("lang"), QLatin1String("language-tag"));
648-
VCardHelper::serializeList(document, vCardElement, d->logo, QLatin1String("logo"), QLatin1String("uri"));
649-
VCardHelper::serializeList(document, vCardElement, d->member, QLatin1String("member"), QLatin1String("uri"));
650-
VCardHelper::serializeList(document, vCardElement, d->photo, QLatin1String("photo"), QLatin1String("uri"));
651-
VCardHelper::serializeList(document, vCardElement, d->related, QLatin1String("related"), QLatin1String("text"));
652-
VCardHelper::serializeList(document, vCardElement, d->timeZone, QLatin1String("tz"), QLatin1String("text"));
653-
VCardHelper::serializeList(document, vCardElement, d->sound, QLatin1String("sound"), QLatin1String("uri"));
654-
VCardHelper::serializeList(document, vCardElement, d->source, QLatin1String("source"), QLatin1String("uri"));
678+
VCardHelper::serializeList(vCardElement, d->geo, QLatin1String("geo"), QLatin1String("uri"));
679+
VCardHelper::serializeList(vCardElement, d->impp, QLatin1String("impp"), QLatin1String("uri"));
680+
VCardHelper::serializeList(vCardElement, d->key, QLatin1String("key"), QLatin1String("uri"));
681+
VCardHelper::serializeList(vCardElement, d->lang, QLatin1String("lang"), QLatin1String("language-tag"));
682+
VCardHelper::serializeList(vCardElement, d->logo, QLatin1String("logo"), QLatin1String("uri"));
683+
VCardHelper::serializeList(vCardElement, d->member, QLatin1String("member"), QLatin1String("uri"));
684+
VCardHelper::serializeList(vCardElement, d->photo, QLatin1String("photo"), QLatin1String("uri"));
685+
VCardHelper::serializeList(vCardElement, d->related, QLatin1String("related"), QLatin1String("text"));
686+
VCardHelper::serializeList(vCardElement, d->timeZone, QLatin1String("tz"), QLatin1String("text"));
687+
VCardHelper::serializeList(vCardElement, d->sound, QLatin1String("sound"), QLatin1String("uri"));
688+
VCardHelper::serializeList(vCardElement, d->source, QLatin1String("source"), QLatin1String("uri"));
655689

656690
if (d->rev.isValid()) {
657691
auto revE = vCardElement.appendChild(document.createElement(QLatin1String("rev")))
@@ -805,17 +839,17 @@ void VCard::setUrls(const PUris &urls)
805839
d->urls = urls;
806840
}
807841

808-
PDate VCard::bday() const { return d ? d->bday : PDate(); }
842+
PHistorical VCard::bday() const { return d ? d->bday : PHistorical(); }
809843

810-
void VCard::setBday(const PDate &bday)
844+
void VCard::setBday(const PHistorical &bday)
811845
{
812846
INIT_D();
813847
d->bday = bday;
814848
}
815849

816-
PDate VCard::anniversary() const { return d ? d->anniversary : PDate(); }
850+
PHistorical VCard::anniversary() const { return d ? d->anniversary : PHistorical(); }
817851

818-
void VCard::setAnniversary(const PDate &anniversary)
852+
void VCard::setAnniversary(const PHistorical &anniversary)
819853
{
820854
INIT_D();
821855
d->anniversary = anniversary;

src/xmpp/xmpp-im/xmpp_vcard4.h

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@
1717
*
1818
*/
1919

20-
#ifndef VCARD_H
21-
#define VCARD_H
20+
#ifndef XMPP_VCARD4_H
21+
#define XMPP_VCARD4_H
2222

2323
#include <QDate>
2424
#include <QDateTime>
@@ -47,7 +47,6 @@ class Parameters {
4747
void addTo(QDomElement parent) const;
4848
bool isEmpty() const;
4949

50-
private:
5150
QStringList type;
5251
QString language;
5352
QString altid;
@@ -101,8 +100,9 @@ class UriValue {
101100
QString mediaType;
102101
};
103102

104-
using UriOrText = std::variant<QUrl, QString>;
105-
using TimeZone = std::variant<QUrl, QString, int>;
103+
using UriOrText = std::variant<QUrl, QString>;
104+
using TimeZone = std::variant<QUrl, QString, int>;
105+
using Historical = std::variant<QDateTime, QDate, QTime, QString>;
106106

107107
using PStringList = std::pair<Parameters, QStringList>;
108108
using PString = std::pair<Parameters, QString>;
@@ -113,6 +113,7 @@ using PAddress = std::pair<Parameters, Address>;
113113
using PNames = std::pair<Parameters, Names>;
114114
using PUriOrText = std::pair<Parameters, UriOrText>;
115115
using PTimeZone = std::pair<Parameters, TimeZone>;
116+
using PHistorical = std::pair<Parameters, Historical>;
116117

117118
using PStringLists = QList<PStringList>;
118119
using PStrings = QList<PString>;
@@ -167,11 +168,11 @@ class VCard {
167168
PUris urls() const;
168169
void setUrls(const PUris &urls);
169170

170-
PDate bday() const;
171-
void setBday(const PDate &bday);
171+
PHistorical bday() const;
172+
void setBday(const PHistorical &bday);
172173

173-
PDate anniversary() const;
174-
void setAnniversary(const PDate &anniversary);
174+
PHistorical anniversary() const;
175+
void setAnniversary(const PHistorical &anniversary);
175176

176177
Gender gender() const;
177178
void setGender(Gender gender);
@@ -249,4 +250,4 @@ class VCard {
249250

250251
} // namespace VCard4
251252

252-
#endif // VCARD_H
253+
#endif // XMPP_VCARD4_H

0 commit comments

Comments
 (0)