gloox  0.9.9.12
vcard.cpp
1 /*
2  Copyright (c) 2006-2008 by Jakob Schroeter <js@camaya.net>
3  This file is part of the gloox library. http://camaya.net/gloox
4 
5  This software is distributed under a license. The full license
6  agreement can be found in the file LICENSE in this distribution.
7  This software may not be copied, modified, sold or distributed
8  other than expressed in the named license agreement.
9 
10  This software is distributed without any warranty.
11 */
12 
13 
14 #include "vcard.h"
15 #include "tag.h"
16 #include "base64.h"
17 
18 namespace gloox
19 {
20 
22  : m_class( ClassNone ), m_prodid( "gloox" + GLOOX_VERSION ),
23  m_N( false ), m_PHOTO( false ), m_LOGO( false )
24  {
25  }
26 
27  VCard::VCard( Tag *vcard )
28  : m_class( ClassNone ), m_prodid( "gloox" + GLOOX_VERSION ),
29  m_N( false ), m_PHOTO( false ), m_LOGO( false )
30  {
31  checkField( vcard, "FN", m_formattedname );
32  checkField( vcard, "NICKNAME", m_nickname );
33  checkField( vcard, "URL", m_url );
34  checkField( vcard, "BDAY", m_bday );
35  checkField( vcard, "JABBERID", m_jabberid );
36  checkField( vcard, "TITLE", m_title );
37  checkField( vcard, "ROLE", m_role );
38  checkField( vcard, "NOTE", m_note );
39  checkField( vcard, "DESC", m_desc );
40  checkField( vcard, "MAILER", m_mailer );
41  checkField( vcard, "TZ", m_tz );
42  checkField( vcard, "PRODID", m_prodid );
43  checkField( vcard, "REV", m_rev );
44  checkField( vcard, "SORT-STRING", m_sortstring );
45  checkField( vcard, "UID", m_uid );
46 
47  Tag::TagList::const_iterator it = vcard->children().begin();
48  for( ; it != vcard->children().end(); ++it )
49  {
50  if( (*it)->name() == "N" )
51  {
52  m_N = true;
53  if( (*it)->hasChild( "FAMILY" ) )
54  m_name.family = (*it)->findChild( "FAMILY" )->cdata();
55  if( (*it)->hasChild( "GIVEN" ) )
56  m_name.given = (*it)->findChild( "GIVEN" )->cdata();
57  if( (*it)->hasChild( "MIDDLE" ) )
58  m_name.middle = (*it)->findChild( "MIDDLE" )->cdata();
59  if( (*it)->hasChild( "PREFIX" ) )
60  m_name.prefix = (*it)->findChild( "PREFIX" )->cdata();
61  if( (*it)->hasChild( "SUFFIX" ) )
62  m_name.suffix = (*it)->findChild( "SUFFIX" )->cdata();
63  }
64  else if( (*it)->name() == "PHOTO" )
65  {
66  if( (*it)->hasChild( "EXTVAL" ) )
67  {
68  m_photo.extval = (*it)->findChild( "EXTVAL" )->cdata();
69  m_PHOTO = true;
70  }
71  else if( (*it)->hasChild( "TYPE" ) && (*it)->hasChild( "BINVAL" ) )
72  {
73  std::string binval = (*it)->findChild( "BINVAL" )->cdata();
74  std::string::size_type pos = 0;
75  while( ( pos = binval.find( '\n' ) ) != std::string::npos )
76  binval.erase( pos, 1 );
77  m_photo.type = (*it)->findChild( "TYPE" )->cdata();
78  m_photo.binval = Base64::decode64( binval );
79  m_PHOTO = true;
80  }
81  }
82  else if( (*it)->name() == "LOGO" )
83  {
84  if( (*it)->hasChild( "EXTVAL" ) )
85  {
86  m_logo.extval = (*it)->findChild( "EXTVAL" )->cdata();
87  m_LOGO = true;
88  }
89  else if( (*it)->hasChild( "TYPE" ) && (*it)->hasChild( "BINVAL" ) )
90  {
91  std::string binval = (*it)->findChild( "BINVAL" )->cdata();
92  std::string::size_type pos = 0;
93  while( ( pos = binval.find( '\n' ) ) != std::string::npos )
94  binval.erase( pos, 1 );
95  m_logo.type = (*it)->findChild( "TYPE" )->cdata();
96  m_logo.binval = Base64::decode64( binval );
97  m_LOGO = true;
98  }
99  }
100  else if( (*it)->name() == "EMAIL" && (*it)->hasChild( "USERID" ) )
101  {
102  Email item;
103  item.userid = (*it)->findChild( "USERID" )->cdata();
104  item.internet = (*it)->hasChild( "INTERNET" );
105  item.x400 = (*it)->hasChild( "X400" );
106  item.work = (*it)->hasChild( "WORK" );
107  item.home = (*it)->hasChild( "HOME" );
108  item.pref = (*it)->hasChild( "PREF" );
109  m_emailList.push_back( item );
110  }
111  else if( (*it)->name() == "ADR" )
112  {
113  Address item;
114  checkField( (*it), "POBOX", item.pobox );
115  checkField( (*it), "EXTADD", item.extadd );
116  checkField( (*it), "STREET", item.street );
117  checkField( (*it), "LOCALITY", item.locality );
118  checkField( (*it), "REGION", item.region );
119  checkField( (*it), "PCODE", item.pcode );
120  checkField( (*it), "CTRY", item.ctry );
121  item.postal = (*it)->hasChild( "POSTAL" );
122  item.parcel = (*it)->hasChild( "PARCEL" );
123  item.work = (*it)->hasChild( "WORK" );
124  item.home = (*it)->hasChild( "HOME" );
125  item.pref = (*it)->hasChild( "PREF" );
126  item.dom = (*it)->hasChild( "DOM" );
127  item.intl = !item.dom && (*it)->hasChild( "INTL" );
128  m_addressList.push_back( item );
129  }
130  else if( (*it)->name() == "LABEL" )
131  {
132  Label item;
133  Tag::TagList::const_iterator it2 = (*it)->children().begin();
134  for( ; it2 != (*it)->children().end(); ++it2 )
135  {
136  if( (*it2)->name() == "LINE" )
137  item.lines.push_back( (*it)->cdata() );
138  item.postal = (*it2)->name() == "POSTAL";
139  item.parcel = (*it2)->name() == "PARCEL";
140  item.work = (*it2)->name() == "WORK";
141  item.home = (*it2)->name() == "HOME";
142  item.pref = (*it2)->name() == "PREF";
143  item.dom = (*it2)->name() == "DOM";
144  item.intl = !item.dom && (*it2)->name() == "INTL";
145  }
146  m_labelList.push_back( item );
147  }
148  else if( (*it)->name() == "TEL" && (*it)->hasChild( "NUMBER" ) )
149  {
150  Telephone item;
151  item.number = (*it)->findChild( "NUMBER" )->cdata();
152  item.work = (*it)->hasChild( "WORK" );
153  item.home = (*it)->hasChild( "HOME" );
154  item.voice = (*it)->hasChild( "VOICE" );
155  item.fax = (*it)->hasChild( "FAX" );
156  item.pager = (*it)->hasChild( "PAGER" );
157  item.msg = (*it)->hasChild( "MSG" );
158  item.cell = (*it)->hasChild( "CELL" );
159  item.video = (*it)->hasChild( "VIDEO" );
160  item.bbs = (*it)->hasChild( "BBS" );
161  item.modem = (*it)->hasChild( "MODEM" );
162  item.isdn = (*it)->hasChild( "ISDN" );
163  item.pcs = (*it)->hasChild( "PCS" );
164  item.pref = (*it)->hasChild( "PREF" );
165  m_telephoneList.push_back( item );
166  }
167  else if( (*it)->name() == "ORG" )
168  {
169  Tag::TagList::const_iterator ito = (*it)->children().begin();
170  for( ; ito != (*it)->children().end(); ++ito )
171  {
172  if( (*ito)->name() == "ORGNAME" )
173  m_org.name = (*ito)->cdata();
174  else if( (*ito)->name() == "ORGUNIT" )
175  m_org.units.push_back( (*ito)->cdata() );
176  }
177  }
178  else if( (*it)->name() == "GEO" )
179  {
180  checkField( (*it), "LON", m_geo.longitude );
181  checkField( (*it), "LAT", m_geo.latitude );
182  }
183  else if( (*it)->name() == "CLASS" )
184  {
185  if( (*it)->hasChild( "PRIVATE" ) )
186  m_class = ClassPrivate;
187  else if( (*it)->hasChild( "PUBLIC" ) )
188  m_class = ClassPublic;
189  else if( (*it)->hasChild( "CONFIDENTIAL" ) )
190  m_class = ClassConfidential;
191  }
192 
193  }
194 
195  }
196 
197  void VCard::checkField( Tag *vcard, const std::string& field, std::string& var )
198  {
199  if( vcard->hasChild( field ) )
200  var = vcard->findChild( field )->cdata();
201  }
202 
203  void VCard::setName( const std::string& family, const std::string& given, const std::string& middle,
204  const std::string& prefix, const std::string& suffix )
205  {
206  m_name.family = family;
207  m_name.given = given;
208  m_name.middle = middle;
209  m_name.prefix = prefix;
210  m_name.suffix = suffix;
211  m_N = true;
212  }
213 
214  void VCard::setPhoto( const std::string& extval )
215  {
216  if( !extval.empty() )
217  {
218  m_photo.extval= extval;
219  m_PHOTO = true;
220  }
221  }
222 
223  void VCard::setPhoto( const std::string& type, const std::string& binval )
224  {
225  if( !type.empty() && !binval.empty() )
226  {
227  m_photo.type = type;
228  m_photo.binval = binval;
229  m_PHOTO = true;
230  }
231  }
232 
233  void VCard::setLogo( const std::string& extval )
234  {
235  if( !extval.empty() )
236  {
237  m_logo.extval = extval;
238  m_LOGO = true;
239  }
240  }
241 
242  void VCard::setLogo( const std::string& type, const std::string& binval )
243  {
244  if( !type.empty() && !binval.empty() )
245  {
246  m_logo.type = type;
247  m_logo.binval = binval;
248  m_LOGO = true;
249  }
250  }
251 
252  void VCard::addEmail( const std::string& userid, int type )
253  {
254  if( userid.empty() )
255  return;
256 
257  Email item;
258  item.userid = userid;
259  item.internet = type & AddrTypeInet ? true : false;
260  item.x400 = type & AddrTypeX400 ? true : false;
261  item.work = type & AddrTypeWork ? true : false;
262  item.home = type & AddrTypeHome ? true : false;
263  item.pref = type & AddrTypePref ? true : false;
264 
265  m_emailList.push_back( item );
266  }
267 
268  void VCard::addAddress( const std::string& pobox, const std::string& extadd,
269  const std::string& street, const std::string& locality,
270  const std::string& region, const std::string& pcode,
271  const std::string& ctry, int type )
272  {
273  if( pobox.empty() && extadd.empty() && street.empty() &&
274  locality.empty() && region.empty() && pcode.empty() && ctry.empty() )
275  return;
276 
277  Address item;
278  item.pobox = pobox;
279  item.extadd = extadd;
280  item.street = street;
281  item.locality = locality;
282  item.region = region;
283  item.pcode = pcode;
284  item.ctry = ctry;
285  item.home = type & AddrTypeHome ? true : false;
286  item.work = type & AddrTypeWork ? true : false;
287  item.parcel = type & AddrTypeParcel ? true : false;
288  item.postal = type & AddrTypePostal ? true : false;
289  item.dom = type & AddrTypeDom ? true : false;
290  item.intl = !item.dom && type & AddrTypeIntl ? true : false;
291  item.pref = type & AddrTypePref ? true : false;
292 
293  m_addressList.push_back( item );
294  }
295 
296  void VCard::addLabel( const StringList& lines, int type )
297  {
298  if( !lines.size() )
299  return;
300 
301  Label item;
302  item.lines = lines;
303  item.work = type & AddrTypeWork ? true : false;
304  item.home = type & AddrTypeHome ? true : false;
305  item.postal = type & AddrTypePostal ? true : false;
306  item.parcel = type & AddrTypeParcel ? true : false;
307  item.pref = type & AddrTypePref ? true : false;
308  item.dom = type & AddrTypeDom ? true : false;
309  item.intl = !item.dom && type & AddrTypeIntl;
310 
311  m_labelList.push_back( item );
312  }
313 
314  void VCard::addTelephone( const std::string& number, int type )
315  {
316  if( number.empty() )
317  return;
318 
319  Telephone item;
320  item.number = number;
321  item.work = type & AddrTypeWork ? true : false;
322  item.home = type & AddrTypeHome ? true : false;
323  item.voice = type & AddrTypeVoice ? true : false;
324  item.fax = type & AddrTypeFax ? true : false;
325  item.pager = type & AddrTypePager ? true : false;
326  item.msg = type & AddrTypeMsg ? true : false;
327  item.cell = type & AddrTypeCell ? true : false;
328  item.video = type & AddrTypeVideo ? true : false;
329  item.bbs = type & AddrTypeBbs ? true : false;
330  item.modem = type & AddrTypeModem ? true : false;
331  item.isdn = type & AddrTypeIsdn ? true : false;
332  item.pcs = type & AddrTypePcs ? true : false;
333  item.pref = type & AddrTypePref ? true : false;
334 
335  m_telephoneList.push_back( item );
336  }
337 
338  void VCard::setGeo( const std::string& lat, const std::string& lon )
339  {
340  if( !lat.empty() && !lon.empty() )
341  {
342  m_geo.latitude = lat;
343  m_geo.longitude = lon;
344  }
345  }
346 
347  void VCard::setOrganization( const std::string& orgname, const StringList& orgunits )
348  {
349  if( !orgname.empty() )
350  {
351  m_org.name = orgname;
352  m_org.units = orgunits;
353  }
354  }
355 
356  Tag* VCard::tag() const
357  {
358  Tag *v = new Tag( "vCard" );
359  v->addAttribute( "xmlns", XMLNS_VCARD_TEMP );
360  v->addAttribute( "version", "3.0" );
361 
362  insertField( v, "FN", m_formattedname );
363  insertField( v, "NICKNAME", m_nickname );
364  insertField( v, "URL", m_url );
365  insertField( v, "BDAY", m_bday );
366  insertField( v, "JABBERID", m_jabberid );
367  insertField( v, "TITLE", m_title );
368  insertField( v, "ROLE", m_role );
369  insertField( v, "NOTE", m_note );
370  insertField( v, "DESC", m_desc );
371  insertField( v, "MAILER", m_mailer );
372  insertField( v, "TZ", m_tz );
373  insertField( v, "REV", m_rev );
374  insertField( v, "SORT_STRING", m_sortstring );
375  insertField( v, "UID", m_uid );
376 
377  if( m_N )
378  {
379  Tag *n = new Tag( v, "N" );
380  insertField( n, "FAMILY", m_name.family );
381  insertField( n, "GIVEN", m_name.given );
382  insertField( n, "MIDDLE", m_name.middle );
383  insertField( n, "PREFIX", m_name.prefix );
384  insertField( n, "SUFFIX", m_name.suffix );
385  }
386 
387  if( m_PHOTO )
388  {
389  Tag *p = new Tag( v, "PHOTO" );
390  if( !m_photo.extval.empty() )
391  {
392  new Tag( p, "EXTVAL", m_photo.extval );
393  }
394  else if( !m_photo.type.empty() && !m_photo.binval.empty() )
395  {
396  new Tag( p, "TYPE", m_photo.type );
397  new Tag( p, "BINVAL", Base64::encode64( m_photo.binval ) );
398  }
399  }
400 
401  if( m_LOGO )
402  {
403  Tag *l = new Tag( v, "LOGO" );
404  if( !m_logo.extval.empty() )
405  {
406  new Tag( l, "EXTVAL", m_logo.extval );
407  }
408  else if( !m_logo.type.empty() && !m_logo.binval.empty() )
409  {
410  new Tag( l, "TYPE", m_logo.type );
411  new Tag( l, "BINVAL", Base64::encode64( m_logo.binval ) );
412  }
413  }
414 
415  EmailList::const_iterator ite = m_emailList.begin();
416  for( ; ite != m_emailList.end(); ++ite )
417  {
418  Tag *e = new Tag( v, "EMAIL" );
419  insertField( e, "INTERNET", (*ite).internet );
420  insertField( e, "WORK", (*ite).work );
421  insertField( e, "HOME", (*ite).home );
422  insertField( e, "X400", (*ite).x400 );
423  insertField( e, "PREF", (*ite).pref );
424  insertField( e, "USERID", (*ite).userid );
425  }
426 
427  AddressList::const_iterator ita = m_addressList.begin();
428  for( ; ita != m_addressList.end(); ++ita )
429  {
430  Tag *a = new Tag( v, "ADR" );
431  insertField( a, "POSTAL", (*ita).postal );
432  insertField( a, "PARCEL", (*ita).parcel );
433  insertField( a, "HOME", (*ita).home );
434  insertField( a, "WORK", (*ita).work );
435  insertField( a, "PREF", (*ita).pref );
436  insertField( a, "DOM", (*ita).dom );
437  if( !(*ita).dom )
438  insertField( a, "INTL", (*ita).intl );
439 
440  insertField( a, "POBOX", (*ita).pobox );
441  insertField( a, "EXTADD", (*ita).extadd );
442  insertField( a, "STREET", (*ita).street );
443  insertField( a, "LOCALITY", (*ita).locality );
444  insertField( a, "REGION", (*ita).region );
445  insertField( a, "PCODE", (*ita).pcode );
446  insertField( a, "CTRY", (*ita).ctry );
447  }
448 
449  TelephoneList::const_iterator itt = m_telephoneList.begin();
450  for( ; itt != m_telephoneList.end(); ++itt )
451  {
452  Tag *t = new Tag( v, "TEL" );
453  insertField( t, "NUMBER", (*itt).number );
454  insertField( t, "HOME", (*itt).home );
455  insertField( t, "WORK", (*itt).work );
456  insertField( t, "VOICE", (*itt).voice );
457  insertField( t, "FAX", (*itt).fax );
458  insertField( t, "PAGER", (*itt).pager );
459  insertField( t, "MSG", (*itt).msg );
460  insertField( t, "CELL", (*itt).cell );
461  insertField( t, "VIDEO", (*itt).video );
462  insertField( t, "BBS", (*itt).bbs );
463  insertField( t, "MODEM", (*itt).modem );
464  insertField( t, "ISDN", (*itt).isdn );
465  insertField( t, "PCS", (*itt).pcs );
466  insertField( t, "PREF", (*itt).pref );
467  }
468 
469  if( !m_geo.latitude.empty() && !m_geo.longitude.empty() )
470  {
471  Tag *g = new Tag( v, "GEO" );
472  new Tag( g, "LAT", m_geo.latitude );
473  new Tag( g, "LON", m_geo.longitude );
474  }
475 
476  if( !m_org.name.empty() )
477  {
478  Tag *o = new Tag( v, "ORG" );
479  new Tag( o, "ORGNAME", m_org.name );
480  StringList::const_iterator ito = m_org.units.begin();
481  for( ; ito != m_org.units.end(); ++ito )
482  new Tag( o, "ORGUNITS", (*ito) );
483  }
484 
485  if( m_class != ClassNone )
486  {
487  Tag *c = new Tag( v, "CLASS" );
488  switch( m_class )
489  {
490  case ClassPublic:
491  new Tag( c, "PUBLIC" );
492  break;
493  case ClassPrivate:
494  new Tag( c, "PRIVATE" );
495  break;
496  case ClassConfidential:
497  new Tag( c, "CONFIDENTIAL" );
498  break;
499  default:
500  break;
501  }
502  }
503 
504  return v;
505  }
506 
507  void VCard::insertField( Tag *vcard, const std::string& field, const std::string& var ) const
508  {
509  if( !var.empty() )
510  new Tag( vcard, field, var );
511  }
512 
513  void VCard::insertField( Tag *vcard, const std::string& field, bool var ) const
514  {
515  if( var )
516  new Tag( vcard, field );
517  }
518 
519 }