1 | /* |
2 | This file is part of the KContacts framework. |
3 | SPDX-FileCopyrightText: 2003 Helge Deller <deller@kde.org> |
4 | |
5 | SPDX-License-Identifier: LGPL-2.0-or-later |
6 | */ |
7 | |
8 | /* |
9 | Useful links: |
10 | - http://tldp.org/HOWTO/LDAP-Implementation-HOWTO/schemas.html |
11 | - http://www.faqs.org/rfcs/rfc2849.html |
12 | |
13 | Not yet handled items: |
14 | - objectclass microsoftaddressbook |
15 | - info, |
16 | - initials, |
17 | - otherfacsimiletelephonenumber, |
18 | - otherpager, |
19 | - physicaldeliveryofficename, |
20 | */ |
21 | |
22 | #include "ldifconverter.h" |
23 | #include "address.h" |
24 | #include "kcontacts_debug.h" |
25 | #include "vcardconverter.h" |
26 | |
27 | #include "ldif_p.h" |
28 | |
29 | #include <KCountry> |
30 | #include <KLocalizedString> |
31 | |
32 | #include <QIODevice> |
33 | #include <QStringList> |
34 | #include <QTextStream> |
35 | |
36 | using namespace KContacts; |
37 | |
38 | /* internal functions - do not use !! */ |
39 | |
40 | namespace KContacts |
41 | { |
42 | /** |
43 | @internal |
44 | |
45 | Evaluates @p fieldname and sets the @p value at the addressee or the address |
46 | objects when appropriate. |
47 | |
48 | @param a The addressee to store information into |
49 | @param homeAddr The home address to store respective information into |
50 | @param workAddr The work address to store respective information into |
51 | @param fieldname LDIF field name to evaluate |
52 | @param value The value of the field addressed by @p fieldname |
53 | */ |
54 | void evaluatePair(Addressee &a, |
55 | Address &homeAddr, |
56 | Address &workAddr, |
57 | QString &fieldname, |
58 | QString &value, |
59 | int &birthday, |
60 | int &birthmonth, |
61 | int &birthyear, |
62 | ContactGroup &contactGroup); |
63 | } |
64 | |
65 | /* generate LDIF stream */ |
66 | |
67 | static void ldif_out(QTextStream &t, const QString &formatStr, const QString &value) |
68 | { |
69 | if (value.isEmpty()) { |
70 | return; |
71 | } |
72 | |
73 | const QByteArray txt = Ldif::assembleLine(fieldname: formatStr, value, linelen: 72); |
74 | |
75 | // write the string |
76 | t << QString::fromUtf8(ba: txt) << "\n" ; |
77 | } |
78 | |
79 | bool LDIFConverter::addresseeAndContactGroupToLDIF(const AddresseeList &addrList, const ContactGroup::List &contactGroupList, QString &str) |
80 | { |
81 | bool result = addresseeToLDIF(addrList, str); |
82 | if (!contactGroupList.isEmpty()) { |
83 | result = (contactGroupToLDIF(contactGroupList, str) || result); // order matters |
84 | } |
85 | return result; |
86 | } |
87 | |
88 | bool LDIFConverter::contactGroupToLDIF(const ContactGroup &contactGroup, QString &str) |
89 | { |
90 | if (contactGroup.dataCount() <= 0) { |
91 | return false; |
92 | } |
93 | QTextStream t(&str, QIODevice::WriteOnly | QIODevice::Append); |
94 | |
95 | t << "objectclass: top\n" ; |
96 | t << "objectclass: groupOfNames\n" ; |
97 | |
98 | for (int i = 0; i < contactGroup.dataCount(); ++i) { |
99 | const ContactGroup::Data &data = contactGroup.data(index: i); |
100 | const QString value = QStringLiteral("cn=%1,mail=%2" ).arg(args: data.name(), args: data.email()); |
101 | ldif_out(t, QStringLiteral("member" ), value); |
102 | } |
103 | |
104 | t << "\n" ; |
105 | return true; |
106 | } |
107 | |
108 | bool LDIFConverter::contactGroupToLDIF(const ContactGroup::List &contactGroupList, QString &str) |
109 | { |
110 | if (contactGroupList.isEmpty()) { |
111 | return false; |
112 | } |
113 | |
114 | bool result = true; |
115 | for (const ContactGroup &group : contactGroupList) { |
116 | result = (contactGroupToLDIF(contactGroup: group, str) || result); // order matters |
117 | } |
118 | return result; |
119 | } |
120 | |
121 | bool LDIFConverter::addresseeToLDIF(const AddresseeList &addrList, QString &str) |
122 | { |
123 | if (addrList.isEmpty()) { |
124 | return false; |
125 | } |
126 | |
127 | bool result = true; |
128 | for (const Addressee &addr : addrList) { |
129 | result = (addresseeToLDIF(addr, str) || result); // order matters |
130 | } |
131 | return result; |
132 | } |
133 | |
134 | static QString countryName(const QString &isoCodeOrName) |
135 | { |
136 | const auto c = KCountry::fromAlpha2(alpha2Code: isoCodeOrName); |
137 | return c.isValid() ? c.name() : isoCodeOrName; |
138 | } |
139 | |
140 | bool LDIFConverter::addresseeToLDIF(const Addressee &addr, QString &str) |
141 | { |
142 | if (addr.isEmpty()) { |
143 | return false; |
144 | } |
145 | |
146 | QTextStream t(&str, QIODevice::WriteOnly | QIODevice::Append); |
147 | |
148 | const Address homeAddr = addr.address(type: Address::Home); |
149 | const Address workAddr = addr.address(type: Address::Work); |
150 | |
151 | ldif_out(t, QStringLiteral("dn" ), QStringLiteral("cn=%1,mail=%2" ).arg(args: addr.formattedName().simplified(), args: addr.preferredEmail())); |
152 | t << "objectclass: top\n" ; |
153 | t << "objectclass: person\n" ; |
154 | t << "objectclass: organizationalPerson\n" ; |
155 | |
156 | ldif_out(t, QStringLiteral("givenname" ), value: addr.givenName()); |
157 | ldif_out(t, QStringLiteral("sn" ), value: addr.familyName()); |
158 | ldif_out(t, QStringLiteral("cn" ), value: addr.formattedName().simplified()); |
159 | ldif_out(t, QStringLiteral("uid" ), value: addr.uid()); |
160 | ldif_out(t, QStringLiteral("nickname" ), value: addr.nickName()); |
161 | ldif_out(t, QStringLiteral("xmozillanickname" ), value: addr.nickName()); |
162 | ldif_out(t, QStringLiteral("mozillanickname" ), value: addr.nickName()); |
163 | |
164 | ldif_out(t, QStringLiteral("mail" ), value: addr.preferredEmail()); |
165 | const QStringList emails = addr.emails(); |
166 | const int numEmails = emails.count(); |
167 | for (int i = 1; i < numEmails; ++i) { |
168 | if (i == 0) { |
169 | // nothing |
170 | } else if (i == 1) { |
171 | ldif_out(t, QStringLiteral("mozillasecondemail" ), value: emails[1]); |
172 | } else { |
173 | ldif_out(t, QStringLiteral("othermailbox" ), value: emails[i]); |
174 | } |
175 | } |
176 | // ldif_out( t, "mozilla_AIMScreenName: %1\n", "screen_name" ); |
177 | |
178 | ldif_out(t, QStringLiteral("telephonenumber" ), value: addr.phoneNumber(type: PhoneNumber::Work).number()); |
179 | ldif_out(t, QStringLiteral("facsimiletelephonenumber" ), value: addr.phoneNumber(type: PhoneNumber::Fax).number()); |
180 | ldif_out(t, QStringLiteral("homephone" ), value: addr.phoneNumber(type: PhoneNumber::Home).number()); |
181 | ldif_out(t, QStringLiteral("mobile" ), |
182 | value: addr.phoneNumber(type: PhoneNumber::Cell).number()); // Netscape 7 |
183 | ldif_out(t, QStringLiteral("cellphone" ), |
184 | value: addr.phoneNumber(type: PhoneNumber::Cell).number()); // Netscape 4.x |
185 | ldif_out(t, QStringLiteral("pager" ), value: addr.phoneNumber(type: PhoneNumber::Pager).number()); |
186 | ldif_out(t, QStringLiteral("pagerphone" ), value: addr.phoneNumber(type: PhoneNumber::Pager).number()); |
187 | |
188 | ldif_out(t, QStringLiteral("streethomeaddress" ), value: homeAddr.street()); |
189 | ldif_out(t, QStringLiteral("postalcode" ), value: workAddr.postalCode()); |
190 | ldif_out(t, QStringLiteral("postofficebox" ), value: workAddr.postOfficeBox()); |
191 | |
192 | QStringList streets = homeAddr.street().split(sep: QLatin1Char('\n')); |
193 | const int numberOfStreets(streets.count()); |
194 | if (numberOfStreets > 0) { |
195 | ldif_out(t, QStringLiteral("homepostaladdress" ), value: streets.at(i: 0)); // Netscape 7 |
196 | } |
197 | if (numberOfStreets > 1) { |
198 | ldif_out(t, QStringLiteral("mozillahomepostaladdress2" ), value: streets.at(i: 1)); // Netscape 7 |
199 | } |
200 | ldif_out(t, QStringLiteral("mozillahomelocalityname" ), value: homeAddr.locality()); // Netscape 7 |
201 | ldif_out(t, QStringLiteral("mozillahomestate" ), value: homeAddr.region()); |
202 | ldif_out(t, QStringLiteral("mozillahomepostalcode" ), value: homeAddr.postalCode()); |
203 | ldif_out(t, QStringLiteral("mozillahomecountryname" ), value: countryName(isoCodeOrName: homeAddr.country())); |
204 | ldif_out(t, QStringLiteral("locality" ), value: workAddr.locality()); |
205 | ldif_out(t, QStringLiteral("streetaddress" ), value: workAddr.street()); // Netscape 4.x |
206 | |
207 | streets = workAddr.street().split(sep: QLatin1Char('\n')); |
208 | const int streetsCount = streets.count(); |
209 | if (streetsCount > 0) { |
210 | ldif_out(t, QStringLiteral("street" ), value: streets.at(i: 0)); |
211 | } |
212 | if (streetsCount > 1) { |
213 | ldif_out(t, QStringLiteral("mozillaworkstreet2" ), value: streets.at(i: 1)); |
214 | } |
215 | ldif_out(t, QStringLiteral("countryname" ), value: countryName(isoCodeOrName: workAddr.country())); |
216 | ldif_out(t, QStringLiteral("l" ), value: workAddr.locality()); |
217 | ldif_out(t, QStringLiteral("c" ), value: countryName(isoCodeOrName: workAddr.country())); |
218 | ldif_out(t, QStringLiteral("st" ), value: workAddr.region()); |
219 | |
220 | ldif_out(t, QStringLiteral("title" ), value: addr.title()); |
221 | ldif_out(t, QStringLiteral("vocation" ), value: addr.prefix()); |
222 | ldif_out(t, QStringLiteral("ou" ), value: addr.role()); |
223 | ldif_out(t, QStringLiteral("o" ), value: addr.organization()); |
224 | ldif_out(t, QStringLiteral("organization" ), value: addr.organization()); |
225 | ldif_out(t, QStringLiteral("organizationname" ), value: addr.organization()); |
226 | |
227 | // Compatibility with older kabc versions. |
228 | if (!addr.department().isEmpty()) { |
229 | ldif_out(t, QStringLiteral("department" ), value: addr.department()); |
230 | } else { |
231 | ldif_out(t, QStringLiteral("department" ), value: addr.custom(QStringLiteral("KADDRESSBOOK" ), QStringLiteral("X-Department" ))); |
232 | } |
233 | |
234 | ldif_out(t, QStringLiteral("workurl" ), value: addr.url().url().toDisplayString()); |
235 | ldif_out(t, QStringLiteral("homeurl" ), value: addr.url().url().toDisplayString()); |
236 | ldif_out(t, QStringLiteral("mozillahomeurl" ), value: addr.url().url().toDisplayString()); |
237 | |
238 | ldif_out(t, QStringLiteral("description" ), value: addr.note()); |
239 | if (addr.revision().isValid()) { |
240 | ldif_out(t, QStringLiteral("modifytimestamp" ), value: dateToVCardString(dateTime: addr.revision())); |
241 | } |
242 | |
243 | const QDate birthday = addr.birthday().date(); |
244 | if (birthday.isValid()) { |
245 | const int year = birthday.year(); |
246 | if (year > 0) { |
247 | ldif_out(t, QStringLiteral("birthyear" ), value: QString::number(year)); |
248 | } |
249 | ldif_out(t, QStringLiteral("birthmonth" ), value: QString::number(birthday.month())); |
250 | ldif_out(t, QStringLiteral("birthday" ), value: QString::number(birthday.day())); |
251 | } |
252 | |
253 | t << "\n" ; |
254 | |
255 | return true; |
256 | } |
257 | |
258 | /* convert from LDIF stream */ |
259 | bool LDIFConverter::LDIFToAddressee(const QString &str, AddresseeList &addrList, ContactGroup::List &contactGroupList, const QDateTime &dt) |
260 | { |
261 | if (str.isEmpty()) { |
262 | return true; |
263 | } |
264 | |
265 | bool endldif = false; |
266 | bool end = false; |
267 | Ldif ldif; |
268 | Ldif::ParseValue ret; |
269 | Addressee a; |
270 | Address homeAddr; |
271 | Address workAddr; |
272 | int birthday = -1; |
273 | int birthmonth = -1; |
274 | int birthyear = -1; |
275 | ContactGroup contactGroup; |
276 | ldif.setLdif(str.toLatin1()); |
277 | QDateTime qdt = dt; |
278 | if (!qdt.isValid()) { |
279 | qdt = QDateTime::currentDateTime(); |
280 | } |
281 | a.setRevision(qdt); |
282 | homeAddr = Address(Address::Home); |
283 | workAddr = Address(Address::Work); |
284 | |
285 | do { |
286 | ret = ldif.nextItem(); |
287 | switch (ret) { |
288 | case Ldif::Item: { |
289 | QString fieldname = ldif.attr().toLower(); |
290 | QString value = QString::fromUtf8(ba: ldif.value()); |
291 | evaluatePair(a, homeAddr, workAddr, fieldname, value, birthday, birthmonth, birthyear, contactGroup); |
292 | break; |
293 | } |
294 | case Ldif::EndEntry: |
295 | if (contactGroup.count() == 0) { |
296 | // if the new address is not empty, append it |
297 | QDate birthDate(birthyear, birthmonth, birthday); |
298 | if (birthDate.isValid()) { |
299 | a.setBirthday(birthDate); |
300 | } |
301 | |
302 | if (!a.formattedName().isEmpty() || !a.name().isEmpty() || !a.familyName().isEmpty()) { |
303 | if (!homeAddr.isEmpty()) { |
304 | a.insertAddress(address: homeAddr); |
305 | } |
306 | if (!workAddr.isEmpty()) { |
307 | a.insertAddress(address: workAddr); |
308 | } |
309 | addrList.append(t: a); |
310 | } |
311 | } else { |
312 | contactGroupList.append(t: contactGroup); |
313 | } |
314 | a = Addressee(); |
315 | contactGroup = ContactGroup(); |
316 | a.setRevision(qdt); |
317 | homeAddr = Address(Address::Home); |
318 | workAddr = Address(Address::Work); |
319 | break; |
320 | case Ldif::MoreData: |
321 | if (endldif) { |
322 | end = true; |
323 | } else { |
324 | ldif.endLdif(); |
325 | endldif = true; |
326 | break; |
327 | } |
328 | default: |
329 | break; |
330 | } |
331 | } while (!end); |
332 | |
333 | return true; |
334 | } |
335 | |
336 | void KContacts::evaluatePair(Addressee &a, |
337 | Address &homeAddr, |
338 | Address &workAddr, |
339 | QString &fieldname, |
340 | QString &value, |
341 | int &birthday, |
342 | int &birthmonth, |
343 | int &birthyear, |
344 | ContactGroup &contactGroup) |
345 | { |
346 | if (fieldname == QLatin1String("dn" )) { // ignore |
347 | return; |
348 | } |
349 | |
350 | if (fieldname.startsWith(c: QLatin1Char('#'))) { |
351 | return; |
352 | } |
353 | |
354 | if (fieldname.isEmpty() && !a.note().isEmpty()) { |
355 | // some LDIF export filters are broken and add additional |
356 | // comments on stand-alone lines. Just add them to the notes for now. |
357 | a.setNote(a.note() + QLatin1Char('\n') + value); |
358 | return; |
359 | } |
360 | |
361 | if (fieldname == QLatin1String("givenname" )) { |
362 | a.setGivenName(value); |
363 | return; |
364 | } |
365 | |
366 | if (fieldname == QLatin1String("xmozillanickname" ) // |
367 | || fieldname == QLatin1String("nickname" ) // |
368 | || fieldname == QLatin1String("mozillanickname" )) { |
369 | a.setNickName(value); |
370 | return; |
371 | } |
372 | |
373 | if (fieldname == QLatin1String("sn" )) { |
374 | a.setFamilyName(value); |
375 | return; |
376 | } |
377 | |
378 | if (fieldname == QLatin1String("uid" )) { |
379 | a.setUid(value); |
380 | return; |
381 | } |
382 | if (fieldname == QLatin1String("mail" ) // |
383 | || fieldname == QLatin1String("mozillasecondemail" ) /* mozilla */ |
384 | || fieldname == QLatin1String("othermailbox" ) /*TheBat!*/) { |
385 | if (a.emails().indexOf(str: value) == -1) { |
386 | a.addEmail(email: value); |
387 | } |
388 | return; |
389 | } |
390 | |
391 | if (fieldname == QLatin1String("title" )) { |
392 | a.setTitle(value); |
393 | return; |
394 | } |
395 | |
396 | if (fieldname == QLatin1String("vocation" )) { |
397 | a.setPrefix(value); |
398 | return; |
399 | } |
400 | |
401 | if (fieldname == QLatin1String("cn" )) { |
402 | a.setFormattedName(value); |
403 | return; |
404 | } |
405 | |
406 | if (fieldname == QLatin1Char('o') || fieldname == QLatin1String("organization" ) // Exchange |
407 | || fieldname == QLatin1String("organizationname" )) { // Exchange |
408 | a.setOrganization(value); |
409 | return; |
410 | } |
411 | |
412 | // clang-format off |
413 | if (fieldname == QLatin1String("description" ) |
414 | || fieldname == QLatin1String("mozillacustom1" ) |
415 | || fieldname == QLatin1String("mozillacustom2" ) |
416 | || fieldname == QLatin1String("mozillacustom3" ) |
417 | || fieldname == QLatin1String("mozillacustom4" ) |
418 | || fieldname == QLatin1String("custom1" ) |
419 | || fieldname == QLatin1String("custom2" ) |
420 | || fieldname == QLatin1String("custom3" ) |
421 | || fieldname == QLatin1String("custom4" )) { |
422 | if (!a.note().isEmpty()) { |
423 | a.setNote(a.note() + QLatin1Char('\n')); |
424 | } |
425 | a.setNote(a.note() + value); |
426 | return; |
427 | } |
428 | // clang-format on |
429 | |
430 | if (fieldname == QLatin1String("homeurl" ) // |
431 | || fieldname == QLatin1String("workurl" ) // |
432 | || fieldname == QLatin1String("mozillahomeurl" )) { |
433 | if (a.url().url().isEmpty()) { |
434 | ResourceLocatorUrl url; |
435 | url.setUrl(QUrl(value)); |
436 | a.setUrl(url); |
437 | return; |
438 | } |
439 | if (a.url().url().toDisplayString() == QUrl(value).toDisplayString()) { |
440 | return; |
441 | } |
442 | // TODO: current version of kabc only supports one URL. |
443 | // TODO: change this with KDE 4 |
444 | } |
445 | |
446 | if (fieldname == QLatin1String("homephone" )) { |
447 | a.insertPhoneNumber(phoneNumber: PhoneNumber(value, PhoneNumber::Home)); |
448 | return; |
449 | } |
450 | |
451 | if (fieldname == QLatin1String("telephonenumber" )) { |
452 | a.insertPhoneNumber(phoneNumber: PhoneNumber(value, PhoneNumber::Work)); |
453 | return; |
454 | } |
455 | if (fieldname == QLatin1String("mobile" ) /* mozilla/Netscape 7 */ |
456 | || fieldname == QLatin1String("cellphone" )) { |
457 | a.insertPhoneNumber(phoneNumber: PhoneNumber(value, PhoneNumber::Cell)); |
458 | return; |
459 | } |
460 | |
461 | if (fieldname == QLatin1String("pager" ) // mozilla |
462 | || fieldname == QLatin1String("pagerphone" )) { // mozilla |
463 | a.insertPhoneNumber(phoneNumber: PhoneNumber(value, PhoneNumber::Pager)); |
464 | return; |
465 | } |
466 | |
467 | if (fieldname == QLatin1String("facsimiletelephonenumber" )) { |
468 | a.insertPhoneNumber(phoneNumber: PhoneNumber(value, PhoneNumber::Fax)); |
469 | return; |
470 | } |
471 | |
472 | if (fieldname == QLatin1String("xmozillaanyphone" )) { // mozilla |
473 | a.insertPhoneNumber(phoneNumber: PhoneNumber(value, PhoneNumber::Work)); |
474 | return; |
475 | } |
476 | |
477 | if (fieldname == QLatin1String("streethomeaddress" ) // |
478 | || fieldname == QLatin1String("mozillahomestreet" )) { // thunderbird |
479 | homeAddr.setStreet(value); |
480 | return; |
481 | } |
482 | |
483 | if (fieldname == QLatin1String("street" ) // |
484 | || fieldname == QLatin1String("postaladdress" )) { // mozilla |
485 | workAddr.setStreet(value); |
486 | return; |
487 | } |
488 | if (fieldname == QLatin1String("mozillapostaladdress2" ) // |
489 | || fieldname == QLatin1String("mozillaworkstreet2" )) { // mozilla |
490 | workAddr.setStreet(workAddr.street() + QLatin1Char('\n') + value); |
491 | return; |
492 | } |
493 | |
494 | if (fieldname == QLatin1String("postalcode" )) { |
495 | workAddr.setPostalCode(value); |
496 | return; |
497 | } |
498 | |
499 | if (fieldname == QLatin1String("postofficebox" )) { |
500 | workAddr.setPostOfficeBox(value); |
501 | return; |
502 | } |
503 | |
504 | if (fieldname == QLatin1String("homepostaladdress" )) { // Netscape 7 |
505 | homeAddr.setStreet(value); |
506 | return; |
507 | } |
508 | |
509 | if (fieldname == QLatin1String("mozillahomepostaladdress2" )) { // mozilla |
510 | homeAddr.setStreet(homeAddr.street() + QLatin1Char('\n') + value); |
511 | return; |
512 | } |
513 | |
514 | if (fieldname == QLatin1String("mozillahomelocalityname" )) { // mozilla |
515 | homeAddr.setLocality(value); |
516 | return; |
517 | } |
518 | |
519 | if (fieldname == QLatin1String("mozillahomestate" )) { // mozilla |
520 | homeAddr.setRegion(value); |
521 | return; |
522 | } |
523 | |
524 | if (fieldname == QLatin1String("mozillahomepostalcode" )) { // mozilla |
525 | homeAddr.setPostalCode(value); |
526 | return; |
527 | } |
528 | |
529 | if (fieldname == QLatin1String("mozillahomecountryname" )) { // mozilla |
530 | if (value.length() <= 2) { |
531 | value = countryName(isoCodeOrName: value); |
532 | } |
533 | homeAddr.setCountry(value); |
534 | return; |
535 | } |
536 | |
537 | if (fieldname == QLatin1String("locality" )) { |
538 | workAddr.setLocality(value); |
539 | return; |
540 | } |
541 | |
542 | if (fieldname == QLatin1String("streetaddress" )) { // Netscape 4.x |
543 | workAddr.setStreet(value); |
544 | return; |
545 | } |
546 | |
547 | if (fieldname == QLatin1String("countryname" ) // |
548 | || fieldname == QLatin1Char('c')) { // mozilla |
549 | if (value.length() <= 2) { |
550 | value = countryName(isoCodeOrName: value); |
551 | } |
552 | workAddr.setCountry(value); |
553 | return; |
554 | } |
555 | |
556 | if (fieldname == QLatin1Char('l')) { // mozilla |
557 | workAddr.setLocality(value); |
558 | return; |
559 | } |
560 | |
561 | if (fieldname == QLatin1String("st" )) { |
562 | workAddr.setRegion(value); |
563 | return; |
564 | } |
565 | |
566 | if (fieldname == QLatin1String("ou" )) { |
567 | a.setRole(value); |
568 | return; |
569 | } |
570 | |
571 | if (fieldname == QLatin1String("department" )) { |
572 | a.setDepartment(value); |
573 | return; |
574 | } |
575 | |
576 | if (fieldname == QLatin1String("member" )) { |
577 | // this is a mozilla list member (cn=xxx, mail=yyy) |
578 | const QStringList list = value.split(sep: QLatin1Char(',')); |
579 | QString name; |
580 | QString email; |
581 | |
582 | const QLatin1String cnTag("cn=" ); |
583 | const QLatin1String mailTag("mail=" ); |
584 | for (const auto &str : list) { |
585 | if (str.startsWith(s: cnTag)) { |
586 | name = QStringView(str).mid(pos: cnTag.size()).trimmed().toString(); |
587 | } else if (str.startsWith(s: mailTag)) { |
588 | email = QStringView(str).mid(pos: mailTag.size()).trimmed().toString(); |
589 | } |
590 | } |
591 | |
592 | if (!name.isEmpty() && !email.isEmpty()) { |
593 | email = QLatin1String(" <" ) + email + QLatin1Char('>'); |
594 | } |
595 | ContactGroup::Data data; |
596 | data.setEmail(email); |
597 | data.setName(name); |
598 | contactGroup.append(data); |
599 | return; |
600 | } |
601 | |
602 | if (fieldname == QLatin1String("modifytimestamp" )) { |
603 | if (value == QLatin1String("0Z" )) { // ignore |
604 | return; |
605 | } |
606 | QDateTime dt = VCardStringToDate(dateString: value); |
607 | if (dt.isValid()) { |
608 | a.setRevision(dt); |
609 | return; |
610 | } |
611 | } |
612 | |
613 | if (fieldname == QLatin1String("display-name" )) { |
614 | contactGroup.setName(value); |
615 | return; |
616 | } |
617 | |
618 | if (fieldname == QLatin1String("objectclass" )) { // ignore |
619 | return; |
620 | } |
621 | |
622 | if (fieldname == QLatin1String("birthyear" )) { |
623 | bool ok; |
624 | birthyear = value.toInt(ok: &ok); |
625 | if (!ok) { |
626 | birthyear = -1; |
627 | } |
628 | return; |
629 | } |
630 | if (fieldname == QLatin1String("birthmonth" )) { |
631 | birthmonth = value.toInt(); |
632 | return; |
633 | } |
634 | if (fieldname == QLatin1String("birthday" )) { |
635 | birthday = value.toInt(); |
636 | return; |
637 | } |
638 | if (fieldname == QLatin1String("xbatbirthday" )) { |
639 | const QStringView str{value}; |
640 | QDate dt(str.mid(pos: 0, n: 4).toInt(), str.mid(pos: 4, n: 2).toInt(), str.mid(pos: 6, n: 2).toInt()); |
641 | if (dt.isValid()) { |
642 | a.setBirthday(dt); |
643 | } |
644 | return; |
645 | } |
646 | qCWarning(KCONTACTS_LOG) << QStringLiteral("LDIFConverter: Unknown field for '%1': '%2=%3'\n" ).arg(args: a.formattedName(), args&: fieldname, args&: value); |
647 | } |
648 | |