• Skip to content
  • Skip to link menu
KDE API Reference
  • KDE API Reference
  • kdepimlibs API Reference
  • KDE Home
  • Contact Us
 

kabc

  • sources
  • kde-4.14
  • kdepimlibs
  • kabc
vcardtool.cpp
1 /*
2  This file is part of libkabc.
3  Copyright (c) 2003 Tobias Koenig <tokoe@kde.org>
4  Copyright (c) 2015 Laurent Montel <montel@kde.org>
5 
6  This library is free software; you can redistribute it and/or
7  modify it under the terms of the GNU Library General Public
8  License as published by the Free Software Foundation; either
9  version 2 of the License, or (at your option) any later version.
10 
11  This library is distributed in the hope that it will be useful,
12  but WITHOUT ANY WARRANTY; without even the implied warranty of
13  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14  Library General Public License for more details.
15 
16  You should have received a copy of the GNU Library General Public License
17  along with this library; see the file COPYING.LIB. If not, write to
18  the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19  Boston, MA 02110-1301, USA.
20 */
21 
22 #include "vcardtool.h"
23 #include "key.h"
24 #include "picture.h"
25 #include "secrecy.h"
26 #include "sound.h"
27 #include "lang.h"
28 #include "gender.h"
29 
30 #include <QtCore/QString>
31 #include <QtCore/QBuffer>
32 #include <QDebug>
33 
34 using namespace KABC;
35 
36 static bool needsEncoding( const QString &value )
37 {
38  uint length = value.length();
39  for ( uint i = 0; i < length; ++i ) {
40  char c = value.at( i ).toLatin1();
41  if ( ( c < 33 || c > 126 ) && c != ' ' && c != '=' ) {
42  return true;
43  }
44  }
45 
46  return false;
47 }
48 
49 VCardTool::VCardTool()
50 {
51  mAddressTypeMap.insert( QLatin1String( "dom" ), Address::Dom );
52  mAddressTypeMap.insert( QLatin1String( "intl" ), Address::Intl );
53  mAddressTypeMap.insert( QLatin1String( "postal" ), Address::Postal );
54  mAddressTypeMap.insert( QLatin1String( "parcel" ), Address::Parcel );
55  mAddressTypeMap.insert( QLatin1String( "home" ), Address::Home );
56  mAddressTypeMap.insert( QLatin1String( "work" ), Address::Work );
57  mAddressTypeMap.insert( QLatin1String( "pref" ), Address::Pref );
58 
59  mPhoneTypeMap.insert( QLatin1String( "HOME" ), PhoneNumber::Home );
60  mPhoneTypeMap.insert( QLatin1String( "WORK" ), PhoneNumber::Work );
61  mPhoneTypeMap.insert( QLatin1String( "MSG" ), PhoneNumber::Msg );
62  mPhoneTypeMap.insert( QLatin1String( "PREF" ), PhoneNumber::Pref );
63  mPhoneTypeMap.insert( QLatin1String( "VOICE" ), PhoneNumber::Voice );
64  mPhoneTypeMap.insert( QLatin1String( "FAX" ), PhoneNumber::Fax );
65  mPhoneTypeMap.insert( QLatin1String( "CELL" ), PhoneNumber::Cell );
66  mPhoneTypeMap.insert( QLatin1String( "VIDEO" ), PhoneNumber::Video );
67  mPhoneTypeMap.insert( QLatin1String( "BBS" ), PhoneNumber::Bbs );
68  mPhoneTypeMap.insert( QLatin1String( "MODEM" ), PhoneNumber::Modem );
69  mPhoneTypeMap.insert( QLatin1String( "CAR" ), PhoneNumber::Car );
70  mPhoneTypeMap.insert( QLatin1String( "ISDN" ), PhoneNumber::Isdn );
71  mPhoneTypeMap.insert( QLatin1String( "PCS" ), PhoneNumber::Pcs );
72  mPhoneTypeMap.insert( QLatin1String( "PAGER" ), PhoneNumber::Pager );
73 }
74 
75 VCardTool::~VCardTool()
76 {
77 }
78 
79 QByteArray VCardTool::exportVCards( const Addressee::List &list, VCard::Version version ) const
80 {
81  return createVCards( list, version, true /*export vcard*/);
82 }
83 
84 QByteArray VCardTool::createVCards( const Addressee::List &list, VCard::Version version ) const
85 {
86  return createVCards( list, version, false /*don't export*/);
87 }
88 
89 void VCardTool::addParameter(VCardLine &line, VCard::Version version, const QString &key, const QStringList &valueStringList) const
90 {
91  if (version == VCard::v2_1) {
92  Q_FOREACH(const QString &valueStr, valueStringList) {
93  line.addParameter( valueStr, QString() );
94  }
95  } else {
96  line.addParameter( key, valueStringList.join(QLatin1String(",")) );
97  }
98 }
99 
100 QByteArray VCardTool::createVCards( const Addressee::List &list,
101  VCard::Version version, bool exportVcard ) const
102 {
103  VCard::List vCardList;
104 
105  Addressee::List::ConstIterator addrIt;
106  Addressee::List::ConstIterator listEnd( list.constEnd() );
107  for ( addrIt = list.constBegin(); addrIt != listEnd; ++addrIt ) {
108  VCard card;
109  QStringList::ConstIterator strIt;
110 
111  // ADR + LABEL
112  const Address::List addresses = ( *addrIt ).addresses();
113  for ( Address::List::ConstIterator it = addresses.begin(); it != addresses.end(); ++it ) {
114  QStringList address;
115 
116  const bool isEmpty = ( ( *it ).postOfficeBox().isEmpty() &&
117  ( *it ).extended().isEmpty() &&
118  ( *it ).street().isEmpty() &&
119  ( *it ).locality().isEmpty() &&
120  ( *it ).region().isEmpty() &&
121  ( *it ).postalCode().isEmpty() &&
122  ( *it ).country().isEmpty() );
123 
124  address.append( ( *it ).postOfficeBox().replace( QLatin1Char( ';' ),
125  QLatin1String( "\\;" ) ) );
126 
127  address.append( ( *it ).extended().replace( QLatin1Char( ';' ),
128  QLatin1String( "\\;" ) ) );
129 
130  address.append( ( *it ).street().replace( QLatin1Char( ';' ),
131  QLatin1String( "\\;" ) ) );
132 
133  address.append( ( *it ).locality().replace( QLatin1Char( ';' ),
134  QLatin1String( "\\;" ) ) );
135 
136  address.append( ( *it ).region().replace( QLatin1Char( ';' ),
137  QLatin1String( "\\;" ) ) );
138 
139  address.append( ( *it ).postalCode().replace( QLatin1Char( ';' ),
140  QLatin1String( "\\;" ) ) );
141 
142  address.append( ( *it ).country().replace( QLatin1Char( ';' ),
143  QLatin1String( "\\;" ) ) );
144 
145  VCardLine adrLine( QLatin1String( "ADR" ), address.join( QLatin1String( ";" ) ) );
146  if ( version == VCard::v2_1 && needsEncoding( address.join( QLatin1String( ";" ) ) ) ) {
147  adrLine.addParameter( QLatin1String( "charset" ), QLatin1String( "UTF-8" ) );
148  adrLine.addParameter( QLatin1String( "encoding" ), QLatin1String( "QUOTED-PRINTABLE" ) );
149  }
150 
151  VCardLine labelLine( QLatin1String( "LABEL" ), ( *it ).label() );
152  if ( version == VCard::v2_1 && needsEncoding( ( *it ).label() ) ) {
153  labelLine.addParameter( QLatin1String( "charset" ), QLatin1String( "UTF-8" ) );
154  labelLine.addParameter( QLatin1String( "encoding" ), QLatin1String( "QUOTED-PRINTABLE" ) );
155  }
156 
157  const bool hasLabel = !( *it ).label().isEmpty();
158  QMap<QString, Address::TypeFlag>::ConstIterator typeIt;
159  for ( typeIt = mAddressTypeMap.constBegin();
160  typeIt != mAddressTypeMap.constEnd(); ++typeIt ) {
161  if ( typeIt.value() & ( *it ).type() ) {
162  addParameter(adrLine, version, QLatin1String( "TYPE" ), QStringList()<<typeIt.key());
163  if ( hasLabel ) {
164  addParameter(labelLine, version, QLatin1String( "TYPE" ), QStringList()<<typeIt.key());
165  }
166  }
167  }
168 
169  if ( !isEmpty ) {
170  card.addLine( adrLine );
171  }
172  if ( hasLabel ) {
173  card.addLine( labelLine );
174  }
175  }
176 
177  // BDAY
178  card.addLine( VCardLine( QLatin1String( "BDAY" ), createDateTime( ( *addrIt ).birthday() ) ) );
179 
180  //Laurent: 31 Jan 2015. Not necessary to export it. When Categories were changes as AkonadiTag nobody thought that it was break categorie support...
181  //=> not necessary to export just tag...
182  // CATEGORIES only > 2.1
183  if (!exportVcard) {
184  if ( version != VCard::v2_1 ) {
185  QStringList categories = ( *addrIt ).categories();
186  QStringList::Iterator catIt;
187  QStringList::Iterator catEnd( categories.end() );
188  for ( catIt = categories.begin(); catIt != catEnd; ++catIt ) {
189  ( *catIt ).replace( QLatin1Char( ',' ), QLatin1String( "\\," ) );
190  }
191 
192  VCardLine catLine( QLatin1String( "CATEGORIES" ), categories.join( QLatin1String( "," ) ) );
193  card.addLine( catLine );
194  }
195  }
196 
197  // MEMBER (only in 4.0)
198  if ( version == VCard::v4_0) {
199  // The KIND property must be set to "group" in order to use this property.
200  if (( *addrIt ).kind().toLower() == QLatin1String("group")) {
201  Q_FOREACH (const QString &member, ( *addrIt ).members() ) {
202  VCardLine line( QLatin1String( "MEMBER" ), member );
203  card.addLine( line );
204  }
205  }
206  }
207 
208  // SOURCE
209  Q_FOREACH (const KUrl &url, ( *addrIt ).sourcesUrlList()) {
210  VCardLine line = VCardLine( QLatin1String( "SOURCE" ), url.url() );
211  card.addLine( line );
212  }
213 
214  // RELATED
215  if (version == VCard::v4_0) {
216  Q_FOREACH (const QString &relation, ( *addrIt ).relationShips() ) {
217  VCardLine line( QLatin1String( "RELATED" ), relation );
218  card.addLine( line );
219  }
220  }
221  // CLASS only for version == 3.0
222  if ( version == VCard::v3_0 ) {
223  card.addLine( createSecrecy( ( *addrIt ).secrecy() ) );
224  }
225 
226  // LANG only for version == 4.0
227  if ( version == VCard::v4_0 ) {
228  const Lang::List langList = ( *addrIt ).langs();
229  Lang::List::ConstIterator langIt;
230  Lang::List::ConstIterator langEnd( langList.end() );
231  for ( langIt = langList.begin(); langIt != langEnd; ++langIt ) {
232  VCardLine line( QLatin1String( "LANG" ), (*langIt).language() );
233  QMapIterator<QString, QStringList> i((*langIt).parameters());
234  while (i.hasNext()) {
235  i.next();
236  line.addParameter( i.key(), i.value().join(QLatin1String(",")) );
237  }
238  card.addLine( line );
239  }
240  }
241  // EMAIL
242  const Email::List emailList = ( *addrIt ).emailList();
243  Email::List::ConstIterator emailIt;
244  Email::List::ConstIterator emailEnd( emailList.end() );
245  bool pref = true;
246 
247  for ( emailIt = emailList.begin(); emailIt != emailEnd; ++emailIt ) {
248  bool needToAddPref = false;
249  VCardLine line( QLatin1String( "EMAIL" ), (*emailIt).mail() );
250  if ( pref == true && emailList.count() > 1 ) {
251  needToAddPref = true;
252  pref = false;
253  }
254  QMapIterator<QString, QStringList> i((*emailIt).parameters());
255  bool foundType = false;
256  while (i.hasNext()) {
257  i.next();
258  QStringList valueStringList = i.value();
259  if (i.key().toLower() == QLatin1String( "type" )) {
260  if (!valueStringList.contains(QLatin1String("PREF"))) {
261  if (needToAddPref) {
262  valueStringList.append(QLatin1String( "PREF" ));
263  } else {
264  needToAddPref = false;
265  }
266  } else {
267  if (!needToAddPref) {
268  valueStringList.removeAll(QLatin1String( "PREF" ));
269  }
270  }
271  foundType = true;
272  }
273  if (!valueStringList.isEmpty()) {
274  if (i.key().toLower() == QLatin1String( "type" )) {
275  addParameter(line, version, i.key(), valueStringList);
276  } else {
277  line.addParameter( i.key(), valueStringList.join(QLatin1String(",")) );
278  }
279  }
280  }
281  if (!foundType && needToAddPref) {
282  if (version == VCard::v2_1) {
283  line.addParameter( QLatin1String( "PREF" ), QString() );
284  } else {
285  line.addParameter( QLatin1String( "TYPE" ), QLatin1String( "PREF" ) );
286  }
287  }
288  card.addLine( line );
289  }
290 
291  // FN required for only version > 2.1
292  VCardLine fnLine( QLatin1String( "FN" ), ( *addrIt ).formattedName() );
293  if ( version == VCard::v2_1 && needsEncoding( ( *addrIt ).formattedName() ) ) {
294  fnLine.addParameter( QLatin1String( "charset" ), QLatin1String( "UTF-8" ) );
295  fnLine.addParameter( QLatin1String( "encoding" ), QLatin1String( "QUOTED-PRINTABLE" ) );
296  }
297  card.addLine( fnLine );
298 
299  // GEO
300  const Geo geo = ( *addrIt ).geo();
301  if ( geo.isValid() ) {
302  QString str;
303  if (version == VCard::v4_0 ) {
304  str.sprintf( "geo:%.6f,%.6f", geo.latitude(), geo.longitude() );
305  } else {
306  str.sprintf( "%.6f;%.6f", geo.latitude(), geo.longitude() );
307  }
308  card.addLine( VCardLine( QLatin1String( "GEO" ), str ) );
309  }
310 
311  // KEY
312  const Key::List keys = ( *addrIt ).keys();
313  Key::List::ConstIterator keyIt;
314  Key::List::ConstIterator keyEnd( keys.end() );
315  for ( keyIt = keys.begin(); keyIt != keyEnd; ++keyIt ) {
316  card.addLine( createKey( *keyIt, version ) );
317  }
318 
319  // LOGO
320  card.addLine( createPicture( QLatin1String( "LOGO" ), ( *addrIt ).logo(), version ) );
321  Q_FOREACH (const KABC::Picture &logo, ( *addrIt ).extraLogoList()) {
322  card.addLine( createPicture( QLatin1String( "LOGO" ), logo, version ) );
323  }
324 
325  // MAILER only for version < 4.0
326  if ( version != VCard::v4_0 ) {
327  VCardLine mailerLine( QLatin1String( "MAILER" ), ( *addrIt ).mailer() );
328  if ( version == VCard::v2_1 && needsEncoding( ( *addrIt ).mailer() ) ) {
329  mailerLine.addParameter( QLatin1String( "charset" ), QLatin1String( "UTF-8" ) );
330  mailerLine.addParameter( QLatin1String( "encoding" ), QLatin1String( "QUOTED-PRINTABLE" ) );
331  }
332  card.addLine( mailerLine );
333  }
334 
335  // N required for only version < 4.0
336  QStringList name;
337  name.append( ( *addrIt ).familyName().replace( QLatin1Char( ';' ),
338  QLatin1String( "\\;" ) ) );
339 
340  name.append( ( *addrIt ).givenName().replace( QLatin1Char( ';' ),
341  QLatin1String( "\\;" ) ) );
342 
343  name.append( ( *addrIt ).additionalName().replace( QLatin1Char( ';' ),
344  QLatin1String( "\\;" ) ) );
345 
346  name.append( ( *addrIt ).prefix().replace( QLatin1Char( ';' ),
347  QLatin1String( "\\;" ) ) );
348 
349  name.append( ( *addrIt ).suffix().replace( QLatin1Char( ';' ),
350  QLatin1String( "\\;" ) ) );
351 
352  VCardLine nLine( QLatin1String( "N" ), name.join( QLatin1String( ";" ) ) );
353  if ( version == VCard::v2_1 && needsEncoding( name.join( QLatin1String( ";" ) ) ) ) {
354  nLine.addParameter( QLatin1String( "charset" ), QLatin1String( "UTF-8" ) );
355  nLine.addParameter( QLatin1String( "encoding" ), QLatin1String( "QUOTED-PRINTABLE" ) );
356  }
357  if ( version == VCard::v4_0 && !( *addrIt ).sortString().isEmpty() ) {
358  nLine.addParameter( QLatin1String( "SORT-AS" ), ( *addrIt ).sortString() );
359  }
360 
361  card.addLine( nLine );
362 
363  // NAME only for version < 4.0
364  if ( version != VCard::v4_0 ) {
365  VCardLine nameLine( QLatin1String( "NAME" ), ( *addrIt ).name() );
366  if ( version == VCard::v2_1 && needsEncoding( ( *addrIt ).name() ) ) {
367  nameLine.addParameter( QLatin1String( "charset" ), QLatin1String( "UTF-8" ) );
368  nameLine.addParameter( QLatin1String( "encoding" ), QLatin1String( "QUOTED-PRINTABLE" ) );
369  }
370  card.addLine( nameLine );
371  }
372 
373  // NICKNAME only for version > 2.1
374  if ( version != VCard::v2_1 ) {
375  card.addLine( VCardLine( QLatin1String( "NICKNAME" ), ( *addrIt ).nickName() ) );
376  }
377 
378  // NOTE
379  VCardLine noteLine( QLatin1String( "NOTE" ), ( *addrIt ).note() );
380  if ( version == VCard::v2_1 && needsEncoding( ( *addrIt ).note() ) ) {
381  noteLine.addParameter( QLatin1String( "charset" ), QLatin1String( "UTF-8" ) );
382  noteLine.addParameter( QLatin1String( "encoding" ), QLatin1String( "QUOTED-PRINTABLE" ) );
383  }
384  card.addLine( noteLine );
385 
386  // ORG
387  QStringList organization;
388  organization.append( ( *addrIt ).organization().replace( QLatin1Char( ';' ),
389  QLatin1String( "\\;" ) ) );
390  if ( !( *addrIt ).department().isEmpty() ) {
391  organization.append( ( *addrIt ).department().replace( QLatin1Char( ';' ),
392  QLatin1String( "\\;" ) ) );
393  }
394  VCardLine orgLine( QLatin1String( "ORG" ), organization.join( QLatin1String( ";" ) ) );
395  if ( version == VCard::v2_1 && needsEncoding( organization.join( QLatin1String( ";" ) ) ) ) {
396  orgLine.addParameter( QLatin1String( "charset" ), QLatin1String( "UTF-8" ) );
397  orgLine.addParameter( QLatin1String( "encoding" ), QLatin1String( "QUOTED-PRINTABLE" ) );
398  }
399  card.addLine( orgLine );
400 
401  // PHOTO
402  card.addLine( createPicture( QLatin1String( "PHOTO" ), ( *addrIt ).photo(), version ) );
403  Q_FOREACH (const KABC::Picture &photo, ( *addrIt ).extraPhotoList()) {
404  card.addLine( createPicture( QLatin1String( "PHOTO" ), photo, version ) );
405  }
406 
407  // PROID only for version > 2.1
408  if ( version != VCard::v2_1 ) {
409  card.addLine( VCardLine( QLatin1String( "PRODID" ), ( *addrIt ).productId() ) );
410  }
411 
412  // REV
413  card.addLine( VCardLine( QLatin1String( "REV" ), createDateTime( ( *addrIt ).revision() ) ) );
414 
415  // ROLE
416  VCardLine roleLine( QLatin1String( "ROLE" ), ( *addrIt ).role() );
417  if ( version == VCard::v2_1 && needsEncoding( ( *addrIt ).role() ) ) {
418  roleLine.addParameter( QLatin1String( "charset" ), QLatin1String( "UTF-8" ) );
419  roleLine.addParameter( QLatin1String( "encoding" ), QLatin1String( "QUOTED-PRINTABLE" ) );
420  }
421  card.addLine( roleLine );
422 
423  // SORT-STRING
424  if ( version == VCard::v3_0 ) {
425  card.addLine( VCardLine( QLatin1String( "SORT-STRING" ), ( *addrIt ).sortString() ) );
426  }
427 
428  // SOUND
429  card.addLine( createSound( ( *addrIt ).sound(), version ) );
430  Q_FOREACH (const KABC::Sound &sound, ( *addrIt ).extraSoundList()) {
431  card.addLine( createSound( sound, version ) );
432  }
433 
434  // TEL
435  const PhoneNumber::List phoneNumbers = ( *addrIt ).phoneNumbers();
436  PhoneNumber::List::ConstIterator phoneIt;
437  PhoneNumber::List::ConstIterator phoneEnd( phoneNumbers.end() );
438  for ( phoneIt = phoneNumbers.begin(); phoneIt != phoneEnd; ++phoneIt ) {
439  VCardLine line( QLatin1String( "TEL" ), ( *phoneIt ).number() );
440 
441  QMap<QString, PhoneNumber::TypeFlag>::ConstIterator typeIt;
442  QMap<QString, PhoneNumber::TypeFlag>::ConstIterator typeEnd( mPhoneTypeMap.constEnd() );
443  for ( typeIt = mPhoneTypeMap.constBegin(); typeIt != typeEnd; ++typeIt ) {
444  if ( typeIt.value() & ( *phoneIt ).type() ) {
445  addParameter(line, version, QLatin1String( "TYPE" ), QStringList()<<typeIt.key());
446  }
447  }
448 
449  card.addLine( line );
450  }
451 
452  // TITLE
453  VCardLine titleLine( QLatin1String( "TITLE" ), ( *addrIt ).title() );
454  if ( version == VCard::v2_1 && needsEncoding( ( *addrIt ).title() ) ) {
455  titleLine.addParameter( QLatin1String( "charset" ), QLatin1String( "UTF-8" ) );
456  titleLine.addParameter( QLatin1String( "encoding" ), QLatin1String( "QUOTED-PRINTABLE" ) );
457  }
458  card.addLine( titleLine );
459 
460  // TZ
461  // TODO Add vcard4.0 support
462  const TimeZone timeZone = ( *addrIt ).timeZone();
463  if ( timeZone.isValid() ) {
464  QString str;
465 
466  int neg = 1;
467  if ( timeZone.offset() < 0 ) {
468  neg = -1;
469  }
470 
471  str.sprintf( "%c%02d:%02d", ( timeZone.offset() >= 0 ? '+' : '-' ),
472  ( timeZone.offset() / 60 ) * neg,
473  ( timeZone.offset() % 60 ) * neg );
474 
475  card.addLine( VCardLine( QLatin1String( "TZ" ), str ) );
476  }
477 
478  // UID
479  card.addLine( VCardLine( QLatin1String( "UID" ), ( *addrIt ).uid() ) );
480 
481  // URL
482  card.addLine( VCardLine( QLatin1String( "URL" ), ( *addrIt ).url().url() ) );
483  Q_FOREACH (const KUrl &url, ( *addrIt ).extraUrlList()) {
484  VCardLine line = VCardLine( QLatin1String( "URL" ), url.url() );
485  card.addLine( line );
486  }
487 
488  // VERSION
489  if ( version == VCard::v2_1 ) {
490  card.addLine( VCardLine( QLatin1String( "VERSION" ), QLatin1String( "2.1" ) ) );
491  } else if ( version == VCard::v3_0 ) {
492  card.addLine( VCardLine( QLatin1String( "VERSION" ), QLatin1String( "3.0" ) ) );
493  } else if ( version == VCard::v4_0 ) {
494  card.addLine( VCardLine( QLatin1String( "VERSION" ), QLatin1String( "4.0" ) ) );
495  }
496 
497  // X-
498  const QStringList customs = ( *addrIt ).customs();
499  for ( strIt = customs.begin(); strIt != customs.end(); ++strIt ) {
500  QString identifier = QLatin1String( "X-" ) +
501  ( *strIt ).left( ( *strIt ).indexOf( QLatin1Char( ':' ) ) );
502  const QString value = ( *strIt ).mid( ( *strIt ).indexOf( QLatin1Char( ':' ) ) + 1 );
503  if ( value.isEmpty() ) {
504  continue;
505  }
506  //Convert to standard identifier
507  if ( exportVcard ) {
508  if ( identifier == QLatin1String( "X-messaging/aim-All" ) ) {
509  identifier = QLatin1String( "X-AIM" );
510  } else if ( identifier == QLatin1String( "X-messaging/icq-All" ) ) {
511  identifier = QLatin1String( "X-ICQ" );
512  } else if ( identifier == QLatin1String( "X-messaging/xmpp-All" ) ) {
513  identifier = QLatin1String( "X-JABBER" );
514  } else if ( identifier == QLatin1String( "X-messaging/msn-All" ) ) {
515  identifier = QLatin1String( "X-MSN" );
516  } else if ( identifier == QLatin1String( "X-messaging/yahoo-All" ) ) {
517  identifier = QLatin1String( "X-YAHOO" );
518  } else if ( identifier == QLatin1String( "X-messaging/gadu-All" ) ) {
519  identifier = QLatin1String( "X-GADUGADU" );
520  } else if ( identifier == QLatin1String( "X-messaging/skype-All" ) ) {
521  identifier = QLatin1String( "X-SKYPE" );
522  } else if ( identifier == QLatin1String( "X-messaging/groupwise-All" ) ) {
523  identifier = QLatin1String( "X-GROUPWISE" );
524  } else if ( identifier == QLatin1String( "X-messaging/sms-All" ) ) {
525  identifier = QLatin1String( "X-SMS" );
526  } else if ( identifier == QLatin1String( "X-messaging/meanwhile-All" ) ) {
527  identifier = QLatin1String( "X-MEANWHILE" );
528  } else if ( identifier == QLatin1String( "X-messaging/irc-All" ) ) {
529  identifier = QLatin1String( "X-IRC" ); //Not defined by rfc but need for fixing #300869
530  } else if ( identifier == QLatin1String( "X-messaging/googletalk-All" ) ) {
531  //Not defined by rfc but need for fixing #300869
532  identifier = QLatin1String( "X-GTALK" );
533  }
534  }
535 
536  if (version == VCard::v4_0) {
537  // GENDER
538  const Gender gender = ( *addrIt ).gender();
539  if (gender.isValid()) {
540  QString genderStr;
541  if (!gender.gender().isEmpty()) {
542  genderStr = gender.gender();
543  }
544  if (!gender.comment().isEmpty()) {
545  genderStr += QLatin1Char(';') + gender.comment();
546  }
547  VCardLine line( QLatin1String( "GENDER" ), genderStr );
548  card.addLine( line );
549  }
550  // KIND
551  if (!( *addrIt ).kind().isEmpty()) {
552  VCardLine line( QLatin1String( "KIND" ), ( *addrIt ).kind() );
553  card.addLine(line);
554  }
555  }
556  if (identifier.toLower() == QLatin1String( "x-kaddressbook-x-anniversary" ) && version == VCard::v4_0) {
557  // ANNIVERSARY
558  if (!value.isEmpty()) {
559  const QDate date = QDate::fromString( value, Qt::ISODate );
560  QDateTime dt = QDateTime(date);
561  dt.setTime(QTime());
562  card.addLine( VCardLine( QLatin1String( "ANNIVERSARY" ), createDateTime( dt ) ) );
563  }
564  } else {
565  VCardLine line( identifier, value );
566  if ( version == VCard::v2_1 && needsEncoding( value ) ) {
567  line.addParameter( QLatin1String( "charset" ), QLatin1String( "UTF-8" ) );
568  line.addParameter( QLatin1String( "encoding" ), QLatin1String( "QUOTED-PRINTABLE" ) );
569  }
570  card.addLine( line );
571  }
572  }
573 
574  vCardList.append( card );
575  }
576 
577  return VCardParser::createVCards( vCardList );
578 }
579 
580 Addressee::List VCardTool::parseVCards( const QByteArray &vcard ) const
581 {
582  static const QLatin1Char semicolonSep( ';' );
583  static const QLatin1Char commaSep( ',' );
584  QString identifier;
585 
586  Addressee::List addrList;
587  const VCard::List vCardList = VCardParser::parseVCards( vcard );
588 
589  VCard::List::ConstIterator cardIt;
590  VCard::List::ConstIterator listEnd( vCardList.end() );
591  for ( cardIt = vCardList.begin(); cardIt != listEnd; ++cardIt ) {
592  Addressee addr;
593 
594  const QStringList idents = ( *cardIt ).identifiers();
595  QStringList::ConstIterator identIt;
596  QStringList::ConstIterator identEnd( idents.end() );
597  for ( identIt = idents.begin(); identIt != identEnd; ++identIt ) {
598  const VCardLine::List lines = ( *cardIt ).lines( ( *identIt ) );
599  VCardLine::List::ConstIterator lineIt;
600 
601  // iterate over the lines
602  for ( lineIt = lines.begin(); lineIt != lines.end(); ++lineIt ) {
603  identifier = ( *lineIt ).identifier().toLower();
604  // ADR
605  if ( identifier == QLatin1String( "adr" ) ) {
606  Address address;
607  const QStringList addrParts = splitString( semicolonSep, ( *lineIt ).value().toString() );
608  if ( addrParts.count() > 0 ) {
609  address.setPostOfficeBox( addrParts.at(0) );
610  }
611  if ( addrParts.count() > 1 ) {
612  address.setExtended( addrParts.at(1) );
613  }
614  if ( addrParts.count() > 2 ) {
615  address.setStreet( addrParts.at(2) );
616  }
617  if ( addrParts.count() > 3 ) {
618  address.setLocality( addrParts.at(3) );
619  }
620  if ( addrParts.count() > 4 ) {
621  address.setRegion( addrParts.at(4) );
622  }
623  if ( addrParts.count() > 5 ) {
624  address.setPostalCode( addrParts.at(5) );
625  }
626  if ( addrParts.count() > 6 ) {
627  address.setCountry( addrParts.at(6) );
628  }
629 
630  Address::Type type;
631 
632  const QStringList types = ( *lineIt ).parameters( QLatin1String( "type" ) );
633  QStringList::ConstIterator end(types.end());
634  for ( QStringList::ConstIterator it = types.begin(); it != end; ++it ) {
635  type |= mAddressTypeMap[ ( *it ).toLower() ];
636  }
637 
638  address.setType( type );
639  if ( !( *lineIt ).parameter( QLatin1String( "label" ) ).isEmpty() ) {
640  address.setLabel( ( *lineIt ).parameter( QLatin1String( "label" ) ) );
641  }
642  addr.insertAddress( address );
643  }
644 
645  // BDAY
646  else if ( identifier == QLatin1String( "bday" ) ) {
647  addr.setBirthday( parseDateTime( ( *lineIt ).value().toString() ) );
648  }
649  // ANNIVERSARY
650  else if ( identifier == QLatin1String( "anniversary" ) ) {
651  const QString t = ( *lineIt ).value().toString();
652  const QDateTime dt(parseDateTime( t ));
653  addr.insertCustom( QLatin1String("KADDRESSBOOK"), QLatin1String("X-Anniversary"), dt.date().toString(Qt::ISODate) );
654  }
655  // CATEGORIES
656  else if ( identifier == QLatin1String( "categories" ) ) {
657  const QStringList categories = splitString( commaSep, ( *lineIt ).value().toString() );
658  addr.setCategories( categories );
659  }
660  // FBURL
661  else if (identifier == QLatin1String( "fburl" ) ) {
662  CalendarUrl calendarUrl(CalendarUrl::FBUrl);
663  //TODO extract emails
664  addr.insertCalendarUrl(calendarUrl);
665  }
666  // CALADRURI
667  else if (identifier == QLatin1String( "caladruri" ) ) {
668  CalendarUrl calendarUrl(CalendarUrl::CALADRUri);
669  //TODO extract emails
670  addr.insertCalendarUrl(calendarUrl);
671  }
672  // CALURI
673  else if (identifier == QLatin1String( "caluri" ) ) {
674  CalendarUrl calendarUrl(CalendarUrl::CALUri);
675  //TODO extract emails
676  addr.insertCalendarUrl(calendarUrl);
677  }
678 
679  // CLASS
680  else if ( identifier == QLatin1String( "class" ) ) {
681  addr.setSecrecy( parseSecrecy( *lineIt ) );
682  }
683 
684  // EMAIL
685  else if ( identifier == QLatin1String( "email" ) ) {
686  const QStringList types = ( *lineIt ).parameters( QLatin1String( "type" ) );
687  addr.insertEmail( ( *lineIt ).value().toString(),
688  types.contains( QLatin1String( "PREF" ) ), (*lineIt).parameterMap() );
689  }
690  // GENDER
691  else if ( identifier == QLatin1String( "gender" ) ) {
692  QString genderStr = ( *lineIt ).value().toString();
693  if (!genderStr.isEmpty()) {
694  Gender gender;
695  if (genderStr.at(0) != QLatin1Char(';')) {
696  gender.setGender(genderStr.at(0));
697  if (genderStr.length() > 2) {
698  gender.setComment(genderStr.right(genderStr.length()-2));
699  }
700  } else {
701  gender.setComment(genderStr.right(genderStr.length()-1));
702  }
703  addr.setGender(gender);
704  }
705  }
706 
707  // LANG
708  else if ( identifier == QLatin1String( "lang" ) ) {
709  Lang lang;
710  lang.setLanguage(( *lineIt ).value().toString());
711  lang.setParameters((*lineIt).parameterMap());
712  addr.insertLang(lang);
713  }
714  // KIND
715  else if ( identifier == QLatin1String( "kind" ) ) {
716  addr.setKind( ( *lineIt ).value().toString() );
717  }
718  // FN
719  else if ( identifier == QLatin1String( "fn" ) ) {
720  addr.setFormattedName( ( *lineIt ).value().toString() );
721  }
722 
723  // GEO
724  else if ( identifier == QLatin1String( "geo" ) ) {
725  Geo geo;
726  QString lineStr = ( *lineIt ).value().toString();
727  if (lineStr.startsWith(QLatin1String("geo:"))) { //VCard 4.0
728  lineStr.remove(QLatin1String("geo:"));
729  const QStringList geoParts =
730  lineStr.split( QLatin1Char( ',' ), QString::KeepEmptyParts );
731  if ( geoParts.size() >= 2 ) {
732  geo.setLatitude( geoParts.at( 0 ).toFloat() );
733  geo.setLongitude( geoParts.at( 1 ).toFloat() );
734  addr.setGeo( geo );
735  }
736  } else {
737  const QStringList geoParts =
738  lineStr.split( QLatin1Char( ';' ), QString::KeepEmptyParts );
739  if ( geoParts.size() >= 2 ) {
740  geo.setLatitude( geoParts.at( 0 ).toFloat() );
741  geo.setLongitude( geoParts.at( 1 ).toFloat() );
742  addr.setGeo( geo );
743  }
744  }
745  }
746 
747  // KEY
748  else if ( identifier == QLatin1String( "key" ) ) {
749  addr.insertKey( parseKey( *lineIt ) );
750  }
751 
752  // LABEL
753  else if ( identifier == QLatin1String( "label" ) ) {
754  Address::Type type;
755 
756  const QStringList types = ( *lineIt ).parameters( QLatin1String( "type" ) );
757  QStringList::ConstIterator end(types.end());
758  for ( QStringList::ConstIterator it = types.begin(); it != end; ++it ) {
759  type |= mAddressTypeMap[ ( *it ).toLower() ];
760  }
761 
762  bool available = false;
763  KABC::Address::List addressList = addr.addresses();
764  for ( KABC::Address::List::Iterator it = addressList.begin();
765  it != addressList.end(); ++it ) {
766  if ( ( *it ).type() == type ) {
767  ( *it ).setLabel( ( *lineIt ).value().toString() );
768  addr.insertAddress( *it );
769  available = true;
770  break;
771  }
772  }
773 
774  if ( !available ) { // a standalone LABEL tag
775  KABC::Address address( type );
776  address.setLabel( ( *lineIt ).value().toString() );
777  addr.insertAddress( address );
778  }
779  }
780 
781  // LOGO
782  else if ( identifier == QLatin1String( "logo" ) ) {
783  Picture picture = parsePicture( *lineIt );
784  if (addr.logo().isEmpty()) {
785  addr.setLogo( picture );
786  } else {
787  addr.insertExtraLogo( picture );
788  }
789  }
790 
791  // MAILER
792  else if ( identifier == QLatin1String( "mailer" ) ) {
793  addr.setMailer( ( *lineIt ).value().toString() );
794  }
795 
796  // N
797  else if ( identifier == QLatin1String( "n" ) ) {
798  const QStringList nameParts = splitString( semicolonSep, ( *lineIt ).value().toString() );
799  const int numberOfParts( nameParts.count() );
800  if ( numberOfParts > 0 ) {
801  addr.setFamilyName( nameParts.at( 0 ) );
802  }
803  if ( numberOfParts > 1 ) {
804  addr.setGivenName( nameParts.at( 1 ) );
805  }
806  if ( numberOfParts > 2 ) {
807  addr.setAdditionalName( nameParts.at( 2 ) );
808  }
809  if ( numberOfParts > 3 ) {
810  addr.setPrefix( nameParts.at( 3 ) );
811  }
812  if ( numberOfParts > 4 ) {
813  addr.setSuffix( nameParts.at( 4 ) );
814  }
815  if ( !( *lineIt ).parameter( QLatin1String( "sort-as" ) ).isEmpty() ) {
816  addr.setSortString( ( *lineIt ).parameter( QLatin1String( "sort-as" ) ) );
817  }
818  }
819 
820  // NAME
821  else if ( identifier == QLatin1String( "name" ) ) {
822  addr.setName( ( *lineIt ).value().toString() );
823  }
824 
825  // NICKNAME
826  else if ( identifier == QLatin1String( "nickname" ) ) {
827  addr.setNickName( ( *lineIt ).value().toString() );
828  }
829 
830  // NOTE
831  else if ( identifier == QLatin1String( "note" ) ) {
832  addr.setNote( ( *lineIt ).value().toString() );
833  }
834 
835  // ORGANIZATION
836  else if ( identifier == QLatin1String( "org" ) ) {
837  const QStringList orgParts = splitString( semicolonSep, ( *lineIt ).value().toString() );
838  if ( orgParts.count() > 0 ) {
839  addr.setOrganization( orgParts.at( 0 ) );
840  }
841  if ( orgParts.count() > 1 ) {
842  addr.setDepartment( orgParts.at( 1 ) );
843  }
844  if ( !( *lineIt ).parameter( QLatin1String( "sort-as" ) ).isEmpty() ) {
845  addr.setSortString( ( *lineIt ).parameter( QLatin1String( "sort-as" ) ) );
846  }
847  }
848 
849  // PHOTO
850  else if ( identifier == QLatin1String( "photo" ) ) {
851  Picture picture = parsePicture( *lineIt );
852  if (addr.photo().isEmpty()) {
853  addr.setPhoto( picture );
854  } else {
855  addr.insertExtraPhoto( picture );
856  }
857  }
858 
859  // PROID
860  else if ( identifier == QLatin1String( "prodid" ) ) {
861  addr.setProductId( ( *lineIt ).value().toString() );
862  }
863 
864  // REV
865  else if ( identifier == QLatin1String( "rev" ) ) {
866  addr.setRevision( parseDateTime( ( *lineIt ).value().toString() ) );
867  }
868 
869  // ROLE
870  else if ( identifier == QLatin1String( "role" ) ) {
871  addr.setRole( ( *lineIt ).value().toString() );
872  }
873 
874  // SORT-STRING
875  else if ( identifier == QLatin1String( "sort-string" ) ) {
876  addr.setSortString( ( *lineIt ).value().toString() );
877  }
878 
879  // SOUND
880  else if ( identifier == QLatin1String( "sound" ) ) {
881  Sound sound = parseSound( *lineIt );
882  if (addr.sound().isEmpty()) {
883  addr.setSound( sound );
884  } else {
885  addr.insertExtraSound(sound);
886  }
887  }
888 
889  // TEL
890  else if ( identifier == QLatin1String( "tel" ) ) {
891  PhoneNumber phone;
892  phone.setNumber( ( *lineIt ).value().toString() );
893 
894  PhoneNumber::Type type;
895 
896  const QStringList types = ( *lineIt ).parameters( QLatin1String( "type" ) );
897  QStringList::ConstIterator typeEnd( types.end() );
898  for ( QStringList::ConstIterator it = types.begin(); it != typeEnd; ++it ) {
899  type |= mPhoneTypeMap[( *it ).toUpper()];
900  }
901 
902  phone.setType( type );
903 
904  addr.insertPhoneNumber( phone );
905  }
906 
907  // TITLE
908  else if ( identifier == QLatin1String( "title" ) ) {
909  addr.setTitle( ( *lineIt ).value().toString() );
910  }
911 
912  // TZ
913  else if ( identifier == QLatin1String( "tz" ) ) {
914  TimeZone tz;
915  const QString date = ( *lineIt ).value().toString();
916 
917  if ( !date.isEmpty() ) {
918  int hours = date.mid( 1, 2 ).toInt();
919  int minutes = date.mid( 4, 2 ).toInt();
920  int offset = ( hours * 60 ) + minutes;
921  offset = offset * ( date[ 0 ] == QLatin1Char( '+' ) ? 1 : -1 );
922 
923  tz.setOffset( offset );
924  addr.setTimeZone( tz );
925  }
926  }
927 
928  // UID
929  else if ( identifier == QLatin1String( "uid" ) ) {
930  addr.setUid( ( *lineIt ).value().toString() );
931  }
932 
933  // URL
934  else if ( identifier == QLatin1String( "url" ) ) {
935  const KUrl url = KUrl( ( *lineIt ).value().toString() );
936  if (addr.url().isEmpty()) {
937  addr.setUrl( url );
938  } else {
939  addr.insertExtraUrl(url);
940  }
941  }
942  // SOURCE
943  else if ( identifier == QLatin1String( "source" ) ) {
944  const KUrl url = KUrl( ( *lineIt ).value().toString() );
945  addr.insertSourceUrl( url );
946  }
947  // MEMBER (vcard 4.0)
948  else if ( identifier == QLatin1String( "member" ) ) {
949  addr.insertMember( ( *lineIt ).value().toString() );
950  }
951  // RELATED (vcard 4.0)
952  else if ( identifier == QLatin1String( "related" ) ) {
953  addr.insertRelationShip( ( *lineIt ).value().toString() );
954  }
955 
956  // X-
957  else if ( identifier.startsWith( QLatin1String( "x-" ) ) ) {
958  QString ident = ( *lineIt ).identifier();
959  //X-Evolution
960  if ( identifier == QLatin1String( "x-evolution-spouse" ) ||
961  identifier == QLatin1String( "x-spouse" ) ) {
962  ident = QLatin1String( "X-KADDRESSBOOK-X-SpousesName" );
963  } else if ( identifier == QLatin1String( "x-evolution-blog-url" ) ) {
964  ident = QLatin1String( "X-KADDRESSBOOK-BlogFeed" );
965  } else if ( identifier == QLatin1String( "x-evolution-assistant" ) ||
966  identifier == QLatin1String( "x-assistant" ) ) {
967  ident = QLatin1String( "X-KADDRESSBOOK-X-AssistantsName" );
968  } else if ( identifier == QLatin1String( "x-evolution-anniversary" ) ||
969  identifier == QLatin1String( "x-anniversary" ) ) {
970  ident = QLatin1String( "X-KADDRESSBOOK-X-Anniversary" );
971  } else if ( identifier == QLatin1String( "x-evolution-manager" ) ||
972  identifier == QLatin1String( "x-manager" ) ) {
973  ident = QLatin1String( "X-KADDRESSBOOK-X-ManagersName" );
974  } else if ( identifier == QLatin1String( "x-aim" ) ) {
975  ident = QLatin1String( "X-messaging/aim-All" );
976  } else if ( identifier == QLatin1String( "x-icq" ) ) {
977  ident = QLatin1String( "X-messaging/icq-All" );
978  } else if ( identifier == QLatin1String( "x-jabber" ) ) {
979  ident = QLatin1String( "X-messaging/xmpp-All" );
980  } else if ( identifier == QLatin1String( "x-jabber" ) ) {
981  ident = QLatin1String( "X-messaging/xmpp-All" );
982  } else if ( identifier == QLatin1String( "x-msn" ) ) {
983  ident = QLatin1String( "X-messaging/msn-All" );
984  } else if ( identifier == QLatin1String( "x-yahoo" ) ) {
985  ident = QLatin1String( "X-messaging/yahoo-All" );
986  } else if ( identifier == QLatin1String( "x-gadugadu" ) ) {
987  ident = QLatin1String( "X-messaging/gadu-All" );
988  } else if ( identifier == QLatin1String( "x-skype" ) ) {
989  ident = QLatin1String( "X-messaging/skype-All" );
990  } else if ( identifier == QLatin1String( "x-groupwise" ) ) {
991  ident = QLatin1String( "X-messaging/groupwise-All" );
992  } else if ( identifier == QLatin1String( "x-sms" ) ) {
993  ident = QLatin1String( "X-messaging/sms-All" );
994  } else if ( identifier == QLatin1String( "x-meanwhile" ) ) {
995  ident = QLatin1String( "X-messaging/meanwhile-All" );
996  } else if ( identifier == QLatin1String( "x-irc" ) ) {
997  ident = QLatin1String( "X-messaging/irc-All" );
998  } else if ( identifier == QLatin1String( "x-gtalk" ) ) {
999  ident = QLatin1String( "X-messaging/googletalk-All" );
1000  }
1001 
1002  const QString key = ident.mid( 2 );
1003  const int dash = key.indexOf( QLatin1Char( '-' ) );
1004  addr.insertCustom( key.left( dash ), key.mid( dash + 1 ),
1005  ( *lineIt ).value().toString() );
1006  }
1007  }
1008  }
1009 
1010  addrList.append( addr );
1011  }
1012 
1013  return addrList;
1014 }
1015 
1016 QDateTime VCardTool::parseDateTime( const QString &str ) const
1017 {
1018  QDate date;
1019  QTime time;
1020 
1021  if ( str.indexOf( QLatin1Char( '-' ) ) == -1 ) { // is base format (yyyymmdd)
1022  date = QDate( str.left( 4 ).toInt(), str.mid( 4, 2 ).toInt(),
1023  str.mid( 6, 2 ).toInt() );
1024  } else { // is extended format yyyy-mm-dd
1025  date = QDate( str.left( 4 ).toInt(), str.mid( 5, 2 ).toInt(),
1026  str.mid( 8, 2 ).toInt() );
1027  }
1028  // does it also contain a time ? (Note: mm, ss are optional according ISO-8601)
1029  int timeStart = str.indexOf( QLatin1Char( 'T' ) );
1030  if ( timeStart >= 0 ) {
1031  int hour = 0, minute = 0, second = 0;
1032 
1033  hour = str.mid( timeStart + 1, 2 ).toInt(); // hour must always be given
1034 
1035  if ( str.indexOf( QLatin1Char( ':' ), timeStart + 1 ) > 0 ) { // extended format (hh:mm:ss)
1036  if ( str.length() >= ( timeStart + 5 ) ) {
1037  minute = str.mid( timeStart + 4, 2 ).toInt();
1038  if ( str.length() >= ( timeStart + 8 ) ) {
1039  second = str.mid( timeStart + 7, 2 ).toInt();
1040  }
1041  }
1042  } else { // basic format (hhmmss)
1043  if ( str.length() >= ( timeStart + 4 ) ) {
1044  minute = str.mid( timeStart + 3, 2 ).toInt();
1045  if ( str.length() >= ( timeStart + 6 ) ) {
1046  second = str.mid( timeStart + 5, 2 ).toInt();
1047  }
1048  }
1049  }
1050 
1051  time = QTime( hour, minute, second );
1052  }
1053 
1054  Qt::TimeSpec spec = ( str.right( 1 ) == QLatin1String( "Z" ) ) ? Qt::UTC : Qt::LocalTime;
1055 
1056  QDateTime dateTime( date );
1057 
1058  // explicitly set the time, which might be invalid, to keep the information
1059  // that the time is invalid. In createDateTime() the time/invalid flag is
1060  // checked which omits then to print the timestamp
1061  // This is needed to reproduce the given string in input
1062  // e.g. BDAY:2008-12-30
1063  // without time shall also result in a string without a time
1064  dateTime.setTime( time );
1065 
1066  dateTime.setTimeSpec( spec );
1067  return dateTime;
1068 }
1069 
1070 QString VCardTool::createDateTime( const QDateTime &dateTime ) const
1071 {
1072  QString str;
1073 
1074  if ( dateTime.date().isValid() ) {
1075  str.sprintf( "%4d-%02d-%02d", dateTime.date().year(), dateTime.date().month(),
1076  dateTime.date().day() );
1077  if ( dateTime.time().isValid() ) {
1078  QString tmp;
1079  tmp.sprintf( "T%02d:%02d:%02d", dateTime.time().hour(), dateTime.time().minute(),
1080  dateTime.time().second() );
1081  str += tmp;
1082 
1083  if ( dateTime.timeSpec() == Qt::UTC ) {
1084  str += QLatin1Char( 'Z' );
1085  }
1086  }
1087  }
1088 
1089  return str;
1090 }
1091 
1092 Picture VCardTool::parsePicture( const VCardLine &line ) const
1093 {
1094  Picture pic;
1095 
1096  const QStringList params = line.parameterList();
1097  QString type;
1098  if ( params.contains( QLatin1String( "type" ) ) ) {
1099  type = line.parameter( QLatin1String( "type" ) );
1100  }
1101  if ( params.contains( QLatin1String( "encoding" ) ) ) {
1102  pic.setRawData( line.value().toByteArray(), type );
1103  } else if ( params.contains( QLatin1String( "value" ) ) ) {
1104  if ( line.parameter( QLatin1String( "value" ) ).toLower() == QLatin1String( "uri" ) ) {
1105  pic.setUrl( line.value().toString() );
1106  }
1107  }
1108 
1109  return pic;
1110 }
1111 
1112 VCardLine VCardTool::createPicture( const QString &identifier, const Picture &pic, VCard::Version version ) const
1113 {
1114  VCardLine line( identifier );
1115 
1116  if ( pic.isEmpty() ) {
1117  return line;
1118  }
1119 
1120  if ( pic.isIntern() ) {
1121  line.setValue( pic.rawData() );
1122  if (version == VCard::v2_1) {
1123  line.addParameter( QLatin1String( "ENCODING" ), QLatin1String( "BASE64" ) );
1124  line.addParameter( pic.type(), QString() );
1125  } else {
1126  line.addParameter( QLatin1String( "encoding" ), QLatin1String( "b" ) );
1127  line.addParameter( QLatin1String( "type" ), pic.type() );
1128  }
1129  } else {
1130  line.setValue( pic.url() );
1131  line.addParameter( QLatin1String( "value" ), QLatin1String( "URI" ) );
1132  }
1133 
1134  return line;
1135 }
1136 
1137 Sound VCardTool::parseSound( const VCardLine &line ) const
1138 {
1139  Sound snd;
1140 
1141  const QStringList params = line.parameterList();
1142  if ( params.contains( QLatin1String( "encoding" ) ) ) {
1143  snd.setData( line.value().toByteArray() );
1144  } else if ( params.contains( QLatin1String( "value" ) ) ) {
1145  if ( line.parameter( QLatin1String( "value" ) ).toLower() == QLatin1String( "uri" ) ) {
1146  snd.setUrl( line.value().toString() );
1147  }
1148  }
1149 
1150 /* TODO: support sound types
1151  if ( params.contains( "type" ) )
1152  snd.setType( line.parameter( "type" ) );
1153 */
1154 
1155  return snd;
1156 }
1157 
1158 VCardLine VCardTool::createSound( const Sound &snd, VCard::Version version ) const
1159 {
1160  VCardLine line( QLatin1String( "SOUND" ) );
1161 
1162  if ( snd.isIntern() ) {
1163  if ( !snd.data().isEmpty() ) {
1164  line.setValue( snd.data() );
1165  if (version == VCard::v2_1) {
1166  line.addParameter( QLatin1String( "ENCODING" ), QLatin1String( "BASE64" ) );
1167  } else {
1168  line.addParameter( QLatin1String( "encoding" ), QLatin1String( "b" ) );
1169  }
1170  // TODO: need to store sound type!!!
1171  }
1172  } else if ( !snd.url().isEmpty() ) {
1173  line.setValue( snd.url() );
1174  line.addParameter( QLatin1String( "value" ), QLatin1String( "URI" ) );
1175  }
1176 
1177  return line;
1178 }
1179 
1180 Key VCardTool::parseKey( const VCardLine &line ) const
1181 {
1182  Key key;
1183 
1184  const QStringList params = line.parameterList();
1185  if ( params.contains( QLatin1String( "encoding" ) ) ) {
1186  key.setBinaryData( line.value().toByteArray() );
1187  } else {
1188  key.setTextData( line.value().toString() );
1189  }
1190 
1191  if ( params.contains( QLatin1String( "type" ) ) ) {
1192  if ( line.parameter( QLatin1String( "type" ) ).toLower() == QLatin1String( "x509" ) ) {
1193  key.setType( Key::X509 );
1194  } else if ( line.parameter( QLatin1String( "type" ) ).toLower() == QLatin1String( "pgp" ) ) {
1195  key.setType( Key::PGP );
1196  } else {
1197  key.setType( Key::Custom );
1198  key.setCustomTypeString( line.parameter( QLatin1String( "type" ) ) );
1199  }
1200  }
1201 
1202  return key;
1203 }
1204 
1205 VCardLine VCardTool::createKey( const Key &key, VCard::Version version ) const
1206 {
1207  Q_UNUSED(version);
1208  VCardLine line( QLatin1String( "KEY" ) );
1209 
1210  if ( key.isBinary() ) {
1211  if ( !key.binaryData().isEmpty() ) {
1212  line.setValue( key.binaryData() );
1213  if (version == VCard::v2_1)
1214  line.addParameter( QLatin1String( "ENCODING" ), QLatin1String( "BASE64" ) );
1215  else
1216  line.addParameter( QLatin1String( "encoding" ), QLatin1String( "b" ) );
1217  }
1218  } else if ( !key.textData().isEmpty() ) {
1219  line.setValue( key.textData() );
1220  }
1221 
1222  if ( key.type() == Key::X509 ) {
1223  line.addParameter( QLatin1String( "type" ), QLatin1String( "X509" ) );
1224  } else if ( key.type() == Key::PGP ) {
1225  line.addParameter( QLatin1String( "type" ), QLatin1String( "PGP" ) );
1226  } else if ( key.type() == Key::Custom ) {
1227  line.addParameter( QLatin1String( "type" ), key.customTypeString() );
1228  }
1229 
1230  return line;
1231 }
1232 
1233 Secrecy VCardTool::parseSecrecy( const VCardLine &line ) const
1234 {
1235  Secrecy secrecy;
1236 
1237  const QString value = line.value().toString().toLower();
1238  if ( value == QLatin1String( "public" ) ) {
1239  secrecy.setType( Secrecy::Public );
1240  } else if ( value == QLatin1String( "private" ) ) {
1241  secrecy.setType( Secrecy::Private );
1242  } else if ( value == QLatin1String( "confidential" ) ) {
1243  secrecy.setType( Secrecy::Confidential );
1244  }
1245 
1246  return secrecy;
1247 }
1248 
1249 VCardLine VCardTool::createSecrecy( const Secrecy &secrecy ) const
1250 {
1251  VCardLine line( QLatin1String( "CLASS" ) );
1252 
1253  int type = secrecy.type();
1254 
1255  if ( type == Secrecy::Public ) {
1256  line.setValue( QLatin1String( "PUBLIC" ) );
1257  } else if ( type == Secrecy::Private ) {
1258  line.setValue( QLatin1String( "PRIVATE" ) );
1259  } else if ( type == Secrecy::Confidential ) {
1260  line.setValue( QLatin1String( "CONFIDENTIAL" ) );
1261  }
1262 
1263  return line;
1264 }
1265 
1266 QStringList VCardTool::splitString( const QChar &sep, const QString &str ) const
1267 {
1268  QStringList list;
1269  QString value( str );
1270 
1271  int start = 0;
1272  int pos = value.indexOf( sep, start );
1273 
1274  while ( pos != -1 ) {
1275  if ( pos == 0 || value[ pos - 1 ] != QLatin1Char( '\\' ) ) {
1276  if ( pos > start && pos <= (int)value.length() ) {
1277  list << value.mid( start, pos - start );
1278  } else {
1279  list << QString();
1280  }
1281 
1282  start = pos + 1;
1283  pos = value.indexOf( sep, start );
1284  } else {
1285  value.replace( pos - 1, 2, sep );
1286  pos = value.indexOf( sep, pos );
1287  }
1288  }
1289 
1290  int l = value.length() - 1;
1291  if ( value.mid( start, l - start + 1 ).length() > 0 ) {
1292  list << value.mid( start, l - start + 1 );
1293  } else {
1294  list << QString();
1295  }
1296 
1297  return list;
1298 }
KABC::Sound
Class that holds a Sound clip for a contact.
Definition: sound.h:58
KABC::PhoneNumber::Pcs
Personal Communication Service.
Definition: phonenumber.h:60
QTime::minute
int minute() const
KABC::Address::Dom
domestic
Definition: address.h:52
KABC::Key::textData
QString textData() const
Returns the text data.
Definition: key.cpp:148
QString::indexOf
int indexOf(QChar ch, int from, Qt::CaseSensitivity cs) const
KABC::Address::setType
void setType(Type type)
Sets the type of address.
Definition: address.cpp:322
KABC::Address
Postal address information.
Definition: address.h:37
KABC::Addressee::setNickName
void setNickName(const QString &nickName)
Set nick name.
Definition: addressee.cpp:690
KABC::Addressee::photo
Picture photo() const
Return photo.
Definition: addressee.cpp:1157
KABC::Key::PGP
Pretty Good Privacy key.
Definition: key.h:50
KABC::PhoneNumber
Phonenumber information.
Definition: phonenumber.h:38
KABC::PhoneNumber::Voice
Voice.
Definition: phonenumber.h:52
KABC::Key::setBinaryData
void setBinaryData(const QByteArray &data)
Sets binary data.
Definition: key.cpp:131
KABC::Sound::setData
void setData(const QByteArray &data)
Sets the raw data of the sound.
Definition: sound.cpp:116
KABC::Addressee::insertEmail
void insertEmail(const QString &email, bool preferred=false)
Insert an email address.
Definition: addressee.cpp:1420
KABC::Picture
A class to store a picture of an addressee.
Definition: picture.h:39
KABC::Sound::setUrl
void setUrl(const QString &url)
Sets a URL for the location of the sound file.
Definition: sound.cpp:110
KABC::Addressee::setMailer
void setMailer(const QString &mailer)
Set mail client.
Definition: addressee.cpp:868
KABC::Addressee::insertPhoneNumber
void insertPhoneNumber(const PhoneNumber &phoneNumber)
Insert a phone number.
Definition: addressee.cpp:1525
KABC::Address::Pref
preferred address
Definition: address.h:58
KABC::Geo::setLongitude
void setLongitude(float longitude)
Sets the longitude.
Definition: geo.cpp:90
KABC::AddresseeList
a QValueList of Addressee, with sorting functionality
Definition: addresseelist.h:288
QDate::toString
QString toString(Qt::DateFormat format) const
QByteArray
KABC::Addressee::setSuffix
void setSuffix(const QString &suffix)
Set honorific suffixes.
Definition: addressee.cpp:670
KABC::Addressee::setPhoto
void setPhoto(const Picture &photo)
Set photo.
Definition: addressee.cpp:1148
KABC::Addressee::setFormattedName
void setFormattedName(const QString &formattedName)
Set formatted name.
Definition: addressee.cpp:570
KABC::Key::setTextData
void setTextData(const QString &data)
Sets text data.
Definition: key.cpp:142
KABC::Key::binaryData
QByteArray binaryData() const
Returns the binary data.
Definition: key.cpp:137
QChar
QString::split
QStringList split(const QString &sep, SplitBehavior behavior, Qt::CaseSensitivity cs) const
KABC::Key
A class to store an encryption key.
Definition: key.h:34
KABC::Addressee::setRole
void setRole(const QString &role)
Set role.
Definition: addressee.cpp:948
KABC::TimeZone::setOffset
void setOffset(int offset)
Set time zone offset relative to UTC.
Definition: timezone.cpp:66
KABC::Geo::setLatitude
void setLatitude(float latitude)
Sets the latitude.
Definition: geo.cpp:74
QMap::constBegin
const_iterator constBegin() const
QList::at
const T & at(int i) const
QMap
QDateTime::setTime
void setTime(const QTime &time)
QStringList::contains
bool contains(const QString &str, Qt::CaseSensitivity cs) const
QByteArray::isEmpty
bool isEmpty() const
KABC::Geo::longitude
float longitude() const
Returns the longitude.
Definition: geo.cpp:101
KABC::Addressee::setCategories
void setCategories(const QStringList &)
Set categories to given value.
Definition: addressee.cpp:1916
QTime::isValid
bool isValid() const
KABC::Addressee::setGivenName
void setGivenName(const QString &givenName)
Set given name.
Definition: addressee.cpp:610
KABC::Key::isBinary
bool isBinary() const
Returns whether the key contains binary or text data.
Definition: key.cpp:153
KABC::TimeZone::isValid
bool isValid() const
Return, if this time zone object is valid.
Definition: timezone.cpp:77
KABC::Key::X509
X509 key.
Definition: key.h:49
QDateTime::time
QTime time() const
KABC::Address::setStreet
void setStreet(const QString &street)
Sets the street (including house number).
Definition: address.cpp:388
KABC::PhoneNumber::Bbs
Mailbox.
Definition: phonenumber.h:56
KABC::Addressee::sound
Sound sound() const
Return sound.
Definition: addressee.cpp:1177
KABC::Addressee::setSortString
void setSortString(const QString &sortString)
Set sort string.
Definition: addressee.cpp:1068
KABC::Addressee::setAdditionalName
void setAdditionalName(const QString &additionalName)
Set additional names.
Definition: addressee.cpp:630
QStringList::join
QString join(const QString &separator) const
KABC::Addressee::setLogo
void setLogo(const Picture &logo)
Set logo.
Definition: addressee.cpp:1128
KABC::Picture::rawData
QByteArray rawData() const
Returns the raw data of this picture.
Definition: picture.cpp:203
QString::remove
QString & remove(int position, int n)
KABC::PhoneNumber::Fax
Fax machine.
Definition: phonenumber.h:53
KABC::Addressee::setFamilyName
void setFamilyName(const QString &familyName)
Set family name.
Definition: addressee.cpp:590
KABC::Addressee::addresses
Address::List addresses() const
Return list of all addresses.
Definition: addressee.cpp:1820
QDate::month
int month() const
KABC::Address::Home
home address
Definition: address.h:56
QTime
QTime::second
int second() const
KABC::Key::Custom
Custom or IANA conform key.
Definition: key.h:51
QList::size
int size() const
QList::value
T value(int i) const
KABC::Addressee::setPrefix
void setPrefix(const QString &prefix)
Set honorific prefixes.
Definition: addressee.cpp:650
KABC::Address::Parcel
parcel
Definition: address.h:55
KABC::Picture::setRawData
void setRawData(const QByteArray &rawData, const QString &type)
Sets the raw data of the picture.
Definition: picture.cpp:171
QDate::fromString
QDate fromString(const QString &string, Qt::DateFormat format)
KABC::Picture::url
QString url() const
Returns the location URL of this picture.
Definition: picture.cpp:189
QList::count
int count(const T &value) const
QList::append
void append(const T &value)
QMapIterator
KABC::PhoneNumber::Cell
Cell phone.
Definition: phonenumber.h:54
KABC::Address::Postal
postal
Definition: address.h:54
KABC::Addressee::setTitle
void setTitle(const QString &title)
Set title.
Definition: addressee.cpp:928
QMapIterator::next
Item next()
KABC::PhoneNumber::setType
void setType(Type type)
Sets the type.
Definition: phonenumber.cpp:133
KABC::Addressee::setDepartment
void setDepartment(const QString &department)
Set department.
Definition: addressee.cpp:988
KABC::PhoneNumber::setNumber
void setNumber(const QString &number)
Sets the phone number.
Definition: phonenumber.cpp:123
QString::toInt
int toInt(bool *ok, int base) const
QList::isEmpty
bool isEmpty() const
QString::isEmpty
bool isEmpty() const
QList::removeAll
int removeAll(const T &value)
QMap::constEnd
const_iterator constEnd() const
QDate::day
int day() const
KABC::Geo::latitude
float latitude() const
Returns the latitude.
Definition: geo.cpp:85
KABC::Address::setPostOfficeBox
void setPostOfficeBox(const QString &postOfficeBox)
Sets the post office box.
Definition: address.cpp:356
QString::startsWith
bool startsWith(const QString &s, Qt::CaseSensitivity cs) const
KABC::Addressee::setSound
void setSound(const Sound &sound)
Set sound.
Definition: addressee.cpp:1168
KABC::TimeZone::offset
int offset() const
Return offset in minutes relative to UTC.
Definition: timezone.cpp:72
QDate::isValid
bool isValid() const
KABC::Addressee::setUid
void setUid(const QString &uid)
Set unique identifier.
Definition: addressee.cpp:433
KABC::Addressee::insertKey
void insertKey(const Key &key)
Insert a key.
Definition: addressee.cpp:1599
KABC::Sound::data
QByteArray data() const
Returns the raw data of this sound.
Definition: sound.cpp:138
KABC::Geo::isValid
bool isValid() const
Returns, whether this object contains a valid geographical position.
Definition: geo.cpp:106
QList::Iterator
typedef Iterator
QDate
KABC::PhoneNumber::Modem
Modem.
Definition: phonenumber.h:57
KABC::TimeZone
Time zone information.
Definition: timezone.h:35
QDate::year
int year() const
KABC::Addressee::setOrganization
void setOrganization(const QString &organization)
Set organization.
Definition: addressee.cpp:968
QString
QList
Definition: contactgrouptool.h:30
KABC::Addressee::setGeo
void setGeo(const Geo &geo)
Set geographic position.
Definition: addressee.cpp:908
KABC::Addressee::setUrl
void setUrl(const KUrl &url)
Set homepage.
Definition: addressee.cpp:1088
KABC::PhoneNumber::Msg
Messaging.
Definition: phonenumber.h:50
KABC::Address::setRegion
void setRegion(const QString &region)
Sets the region, e.g.
Definition: address.cpp:420
QStringList
KABC::Key::setCustomTypeString
void setCustomTypeString(const QString &type)
Sets custom type string.
Definition: key.cpp:163
QString::right
QString right(int n) const
KABC::PhoneNumber::Video
Video phone.
Definition: phonenumber.h:55
QTime::hour
int hour() const
QList::end
iterator end()
QString::toLower
QString toLower() const
KABC::PhoneNumber::Home
Home number.
Definition: phonenumber.h:48
QLatin1Char
QDateTime::timeSpec
Qt::TimeSpec timeSpec() const
KABC::Addressee::setName
void setName(const QString &name)
Set name.
Definition: addressee.cpp:452
QChar::toLatin1
char toLatin1() const
KABC::Address::setLabel
void setLabel(const QString &label)
Sets the delivery label.
Definition: address.cpp:468
KABC::Addressee
address book entry
Definition: addressee.h:78
KABC::Addressee::setNote
void setNote(const QString &note)
Set note.
Definition: addressee.cpp:1008
KABC::PhoneNumber::Work
Office number.
Definition: phonenumber.h:49
KABC::Addressee::insertAddress
void insertAddress(const Address &address)
Insert an address.
Definition: addressee.cpp:1773
QMap::key
const Key key(const T &value) const
QString::replace
QString & replace(int position, int n, QChar after)
KABC::Address::Intl
international
Definition: address.h:53
KABC::Picture::isEmpty
bool isEmpty() const
Returns true, if the picture is empty.
Definition: picture.cpp:136
KABC::Addressee::insertCustom
void insertCustom(const QString &app, const QString &name, const QString &value)
Insert custom entry.
Definition: addressee.cpp:1928
QString::mid
QString mid(int position, int n) const
KABC::Key::setType
void setType(Type type)
Sets the type.
Definition: key.cpp:158
QDateTime::date
QDate date() const
QLatin1String
KABC::Address::setCountry
void setCountry(const QString &country)
Sets the country.
Definition: address.cpp:452
KABC::Addressee::setRevision
void setRevision(const QDateTime &revision)
Set revision date.
Definition: addressee.cpp:1048
KABC::Geo
Geographic position.
Definition: geo.h:35
KABC::Picture::type
QString type() const
Returns the type of this picture.
Definition: picture.cpp:216
KABC::Addressee::setProductId
void setProductId(const QString &productId)
Set product identifier.
Definition: addressee.cpp:1028
QString::sprintf
QString & sprintf(const char *cformat,...)
QString::at
const QChar at(int position) const
QList< Addressee >::ConstIterator
typedef ConstIterator
KABC::Picture::setUrl
void setUrl(const QString &url)
Sets a URL for the location of the picture file.
Definition: picture.cpp:143
KABC::Key::customTypeString
QString customTypeString() const
Returns the custom type string.
Definition: key.cpp:173
KABC::Addressee::logo
Picture logo() const
Return logo.
Definition: addressee.cpp:1137
KABC::Address::setLocality
void setLocality(const QString &locality)
Sets the locality, e.g.
Definition: address.cpp:404
KABC::PhoneNumber::Pager
Pager.
Definition: phonenumber.h:61
KABC::Address::setPostalCode
void setPostalCode(const QString &code)
Sets the postal code.
Definition: address.cpp:436
KABC::Address::setExtended
void setExtended(const QString &extended)
Sets the extended address information.
Definition: address.cpp:372
KABC::Address::Work
address at work
Definition: address.h:57
QString::length
int length() const
KABC::Addressee::setBirthday
void setBirthday(const QDateTime &birthday)
Set birthday.
Definition: addressee.cpp:710
QString::left
QString left(int n) const
KABC::PhoneNumber::Pref
Preferred number.
Definition: phonenumber.h:51
KABC::Sound::isIntern
bool isIntern() const
Returns whether the sound is described by a URL (extern) or by the raw data (intern).
Definition: sound.cpp:122
KABC::PhoneNumber::Car
Car phone.
Definition: phonenumber.h:58
KABC::Addressee::setTimeZone
void setTimeZone(const TimeZone &timeZone)
Set time zone.
Definition: addressee.cpp:888
KABC::PhoneNumber::Isdn
ISDN connection.
Definition: phonenumber.h:59
KABC::Key::type
Type type() const
Returns the type, see Type.
Definition: key.cpp:168
QList::constEnd
const_iterator constEnd() const
QList::constBegin
const_iterator constBegin() const
KABC::Sound::isEmpty
bool isEmpty() const
Returns true, if the sound object is empty.
Definition: sound.cpp:127
KABC::Picture::isIntern
bool isIntern() const
Returns whether the picture is described by a URL (extern) or by the raw data (intern).
Definition: picture.cpp:184
KABC::Addressee::url
KUrl url() const
Return homepage.
Definition: addressee.cpp:1097
KABC::Addressee::setSecrecy
void setSecrecy(const Secrecy &secrecy)
Set security class.
Definition: addressee.cpp:1108
KABC::Sound::url
QString url() const
Returns the location URL of this sound.
Definition: sound.cpp:133
QList::begin
iterator begin()
QDateTime
QMap::value
const T value(const Key &key) const
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Mon Jun 22 2020 13:38:39 by doxygen 1.8.7 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.

kabc

Skip menu "kabc"
  • Main Page
  • Namespace List
  • Namespace Members
  • Alphabetical List
  • Class List
  • Class Hierarchy
  • Class Members
  • File List
  • Related Pages

kdepimlibs API Reference

Skip menu "kdepimlibs API Reference"
  • akonadi
  •   contact
  •   kmime
  •   socialutils
  • kabc
  • kalarmcal
  • kblog
  • kcal
  • kcalcore
  • kcalutils
  • kholidays
  • kimap
  • kioslave
  •   imap4
  •   mbox
  •   nntp
  • kldap
  • kmbox
  • kmime
  • kontactinterface
  • kpimidentities
  • kpimtextedit
  • kpimutils
  • kresources
  • ktnef
  • kxmlrpcclient
  • mailtransport
  • microblog
  • qgpgme
  • syndication
  •   atom
  •   rdf
  •   rss2

Search



Report problems with this website to our bug tracking system.
Contact the specific authors with questions and comments about the page contents.

KDE® and the K Desktop Environment® logo are registered trademarks of KDE e.V. | Legal