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