source: psi/trunk/iris/xmpp-im/xmpp_vcard.cpp

Last change on this file was 2, checked in by dmik, 19 years ago

Imported original Psi 0.10 sources from Affinix

File size: 26.5 KB
Line 
1/*
2 * xmpp_vcard.cpp - classes for handling vCards
3 * Copyright (C) 2003 Michail Pishchagin
4 *
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
9 *
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
14 *
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18 *
19 */
20
21#include "xmpp_vcard.h"
22
23#include "base64.h"
24
25#include <qdom.h>
26#include <qdatetime.h>
27
28#include <qimage.h> // needed for image format recognition
29#include <qbuffer.h>
30
31// Justin's XML helper functions
32
33static QDomElement textTag(QDomDocument *doc, const QString &name, const QString &content)
34{
35 QDomElement tag = doc->createElement(name);
36 QDomText text = doc->createTextNode(content);
37 tag.appendChild(text);
38
39 return tag;
40}
41
42static QDomElement findSubTag(const QDomElement &e, const QString &name, bool *found)
43{
44 if(found)
45 *found = FALSE;
46
47 for(QDomNode n = e.firstChild(); !n.isNull(); n = n.nextSibling()) {
48 QDomElement i = n.toElement();
49 if(i.isNull())
50 continue;
51 if(i.tagName().upper() == name.upper()) { // mblsha: ignore case when searching
52 if(found)
53 *found = TRUE;
54 return i;
55 }
56 }
57
58 QDomElement tmp;
59 return tmp;
60}
61
62// mblsha's own functions
63
64static QDomElement emptyTag(QDomDocument *doc, const QString &name)
65{
66 QDomElement tag = doc->createElement(name);
67
68 return tag;
69}
70
71static bool hasSubTag(const QDomElement &e, const QString &name)
72{
73 bool found;
74 findSubTag(e, name, &found);
75 return found;
76}
77
78static QString subTagText(const QDomElement &e, const QString &name)
79{
80 bool found;
81 QDomElement i = findSubTag(e, name, &found);
82 if ( found )
83 return i.text().stripWhiteSpace();
84 return QString::null;
85}
86
87using namespace XMPP;
88
89//----------------------------------------------------------------------------
90// VCard
91//----------------------------------------------------------------------------
92static QString image2type(const QByteArray &ba)
93{
94 QBuffer buf(ba);
95 buf.open(IO_ReadOnly);
96 QString format = QImageIO::imageFormat( &buf );
97
98 // TODO: add more formats
99 if ( format == "PNG" || format == "PsiPNG" )
100 return "image/png";
101 if ( format == "MNG" )
102 return "video/x-mng";
103 if ( format == "GIF" )
104 return "image/gif";
105 if ( format == "BMP" )
106 return "image/bmp";
107 if ( format == "XPM" )
108 return "image/x-xpm";
109 if ( format == "SVG" )
110 return "image/svg+xml";
111 if ( format == "JPEG" )
112 return "image/jpeg";
113
114 qWarning("WARNING! VCard::image2type: unknown format = '%s'", format.latin1());
115
116 return "image/unknown";
117}
118
119// Long lines of encoded binary data SHOULD BE folded to 75 characters using the folding method defined in [MIME-DIR].
120static QString foldString(const QString &s)
121{
122 QString ret;
123
124 for (int i = 0; i < (int)s.length(); i++) {
125 if ( !(i % 75) )
126 ret += '\n';
127 ret += s[i];
128 }
129
130 return ret;
131}
132
133class VCard::Private
134{
135public:
136 Private();
137 ~Private();
138
139 QString version;
140 QString fullName;
141 QString familyName, givenName, middleName, prefixName, suffixName;
142 QString nickName;
143
144 QByteArray photo;
145 QString photoURI;
146
147 QString bday;
148 AddressList addressList;
149 LabelList labelList;
150 PhoneList phoneList;
151 EmailList emailList;
152 QString jid;
153 QString mailer;
154 QString timezone;
155 Geo geo;
156 QString title;
157 QString role;
158
159 QByteArray logo;
160 QString logoURI;
161
162 VCard *agent;
163 QString agentURI;
164
165 Org org;
166 QStringList categories;
167 QString note;
168 QString prodId;
169 QString rev;
170 QString sortString;
171
172 QByteArray sound;
173 QString soundURI, soundPhonetic;
174
175 QString uid;
176 QString url;
177 QString desc;
178 PrivacyClass privacyClass;
179 QByteArray key;
180
181 bool isEmpty();
182};
183
184VCard::Private::Private()
185{
186 privacyClass = pcNone;
187 agent = 0;
188}
189
190VCard::Private::~Private()
191{
192 delete agent;
193}
194
195bool VCard::Private::isEmpty()
196{
197 if ( !version.isEmpty() ||
198 !fullName.isEmpty() ||
199 !familyName.isEmpty() || !givenName.isEmpty() || !middleName.isEmpty() || !prefixName.isEmpty() || !suffixName.isEmpty() ||
200 !nickName.isEmpty() ||
201 !photo.isEmpty() || !photoURI.isEmpty() ||
202 !bday.isEmpty() ||
203 !addressList.isEmpty() ||
204 !labelList.isEmpty() ||
205 !phoneList.isEmpty() ||
206 !emailList.isEmpty() ||
207 !jid.isEmpty() ||
208 !mailer.isEmpty() ||
209 !timezone.isEmpty() ||
210 !geo.lat.isEmpty() || !geo.lon.isEmpty() ||
211 !title.isEmpty() ||
212 !role.isEmpty() ||
213 !logo.isEmpty() || !logoURI.isEmpty() ||
214 (agent && !agent->isEmpty()) || !agentURI.isEmpty() ||
215 !org.name.isEmpty() || !org.unit.isEmpty() ||
216 !categories.isEmpty() ||
217 !note.isEmpty() ||
218 !prodId.isEmpty() ||
219 !rev.isEmpty() ||
220 !sortString.isEmpty() ||
221 !sound.isEmpty() || !soundURI.isEmpty() || !soundPhonetic.isEmpty() ||
222 !uid.isEmpty() ||
223 !url.isEmpty() ||
224 !desc.isEmpty() ||
225 (privacyClass != pcNone) ||
226 !key.isEmpty() )
227 {
228 return false;
229 }
230 return true;
231}
232
233VCard::VCard()
234{
235 d = new Private;
236}
237
238VCard::VCard(const VCard &from)
239{
240 d = new Private;
241 *this = from;
242}
243
244VCard & VCard::operator=(const VCard &from)
245{
246 if(d->agent) {
247 delete d->agent;
248 d->agent = 0;
249 }
250
251 *d = *from.d;
252
253 if(from.d->agent) {
254 // dup the agent
255 d->agent = new VCard(*from.d->agent);
256 }
257
258 return *this;
259}
260
261VCard::~VCard()
262{
263 delete d;
264}
265
266QDomElement VCard::toXml(QDomDocument *doc) const
267{
268 QDomElement v = doc->createElement("vCard");
269 v.setAttribute("version", "2.0");
270 v.setAttribute("prodid", "-//HandGen//NONSGML vGen v1.0//EN");
271 v.setAttribute("xmlns", "vcard-temp");
272
273 if ( !d->version.isEmpty() )
274 v.appendChild( textTag(doc, "VERSION", d->version) );
275 if ( !d->fullName.isEmpty() )
276 v.appendChild( textTag(doc, "FN", d->fullName) );
277
278 if ( !d->familyName.isEmpty() || !d->givenName.isEmpty() || !d->middleName.isEmpty() ||
279 !d->prefixName.isEmpty() || !d->suffixName.isEmpty() ) {
280 QDomElement w = doc->createElement("N");
281
282 if ( !d->familyName.isEmpty() )
283 w.appendChild( textTag(doc, "FAMILY", d->familyName) );
284 if ( !d->givenName.isEmpty() )
285 w.appendChild( textTag(doc, "GIVEN", d->givenName) );
286 if ( !d->middleName.isEmpty() )
287 w.appendChild( textTag(doc, "MIDDLE", d->middleName) );
288 if ( !d->prefixName.isEmpty() )
289 w.appendChild( textTag(doc, "PREFIX", d->prefixName) );
290 if ( !d->suffixName.isEmpty() )
291 w.appendChild( textTag(doc, "SUFFIX", d->suffixName) );
292
293 v.appendChild(w);
294 }
295
296 if ( !d->nickName.isEmpty() )
297 v.appendChild( textTag(doc, "NICKNAME", d->nickName) );
298
299 if ( !d->photo.isEmpty() || !d->photoURI.isEmpty() ) {
300 QDomElement w = doc->createElement("PHOTO");
301
302 if ( !d->photo.isEmpty() ) {
303 w.appendChild( textTag(doc, "TYPE", image2type(d->photo)) );
304 w.appendChild( textTag(doc, "BINVAL", foldString( Base64::arrayToString(d->photo)) ) );
305 }
306 else if ( !d->photoURI.isEmpty() )
307 w.appendChild( textTag(doc, "EXTVAL", d->photoURI) );
308
309 v.appendChild(w);
310 }
311
312 if ( !d->bday.isEmpty() )
313 v.appendChild( textTag(doc, "BDAY", d->bday) );
314
315 if ( !d->addressList.isEmpty() ) {
316 AddressList::Iterator it = d->addressList.begin();
317 for ( ; it != d->addressList.end(); ++it ) {
318 QDomElement w = doc->createElement("ADR");
319 Address a = *it;
320
321 if ( a.home )
322 w.appendChild( emptyTag(doc, "HOME") );
323 if ( a.work )
324 w.appendChild( emptyTag(doc, "WORK") );
325 if ( a.postal )
326 w.appendChild( emptyTag(doc, "POSTAL") );
327 if ( a.parcel )
328 w.appendChild( emptyTag(doc, "PARCEL") );
329 if ( a.dom )
330 w.appendChild( emptyTag(doc, "DOM") );
331 if ( a.intl )
332 w.appendChild( emptyTag(doc, "INTL") );
333 if ( a.pref )
334 w.appendChild( emptyTag(doc, "PREF") );
335
336 if ( !a.pobox.isEmpty() )
337 w.appendChild( textTag(doc, "POBOX", a.pobox) );
338 if ( !a.extaddr.isEmpty() )
339 w.appendChild( textTag(doc, "EXTADR", a.extaddr) );
340 if ( !a.street.isEmpty() )
341 w.appendChild( textTag(doc, "STREET", a.street) );
342 if ( !a.locality.isEmpty() )
343 w.appendChild( textTag(doc, "LOCALITY", a.locality) );
344 if ( !a.region.isEmpty() )
345 w.appendChild( textTag(doc, "REGION", a.region) );
346 if ( !a.pcode.isEmpty() )
347 w.appendChild( textTag(doc, "PCODE", a.pcode) );
348 if ( !a.country.isEmpty() )
349 w.appendChild( textTag(doc, "CTRY", a.country) );
350
351 v.appendChild(w);
352 }
353 }
354
355 if ( !d->labelList.isEmpty() ) {
356 LabelList::Iterator it = d->labelList.begin();
357 for ( ; it != d->labelList.end(); ++it ) {
358 QDomElement w = doc->createElement("LABEL");
359 Label l = *it;
360
361 if ( l.home )
362 w.appendChild( emptyTag(doc, "HOME") );
363 if ( l.work )
364 w.appendChild( emptyTag(doc, "WORK") );
365 if ( l.postal )
366 w.appendChild( emptyTag(doc, "POSTAL") );
367 if ( l.parcel )
368 w.appendChild( emptyTag(doc, "PARCEL") );
369 if ( l.dom )
370 w.appendChild( emptyTag(doc, "DOM") );
371 if ( l.intl )
372 w.appendChild( emptyTag(doc, "INTL") );
373 if ( l.pref )
374 w.appendChild( emptyTag(doc, "PREF") );
375
376 if ( !l.lines.isEmpty() ) {
377 QStringList::Iterator it = l.lines.begin();
378 for ( ; it != l.lines.end(); ++it )
379 w.appendChild( textTag(doc, "LINE", *it) );
380 }
381
382 v.appendChild(w);
383 }
384 }
385
386 if ( !d->phoneList.isEmpty() ) {
387 PhoneList::Iterator it = d->phoneList.begin();
388 for ( ; it != d->phoneList.end(); ++it ) {
389 QDomElement w = doc->createElement("TEL");
390 Phone p = *it;
391
392 if ( p.home )
393 w.appendChild( emptyTag(doc, "HOME") );
394 if ( p.work )
395 w.appendChild( emptyTag(doc, "WORK") );
396 if ( p.voice )
397 w.appendChild( emptyTag(doc, "VOICE") );
398 if ( p.fax )
399 w.appendChild( emptyTag(doc, "FAX") );
400 if ( p.pager )
401 w.appendChild( emptyTag(doc, "PAGER") );
402 if ( p.msg )
403 w.appendChild( emptyTag(doc, "MSG") );
404 if ( p.cell )
405 w.appendChild( emptyTag(doc, "CELL") );
406 if ( p.video )
407 w.appendChild( emptyTag(doc, "VIDEO") );
408 if ( p.bbs )
409 w.appendChild( emptyTag(doc, "BBS") );
410 if ( p.modem )
411 w.appendChild( emptyTag(doc, "MODEM") );
412 if ( p.isdn )
413 w.appendChild( emptyTag(doc, "ISDN") );
414 if ( p.pcs )
415 w.appendChild( emptyTag(doc, "PCS") );
416 if ( p.pref )
417 w.appendChild( emptyTag(doc, "PREF") );
418
419 if ( !p.number.isEmpty() )
420 w.appendChild( textTag(doc, "NUMBER", p.number) );
421
422 v.appendChild(w);
423 }
424 }
425
426 if ( !d->emailList.isEmpty() ) {
427 EmailList::Iterator it = d->emailList.begin();
428 for ( ; it != d->emailList.end(); ++it ) {
429 QDomElement w = doc->createElement("EMAIL");
430 Email e = *it;
431
432 if ( e.home )
433 w.appendChild( emptyTag(doc, "HOME") );
434 if ( e.work )
435 w.appendChild( emptyTag(doc, "WORK") );
436 if ( e.internet )
437 w.appendChild( emptyTag(doc, "INTERNET") );
438 if ( e.x400 )
439 w.appendChild( emptyTag(doc, "X400") );
440
441 if ( !e.userid.isEmpty() )
442 w.appendChild( textTag(doc, "USERID", e.userid) );
443
444 v.appendChild(w);
445 }
446 }
447
448 if ( !d->jid.isEmpty() )
449 v.appendChild( textTag(doc, "JABBERID", d->jid) );
450 if ( !d->mailer.isEmpty() )
451 v.appendChild( textTag(doc, "MAILER", d->mailer) );
452 if ( !d->timezone.isEmpty() )
453 v.appendChild( textTag(doc, "TZ", d->timezone) );
454
455 if ( !d->geo.lat.isEmpty() || !d->geo.lon.isEmpty() ) {
456 QDomElement w = doc->createElement("GEO");
457
458 if ( !d->geo.lat.isEmpty() )
459 w.appendChild( textTag(doc, "LAT", d->geo.lat) );
460 if ( !d->geo.lon.isEmpty() )
461 w.appendChild( textTag(doc, "LON", d->geo.lon));
462
463 v.appendChild(w);
464 }
465
466 if ( !d->title.isEmpty() )
467 v.appendChild( textTag(doc, "TITLE", d->title) );
468 if ( !d->role.isEmpty() )
469 v.appendChild( textTag(doc, "ROLE", d->role) );
470
471 if ( !d->logo.isEmpty() || !d->logoURI.isEmpty() ) {
472 QDomElement w = doc->createElement("LOGO");
473
474 if ( !d->logo.isEmpty() ) {
475 w.appendChild( textTag(doc, "TYPE", image2type(d->logo)) );
476 w.appendChild( textTag(doc, "BINVAL", foldString( Base64::arrayToString(d->logo)) ) );
477 }
478 else if ( !d->logoURI.isEmpty() )
479 w.appendChild( textTag(doc, "EXTVAL", d->logoURI) );
480
481 v.appendChild(w);
482 }
483
484 if ( !d->agentURI.isEmpty() || (d->agent && d->agent->isEmpty()) ) {
485 QDomElement w = doc->createElement("AGENT");
486
487 if ( d->agent && !d->agent->isEmpty() )
488 w.appendChild( d->agent->toXml(doc) );
489 else if ( !d->agentURI.isEmpty() )
490 w.appendChild( textTag(doc, "EXTVAL", d->agentURI) );
491
492 v.appendChild(w);
493 }
494
495 if ( !d->org.name.isEmpty() || !d->org.unit.isEmpty() ) {
496 QDomElement w = doc->createElement("ORG");
497
498 if ( !d->org.name.isEmpty() )
499 w.appendChild( textTag(doc, "ORGNAME", d->org.name) );
500
501 if ( !d->org.unit.isEmpty() ) {
502 QStringList::Iterator it = d->org.unit.begin();
503 for ( ; it != d->org.unit.end(); ++it )
504 w.appendChild( textTag(doc, "ORGUNIT", *it) );
505 }
506
507 v.appendChild(w);
508 }
509
510 if ( !d->categories.isEmpty() ) {
511 QDomElement w = doc->createElement("CATEGORIES");
512
513 QStringList::Iterator it = d->categories.begin();
514 for ( ; it != d->categories.end(); ++it )
515 w.appendChild( textTag(doc, "KEYWORD", *it) );
516
517 v.appendChild(w);
518 }
519
520 if ( !d->note.isEmpty() )
521 v.appendChild( textTag(doc, "NOTE", d->note) );
522 if ( !d->prodId.isEmpty() )
523 v.appendChild( textTag(doc, "PRODID", d->prodId) );
524 if ( !d->rev.isEmpty() )
525 v.appendChild( textTag(doc, "REV", d->rev) );
526 if ( !d->sortString.isEmpty() )
527 v.appendChild( textTag(doc, "SORT-STRING", d->sortString) );
528
529 if ( !d->sound.isEmpty() || !d->soundURI.isEmpty() || !d->soundPhonetic.isEmpty() ) {
530 QDomElement w = doc->createElement("SOUND");
531
532 if ( !d->sound.isEmpty() )
533 w.appendChild( textTag(doc, "BINVAL", foldString( Base64::arrayToString(d->sound)) ) );
534 else if ( !d->soundURI.isEmpty() )
535 w.appendChild( textTag(doc, "EXTVAL", d->soundURI) );
536 else if ( !d->soundPhonetic.isEmpty() )
537 w.appendChild( textTag(doc, "PHONETIC", d->soundPhonetic) );
538
539 v.appendChild(w);
540 }
541
542 if ( !d->uid.isEmpty() )
543 v.appendChild( textTag(doc, "UID", d->uid) );
544 if ( !d->url.isEmpty() )
545 v.appendChild( textTag(doc, "URL", d->url) );
546 if ( !d->desc.isEmpty() )
547 v.appendChild( textTag(doc, "DESC", d->desc) );
548
549 if ( d->privacyClass != pcNone ) {
550 QDomElement w = doc->createElement("CLASS");
551
552 if ( d->privacyClass == pcPublic )
553 w.appendChild( emptyTag(doc, "PUBLIC") );
554 else if ( d->privacyClass == pcPrivate )
555 w.appendChild( emptyTag(doc, "PRIVATE") );
556 else if ( d->privacyClass == pcConfidential )
557 w.appendChild( emptyTag(doc, "CONFIDENTIAL") );
558
559 v.appendChild(w);
560 }
561
562 if ( !d->key.isEmpty() ) {
563 QDomElement w = doc->createElement("KEY");
564
565 // TODO: Justin, please check out this code
566 w.appendChild( textTag(doc, "TYPE", "text/plain")); // FIXME
567 w.appendChild( textTag(doc, "CRED", QString::fromUtf8(d->key)) ); // FIXME
568
569 v.appendChild(w);
570 }
571
572 return v;
573}
574
575bool VCard::fromXml(const QDomElement &q)
576{
577 if ( q.tagName().upper() != "VCARD" )
578 return false;
579
580 QDomNode n = q.firstChild();
581 for ( ; !n.isNull(); n = n.nextSibling() ) {
582 QDomElement i = n.toElement();
583 if ( i.isNull() )
584 continue;
585
586 QString tag = i.tagName().upper();
587
588 bool found;
589 QDomElement e;
590
591 if ( tag == "VERSION" )
592 d->version = i.text().stripWhiteSpace();
593 else if ( tag == "FN" )
594 d->fullName = i.text().stripWhiteSpace();
595 else if ( tag == "N" ) {
596 d->familyName = subTagText(i, "FAMILY");
597 d->givenName = subTagText(i, "GIVEN");
598 d->middleName = subTagText(i, "MIDDLE");
599 d->prefixName = subTagText(i, "PREFIX");
600 d->suffixName = subTagText(i, "SUFFIX");
601 }
602 else if ( tag == "NICKNAME" )
603 d->nickName = i.text().stripWhiteSpace();
604 else if ( tag == "PHOTO" ) {
605 d->photo = Base64::stringToArray( subTagText(i, "BINVAL") );
606 d->photoURI = subTagText(i, "EXTVAL");
607 }
608 else if ( tag == "BDAY" )
609 d->bday = i.text().stripWhiteSpace();
610 else if ( tag == "ADR" ) {
611 Address a;
612
613 a.home = hasSubTag(i, "HOME");
614 a.work = hasSubTag(i, "WORK");
615 a.postal = hasSubTag(i, "POSTAL");
616 a.parcel = hasSubTag(i, "PARCEL");
617 a.dom = hasSubTag(i, "DOM");
618 a.intl = hasSubTag(i, "INTL");
619 a.pref = hasSubTag(i, "PREF");
620
621 a.pobox = subTagText(i, "POBOX");
622 a.extaddr = subTagText(i, "EXTADR");
623 a.street = subTagText(i, "STREET");
624 a.locality = subTagText(i, "LOCALITY");
625 a.region = subTagText(i, "REGION");
626 a.pcode = subTagText(i, "PCODE");
627 a.country = subTagText(i, "CTRY");
628
629 if ( a.country.isEmpty() ) // FIXME: Workaround for Psi prior to 0.9
630 if ( hasSubTag(i, "COUNTRY") )
631 a.country = subTagText(i, "COUNTRY");
632
633 if ( a.extaddr.isEmpty() ) // FIXME: Workaround for Psi prior to 0.9
634 if ( hasSubTag(i, "EXTADD") )
635 a.extaddr = subTagText(i, "EXTADD");
636
637 d->addressList.append ( a );
638 }
639 else if ( tag == "LABEL" ) {
640 Label l;
641
642 l.home = hasSubTag(i, "HOME");
643 l.work = hasSubTag(i, "WORK");
644 l.postal = hasSubTag(i, "POSTAL");
645 l.parcel = hasSubTag(i, "PARCEL");
646 l.dom = hasSubTag(i, "DOM");
647 l.intl = hasSubTag(i, "INTL");
648 l.pref = hasSubTag(i, "PREF");
649
650 QDomNode nn = i.firstChild();
651 for ( ; !nn.isNull(); nn = nn.nextSibling() ) {
652 QDomElement ii = nn.toElement();
653 if ( ii.isNull() )
654 continue;
655
656 if ( ii.tagName().upper() == "LINE" )
657 l.lines.append ( ii.text().stripWhiteSpace() );
658 }
659
660 d->labelList.append ( l );
661 }
662 else if ( tag == "TEL" ) {
663 Phone p;
664
665 p.home = hasSubTag(i, "HOME");
666 p.work = hasSubTag(i, "WORK");
667 p.voice = hasSubTag(i, "VOICE");
668 p.fax = hasSubTag(i, "FAX");
669 p.pager = hasSubTag(i, "PAGER");
670 p.msg = hasSubTag(i, "MSG");
671 p.cell = hasSubTag(i, "CELL");
672 p.video = hasSubTag(i, "VIDEO");
673 p.bbs = hasSubTag(i, "BBS");
674 p.modem = hasSubTag(i, "MODEM");
675 p.isdn = hasSubTag(i, "ISDN");
676 p.pcs = hasSubTag(i, "PCS");
677 p.pref = hasSubTag(i, "PREF");
678
679 p.number = subTagText(i, "NUMBER");
680
681 if ( p.number.isEmpty() ) // FIXME: Workaround for Psi prior to 0.9
682 if ( hasSubTag(i, "VOICE") )
683 p.number = subTagText(i, "VOICE");
684
685 d->phoneList.append ( p );
686 }
687 else if ( tag == "EMAIL" ) {
688 Email m;
689
690 m.home = hasSubTag(i, "HOME");
691 m.work = hasSubTag(i, "WORK");
692 m.internet = hasSubTag(i, "INTERNET");
693 m.x400 = hasSubTag(i, "X400");
694
695 m.userid = subTagText(i, "USERID");
696
697 if ( m.userid.isEmpty() ) // FIXME: Workaround for Psi prior to 0.9
698 if ( !i.text().isEmpty() )
699 m.userid = i.text().stripWhiteSpace();
700
701 d->emailList.append ( m );
702 }
703 else if ( tag == "JABBERID" )
704 d->jid = i.text().stripWhiteSpace();
705 else if ( tag == "MAILER" )
706 d->mailer = i.text().stripWhiteSpace();
707 else if ( tag == "TZ" )
708 d->timezone = i.text().stripWhiteSpace();
709 else if ( tag == "GEO" ) {
710 d->geo.lat = subTagText(i, "LAT");
711 d->geo.lon = subTagText(i, "LON");
712 }
713 else if ( tag == "TITLE" )
714 d->title = i.text().stripWhiteSpace();
715 else if ( tag == "ROLE" )
716 d->role = i.text().stripWhiteSpace();
717 else if ( tag == "LOGO" ) {
718 d->logo = Base64::stringToArray( subTagText(i, "BINVAL") );
719 d->logoURI = subTagText(i, "EXTVAL");
720 }
721 else if ( tag == "AGENT" ) {
722 e = findSubTag(i, "VCARD", &found);
723 if ( found ) {
724 VCard a;
725 if ( a.fromXml(e) ) {
726 if ( !d->agent )
727 d->agent = new VCard;
728 *(d->agent) = a;
729 }
730 }
731
732 d->agentURI = subTagText(i, "EXTVAL");
733 }
734 else if ( tag == "ORG" ) {
735 d->org.name = subTagText(i, "ORGNAME");
736
737 QDomNode nn = i.firstChild();
738 for ( ; !nn.isNull(); nn = nn.nextSibling() ) {
739 QDomElement ii = nn.toElement();
740 if ( ii.isNull() )
741 continue;
742
743 if ( ii.tagName().upper() == "ORGUNIT" )
744 d->org.unit.append( ii.text().stripWhiteSpace() );
745 }
746 }
747 else if ( tag == "CATEGORIES") {
748 QDomNode nn = i.firstChild();
749 for ( ; !nn.isNull(); nn = nn.nextSibling() ) {
750 QDomElement ee = nn.toElement();
751 if ( ee.isNull() )
752 continue;
753
754 if ( ee.tagName().upper() == "KEYWORD" )
755 d->categories << ee.text().stripWhiteSpace();
756 }
757 }
758 else if ( tag == "NOTE" )
759 d->note = i.text().stripWhiteSpace();
760 else if ( tag == "PRODID" )
761 d->prodId = i.text().stripWhiteSpace();
762 else if ( tag == "REV" )
763 d->rev = i.text().stripWhiteSpace();
764 else if ( tag == "SORT-STRING" )
765 d->sortString = i.text().stripWhiteSpace();
766 else if ( tag == "SOUND" ) {
767 d->sound = Base64::stringToArray( subTagText(i, "BINVAL") );
768 d->soundURI = subTagText(i, "EXTVAL");
769 d->soundPhonetic = subTagText(i, "PHONETIC");
770 }
771 else if ( tag == "UID" )
772 d->uid = i.text().stripWhiteSpace();
773 else if ( tag == "URL")
774 d->url = i.text().stripWhiteSpace();
775 else if ( tag == "DESC" )
776 d->desc = i.text().stripWhiteSpace();
777 else if ( tag == "CLASS" ) {
778 if ( hasSubTag(i, "PUBLIC") )
779 d->privacyClass = pcPublic;
780 else if ( hasSubTag(i, "PRIVATE") )
781 d->privacyClass = pcPrivate;
782 else if ( hasSubTag(i, "CONFIDENTIAL") )
783 d->privacyClass = pcConfidential;
784 }
785 else if ( tag == "KEY" ) {
786 // TODO: Justin, please check out this code
787 e = findSubTag(i, "TYPE", &found);
788 QString type = "text/plain";
789 if ( found )
790 type = e.text().stripWhiteSpace();
791
792 e = findSubTag(i, "CRED", &found );
793 if ( !found )
794 e = findSubTag(i, "BINVAL", &found); // case for very clever clients ;-)
795
796 if ( found )
797 d->key = e.text().utf8(); // FIXME
798 }
799 }
800
801 return true;
802}
803
804bool VCard::isEmpty() const
805{
806 return d->isEmpty();
807}
808
809// Some constructors
810
811VCard::Address::Address()
812{
813 home = work = postal = parcel = dom = intl = pref = false;
814}
815
816VCard::Label::Label()
817{
818 home = work = postal = parcel = dom = intl = pref = false;
819}
820
821VCard::Phone::Phone()
822{
823 home = work = voice = fax = pager = msg = cell = video = bbs = modem = isdn = pcs = pref = false;
824}
825
826VCard::Email::Email()
827{
828 home = work = internet = x400 = false;
829}
830
831VCard::Geo::Geo()
832{
833}
834
835VCard::Org::Org()
836{
837}
838
839// vCard properties...
840
841const QString &VCard::version() const
842{
843 return d->version;
844}
845
846void VCard::setVersion(const QString &v)
847{
848 d->version = v;
849}
850
851const QString &VCard::fullName() const
852{
853 return d->fullName;
854}
855
856void VCard::setFullName(const QString &n)
857{
858 d->fullName = n;
859}
860
861const QString &VCard::familyName() const
862{
863 return d->familyName;
864}
865
866void VCard::setFamilyName(const QString &n)
867{
868 d->familyName = n;
869}
870
871const QString &VCard::givenName() const
872{
873 return d->givenName;
874}
875
876void VCard::setGivenName(const QString &n)
877{
878 d->givenName = n;
879}
880
881const QString &VCard::middleName() const
882{
883 return d->middleName;
884}
885
886void VCard::setMiddleName(const QString &n)
887{
888 d->middleName = n;
889}
890
891const QString &VCard::prefixName() const
892{
893 return d->prefixName;
894}
895
896void VCard::setPrefixName(const QString &p)
897{
898 d->prefixName = p;
899}
900
901const QString &VCard::suffixName() const
902{
903 return d->suffixName;
904}
905
906void VCard::setSuffixName(const QString &s)
907{
908 d->suffixName = s;
909}
910
911const QString &VCard::nickName() const
912{
913 return d->nickName;
914}
915
916void VCard::setNickName(const QString &n)
917{
918 d->nickName = n;
919}
920
921const QByteArray &VCard::photo() const
922{
923 return d->photo;
924}
925
926void VCard::setPhoto(const QByteArray &i)
927{
928 d->photo = i;
929}
930
931const QString &VCard::photoURI() const
932{
933 return d->photoURI;
934}
935
936void VCard::setPhotoURI(const QString &p)
937{
938 d->photoURI = p;
939}
940
941const QDate VCard::bday() const
942{
943 return QDate::fromString(d->bday);
944}
945
946void VCard::setBday(const QDate &date)
947{
948 d->bday = date.toString();
949}
950
951const QString &VCard::bdayStr() const
952{
953 return d->bday;
954}
955
956void VCard::setBdayStr(const QString &date)
957{
958 d->bday = date;
959}
960
961const VCard::AddressList &VCard::addressList() const
962{
963 return d->addressList;
964}
965
966void VCard::setAddressList(const VCard::AddressList &a)
967{
968 d->addressList = a;
969}
970
971const VCard::LabelList &VCard::labelList() const
972{
973 return d->labelList;
974}
975
976void VCard::setLabelList(const VCard::LabelList &l)
977{
978 d->labelList = l;
979}
980
981const VCard::PhoneList &VCard::phoneList() const
982{
983 return d->phoneList;
984}
985
986void VCard::setPhoneList(const VCard::PhoneList &p)
987{
988 d->phoneList = p;
989}
990
991const VCard::EmailList &VCard::emailList() const
992{
993 return d->emailList;
994}
995
996void VCard::setEmailList(const VCard::EmailList &e)
997{
998 d->emailList = e;
999}
1000
1001const QString &VCard::jid() const
1002{
1003 return d->jid;
1004}
1005
1006void VCard::setJid(const QString &j)
1007{
1008 d->jid = j;
1009}
1010
1011const QString &VCard::mailer() const
1012{
1013 return d->mailer;
1014}
1015
1016void VCard::setMailer(const QString &m)
1017{
1018 d->mailer = m;
1019}
1020
1021const QString &VCard::timezone() const
1022{
1023 return d->timezone;
1024}
1025
1026void VCard::setTimezone(const QString &t)
1027{
1028 d->timezone = t;
1029}
1030
1031const VCard::Geo &VCard::geo() const
1032{
1033 return d->geo;
1034}
1035
1036void VCard::setGeo(const VCard::Geo &g)
1037{
1038 d->geo = g;
1039}
1040
1041const QString &VCard::title() const
1042{
1043 return d->title;
1044}
1045
1046void VCard::setTitle(const QString &t)
1047{
1048 d->title = t;
1049}
1050
1051const QString &VCard::role() const
1052{
1053 return d->role;
1054}
1055
1056void VCard::setRole(const QString &r)
1057{
1058 d->role = r;
1059}
1060
1061const QByteArray &VCard::logo() const
1062{
1063 return d->logo;
1064}
1065
1066void VCard::setLogo(const QByteArray &i)
1067{
1068 d->logo = i;
1069}
1070
1071const QString &VCard::logoURI() const
1072{
1073 return d->logoURI;
1074}
1075
1076void VCard::setLogoURI(const QString &l)
1077{
1078 d->logoURI = l;
1079}
1080
1081const VCard *VCard::agent() const
1082{
1083 return d->agent;
1084}
1085
1086void VCard::setAgent(const VCard &v)
1087{
1088 if ( !d->agent )
1089 d->agent = new VCard;
1090 *(d->agent) = v;
1091}
1092
1093const QString VCard::agentURI() const
1094{
1095 return d->agentURI;
1096}
1097
1098void VCard::setAgentURI(const QString &a)
1099{
1100 d->agentURI = a;
1101}
1102
1103const VCard::Org &VCard::org() const
1104{
1105 return d->org;
1106}
1107
1108void VCard::setOrg(const VCard::Org &o)
1109{
1110 d->org = o;
1111}
1112
1113const QStringList &VCard::categories() const
1114{
1115 return d->categories;
1116}
1117
1118void VCard::setCategories(const QStringList &c)
1119{
1120 d->categories = c;
1121}
1122
1123const QString &VCard::note() const
1124{
1125 return d->note;
1126}
1127
1128void VCard::setNote(const QString &n)
1129{
1130 d->note = n;
1131}
1132
1133const QString &VCard::prodId() const
1134{
1135 return d->prodId;
1136}
1137
1138void VCard::setProdId(const QString &p)
1139{
1140 d->prodId = p;
1141}
1142
1143const QString &VCard::rev() const
1144{
1145 return d->rev;
1146}
1147
1148void VCard::setRev(const QString &r)
1149{
1150 d->rev = r;
1151}
1152
1153const QString &VCard::sortString() const
1154{
1155 return d->sortString;
1156}
1157
1158void VCard::setSortString(const QString &s)
1159{
1160 d->sortString = s;
1161}
1162
1163const QByteArray &VCard::sound() const
1164{
1165 return d->sound;
1166}
1167
1168void VCard::setSound(const QByteArray &s)
1169{
1170 d->sound = s;
1171}
1172
1173const QString &VCard::soundURI() const
1174{
1175 return d->soundURI;
1176}
1177
1178void VCard::setSoundURI(const QString &s)
1179{
1180 d->soundURI = s;
1181}
1182
1183const QString &VCard::soundPhonetic() const
1184{
1185 return d->soundPhonetic;
1186}
1187
1188void VCard::setSoundPhonetic(const QString &s)
1189{
1190 d->soundPhonetic = s;
1191}
1192
1193const QString &VCard::uid() const
1194{
1195 return d->uid;
1196}
1197
1198void VCard::setUid(const QString &u)
1199{
1200 d->uid = u;
1201}
1202
1203const QString &VCard::url() const
1204{
1205 return d->url;
1206}
1207
1208void VCard::setUrl(const QString &u)
1209{
1210 d->url = u;
1211}
1212
1213const QString &VCard::desc() const
1214{
1215 return d->desc;
1216}
1217
1218void VCard::setDesc(const QString &desc)
1219{
1220 d->desc = desc;
1221}
1222
1223const VCard::PrivacyClass &VCard::privacyClass() const
1224{
1225 return d->privacyClass;
1226}
1227
1228void VCard::setPrivacyClass(const VCard::PrivacyClass &c)
1229{
1230 d->privacyClass = c;
1231}
1232
1233const QByteArray &VCard::key() const
1234{
1235 return d->key;
1236}
1237
1238void VCard::setKey(const QByteArray &k)
1239{
1240 d->key = k;
1241}
Note: See TracBrowser for help on using the repository browser.