KContacts

vcardtool.cpp
1 /*
2  This file is part of the KContacts framework.
3  SPDX-FileCopyrightText: 2003 Tobias Koenig <[email protected]>
4  SPDX-FileCopyrightText: 2015-2019 Laurent Montel <[email protected]>
5 
6  SPDX-License-Identifier: LGPL-2.0-or-later
7 */
8 
9 #include "vcardtool_p.h"
10 #include "key.h"
11 #include "picture.h"
12 #include "secrecy.h"
13 #include "sound.h"
14 #include "lang.h"
15 #include "gender.h"
16 #include "related.h"
17 #include "fieldgroup.h"
18 #include "kcontacts_debug.h"
19 #include <QString>
20 
21 using namespace KContacts;
22 
23 static bool needsEncoding(const QString &value)
24 {
25  int length = value.length();
26  for (int i = 0; i < length; ++i) {
27  char c = value.at(i).toLatin1();
28  if ((c < 33 || c > 126) && c != ' ' && c != '=') {
29  return true;
30  }
31  }
32 
33  return false;
34 }
35 
36 static const struct {
37  const char *addressType;
38  Address::TypeFlag flag;
39 } s_addressTypes[] = {
40  { "dom", Address::Dom },
41  { "home", Address::Home },
42  { "intl", Address::Intl },
43  { "parcel", Address::Parcel },
44  { "postal", Address::Postal },
45  { "pref", Address::Pref },
46  { "work", Address::Work },
47 };
48 
49 static const unsigned int s_numAddressTypes
50  = sizeof s_addressTypes / sizeof *s_addressTypes;
51 
52 static Address::TypeFlag stringToAddressType(const QString &str)
53 {
54  for (unsigned int i = 0; i < s_numAddressTypes; ++i) {
55  if (str == QLatin1String(s_addressTypes[i].addressType)) {
56  return s_addressTypes[i].flag;
57  }
58  }
59  return {};
60 }
61 
62 static const struct {
63  const char *phoneType;
65 } s_phoneTypes[] = {
66  { "BBS", PhoneNumber::Bbs },
67  { "CAR", PhoneNumber::Car },
68  { "CELL", PhoneNumber::Cell },
69  { "FAX", PhoneNumber::Fax },
70  { "HOME", PhoneNumber::Home },
71  { "ISDN", PhoneNumber::Isdn },
72  { "MODEM", PhoneNumber::Modem },
73  { "MSG", PhoneNumber::Msg },
74  { "PAGER", PhoneNumber::Pager },
75  { "PCS", PhoneNumber::Pcs },
76  { "PREF", PhoneNumber::Pref },
77  { "VIDEO", PhoneNumber::Video },
78  { "VOICE", PhoneNumber::Voice },
79  { "WORK", PhoneNumber::Work },
80 };
81 
82 static const unsigned int s_numPhoneTypes
83  = sizeof s_phoneTypes / sizeof *s_phoneTypes;
84 
85 static PhoneNumber::TypeFlag stringToPhoneType(const QString &str)
86 {
87  for (unsigned int i = 0; i < s_numPhoneTypes; ++i) {
88  if (str == QLatin1String(s_phoneTypes[i].phoneType)) {
89  return s_phoneTypes[i].flag;
90  }
91  }
92  return {};
93 }
94 
95 VCardTool::VCardTool()
96 {
97 }
98 
99 VCardTool::~VCardTool()
100 {
101 }
102 
103 QByteArray VCardTool::exportVCards(const Addressee::List &list, VCard::Version version) const
104 {
105  return createVCards(list, version, true /*export vcard*/);
106 }
107 
108 QByteArray VCardTool::createVCards(const Addressee::List &list, VCard::Version version) const
109 {
110  return createVCards(list, version, false /*don't export*/);
111 }
112 
113 void VCardTool::addParameters(VCardLine &line, const QMap<QString, QStringList> &params) const
114 {
116  while (i.hasNext()) {
117  i.next();
118  line.addParameter(i.key(), i.value().join(QLatin1Char(',')));
119  }
120 }
121 
122 void VCardTool::addParameter(VCardLine &line, VCard::Version version, const QString &key, const QStringList &valueStringList) const
123 {
124  if (version == VCard::v2_1) {
125  for (const QString &valueStr : valueStringList) {
126  line.addParameter(valueStr, QString());
127  }
128  } else if (version == VCard::v3_0) {
129  line.addParameter(key, valueStringList.join(QLatin1Char(',')));
130  } else {
131  if (valueStringList.count() < 2) {
132  line.addParameter(key, valueStringList.join(QLatin1Char(',')));
133  } else {
134  line.addParameter(key, QLatin1Char('"') + valueStringList.join(QLatin1Char(',')) + QLatin1Char('"'));
135  }
136  }
137 }
138 
139 QByteArray VCardTool::createVCards(const Addressee::List &list, VCard::Version version, bool exportVcard) const
140 {
141  VCard::List vCardList;
142 
145  for (addrIt = list.constBegin(); addrIt != listEnd; ++addrIt) {
146  VCard card;
148  // VERSION
149  if (version == VCard::v2_1) {
150  card.addLine(VCardLine(QStringLiteral("VERSION"), QStringLiteral("2.1")));
151  } else if (version == VCard::v3_0) {
152  card.addLine(VCardLine(QStringLiteral("VERSION"), QStringLiteral("3.0")));
153  } else if (version == VCard::v4_0) {
154  card.addLine(VCardLine(QStringLiteral("VERSION"), QStringLiteral("4.0")));
155  }
156 
157  // ADR + LABEL
158  const Address::List addresses = (*addrIt).addresses();
159  Address::List::ConstIterator end(addresses.end());
160  for (Address::List::ConstIterator it = addresses.begin(); it != end; ++it) {
162 
163  const bool isEmpty = ((*it).postOfficeBox().isEmpty()
164  && (*it).extended().isEmpty()
165  && (*it).street().isEmpty()
166  && (*it).locality().isEmpty()
167  && (*it).region().isEmpty()
168  && (*it).postalCode().isEmpty()
169  && (*it).country().isEmpty());
170 
171  address.append((*it).postOfficeBox().replace(QLatin1Char(';'),
172  QStringLiteral("\\;")));
173 
174  address.append((*it).extended().replace(QLatin1Char(';'),
175  QStringLiteral("\\;")));
176 
177  address.append((*it).street().replace(QLatin1Char(';'),
178  QStringLiteral("\\;")));
179 
180  address.append((*it).locality().replace(QLatin1Char(';'),
181  QStringLiteral("\\;")));
182 
183  address.append((*it).region().replace(QLatin1Char(';'),
184  QStringLiteral("\\;")));
185 
186  address.append((*it).postalCode().replace(QLatin1Char(';'),
187  QStringLiteral("\\;")));
188 
189  address.append((*it).country().replace(QLatin1Char(';'),
190  QStringLiteral("\\;")));
191 
192  const QString addressJoined(address.join(QLatin1Char(';')));
193  VCardLine adrLine(QStringLiteral("ADR"), addressJoined);
194  if (version == VCard::v2_1 && needsEncoding(addressJoined)) {
195  adrLine.addParameter(QStringLiteral("charset"), QStringLiteral("UTF-8"));
196  adrLine.addParameter(QStringLiteral("encoding"), QStringLiteral("QUOTED-PRINTABLE"));
197  }
198 
199  const bool hasLabel = !(*it).label().isEmpty();
200  QStringList addreLineType;
201  QStringList labelLineType;
202  for (unsigned int i = 0; i < s_numAddressTypes; ++i) {
203  if (s_addressTypes[i].flag & (*it).type()) {
204  const QString str = QString::fromLatin1(s_addressTypes[i].addressType);
205  addreLineType << str;
206  if (hasLabel) {
207  labelLineType << str;
208  }
209  }
210  }
211 
212  if (hasLabel) {
213  if (version == VCard::v4_0) {
214  if (!(*it).label().isEmpty()) {
215  adrLine.addParameter(QStringLiteral("LABEL"), QStringLiteral("\"%1\"").arg((*it).label()));
216  }
217  } else {
218  VCardLine labelLine(QStringLiteral("LABEL"), (*it).label());
219  if (version == VCard::v2_1 && needsEncoding((*it).label())) {
220  labelLine.addParameter(QStringLiteral("charset"), QStringLiteral("UTF-8"));
221  labelLine.addParameter(QStringLiteral("encoding"), QStringLiteral("QUOTED-PRINTABLE"));
222  }
223  addParameter(labelLine, version, QStringLiteral("TYPE"), labelLineType);
224  card.addLine(labelLine);
225  }
226  }
227  if (version == VCard::v4_0) {
228  Geo geo = (*it).geo();
229  if (geo.isValid()) {
230  QString str = QString::asprintf("\"geo:%.6f,%.6f\"", geo.latitude(), geo.longitude());
231  adrLine.addParameter(QStringLiteral("GEO"), str);
232  }
233  }
234  if (!isEmpty) {
235  addParameter(adrLine, version, QStringLiteral("TYPE"), addreLineType);
236  card.addLine(adrLine);
237  }
238  }
239 
240  // BDAY
241  const bool withTime = (*addrIt).birthdayHasTime();
242  const QString birthdayString = createDateTime((*addrIt).birthday(), version, withTime);
243  card.addLine(VCardLine(QStringLiteral("BDAY"), birthdayString));
244 
245  //Laurent: 31 Jan 2015. Not necessary to export it. When Categories were changes as AkonadiTag nobody thought that it was break categorie support...
246  //=> not necessary to export just tag...
247  // CATEGORIES only > 2.1
248  if (!exportVcard) {
249  if (version != VCard::v2_1) {
250  QStringList categories = (*addrIt).categories();
251  QStringList::Iterator catIt;
252  QStringList::Iterator catEnd(categories.end());
253  for (catIt = categories.begin(); catIt != catEnd; ++catIt) {
254  (*catIt).replace(QLatin1Char(','), QStringLiteral("\\,"));
255  }
256 
257  VCardLine catLine(QStringLiteral("CATEGORIES"), categories.join(QLatin1Char(',')));
258  card.addLine(catLine);
259  }
260  }
261  // MEMBER (only in 4.0)
262  if (version == VCard::v4_0) {
263  // The KIND property must be set to "group" in order to use this property.
264  if ((*addrIt).kind().toLower() == QLatin1String("group")) {
265  const QStringList lst = (*addrIt).members();
266  for (const QString &member : lst) {
267  VCardLine line(QStringLiteral("MEMBER"), member);
268  card.addLine(line);
269  }
270  }
271  }
272  // SOURCE
273  const QVector<QUrl> lstUrl = (*addrIt).sourcesUrlList();
274  for (const QUrl &url : lstUrl) {
275  VCardLine line = VCardLine(QStringLiteral("SOURCE"), url.url());
276  card.addLine(line);
277  }
278 
279  const Related::List relatedList = (*addrIt).relationships();
281  Related::List::ConstIterator relatedEnd(relatedList.end());
282  for (relatedIt = relatedList.begin(); relatedIt != relatedEnd; ++relatedIt) {
283  VCardLine line(QStringLiteral("RELATED"), (*relatedIt).related());
284  addParameters(line, (*relatedIt).parameters());
285  card.addLine(line);
286  }
287  // CLASS only for version == 3.0
288  if (version == VCard::v3_0) {
289  card.addLine(createSecrecy((*addrIt).secrecy()));
290  }
291  // LANG only for version == 4.0
292  if (version == VCard::v4_0) {
293  const Lang::List langList = (*addrIt).langs();
295  Lang::List::ConstIterator langEnd(langList.end());
296  for (langIt = langList.begin(); langIt != langEnd; ++langIt) {
297  VCardLine line(QStringLiteral("LANG"), (*langIt).language());
298  addParameters(line, (*langIt).parameters());
299  card.addLine(line);
300  }
301  }
302  // CLIENTPIDMAP
303  if (version == VCard::v4_0) {
304  const ClientPidMap::List clientpidmapList = (*addrIt).clientPidMapList();
305  ClientPidMap::List::ConstIterator clientPidMapIt;
306  ClientPidMap::List::ConstIterator clientPidMapEnd(clientpidmapList.end());
307  for (clientPidMapIt = clientpidmapList.begin(); clientPidMapIt != clientPidMapEnd; ++clientPidMapIt) {
308  VCardLine line(QStringLiteral("CLIENTPIDMAP"), (*clientPidMapIt).clientPidMap());
309  addParameters(line, (*clientPidMapIt).parameters());
310  card.addLine(line);
311  }
312  }
313  // EMAIL
314  const Email::List emailList = (*addrIt).emailList();
316  Email::List::ConstIterator emailEnd(emailList.end());
317  for (emailIt = emailList.begin(); emailIt != emailEnd; ++emailIt) {
318  VCardLine line(QStringLiteral("EMAIL"), (*emailIt).mail());
319  QMapIterator<QString, QStringList> i((*emailIt).parameters());
320  while (i.hasNext()) {
321  i.next();
322  if (version == VCard::v2_1) {
323  if (i.key().toLower() == QLatin1String("type")) {
324  QStringList valueStringList = i.value();
325  bool hasPreferred = false;
326  const int removeItems = valueStringList.removeAll(QStringLiteral("PREF"));
327  if (removeItems > 0) {
328  hasPreferred = true;
329  }
330  if (!valueStringList.isEmpty()) {
331  addParameter(line, version, i.key(), valueStringList);
332  }
333  if (hasPreferred) {
334  line.addParameter(QStringLiteral("PREF"), QString());
335  }
336  } else {
337  line.addParameter(i.key(), i.value().join(QLatin1Char(',')));
338  }
339  } else {
340  line.addParameter(i.key(), i.value().join(QLatin1Char(',')));
341  }
342  }
343  card.addLine(line);
344  }
345 
346  // FN required for only version > 2.1
347  VCardLine fnLine(QStringLiteral("FN"), (*addrIt).formattedName());
348  if (version == VCard::v2_1 && needsEncoding((*addrIt).formattedName())) {
349  fnLine.addParameter(QStringLiteral("charset"), QStringLiteral("UTF-8"));
350  fnLine.addParameter(QStringLiteral("encoding"), QStringLiteral("QUOTED-PRINTABLE"));
351  }
352  card.addLine(fnLine);
353 
354  // GEO
355  const Geo geo = (*addrIt).geo();
356  if (geo.isValid()) {
357  QString str;
358  if (version == VCard::v4_0) {
359  str = QString::asprintf("geo:%.6f,%.6f", geo.latitude(), geo.longitude());
360  } else {
361  str = QString::asprintf("%.6f;%.6f", geo.latitude(), geo.longitude());
362  }
363  card.addLine(VCardLine(QStringLiteral("GEO"), str));
364  }
365 
366  // KEY
367  const Key::List keys = (*addrIt).keys();
369  Key::List::ConstIterator keyEnd(keys.end());
370  for (keyIt = keys.begin(); keyIt != keyEnd; ++keyIt) {
371  card.addLine(createKey(*keyIt, version));
372  }
373 
374  // LOGO
375  card.addLine(createPicture(QStringLiteral("LOGO"), (*addrIt).logo(), version));
376  const QVector<Picture> lstLogo = (*addrIt).extraLogoList();
377  for (const Picture &logo : lstLogo) {
378  card.addLine(createPicture(QStringLiteral("LOGO"), logo, version));
379  }
380 
381  // MAILER only for version < 4.0
382  if (version != VCard::v4_0) {
383  VCardLine mailerLine(QStringLiteral("MAILER"), (*addrIt).mailer());
384  if (version == VCard::v2_1 && needsEncoding((*addrIt).mailer())) {
385  mailerLine.addParameter(QStringLiteral("charset"), QStringLiteral("UTF-8"));
386  mailerLine.addParameter(QStringLiteral("encoding"), QStringLiteral("QUOTED-PRINTABLE"));
387  }
388  card.addLine(mailerLine);
389  }
390 
391  // N required for only version < 4.0
393  name.append((*addrIt).familyName().replace(QLatin1Char(';'),
394  QStringLiteral("\\;")));
395 
396  name.append((*addrIt).givenName().replace(QLatin1Char(';'),
397  QStringLiteral("\\;")));
398 
399  name.append((*addrIt).additionalName().replace(QLatin1Char(';'),
400  QStringLiteral("\\;")));
401 
402  name.append((*addrIt).prefix().replace(QLatin1Char(';'),
403  QStringLiteral("\\;")));
404 
405  name.append((*addrIt).suffix().replace(QLatin1Char(';'),
406  QStringLiteral("\\;")));
407 
408  VCardLine nLine(QStringLiteral("N"), name.join(QLatin1Char(';')));
409  if (version == VCard::v2_1 && needsEncoding(name.join(QLatin1Char(';')))) {
410  nLine.addParameter(QStringLiteral("charset"), QStringLiteral("UTF-8"));
411  nLine.addParameter(QStringLiteral("encoding"), QStringLiteral("QUOTED-PRINTABLE"));
412  }
413  if (version == VCard::v4_0 && !(*addrIt).sortString().isEmpty()) {
414  nLine.addParameter(QStringLiteral("SORT-AS"), (*addrIt).sortString());
415  }
416 
417  card.addLine(nLine);
418 
419  // NAME only for version < 4.0
420  if (version != VCard::v4_0) {
421  VCardLine nameLine(QStringLiteral("NAME"), (*addrIt).name());
422  if (version == VCard::v2_1 && needsEncoding((*addrIt).name())) {
423  nameLine.addParameter(QStringLiteral("charset"), QStringLiteral("UTF-8"));
424  nameLine.addParameter(QStringLiteral("encoding"), QStringLiteral("QUOTED-PRINTABLE"));
425  }
426  card.addLine(nameLine);
427  }
428 
429  // NICKNAME only for version > 2.1
430  if (version != VCard::v2_1) {
431  const QVector<NickName> lstNickName = (*addrIt).extraNickNameList();
432  for (const NickName &nickName : lstNickName) {
433  VCardLine nickNameLine(QStringLiteral("NICKNAME"), nickName.nickname());
434  addParameters(nickNameLine, nickName.parameters());
435 
436  card.addLine(nickNameLine);
437  }
438  }
439 
440  // NOTE
441  VCardLine noteLine(QStringLiteral("NOTE"), (*addrIt).note());
442  if (version == VCard::v2_1 && needsEncoding((*addrIt).note())) {
443  noteLine.addParameter(QStringLiteral("charset"), QStringLiteral("UTF-8"));
444  noteLine.addParameter(QStringLiteral("encoding"), QStringLiteral("QUOTED-PRINTABLE"));
445  }
446  card.addLine(noteLine);
447 
448  // ORG
449  const QVector<Org> lstOrg = (*addrIt).extraOrganizationList();
450  for (const Org &org : lstOrg) {
451  QStringList organization;
452  organization.append(org.organization().replace(QLatin1Char(';'),
453  QStringLiteral("\\;")));
454  if (!(*addrIt).department().isEmpty()) {
455  organization.append((*addrIt).department().replace(QLatin1Char(';'),
456  QStringLiteral("\\;")));
457  }
458  const QString orgStr = organization.join(QLatin1Char(';'));
459  VCardLine orgLine(QStringLiteral("ORG"), orgStr);
460  if (version == VCard::v2_1 && needsEncoding(orgStr)) {
461  orgLine.addParameter(QStringLiteral("charset"), QStringLiteral("UTF-8"));
462  orgLine.addParameter(QStringLiteral("encoding"), QStringLiteral("QUOTED-PRINTABLE"));
463  }
464  addParameters(orgLine, org.parameters());
465  card.addLine(orgLine);
466  }
467 
468  // PHOTO
469  card.addLine(createPicture(QStringLiteral("PHOTO"), (*addrIt).photo(), version));
470  const QVector<Picture> lstExtraPhoto = (*addrIt).extraPhotoList();
471  for (const Picture &photo : lstExtraPhoto) {
472  card.addLine(createPicture(QStringLiteral("PHOTO"), photo, version));
473  }
474 
475  // PROID only for version > 2.1
476  if (version != VCard::v2_1) {
477  card.addLine(VCardLine(QStringLiteral("PRODID"), (*addrIt).productId()));
478  }
479 
480  // REV
481  card.addLine(VCardLine(QStringLiteral("REV"), createDateTime((*addrIt).revision(), version)));
482 
483  // ROLE
484  const QVector<Role> lstExtraRole = (*addrIt).extraRoleList();
485  for (const Role &role : lstExtraRole) {
486  VCardLine roleLine(QStringLiteral("ROLE"), role.role());
487  if (version == VCard::v2_1 && needsEncoding(role.role())) {
488  roleLine.addParameter(QStringLiteral("charset"), QStringLiteral("UTF-8"));
489  roleLine.addParameter(QStringLiteral("encoding"), QStringLiteral("QUOTED-PRINTABLE"));
490  }
491  addParameters(roleLine, role.parameters());
492  card.addLine(roleLine);
493  }
494 
495  // SORT-STRING
496  if (version == VCard::v3_0) {
497  card.addLine(VCardLine(QStringLiteral("SORT-STRING"), (*addrIt).sortString()));
498  }
499 
500  // SOUND
501  card.addLine(createSound((*addrIt).sound(), version));
502  const QVector<Sound> lstSound = (*addrIt).extraSoundList();
503  for (const Sound &sound : lstSound) {
504  card.addLine(createSound(sound, version));
505  }
506 
507  // TEL
508  const PhoneNumber::List phoneNumbers = (*addrIt).phoneNumbers();
510  PhoneNumber::List::ConstIterator phoneEnd(phoneNumbers.end());
511  for (phoneIt = phoneNumbers.begin(); phoneIt != phoneEnd; ++phoneIt) {
512  VCardLine line(QStringLiteral("TEL"), (*phoneIt).number());
513  QMapIterator<QString, QStringList> i((*phoneIt).parameters());
514  while (i.hasNext()) {
515  i.next();
516  if (i.key().toUpper() != QLatin1String("TYPE")) {
517  line.addParameter(i.key(), i.value().join(QLatin1Char(',')));
518  }
519  }
520 
521  QStringList lst;
522  for (unsigned int i = 0; i < s_numPhoneTypes; ++i) {
523  if (s_phoneTypes[i].flag & (*phoneIt).type()) {
524  const QString str = QString::fromLatin1(s_phoneTypes[i].phoneType);
525  if (version == VCard::v4_0) {
526  lst << str.toLower();
527  } else {
528  lst << str;
529  }
530  }
531  }
532  if (!lst.isEmpty()) {
533  addParameter(line, version, QStringLiteral("TYPE"), lst);
534  }
535  card.addLine(line);
536  }
537 
538  // TITLE
539  const QVector<Title> lstTitle = (*addrIt).extraTitleList();
540  for (const Title &title : lstTitle) {
541  VCardLine titleLine(QStringLiteral("TITLE"), title.title());
542  if (version == VCard::v2_1 && needsEncoding(title.title())) {
543  titleLine.addParameter(QStringLiteral("charset"), QStringLiteral("UTF-8"));
544  titleLine.addParameter(QStringLiteral("encoding"), QStringLiteral("QUOTED-PRINTABLE"));
545  }
546  addParameters(titleLine, title.parameters());
547 
548  card.addLine(titleLine);
549  }
550 
551  // TZ
552  // TODO Add vcard4.0 support
553  const TimeZone timeZone = (*addrIt).timeZone();
554  if (timeZone.isValid()) {
555 
556  int neg = 1;
557  if (timeZone.offset() < 0) {
558  neg = -1;
559  }
560 
561  QString str = QString::asprintf("%c%02d:%02d", (timeZone.offset() >= 0 ? '+' : '-'),
562  (timeZone.offset() / 60) * neg,
563  (timeZone.offset() % 60) * neg);
564 
565  card.addLine(VCardLine(QStringLiteral("TZ"), str));
566  }
567 
568  // UID
569  card.addLine(VCardLine(QStringLiteral("UID"), (*addrIt).uid()));
570 
571  // URL
572  const QVector<ResourceLocatorUrl> lstExtraUrl = (*addrIt).extraUrlList();
573  for (const ResourceLocatorUrl &url : lstExtraUrl) {
574  VCardLine line(QStringLiteral("URL"), url.url());
575  addParameters(line, url.parameters());
576  card.addLine(line);
577  }
578  if (version == VCard::v4_0) {
579  // GENDER
580  const Gender gender = (*addrIt).gender();
581  if (gender.isValid()) {
582  QString genderStr;
583  if (!gender.gender().isEmpty()) {
584  genderStr = gender.gender();
585  }
586  if (!gender.comment().isEmpty()) {
587  genderStr += QLatin1Char(';') + gender.comment();
588  }
589  VCardLine line(QStringLiteral("GENDER"), genderStr);
590  card.addLine(line);
591  }
592  // KIND
593  if (!(*addrIt).kind().isEmpty()) {
594  VCardLine line(QStringLiteral("KIND"), (*addrIt).kind());
595  card.addLine(line);
596  }
597  }
598  // From vcard4.
599  if (version == VCard::v4_0) {
600  const QVector<CalendarUrl> lstCalendarUrl = (*addrIt).calendarUrlList();
601  for (const CalendarUrl &url : lstCalendarUrl) {
602  if (url.isValid()) {
603  QString type;
604  switch (url.type()) {
605  case CalendarUrl::Unknown:
606  case CalendarUrl::EndCalendarType:
607  break;
608  case CalendarUrl::FBUrl:
609  type = QStringLiteral("FBURL");
610  break;
611  case CalendarUrl::CALUri:
612  type = QStringLiteral("CALURI");
613  break;
614  case CalendarUrl::CALADRUri:
615  type = QStringLiteral("CALADRURI");
616  break;
617  }
618  if (!type.isEmpty()) {
619  VCardLine line(type, url.url().toDisplayString());
620  addParameters(line, url.parameters());
621  card.addLine(line);
622  }
623  }
624  }
625  }
626  //FieldGroup
627  const QVector<FieldGroup> lstGroup = (*addrIt).fieldGroupList();
628  for (const FieldGroup &group : lstGroup) {
629  VCardLine line(group.fieldGroupName(), group.value());
630  addParameters(line, group.parameters());
631  card.addLine(line);
632  }
633 
634  // IMPP (supported in vcard 3 too)
635  const QVector<Impp> lstImpp = (*addrIt).imppList();
636  for (const Impp &impp : lstImpp) {
637  VCardLine line(QStringLiteral("IMPP"), impp.address().url());
638  QMapIterator<QString, QStringList> i(impp.parameters());
639  while (i.hasNext()) {
640  i.next();
641  if (i.key().toLower() != QLatin1String("x-service-type")) {
642  line.addParameter(i.key(), i.value().join(QLatin1Char(',')));
643  }
644  }
645  card.addLine(line);
646  }
647 
648  // X-
649  const QStringList customs = (*addrIt).customs();
650  for (strIt = customs.begin(); strIt != customs.end(); ++strIt) {
651  QString identifier = QLatin1String("X-")
652  +(*strIt).left((*strIt).indexOf(QLatin1Char(':')));
653  const QString value = (*strIt).mid((*strIt).indexOf(QLatin1Char(':')) + 1);
654  if (value.isEmpty()) {
655  continue;
656  }
657  //Convert to standard identifier
658  if (exportVcard) {
659  if (identifier == QLatin1String("X-messaging/aim-All")) {
660  identifier = QStringLiteral("X-AIM");
661  } else if (identifier == QLatin1String("X-messaging/icq-All")) {
662  identifier = QStringLiteral("X-ICQ");
663  } else if (identifier == QLatin1String("X-messaging/xmpp-All")) {
664  identifier = QStringLiteral("X-JABBER");
665  } else if (identifier == QLatin1String("X-messaging/msn-All")) {
666  identifier = QStringLiteral("X-MSN");
667  } else if (identifier == QLatin1String("X-messaging/yahoo-All")) {
668  identifier = QStringLiteral("X-YAHOO");
669  } else if (identifier == QLatin1String("X-messaging/gadu-All")) {
670  identifier = QStringLiteral("X-GADUGADU");
671  } else if (identifier == QLatin1String("X-messaging/skype-All")) {
672  identifier = QStringLiteral("X-SKYPE");
673  } else if (identifier == QLatin1String("X-messaging/groupwise-All")) {
674  identifier = QStringLiteral("X-GROUPWISE");
675  } else if (identifier == QLatin1String("X-messaging/sms-All")) {
676  identifier = QStringLiteral("X-SMS");
677  } else if (identifier == QLatin1String("X-messaging/meanwhile-All")) {
678  identifier = QStringLiteral("X-MEANWHILE");
679  } else if (identifier == QLatin1String("X-messaging/irc-All")) {
680  identifier = QStringLiteral("X-IRC"); //Not defined by rfc but need for fixing #300869
681  } else if (identifier == QLatin1String("X-messaging/googletalk-All")) {
682  //Not defined by rfc but need for fixing #300869
683  identifier = QStringLiteral("X-GTALK");
684  } else if (identifier == QLatin1String("X-messaging/twitter-All")) {
685  identifier = QStringLiteral("X-TWITTER");
686  }
687  }
688  if (identifier.toLower() == QLatin1String("x-kaddressbook-x-anniversary") && version == VCard::v4_0) {
689  // ANNIVERSARY
690  if (!value.isEmpty()) {
691  const QDate date = QDate::fromString(value, Qt::ISODate);
692  QDateTime dt = QDateTime(date);
693  dt.setTime(QTime());
694  VCardLine line(QStringLiteral("ANNIVERSARY"), createDateTime(dt, version, false));
695  card.addLine(line);
696  }
697  } else if (identifier.toLower() == QLatin1String("x-kaddressbook-x-spousesname") && version == VCard::v4_0) {
698  if (!value.isEmpty()) {
699  VCardLine line(QStringLiteral("RELATED"), QStringLiteral(";"));
700  line.addParameter(QStringLiteral("TYPE"), QStringLiteral("spouse"));
701  line.addParameter(QStringLiteral("VALUE"), value);
702  card.addLine(line);
703  }
704  } else {
705  VCardLine line(identifier, value);
706  if (version == VCard::v2_1 && needsEncoding(value)) {
707  line.addParameter(QStringLiteral("charset"), QStringLiteral("UTF-8"));
708  line.addParameter(QStringLiteral("encoding"), QStringLiteral("QUOTED-PRINTABLE"));
709  }
710  card.addLine(line);
711  }
712  }
713 
714  vCardList.append(card);
715  }
716 
717  return VCardParser::createVCards(vCardList);
718 }
719 
720 Addressee::List VCardTool::parseVCards(const QByteArray &vcard) const
721 {
722  static const QLatin1Char semicolonSep(';');
723  static const QLatin1Char commaSep(',');
724  QString identifier;
725  QString group;
726  Addressee::List addrList;
727  const VCard::List vCardList = VCardParser::parseVCards(vcard);
728 
730  VCard::List::ConstIterator listEnd(vCardList.end());
731  for (cardIt = vCardList.begin(); cardIt != listEnd; ++cardIt) {
732  Addressee addr;
733 
734  const QStringList idents = (*cardIt).identifiers();
736  QStringList::ConstIterator identEnd(idents.end());
737  for (identIt = idents.begin(); identIt != identEnd; ++identIt) {
738  const VCardLine::List lines = (*cardIt).lines((*identIt));
740 
741  // iterate over the lines
742  for (lineIt = lines.begin(); lineIt != lines.end(); ++lineIt) {
743  identifier = (*lineIt).identifier().toLower();
744  group = (*lineIt).group();
745  if (!group.isEmpty() && identifier != QLatin1String("adr")) {
746  KContacts::FieldGroup groupField(group + QLatin1Char('.') + (*lineIt).identifier());
747  groupField.setParameters((*lineIt).parameterMap());
748  groupField.setValue((*lineIt).value().toString());
749  addr.insertFieldGroup(groupField);
750  }
751  // ADR
752  else if (identifier == QLatin1String("adr")) {
753  Address address;
754  const QStringList addrParts = splitString(semicolonSep, (*lineIt).value().toString());
755  const int addrPartsCount(addrParts.count());
756  if (addrPartsCount > 0) {
757  address.setPostOfficeBox(addrParts.at(0));
758  }
759  if (addrPartsCount > 1) {
760  address.setExtended(addrParts.at(1));
761  }
762  if (addrPartsCount > 2) {
763  address.setStreet(addrParts.at(2));
764  }
765  if (addrPartsCount > 3) {
766  address.setLocality(addrParts.at(3));
767  }
768  if (addrPartsCount > 4) {
769  address.setRegion(addrParts.at(4));
770  }
771  if (addrPartsCount > 5) {
772  address.setPostalCode(addrParts.at(5));
773  }
774  if (addrPartsCount > 6) {
775  address.setCountry(addrParts.at(6));
776  }
777 
778  Address::Type type;
779 
780  const QStringList types = (*lineIt).parameters(QStringLiteral("type"));
782  for (QStringList::ConstIterator it = types.begin(); it != end; ++it) {
783  type |= stringToAddressType((*it).toLower());
784  }
785 
786  address.setType(type);
787  QString label = (*lineIt).parameter(QStringLiteral("label"));
788  if (!label.isEmpty()) {
789  if (label.length() > 1) {
790  if (label.at(0) == QLatin1Char('"') && label.at(label.length() - 1) == QLatin1Char('"')) {
791  label = label.mid(1, label.length() - 2);
792  }
793  }
794  address.setLabel(label);
795  }
796  QString geoStr = (*lineIt).parameter(QStringLiteral("geo"));
797  if (!geoStr.isEmpty()) {
798  geoStr.remove(QLatin1Char('\"'));
799  geoStr.remove(QStringLiteral("geo:"));
800  if (geoStr.contains(QLatin1Char(','))) {
801  QStringList arguments = geoStr.split(QLatin1Char(','));
802  KContacts::Geo geo;
803  geo.setLatitude(arguments.at(0).toDouble());
804  geo.setLongitude(arguments.at(1).toDouble());
805  address.setGeo(geo);
806  }
807  }
808  addr.insertAddress(address);
809  }
810  // ANNIVERSARY
811  else if (identifier == QLatin1String("anniversary")) {
812  const QString t = (*lineIt).value().toString();
813  const QDateTime dt(parseDateTime(t));
814  addr.insertCustom(QStringLiteral("KADDRESSBOOK"), QStringLiteral("X-Anniversary"), dt.date().toString(Qt::ISODate));
815  }
816  // BDAY
817  else if (identifier == QLatin1String("bday")) {
818  bool withTime;
819  const QDateTime bday = parseDateTime((*lineIt).value().toString(), &withTime);
820  addr.setBirthday(bday, withTime);
821  }
822  // CATEGORIES
823  else if (identifier == QLatin1String("categories")) {
824  const QStringList categories = splitString(commaSep, (*lineIt).value().toString());
825  addr.setCategories(categories);
826  }
827  // FBURL
828  else if (identifier == QLatin1String("fburl")) {
829  CalendarUrl calurl;
830  calurl.setType(CalendarUrl::FBUrl);
831  const QUrl url = QUrl((*lineIt).value().toString());
832  calurl.setUrl(url);
833  calurl.setParameters((*lineIt).parameterMap());
834  addr.insertCalendarUrl(calurl);
835  }
836  // CALADRURI
837  else if (identifier == QLatin1String("caladruri")) {
838  CalendarUrl calurl;
839  calurl.setType(CalendarUrl::CALADRUri);
840  const QUrl url = QUrl((*lineIt).value().toString());
841  calurl.setUrl(url);
842  calurl.setParameters((*lineIt).parameterMap());
843  addr.insertCalendarUrl(calurl);
844  }
845  // CALURI
846  else if (identifier == QLatin1String("caluri")) {
847  CalendarUrl calurl;
848  calurl.setType(CalendarUrl::CALUri);
849  const QUrl url = QUrl((*lineIt).value().toString());
850  calurl.setUrl(url);
851  calurl.setParameters((*lineIt).parameterMap());
852  addr.insertCalendarUrl(calurl);
853  }
854  //IMPP
855  else if (identifier == QLatin1String("impp")) {
856  QUrl imppUrl((*lineIt).value().toString());
857  Impp impp;
858  impp.setParameters((*lineIt).parameterMap());
859  if (!(*lineIt).parameter(QStringLiteral("x-service-type")).isEmpty() && imppUrl.scheme().isEmpty()) {
860  imppUrl.setScheme(normalizeImppServiceType((*lineIt).parameter(QStringLiteral("x-service-type")).toLower()));
861  }
862  impp.setAddress(imppUrl);
863  addr.insertImpp(impp);
864  }
865  // CLASS
866  else if (identifier == QLatin1String("class")) {
867  addr.setSecrecy(parseSecrecy(*lineIt));
868  }
869  // GENDER
870  else if (identifier == QLatin1String("gender")) {
871  QString genderStr = (*lineIt).value().toString();
872  if (!genderStr.isEmpty()) {
873  Gender gender;
874  if (genderStr.at(0) != QLatin1Char(';')) {
875  gender.setGender(genderStr.at(0));
876  if (genderStr.length() > 2 && (genderStr.at(1) == QLatin1Char(';'))) {
877  gender.setComment(genderStr.right(genderStr.length() - 2));
878  }
879  } else {
880  gender.setComment(genderStr.right(genderStr.length() - 1));
881  }
882  addr.setGender(gender);
883  }
884  }
885  // LANG
886  else if (identifier == QLatin1String("lang")) {
887  Lang lang;
888  lang.setLanguage((*lineIt).value().toString());
889  lang.setParameters((*lineIt).parameterMap());
890  addr.insertLang(lang);
891  }
892  // EMAIL
893  else if (identifier == QLatin1String("email")) {
894  const QStringList types = (*lineIt).parameters(QStringLiteral("type"));
895  addr.insertEmail((*lineIt).value().toString(),
896  types.contains(QLatin1String("PREF")), (*lineIt).parameterMap());
897  }
898  // KIND
899  else if (identifier == QLatin1String("kind")) {
900  addr.setKind((*lineIt).value().toString());
901  }
902  // FN
903  else if (identifier == QLatin1String("fn")) {
904  addr.setFormattedName((*lineIt).value().toString());
905  }
906  // GEO
907  else if (identifier == QLatin1String("geo")) {
908  Geo geo;
909  QString lineStr = (*lineIt).value().toString();
910  if (lineStr.startsWith(QLatin1String("geo:"))) { //VCard 4.0
911  lineStr.remove(QStringLiteral("geo:"));
912  const QStringList geoParts
913 #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
914  = lineStr.split(QLatin1Char(','), QString::KeepEmptyParts);
915 #else
916  = lineStr.split(QLatin1Char(','), Qt::KeepEmptyParts);
917 #endif
918  if (geoParts.size() >= 2) {
919  geo.setLatitude(geoParts.at(0).toFloat());
920  geo.setLongitude(geoParts.at(1).toFloat());
921  addr.setGeo(geo);
922  }
923  } else {
924  const QStringList geoParts
925 #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
926  = lineStr.split(QLatin1Char(';'), QString::KeepEmptyParts);
927 #else
928  = lineStr.split(QLatin1Char(';'), Qt::KeepEmptyParts);
929 #endif
930  if (geoParts.size() >= 2) {
931  geo.setLatitude(geoParts.at(0).toFloat());
932  geo.setLongitude(geoParts.at(1).toFloat());
933  addr.setGeo(geo);
934  }
935  }
936  }
937  // KEY
938  else if (identifier == QLatin1String("key")) {
939  addr.insertKey(parseKey(*lineIt));
940  }
941  // LABEL
942  else if (identifier == QLatin1String("label")) {
943  Address::Type type;
944 
945  const QStringList types = (*lineIt).parameters(QStringLiteral("type"));
947  for (QStringList::ConstIterator it = types.begin(); it != end; ++it) {
948  type |= stringToAddressType((*it).toLower());
949  }
950 
951  bool available = false;
952  KContacts::Address::List addressList = addr.addresses();
953  for (KContacts::Address::List::Iterator it = addressList.begin();
954  it != addressList.end(); ++it) {
955  if ((*it).type() == type) {
956  (*it).setLabel((*lineIt).value().toString());
957  addr.insertAddress(*it);
958  available = true;
959  break;
960  }
961  }
962 
963  if (!available) { // a standalone LABEL tag
964  KContacts::Address address(type);
965  address.setLabel((*lineIt).value().toString());
966  addr.insertAddress(address);
967  }
968  }
969  // LOGO
970  else if (identifier == QLatin1String("logo")) {
971  Picture picture = parsePicture(*lineIt);
972  if (addr.logo().isEmpty()) {
973  addr.setLogo(picture);
974  } else {
975  addr.insertExtraLogo(picture);
976  }
977  }
978  // MAILER
979  else if (identifier == QLatin1String("mailer")) {
980  addr.setMailer((*lineIt).value().toString());
981  }
982  // N
983  else if (identifier == QLatin1Char('n')) {
984  const QStringList nameParts = splitString(semicolonSep, (*lineIt).value().toString());
985  const int numberOfParts(nameParts.count());
986  if (numberOfParts > 0) {
987  addr.setFamilyName(nameParts.at(0));
988  }
989  if (numberOfParts > 1) {
990  addr.setGivenName(nameParts.at(1));
991  }
992  if (numberOfParts > 2) {
993  addr.setAdditionalName(nameParts.at(2));
994  }
995  if (numberOfParts > 3) {
996  addr.setPrefix(nameParts.at(3));
997  }
998  if (numberOfParts > 4) {
999  addr.setSuffix(nameParts.at(4));
1000  }
1001  if (!(*lineIt).parameter(QStringLiteral("sort-as")).isEmpty()) {
1002  addr.setSortString((*lineIt).parameter(QStringLiteral("sort-as")));
1003  }
1004  }
1005  // NAME
1006  else if (identifier == QLatin1String("name")) {
1007  addr.setName((*lineIt).value().toString());
1008  }
1009  // NICKNAME
1010  else if (identifier == QLatin1String("nickname")) {
1011  NickName nickName((*lineIt).value().toString());
1012  nickName.setParameters((*lineIt).parameterMap());
1013  addr.insertExtraNickName(nickName);
1014  }
1015  // NOTE
1016  else if (identifier == QLatin1String("note")) {
1017  addr.setNote((*lineIt).value().toString());
1018  }
1019  // ORGANIZATION
1020  else if (identifier == QLatin1String("org")) {
1021  const QStringList orgParts = splitString(semicolonSep, (*lineIt).value().toString());
1022  const int orgPartsCount(orgParts.count());
1023  if (orgPartsCount > 0) {
1024  Org organization(orgParts.at(0));
1025  organization.setParameters((*lineIt).parameterMap());
1026  addr.insertExtraOrganization(organization);
1027  }
1028  if (orgPartsCount > 1) {
1029  addr.setDepartment(orgParts.at(1));
1030  }
1031  if (!(*lineIt).parameter(QStringLiteral("sort-as")).isEmpty()) {
1032  addr.setSortString((*lineIt).parameter(QStringLiteral("sort-as")));
1033  }
1034  }
1035  // PHOTO
1036  else if (identifier == QLatin1String("photo")) {
1037  Picture picture = parsePicture(*lineIt);
1038  if (addr.photo().isEmpty()) {
1039  addr.setPhoto(picture);
1040  } else {
1041  addr.insertExtraPhoto(picture);
1042  }
1043  }
1044  // PROID
1045  else if (identifier == QLatin1String("prodid")) {
1046  addr.setProductId((*lineIt).value().toString());
1047  }
1048  // REV
1049  else if (identifier == QLatin1String("rev")) {
1050  addr.setRevision(parseDateTime((*lineIt).value().toString()));
1051  }
1052  // ROLE
1053  else if (identifier == QLatin1String("role")) {
1054  Role role((*lineIt).value().toString());
1055  role.setParameters((*lineIt).parameterMap());
1056  addr.insertExtraRole(role);
1057  }
1058  // SORT-STRING
1059  else if (identifier == QLatin1String("sort-string")) {
1060  addr.setSortString((*lineIt).value().toString());
1061  }
1062  // SOUND
1063  else if (identifier == QLatin1String("sound")) {
1064  Sound sound = parseSound(*lineIt);
1065  if (addr.sound().isEmpty()) {
1066  addr.setSound(sound);
1067  } else {
1068  addr.insertExtraSound(sound);
1069  }
1070  }
1071  // TEL
1072  else if (identifier == QLatin1String("tel")) {
1073  PhoneNumber phone;
1074  phone.setNumber((*lineIt).value().toString());
1075 
1076  PhoneNumber::Type type;
1077  bool foundType = false;
1078  const QStringList types = (*lineIt).parameters(QStringLiteral("type"));
1079  QStringList::ConstIterator typeEnd(types.constEnd());
1080  for (QStringList::ConstIterator it = types.constBegin(); it != typeEnd; ++it) {
1081  type |= stringToPhoneType((*it).toUpper());
1082  foundType = true;
1083  }
1084  phone.setType(foundType ? type : PhoneNumber::Undefined);
1085  phone.setParameters((*lineIt).parameterMap());
1086 
1087  addr.insertPhoneNumber(phone);
1088  }
1089  // TITLE
1090  else if (identifier == QLatin1String("title")) {
1091  Title title((*lineIt).value().toString());
1092  title.setParameters((*lineIt).parameterMap());
1093  addr.insertExtraTitle(title);
1094  }
1095  // TZ
1096  else if (identifier == QLatin1String("tz")) {
1097  //TODO add vcard4 support
1098  TimeZone tz;
1099  const QString date = (*lineIt).value().toString();
1100 
1101  if (!date.isEmpty()) {
1102  int hours = date.midRef(1, 2).toInt();
1103  int minutes = date.midRef(4, 2).toInt();
1104  int offset = (hours * 60) + minutes;
1105  offset = offset * (date[ 0 ] == QLatin1Char('+') ? 1 : -1);
1106 
1107  tz.setOffset(offset);
1108  addr.setTimeZone(tz);
1109  }
1110  }
1111  // UID
1112  else if (identifier == QLatin1String("uid")) {
1113  addr.setUid((*lineIt).value().toString());
1114  }
1115  // URL
1116  else if (identifier == QLatin1String("url")) {
1117  const QUrl url = QUrl((*lineIt).value().toString());
1118  ResourceLocatorUrl resourceLocatorUrl;
1119  resourceLocatorUrl.setUrl(url);
1120  resourceLocatorUrl.setParameters((*lineIt).parameterMap());
1121  addr.insertExtraUrl(resourceLocatorUrl);
1122  }
1123  // SOURCE
1124  else if (identifier == QLatin1String("source")) {
1125  const QUrl url = QUrl((*lineIt).value().toString());
1126  addr.insertSourceUrl(url);
1127  }
1128  // MEMBER (vcard 4.0)
1129  else if (identifier == QLatin1String("member")) {
1130  addr.insertMember((*lineIt).value().toString());
1131  }
1132  // RELATED (vcard 4.0)
1133  else if (identifier == QLatin1String("related")) {
1134  Related related;
1135  related.setRelated((*lineIt).value().toString());
1136  related.setParameters((*lineIt).parameterMap());
1137  addr.insertRelationship(related);
1138  }
1139  // CLIENTPIDMAP (vcard 4.0)
1140  else if (identifier == QLatin1String("clientpidmap")) {
1141  ClientPidMap clientpidmap;
1142  clientpidmap.setClientPidMap((*lineIt).value().toString());
1143  clientpidmap.setParameters((*lineIt).parameterMap());
1144  addr.insertClientPidMap(clientpidmap);
1145  }
1146  // X-
1147  //TODO import X-GENDER
1148  else if (identifier.startsWith(QLatin1String("x-"))) {
1149  QString ident = (*lineIt).identifier();
1150  //X-Evolution
1151  // also normalize case of our own extensions, some backends "adjust" that
1152  if (identifier == QLatin1String("x-evolution-spouse")
1153  || identifier == QLatin1String("x-spouse")) {
1154  ident = QStringLiteral("X-KADDRESSBOOK-X-SpousesName");
1155  } else if (identifier == QLatin1String("x-evolution-blog-url") || identifier.compare(QLatin1String("X-KADDRESSBOOK-BLOGFEED"), Qt::CaseInsensitive) == 0) {
1156  ident = QStringLiteral("X-KADDRESSBOOK-BlogFeed");
1157  } else if (identifier == QLatin1String("x-evolution-assistant")
1158  || identifier == QLatin1String("x-assistant")
1159  || identifier.compare(QLatin1String("X-KADDRESSBOOK-X-ASSISTANTSNAME"), Qt::CaseInsensitive) == 0) {
1160  ident = QStringLiteral("X-KADDRESSBOOK-X-AssistantsName");
1161  } else if (identifier == QLatin1String("x-evolution-anniversary")
1162  || identifier == QLatin1String("x-anniversary")
1163  || identifier.compare(QLatin1String("X-KADDRESSBOOK-X-ANNIVERSARY"), Qt::CaseInsensitive) == 0) {
1164  ident = QStringLiteral("X-KADDRESSBOOK-X-Anniversary");
1165  } else if (identifier == QLatin1String("x-evolution-manager")
1166  || identifier == QLatin1String("x-manager")
1167  || identifier.compare(QLatin1String("X-KADDRESSBOOK-X-MANAGERSNAME"), Qt::CaseInsensitive) == 0) {
1168  ident = QStringLiteral("X-KADDRESSBOOK-X-ManagersName");
1169  } else if (identifier.compare(QLatin1String("X-KADDRESSBOOK-X-PROFESSION"), Qt::CaseInsensitive) == 0) {
1170  ident = QStringLiteral("X-KADDRESSBOOK-X-Profession");
1171  } else if (identifier.compare(QLatin1String("X-KADDRESSBOOK-X-OFFICE"), Qt::CaseInsensitive) == 0) {
1172  ident = QStringLiteral("X-KADDRESSBOOK-X-Office");
1173  } else if (identifier.compare(QLatin1String("X-KADDRESSBOOK-X-SPOUSESNAME"), Qt::CaseInsensitive) == 0) {
1174  ident = QStringLiteral("X-KADDRESSBOOK-X-SpousesName");
1175  } else if (identifier == QLatin1String("x-aim")) {
1176  ident = QStringLiteral("X-messaging/aim-All");
1177  } else if (identifier == QLatin1String("x-icq")) {
1178  ident = QStringLiteral("X-messaging/icq-All");
1179  } else if (identifier == QLatin1String("x-jabber")) {
1180  ident = QStringLiteral("X-messaging/xmpp-All");
1181  } else if (identifier == QLatin1String("x-jabber")) {
1182  ident = QStringLiteral("X-messaging/xmpp-All");
1183  } else if (identifier == QLatin1String("x-msn")) {
1184  ident = QStringLiteral("X-messaging/msn-All");
1185  } else if (identifier == QLatin1String("x-yahoo")) {
1186  ident = QStringLiteral("X-messaging/yahoo-All");
1187  } else if (identifier == QLatin1String("x-gadugadu")) {
1188  ident = QStringLiteral("X-messaging/gadu-All");
1189  } else if (identifier == QLatin1String("x-skype")) {
1190  ident = QStringLiteral("X-messaging/skype-All");
1191  } else if (identifier == QLatin1String("x-groupwise")) {
1192  ident = QStringLiteral("X-messaging/groupwise-All");
1193  } else if (identifier == QLatin1String("x-sms")) {
1194  ident = QStringLiteral("X-messaging/sms-All");
1195  } else if (identifier == QLatin1String("x-meanwhile")) {
1196  ident = QStringLiteral("X-messaging/meanwhile-All");
1197  } else if (identifier == QLatin1String("x-irc")) {
1198  ident = QStringLiteral("X-messaging/irc-All");
1199  } else if (identifier == QLatin1String("x-gtalk")) {
1200  ident = QStringLiteral("X-messaging/googletalk-All");
1201  } else if (identifier == QLatin1String("x-twitter")) {
1202  ident = QStringLiteral("X-messaging/twitter-All");
1203  }
1204 
1205  const QString key = ident.mid(2);
1206  const int dash = key.indexOf(QLatin1Char('-'));
1207 
1208  // convert legacy messaging fields into IMPP ones
1209  if (key.startsWith(QLatin1String("messaging/"))) {
1210  QUrl url;
1211  url.setScheme(normalizeImppServiceType(key.mid(10, dash - 10)));
1212 #if QT_VERSION < QT_VERSION_CHECK(5, 15, 0)
1213  const auto values = (*lineIt).value().toString().split(QChar(0xE000), QString::SkipEmptyParts);
1214 #else
1215  const auto values = (*lineIt).value().toString().split(QChar(0xE000), Qt::SkipEmptyParts);
1216 #endif
1217  for (const auto &value : values) {
1218  url.setPath(value);
1219  Impp impp;
1220  impp.setParameters((*lineIt).parameterMap());
1221  impp.setAddress(url);
1222  addr.insertImpp(impp);
1223  }
1224  } else {
1225  addr.insertCustom(key.left(dash), key.mid(dash + 1), (*lineIt).value().toString());
1226  }
1227  }
1228  }
1229  }
1230 
1231  addrList.append(addr);
1232  }
1233 
1234  return addrList;
1235 }
1236 
1237 QDateTime VCardTool::parseDateTime(const QString &str, bool *timeValid)
1238 {
1239  const int posT = str.indexOf(QLatin1Char('T'));
1240  QString dateString = posT >= 0 ? str.left(posT) : str;
1241  const bool noYear = dateString.startsWith(QLatin1String("--"));
1242  dateString.remove(QLatin1Char('-'));
1243  QDate date;
1244  if (noYear) {
1245  date = QDate::fromString(dateString, QStringLiteral("MMdd"));
1246  date = date.addYears(-1900);
1247  } else {
1248  date = QDate::fromString(dateString, QStringLiteral("yyyyMMdd"));
1249  }
1250 
1251  QTime time;
1252  Qt::TimeSpec spec = Qt::LocalTime;
1253  int offsetSecs = 0;
1254  if (posT >= 0) {
1255  QString timeString = str.mid(posT + 1);
1256  timeString.remove(QLatin1Char(':'));
1257  const int zPos = timeString.indexOf(QLatin1Char('Z'));
1258  const int plusPos = timeString.indexOf(QLatin1Char('+'));
1259  const int minusPos = timeString.indexOf(QLatin1Char('-'));
1260  const int tzPos = qMax(qMax(zPos, plusPos), minusPos);
1261  const QString hhmmssString = tzPos >= 0 ? timeString.left(tzPos) : timeString;
1262  switch (hhmmssString.size()) {
1263  case 2:
1264  time = QTime::fromString(hhmmssString, QStringLiteral("hh"));
1265  break;
1266  case 4:
1267  time = QTime::fromString(hhmmssString, QStringLiteral("hhmm"));
1268  break;
1269  case 6:
1270  time = QTime::fromString(hhmmssString, QStringLiteral("hhmmss"));
1271  break;
1272  }
1273  if (tzPos >= 0) {
1274  if (zPos >= 0) {
1275  spec = Qt::UTC;
1276  } else {
1277  spec = Qt::OffsetFromUTC;
1278  QTime offsetTime;
1279  const QString offsetString = timeString.mid(tzPos + 1);
1280  switch (offsetString.size()) {
1281  case 2:
1282  offsetTime = QTime::fromString(offsetString, QStringLiteral("hh"));
1283  break;
1284  case 4:
1285  offsetTime = QTime::fromString(offsetString, QStringLiteral("hhmm"));
1286  break;
1287  }
1288  offsetSecs = offsetTime.hour() * 3600 + offsetTime.minute() * 60;
1289  }
1290  if (minusPos >= 0) {
1291  offsetSecs *= -1;
1292  }
1293  }
1294  }
1295  if (timeValid) {
1296  *timeValid = time.isValid();
1297  }
1298 
1299  return QDateTime(date, time, spec, offsetSecs);
1300 }
1301 
1302 QString VCardTool::createDateTime(const QDateTime &dateTime, VCard::Version version, bool withTime)
1303 {
1304  if (!dateTime.date().isValid()) {
1305  return QString();
1306  }
1307  QString str = createDate(dateTime.date(), version);
1308  if (!withTime) {
1309  return str;
1310  }
1311  str += createTime(dateTime.time(), version);
1312  if (dateTime.timeSpec() == Qt::UTC) {
1313  str += QLatin1Char('Z');
1314  } else if (dateTime.timeSpec() == Qt::OffsetFromUTC) {
1315  const int offsetSecs = dateTime.offsetFromUtc();
1316  if (offsetSecs >= 0) {
1317  str += QLatin1Char('+');
1318  } else {
1319  str += QLatin1Char('-');
1320  }
1321  QTime offsetTime = QTime(0, 0).addSecs(abs(offsetSecs));
1322  if (version == VCard::v4_0) {
1323  str += offsetTime.toString(QStringLiteral("HHmm"));
1324  } else {
1325  str += offsetTime.toString(QStringLiteral("HH:mm"));
1326  }
1327  }
1328  return str;
1329 }
1330 
1331 QString VCardTool::createDate(const QDate &date, VCard::Version version)
1332 {
1333  QString format;
1334  if (date.year() > 0) {
1335  format = QStringLiteral("yyyyMMdd");
1336  } else {
1337  format = QStringLiteral("--MMdd");
1338  }
1339  if (version != VCard::v4_0) {
1340  format.replace(QStringLiteral("yyyy"), QStringLiteral("yyyy-"));
1341  format.replace(QStringLiteral("MM"), QStringLiteral("MM-"));
1342  }
1343  return date.toString(format);
1344 }
1345 
1346 QString VCardTool::createTime(const QTime &time, VCard::Version version)
1347 {
1348  QString format;
1349  if (version == VCard::v4_0) {
1350  format = QStringLiteral("HHmmss");
1351  } else {
1352  format = QStringLiteral("HH:mm:ss");
1353  }
1354  return QLatin1Char('T') + time.toString(format);
1355 }
1356 
1357 Picture VCardTool::parsePicture(const VCardLine &line) const
1358 {
1359  Picture pic;
1360 
1361  const QStringList params = line.parameterList();
1362  QString type;
1363  if (params.contains(QLatin1String("type"))) {
1364  type = line.parameter(QStringLiteral("type"));
1365  }
1366  if (params.contains(QLatin1String("encoding"))) {
1367  pic.setRawData(line.value().toByteArray(), type);
1368  } else if (params.contains(QLatin1String("value"))) {
1369  if (line.parameter(QStringLiteral("value")).toLower() == QLatin1String("uri")) {
1370  pic.setUrl(line.value().toString());
1371  }
1372  }
1373 
1374  return pic;
1375 }
1376 
1377 VCardLine VCardTool::createPicture(const QString &identifier, const Picture &pic, VCard::Version version) const
1378 {
1379  VCardLine line(identifier);
1380 
1381  if (pic.isEmpty()) {
1382  return line;
1383  }
1384 
1385  if (pic.isIntern()) {
1386  line.setValue(pic.rawData());
1387  if (version == VCard::v2_1) {
1388  line.addParameter(QStringLiteral("ENCODING"), QStringLiteral("BASE64"));
1389  line.addParameter(pic.type(), QString());
1390  } else { /*if (version == VCard::v3_0) */
1391  line.addParameter(QStringLiteral("encoding"), QStringLiteral("b"));
1392  line.addParameter(QStringLiteral("type"), pic.type());
1393 #if 0
1394  } else { //version 4.0
1395  line.addParameter(QStringLiteral("data") + QStringLiteral(":image/") + pic.type(), QStringLiteral("base64"));
1396 #endif
1397  }
1398  } else {
1399  line.setValue(pic.url());
1400  line.addParameter(QStringLiteral("value"), QStringLiteral("URI"));
1401  }
1402 
1403  return line;
1404 }
1405 
1406 Sound VCardTool::parseSound(const VCardLine &line) const
1407 {
1408  Sound snd;
1409 
1410  const QStringList params = line.parameterList();
1411  if (params.contains(QLatin1String("encoding"))) {
1412  snd.setData(line.value().toByteArray());
1413  } else if (params.contains(QLatin1String("value"))) {
1414  if (line.parameter(QStringLiteral("value")).toLower() == QLatin1String("uri")) {
1415  snd.setUrl(line.value().toString());
1416  }
1417  }
1418 
1419  /* TODO: support sound types
1420  if ( params.contains( "type" ) )
1421  snd.setType( line.parameter( "type" ) );
1422  */
1423 
1424  return snd;
1425 }
1426 
1427 VCardLine VCardTool::createSound(const Sound &snd, VCard::Version version) const
1428 {
1429  Q_UNUSED(version);
1430  VCardLine line(QStringLiteral("SOUND"));
1431 
1432  if (snd.isIntern()) {
1433  if (!snd.data().isEmpty()) {
1434  line.setValue(snd.data());
1435  if (version == VCard::v2_1) {
1436  line.addParameter(QStringLiteral("ENCODING"), QStringLiteral("BASE64"));
1437  } else {
1438  line.addParameter(QStringLiteral("encoding"), QStringLiteral("b"));
1439  }
1440  // TODO: need to store sound type!!!
1441  }
1442  } else if (!snd.url().isEmpty()) {
1443  line.setValue(snd.url());
1444  line.addParameter(QStringLiteral("value"), QStringLiteral("URI"));
1445  }
1446 
1447  return line;
1448 }
1449 
1450 Key VCardTool::parseKey(const VCardLine &line) const
1451 {
1452  Key key;
1453 
1454  const QStringList params = line.parameterList();
1455  if (params.contains(QLatin1String("encoding"))) {
1456  key.setBinaryData(line.value().toByteArray());
1457  } else {
1458  key.setTextData(line.value().toString());
1459  }
1460 
1461  if (params.contains(QLatin1String("type"))) {
1462  if (line.parameter(QStringLiteral("type")).toLower() == QLatin1String("x509")) {
1463  key.setType(Key::X509);
1464  } else if (line.parameter(QStringLiteral("type")).toLower() == QLatin1String("pgp")) {
1465  key.setType(Key::PGP);
1466  } else {
1467  key.setType(Key::Custom);
1468  key.setCustomTypeString(line.parameter(QStringLiteral("type")));
1469  }
1470  } else if (params.contains(QLatin1String("mediatype"))) {
1471  const QString param = line.parameter(QStringLiteral("mediatype")).toLower();
1472  if (param == QLatin1String("application/x-x509-ca-cert")) {
1473  key.setType(Key::X509);
1474  } else if (param == QLatin1String("application/pgp-keys")) {
1475  key.setType(Key::PGP);
1476  } else {
1477  key.setType(Key::Custom);
1478  key.setCustomTypeString(line.parameter(QStringLiteral("type")));
1479  }
1480  }
1481 
1482  return key;
1483 }
1484 
1485 VCardLine VCardTool::createKey(const Key &key, VCard::Version version) const
1486 {
1487  VCardLine line(QStringLiteral("KEY"));
1488 
1489  if (key.isBinary()) {
1490  if (!key.binaryData().isEmpty()) {
1491  line.setValue(key.binaryData());
1492  if (version == VCard::v2_1) {
1493  line.addParameter(QStringLiteral("ENCODING"), QStringLiteral("BASE64"));
1494  } else {
1495  line.addParameter(QStringLiteral("encoding"), QStringLiteral("b"));
1496  }
1497  }
1498  } else if (!key.textData().isEmpty()) {
1499  line.setValue(key.textData());
1500  }
1501 
1502  if (version == VCard::v4_0) {
1503  if (key.type() == Key::X509) {
1504  line.addParameter(QStringLiteral("MEDIATYPE"), QStringLiteral("application/x-x509-ca-cert"));
1505  } else if (key.type() == Key::PGP) {
1506  line.addParameter(QStringLiteral("MEDIATYPE"), QStringLiteral("application/pgp-keys"));
1507  } else if (key.type() == Key::Custom) {
1508  line.addParameter(QStringLiteral("MEDIATYPE"), key.customTypeString());
1509  }
1510  } else {
1511  if (key.type() == Key::X509) {
1512  line.addParameter(QStringLiteral("type"), QStringLiteral("X509"));
1513  } else if (key.type() == Key::PGP) {
1514  line.addParameter(QStringLiteral("type"), QStringLiteral("PGP"));
1515  } else if (key.type() == Key::Custom) {
1516  line.addParameter(QStringLiteral("type"), key.customTypeString());
1517  }
1518  }
1519 
1520  return line;
1521 }
1522 
1523 Secrecy VCardTool::parseSecrecy(const VCardLine &line) const
1524 {
1525  Secrecy secrecy;
1526 
1527  const QString value = line.value().toString().toLower();
1528  if (value == QLatin1String("public")) {
1529  secrecy.setType(Secrecy::Public);
1530  } else if (value == QLatin1String("private")) {
1531  secrecy.setType(Secrecy::Private);
1532  } else if (value == QLatin1String("confidential")) {
1533  secrecy.setType(Secrecy::Confidential);
1534  }
1535 
1536  return secrecy;
1537 }
1538 
1539 VCardLine VCardTool::createSecrecy(const Secrecy &secrecy) const
1540 {
1541  VCardLine line(QStringLiteral("CLASS"));
1542 
1543  int type = secrecy.type();
1544 
1545  if (type == Secrecy::Public) {
1546  line.setValue(QStringLiteral("PUBLIC"));
1547  } else if (type == Secrecy::Private) {
1548  line.setValue(QStringLiteral("PRIVATE"));
1549  } else if (type == Secrecy::Confidential) {
1550  line.setValue(QStringLiteral("CONFIDENTIAL"));
1551  }
1552 
1553  return line;
1554 }
1555 
1556 QStringList VCardTool::splitString(QChar sep, const QString &str) const
1557 {
1558  QStringList list;
1559  QString value(str);
1560 
1561  int start = 0;
1562  int pos = value.indexOf(sep, start);
1563 
1564  while (pos != -1) {
1565  if (pos == 0 || value[ pos - 1 ] != QLatin1Char('\\')) {
1566  if (pos > start && pos <= value.length()) {
1567  list << value.mid(start, pos - start);
1568  } else {
1569  list << QString();
1570  }
1571 
1572  start = pos + 1;
1573  pos = value.indexOf(sep, start);
1574  } else {
1575  value.replace(pos - 1, 2, sep);
1576  pos = value.indexOf(sep, pos);
1577  }
1578  }
1579 
1580  int l = value.length() - 1;
1581  const QString mid = value.mid(start, l - start + 1);
1582  if (!mid.isEmpty()) {
1583  list << mid;
1584  } else {
1585  list << QString();
1586  }
1587 
1588  return list;
1589 }
1590 
1591 QString VCardTool::normalizeImppServiceType(const QString &serviceType) const
1592 {
1593  if (serviceType == QLatin1String("jabber")) {
1594  return QStringLiteral("xmpp");
1595  }
1596  if (serviceType == QLatin1String("yahoo")) {
1597  return QStringLiteral("ymsgr");
1598  }
1599  if (serviceType == QLatin1String("gadugadu")) {
1600  return QStringLiteral("gg");
1601  }
1602  return serviceType;
1603 }
void setFormattedName(const QString &formattedName)
Set formatted name.
Definition: addressee.cpp:619
Class that holds a FieldGroup for a contact.
Definition: fieldgroup.h:21
void setOffset(int offset)
Set time zone offset relative to UTC.
Definition: timezone.cpp:54
void setMailer(const QString &mailer)
Set mail client.
Definition: addressee.cpp:945
int toInt(bool *ok, int base) const const
int minute() const const
int indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const const
QString type() const
Returns the type of this picture.
Definition: picture.cpp:198
void setTextData(const QString &data)
Sets text data.
Definition: key.cpp:129
void setNumber(const QString &number)
Sets the phone number.
typedef Iterator
Custom or IANA conform key.
Definition: key.h:37
void insertLang(const Lang &language)
Insert Language.
Definition: addressee.cpp:1677
bool isBinary() const
Returns whether the key contains binary or text data.
Definition: key.cpp:140
void setLocality(const QString &locality)
Sets the locality, e.g.
Definition: address.cpp:419
Type type() const
Returns the type, see Type.
Definition: key.cpp:155
QString name(const QVariant &location)
QString asprintf(const char *cformat,...)
void insertPhoneNumber(const PhoneNumber &phoneNumber)
Insert a phone number.
Definition: addressee.cpp:1716
QString toString(Qt::DateFormat format) const const
QString toString(Qt::DateFormat format) const const
Descripes a relationship of an Addressee.
Definition: related.h:18
void append(const T &value)
QVector::iterator begin()
void setTimeZone(const TimeZone &timeZone)
Set time zone.
Definition: addressee.cpp:965
Class that holds a Role for a contact.
Definition: role.h:20
void setPhoto(const Picture &photo)
Set photo.
Definition: addressee.cpp:1324
void setSuffix(const QString &suffix)
Set honorific suffixes.
Definition: addressee.cpp:719
QByteArray data() const
Returns the raw data of this sound.
Definition: sound.cpp:125
Class that holds a Resource Locator.
void setUid(const QString &uid)
Set unique identifier.
Definition: addressee.cpp:403
QVector::const_iterator constEnd() const const
const T & at(int i) const const
int size() const const
Geographic position.
Definition: geo.h:23
Class that holds a Calendar Url (FBURL/CALADRURI/CALURI)
Definition: calendarurl.h:21
void setTime(const QTime &time)
bool contains(const QString &str, Qt::CaseSensitivity cs) const const
bool isEmpty() const const
bool isValid() const const
void setStreet(const QString &street)
Sets the street (including house number).
Definition: address.cpp:403
Type type() const
Returns the type.
Definition: secrecy.cpp:78
void setPrefix(const QString &prefix)
Set honorific prefixes.
Definition: addressee.cpp:699
QTime time() const const
void setLabel(const QString &label)
Sets the delivery label.
Definition: address.cpp:483
void setGeo(const Geo &geo)
Set geographic position.
Definition: address.cpp:531
QTime fromString(const QString &string, Qt::DateFormat format)
Personal Communication Service.
Definition: phonenumber.h:60
void setType(Type type)
Sets the type.
QString join(const QString &separator) const const
bool isEmpty() const
Returns true, if the picture is empty.
Definition: picture.cpp:123
void setGivenName(const QString &givenName)
Set given name.
Definition: addressee.cpp:659
QString & remove(int position, int n)
typedef ConstIterator
void setDepartment(const QString &department)
Set department.
Definition: addressee.cpp:1158
Sound sound() const
Return sound.
Definition: addressee.cpp:1354
void setAdditionalName(const QString &additionalName)
Set additional names.
Definition: addressee.cpp:679
TypeFlag
Phone number types.
Definition: phonenumber.h:47
preferred address
Definition: address.h:71
void setLongitude(float longitude)
Sets the longitude.
Definition: geo.cpp:79
void insertEmail(const QString &email, bool preferred=false, const QMap< QString, QStringList > &param=QMap< QString, QStringList >())
Insert an email address.
Definition: addressee.cpp:1583
int size() const const
bool isEmpty() const
Returns true, if the sound object is empty.
Definition: sound.cpp:114
TimeSpec
T value(int i) const const
QVector< V > values(const QMultiHash< K, V > &c)
void setPath(const QString &path, QUrl::ParsingMode mode)
void setType(Type type)
Sets the type of address.
Definition: address.cpp:311
void setCategories(const QStringList &category)
Set categories to given value.
Definition: addressee.cpp:2081
Preferred number.
Definition: phonenumber.h:51
QDate fromString(const QString &string, Qt::DateFormat format)
int count(const T &value) const const
Class that holds a ClientPidMap for a contact.
Definition: clientpidmap.h:20
void append(const T &value)
int offset() const
Return offset in minutes relative to UTC.
Definition: timezone.cpp:60
void setSortString(const QString &sortString)
Set sort string.
Definition: addressee.cpp:1238
PostalAddress address(const QVariant &location)
QString textData() const
Returns the text data.
Definition: key.cpp:135
QMapIterator::Item next()
Type type(const QSqlDatabase &db)
QString label(StandardShortcut id)
void setFamilyName(const QString &familyName)
Set family name.
Definition: addressee.cpp:639
GeoCoordinates geo(const QVariant &location)
CaseInsensitive
bool isEmpty() const const
QString url() const
Returns the location URL of this picture.
Definition: picture.cpp:171
bool isEmpty() const const
int removeAll(const T &value)
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const const
home address
Definition: address.h:69
A class to store an encryption key.
Definition: key.h:20
void setScheme(const QString &scheme)
QStringList split(const QString &sep, QString::SplitBehavior behavior, Qt::CaseSensitivity cs) const const
bool isValid() const const
void setRegion(const QString &region)
Sets the region, e.g.
Definition: address.cpp:435
QTime addSecs(int s) const const
typedef Iterator
Picture photo() const
Return photo.
Definition: addressee.cpp:1334
void setType(Type type)
Sets the type.
Definition: secrecy.cpp:73
QDate addYears(int nyears) const const
Class that holds a IMPP for a contact.
Definition: impp.h:26
QString right(int n) const const
QLatin1String left(int length) const const
void setLatitude(float latitude)
Sets the latitude.
Definition: geo.cpp:63
A class to store a picture of an addressee.
Definition: picture.h:26
int hour() const const
QList::iterator end()
QString toLower() const const
void setData(const QByteArray &data)
Sets the raw data of the sound.
Definition: sound.cpp:103
QByteArray rawData() const
Returns the raw data of this picture.
Definition: picture.cpp:185
bool contains(QChar ch, Qt::CaseSensitivity cs) const const
KeepEmptyParts
void setExtended(const QString &extended)
Sets the extended address information.
Definition: address.cpp:387
Qt::TimeSpec timeSpec() const const
void setProductId(const QString &productId)
Set product identifier.
Definition: addressee.cpp:1198
QStringRef midRef(int position, int n) const const
char toLatin1() const const
void setPostalCode(const QString &code)
Sets the postal code.
Definition: address.cpp:451
QByteArray binaryData() const
Returns the binary data.
Definition: key.cpp:124
void insertCustom(const QString &app, const QString &name, const QString &value)
Insert custom entry.
Definition: addressee.cpp:2244
QString & replace(int position, int n, QChar after)
const QList< QKeySequence > & end()
void insertKey(const Key &key)
Insert a key.
Definition: addressee.cpp:1799
QVector::const_iterator constBegin() const const
Class that holds a Sound clip for a contact.
Definition: sound.h:44
QString url() const
Returns the location URL of this sound.
Definition: sound.cpp:120
QString mid(int position, int n) const const
QDate date() const const
Pretty Good Privacy key.
Definition: key.h:36
void setNote(const QString &note)
Set note.
Definition: addressee.cpp:1178
Postal address information.
Definition: address.h:27
void setPostOfficeBox(const QString &postOfficeBox)
Sets the post office box.
Definition: address.cpp:371
Class that holds a NickName for a contact.
Definition: nickname.h:20
void setCountry(const QString &country)
Sets the country.
Definition: address.cpp:467
void setRawData(const QByteArray &rawData, const QString &type)
Sets the raw data of the picture.
Definition: picture.cpp:158
void setUrl(const QString &url)
Sets a URL for the location of the picture file.
Definition: picture.cpp:130
void setGeo(const Geo &geo)
Set geographic position.
Definition: addressee.cpp:985
const QChar at(int position) const const
void setRevision(const QDateTime &revision)
Set revision date.
Definition: addressee.cpp:1218
Class that holds a Language for a contact.
Definition: lang.h:20
X509 key.
Definition: key.h:35
typedef ConstIterator
Descripes the confidentiality of an addressee.
Definition: secrecy.h:17
void setLogo(const Picture &logo)
Set logo.
Definition: addressee.cpp:1304
void setBirthday(const QDateTime &birthday, bool withTime=true)
Set birthday (date and time).
Definition: addressee.cpp:790
Class that holds a Gender for a contact.
Definition: gender.h:19
Class that holds a Title for a contact.
Definition: title.h:20
int length() const const
QString left(int n) const const
QString fromLatin1(const char *str, int size)
bool isValid() const
Return, if this time zone object is valid.
Definition: timezone.cpp:65
void setType(Type type)
Sets the type.
Definition: key.cpp:145
void setCustomTypeString(const QString &type)
Sets custom type string.
Definition: key.cpp:150
bool isIntern() const
Returns whether the sound is described by a URL (extern) or by the raw data (intern).
Definition: sound.cpp:109
bool isIntern() const
Returns whether the picture is described by a URL (extern) or by the raw data (intern).
Definition: picture.cpp:166
address book entry
Definition: addressee.h:68
international
Definition: address.h:66
Class that holds a Organization for a contact.
Definition: org.h:20
Time zone information.
Definition: timezone.h:21
void setName(const QString &name)
Set name.
Definition: addressee.cpp:423
TypeFlag
Address types:
Definition: address.h:64
QList::const_iterator constEnd() const const
QList::const_iterator constBegin() const const
address at work
Definition: address.h:70
int offsetFromUtc() const const
int year() const const
int compare(const QString &other, Qt::CaseSensitivity cs) const const
void setUrl(const QString &url)
Sets a URL for the location of the sound file.
Definition: sound.cpp:97
QVector::iterator end()
QString customTypeString() const
Returns the custom type string.
Definition: key.cpp:160
QList::iterator begin()
void setSecrecy(const Secrecy &secrecy)
Set security class.
Definition: addressee.cpp:1284
Phonenumber information.
Definition: phonenumber.h:27
void setBinaryData(const QByteArray &data)
Sets binary data.
Definition: key.cpp:118
void insertAddress(const Address &address)
Insert an address.
Definition: addressee.cpp:1977
Types types(const QStringList &mimeTypes)
void setSound(const Sound &sound)
Set sound.
Definition: addressee.cpp:1344
Picture logo() const
Return logo.
Definition: addressee.cpp:1314
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Thu Jul 9 2020 22:54:11 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.