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