~ubuntu-branches/ubuntu/quantal/psi/quantal

« back to all changes in this revision

Viewing changes to iris/src/xmpp/xmpp-im/xmpp_vcard.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Jan Niehusmann
  • Date: 2009-09-25 17:49:51 UTC
  • mfrom: (6.1.3 sid)
  • Revision ID: james.westby@ubuntu.com-20090925174951-lvm7kdap82o8xhn3
Tags: 0.13-1
* Updated to upstream version 0.13
* Set Standards-Version to 3.8.3

Show diffs side-by-side

added added

removed removed

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