gloox  1.0
vcard.cpp
00001 /*
00002   Copyright (c) 2006-2009 by Jakob Schroeter <js@camaya.net>
00003   This file is part of the gloox library. http://camaya.net/gloox
00004 
00005   This software is distributed under a license. The full license
00006   agreement can be found in the file LICENSE in this distribution.
00007   This software may not be copied, modified, sold or distributed
00008   other than expressed in the named license agreement.
00009 
00010   This software is distributed without any warranty.
00011 */
00012 
00013 
00014 #include "vcard.h"
00015 #include "tag.h"
00016 #include "base64.h"
00017 
00018 namespace gloox
00019 {
00020 
00021   void VCard::insertField( Tag* vcard, const char* field, const std::string& var )
00022   {
00023     if( field && !var.empty() )
00024       new Tag( vcard, field, var );
00025   }
00026 
00027   void VCard::insertField( Tag* vcard, const char* field, bool var )
00028   {
00029     if( field && var )
00030       new Tag( vcard, field );
00031   }
00032 
00033   void VCard::checkField( const Tag* vcard, const char* field, std::string& var )
00034   {
00035     if( field )
00036     {
00037       Tag* child = vcard->findChild( field );
00038       if( child )
00039         var = child->cdata();
00040     }
00041   }
00042 
00043   VCard::VCard()
00044     : StanzaExtension( ExtVCard ), m_class( ClassNone ), m_prodid( "gloox" + GLOOX_VERSION ),
00045       m_N( false ), m_PHOTO( false ), m_LOGO( false )
00046   {
00047     m_valid = true;
00048   }
00049 
00050   VCard::VCard( const Tag* vcard )
00051     : StanzaExtension( ExtVCard ), m_class( ClassNone ), m_prodid( "gloox" + GLOOX_VERSION ),
00052       m_N( false ), m_PHOTO( false ), m_LOGO( false )
00053   {
00054     if( !vcard || vcard->name() != "vCard" || vcard->xmlns() != XMLNS_VCARD_TEMP )
00055       return;
00056 
00057     m_valid = true;
00058 
00059     checkField( vcard, "FN", m_formattedname );
00060     checkField( vcard, "NICKNAME", m_nickname );
00061     checkField( vcard, "URL", m_url );
00062     checkField( vcard, "BDAY", m_bday );
00063     checkField( vcard, "JABBERID", m_jabberid );
00064     checkField( vcard, "TITLE", m_title );
00065     checkField( vcard, "ROLE", m_role );
00066     checkField( vcard, "NOTE", m_note );
00067     checkField( vcard, "DESC", m_desc );
00068     checkField( vcard, "MAILER", m_mailer );
00069     checkField( vcard, "TZ", m_tz );
00070     checkField( vcard, "PRODID", m_prodid );
00071     checkField( vcard, "REV", m_rev );
00072     checkField( vcard, "SORT-STRING", m_sortstring );
00073     checkField( vcard, "UID", m_uid );
00074 
00075     TagList::const_iterator it = vcard->children().begin();
00076     for( ; it != vcard->children().end(); ++it )
00077     {
00078       const Tag& tag = *(*it);
00079       if( tag.name() == "N" )
00080       {
00081         m_N = true;
00082         const Tag * child = tag.findChild( "FAMILY" );
00083         if( child )
00084           m_name.family = child->cdata();
00085         if( ( child = tag.findChild( "GIVEN" ) ) )
00086           m_name.given = child->cdata();
00087         if( ( child = tag.findChild( "MIDDLE" ) ) )
00088           m_name.middle = child->cdata();
00089         if( ( child = tag.findChild( "PREFIX" ) ) )
00090           m_name.prefix = child->cdata();
00091         if( ( child = tag.findChild( "SUFFIX" ) ) )
00092           m_name.suffix = child->cdata();
00093       }
00094       else if( tag.name() == "PHOTO" )
00095       {
00096         if( tag.hasChild( "EXTVAL" ) )
00097         {
00098           m_photo.extval = tag.findChild( "EXTVAL" )->cdata();
00099           m_PHOTO = true;
00100         }
00101         else if( tag.hasChild( "TYPE" ) && tag.hasChild( "BINVAL" ) )
00102         {
00103           std::string binval = tag.findChild( "BINVAL" )->cdata();
00104           std::string::size_type pos = 0;
00105           while( ( pos = binval.find( '\n' ) ) != std::string::npos )
00106             binval.erase( pos, 1 );
00107           m_photo.type = tag.findChild( "TYPE" )->cdata();
00108           m_photo.binval = Base64::decode64( binval );
00109           m_PHOTO = true;
00110         }
00111       }
00112       else if( tag.name() == "LOGO" )
00113       {
00114         if( tag.hasChild( "EXTVAL" ) )
00115         {
00116           m_logo.extval = tag.findChild( "EXTVAL" )->cdata();
00117           m_LOGO = true;
00118         }
00119         else if( tag.hasChild( "TYPE" ) && tag.hasChild( "BINVAL" ) )
00120         {
00121           std::string binval = tag.findChild( "BINVAL" )->cdata();
00122           std::string::size_type pos = 0;
00123           while( ( pos = binval.find( '\n' ) ) != std::string::npos )
00124             binval.erase( pos, 1 );
00125           m_logo.type = tag.findChild( "TYPE" )->cdata();
00126           m_logo.binval = Base64::decode64( binval );
00127           m_LOGO = true;
00128         }
00129       }
00130       else if( tag.name() == "EMAIL" && tag.hasChild( "USERID" ) )
00131       {
00132         Email item;
00133         item.userid = tag.findChild( "USERID" )->cdata();
00134         item.internet = tag.hasChild( "INTERNET" );
00135         item.x400 = tag.hasChild( "X400" );
00136         item.work = tag.hasChild( "WORK" );
00137         item.home = tag.hasChild( "HOME" );
00138         item.pref = tag.hasChild( "PREF" );
00139         m_emailList.push_back( item );
00140       }
00141       else if( tag.name() == "ADR" )
00142       {
00143         Address item;
00144         checkField( &tag, "POBOX", item.pobox );
00145         checkField( &tag, "EXTADD", item.extadd );
00146         checkField( &tag, "STREET", item.street );
00147         checkField( &tag, "LOCALITY", item.locality );
00148         checkField( &tag, "REGION", item.region );
00149         checkField( &tag, "PCODE", item.pcode );
00150         checkField( &tag, "CTRY", item.ctry );
00151         item.postal = tag.hasChild( "POSTAL" );
00152         item.parcel = tag.hasChild( "PARCEL" );
00153         item.work = tag.hasChild( "WORK" );
00154         item.home = tag.hasChild( "HOME" );
00155         item.pref = tag.hasChild( "PREF" );
00156         item.dom = tag.hasChild( "DOM" );
00157         item.intl = !item.dom && tag.hasChild( "INTL" );
00158         m_addressList.push_back( item );
00159       }
00160       else if( tag.name() == "LABEL" )
00161       {
00162         Label item;
00163         TagList::const_iterator it2 = tag.children().begin();
00164         for( ; it2 != tag.children().end(); ++it2 )
00165         {
00166           if( (*it2)->name() == "LINE" )
00167             item.lines.push_back( (*it)->cdata() );
00168           item.postal = (*it2)->name() == "POSTAL";
00169           item.parcel = (*it2)->name() == "PARCEL";
00170           item.work = (*it2)->name() == "WORK";
00171           item.home = (*it2)->name() == "HOME";
00172           item.pref = (*it2)->name() == "PREF";
00173           item.dom = (*it2)->name() == "DOM";
00174           item.intl = !item.dom && (*it2)->name() == "INTL";
00175         }
00176         m_labelList.push_back( item );
00177       }
00178       else if( tag.name() == "TEL" && tag.hasChild( "NUMBER" ) )
00179       {
00180         Telephone item;
00181         item.number = tag.findChild( "NUMBER" )->cdata();
00182         item.work = tag.hasChild( "WORK" );
00183         item.home = tag.hasChild( "HOME" );
00184         item.voice = tag.hasChild( "VOICE" );
00185         item.fax = tag.hasChild( "FAX" );
00186         item.pager = tag.hasChild( "PAGER" );
00187         item.msg = tag.hasChild( "MSG" );
00188         item.cell = tag.hasChild( "CELL" );
00189         item.video = tag.hasChild( "VIDEO" );
00190         item.bbs = tag.hasChild( "BBS" );
00191         item.modem = tag.hasChild( "MODEM" );
00192         item.isdn = tag.hasChild( "ISDN" );
00193         item.pcs = tag.hasChild( "PCS" );
00194         item.pref = tag.hasChild( "PREF" );
00195         m_telephoneList.push_back( item );
00196       }
00197       else if( tag.name() == "ORG" )
00198       {
00199         TagList::const_iterator ito = tag.children().begin();
00200         for( ; ito != tag.children().end(); ++ito )
00201         {
00202           if( (*ito)->name() == "ORGNAME" )
00203             m_org.name = (*ito)->cdata();
00204           else if( (*ito)->name() == "ORGUNIT" )
00205             m_org.units.push_back( (*ito)->cdata() );
00206         }
00207       }
00208       else if( tag.name() == "GEO" )
00209       {
00210         checkField( &tag, "LON", m_geo.longitude );
00211         checkField( &tag, "LAT", m_geo.latitude );
00212       }
00213       else if( tag.name() == "CLASS" )
00214       {
00215         if( tag.hasChild( "PRIVATE" ) )
00216           m_class = ClassPrivate;
00217         else if( tag.hasChild( "PUBLIC" ) )
00218           m_class = ClassPublic;
00219         else if( tag.hasChild( "CONFIDENTIAL" ) )
00220           m_class = ClassConfidential;
00221       }
00222 
00223     }
00224 
00225   }
00226 
00227   void VCard::setName( const std::string& family, const std::string& given,
00228                        const std::string& middle, const std::string& prefix,
00229                        const std::string& suffix )
00230   {
00231     m_name.family = family;
00232     m_name.given = given;
00233     m_name.middle = middle;
00234     m_name.prefix = prefix;
00235     m_name.suffix = suffix;
00236     m_N = true;
00237   }
00238 
00239   void VCard::setPhoto( const std::string& extval )
00240   {
00241     if( !extval.empty() )
00242     {
00243       m_photo.extval= extval;
00244       m_PHOTO = true;
00245     }
00246   }
00247 
00248   void VCard::setPhoto( const std::string& type, const std::string& binval )
00249   {
00250     if( !type.empty() && !binval.empty() )
00251     {
00252       m_photo.type = type;
00253       m_photo.binval = binval;
00254       m_PHOTO = true;
00255     }
00256     else
00257     {
00258       m_photo.type = EmptyString;
00259       m_photo.binval = EmptyString;
00260       m_photo.extval = EmptyString;
00261       m_PHOTO = false;
00262     }
00263   }
00264 
00265   void VCard::setLogo( const std::string& extval )
00266   {
00267     if( !extval.empty() )
00268     {
00269       m_logo.extval = extval;
00270       m_LOGO = true;
00271     }
00272   }
00273 
00274   void VCard::setLogo( const std::string& type, const std::string& binval )
00275   {
00276     if( !type.empty() && !binval.empty() )
00277     {
00278       m_logo.type = type;
00279       m_logo.binval = binval;
00280       m_LOGO = true;
00281     }
00282     else
00283     {
00284       m_logo.type = EmptyString;
00285       m_logo.binval = EmptyString;
00286       m_logo.extval = EmptyString;
00287       m_LOGO = false;
00288     }
00289   }
00290 
00291   void VCard::addEmail( const std::string& userid, int type )
00292   {
00293     if( userid.empty() )
00294       return;
00295 
00296     Email item;
00297     item.userid = userid;
00298     item.internet = ((type & AddrTypeInet) == AddrTypeInet);
00299     item.x400 = ((type & AddrTypeX400) == AddrTypeX400);
00300     item.work = ((type & AddrTypeWork) == AddrTypeWork);
00301     item.home = ((type & AddrTypeHome) == AddrTypeHome);
00302     item.pref = ((type & AddrTypePref) == AddrTypePref);
00303 
00304     m_emailList.push_back( item );
00305   }
00306 
00307   void VCard::addAddress( const std::string& pobox, const std::string& extadd,
00308                           const std::string& street, const std::string& locality,
00309                           const std::string& region, const std::string& pcode,
00310                           const std::string& ctry, int type )
00311   {
00312     if( pobox.empty() && extadd.empty() && street.empty() &&
00313         locality.empty() && region.empty() && pcode.empty() && ctry.empty() )
00314       return;
00315 
00316     Address item;
00317     item.pobox = pobox;
00318     item.extadd = extadd;
00319     item.street = street;
00320     item.locality = locality;
00321     item.region = region;
00322     item.pcode = pcode;
00323     item.ctry = ctry;
00324     item.home = ((type & AddrTypeHome) == AddrTypeHome);
00325     item.work = ((type & AddrTypeWork) == AddrTypeWork);
00326     item.parcel = ((type & AddrTypeParcel) == AddrTypeParcel);
00327     item.postal = ((type & AddrTypePostal) == AddrTypePostal);
00328     item.dom = ((type & AddrTypeDom) == AddrTypeDom);
00329     item.intl = !item.dom && ((type & AddrTypeIntl) == AddrTypeIntl);
00330     item.pref = ((type & AddrTypePref) == AddrTypePref);
00331 
00332     m_addressList.push_back( item );
00333   }
00334 
00335   void VCard::addLabel( const StringList& lines, int type )
00336   {
00337     if( lines.empty() )
00338       return;
00339 
00340     Label item;
00341     item.lines = lines;
00342     item.work = ((type & AddrTypeWork) == AddrTypeWork);
00343     item.home = ((type & AddrTypeHome) == AddrTypeHome);
00344     item.postal = ((type & AddrTypePostal) == AddrTypePostal);
00345     item.parcel = ((type & AddrTypeParcel) == AddrTypeParcel);
00346     item.pref = ((type & AddrTypePref) == AddrTypePref);
00347     item.dom = ((type & AddrTypeDom) == AddrTypeDom);
00348     item.intl = !item.dom && ((type & AddrTypeIntl) == AddrTypeIntl);
00349 
00350     m_labelList.push_back( item );
00351   }
00352 
00353   void VCard::addTelephone( const std::string& number, int type )
00354   {
00355     if( number.empty() )
00356       return;
00357 
00358     Telephone item;
00359     item.number = number;
00360     item.work = ((type & AddrTypeWork) == AddrTypeWork);
00361     item.home = ((type & AddrTypeHome) == AddrTypeHome);
00362     item.voice = ((type & AddrTypeVoice) == AddrTypeVoice);
00363     item.fax = ((type & AddrTypeFax) == AddrTypeFax);
00364     item.pager = ((type & AddrTypePager) == AddrTypePager);
00365     item.msg = ((type & AddrTypeMsg) == AddrTypeMsg);
00366     item.cell = ((type & AddrTypeCell) == AddrTypeCell);
00367     item.video = ((type & AddrTypeVideo) == AddrTypeVideo);
00368     item.bbs = ((type & AddrTypeBbs) == AddrTypeBbs);
00369     item.modem = ((type & AddrTypeModem) == AddrTypeModem);
00370     item.isdn = ((type & AddrTypeIsdn) == AddrTypeIsdn);
00371     item.pcs = ((type & AddrTypePcs) == AddrTypePcs);
00372     item.pref = ((type & AddrTypePref) == AddrTypePref);
00373 
00374     m_telephoneList.push_back( item );
00375   }
00376 
00377   void VCard::setGeo( const std::string& lat, const std::string& lon )
00378   {
00379     if( !lat.empty() && !lon.empty() )
00380     {
00381       m_geo.latitude = lat;
00382       m_geo.longitude = lon;
00383     }
00384   }
00385 
00386   void VCard::setOrganization( const std::string& orgname, const StringList& orgunits )
00387   {
00388     if( !orgname.empty() )
00389     {
00390       m_org.name = orgname;
00391       m_org.units = orgunits;
00392     }
00393   }
00394 
00395   const std::string& VCard::filterString() const
00396   {
00397     static const std::string filter = "/iq/vCard[@xmlns='" + XMLNS_VCARD_TEMP + "']";
00398     return filter;
00399   }
00400 
00401   Tag* VCard::tag() const
00402   {
00403     Tag* v = new Tag( "vCard" );
00404     v->setXmlns( XMLNS_VCARD_TEMP );
00405 
00406     if( !m_valid )
00407       return v;
00408 
00409     v->addAttribute( "version", "3.0" );
00410 
00411     insertField( v, "FN", m_formattedname );
00412     insertField( v, "NICKNAME", m_nickname );
00413     insertField( v, "URL", m_url );
00414     insertField( v, "BDAY", m_bday );
00415     insertField( v, "JABBERID", m_jabberid );
00416     insertField( v, "TITLE", m_title );
00417     insertField( v, "ROLE", m_role );
00418     insertField( v, "NOTE", m_note );
00419     insertField( v, "DESC", m_desc );
00420     insertField( v, "MAILER", m_mailer );
00421     insertField( v, "TZ", m_tz );
00422     insertField( v, "REV", m_rev );
00423     insertField( v, "SORT_STRING", m_sortstring );
00424     insertField( v, "UID", m_uid );
00425 
00426     if( m_N )
00427     {
00428       Tag* n = new Tag( v, "N" );
00429       insertField( n, "FAMILY", m_name.family );
00430       insertField( n, "GIVEN", m_name.given );
00431       insertField( n, "MIDDLE", m_name.middle );
00432       insertField( n, "PREFIX", m_name.prefix );
00433       insertField( n, "SUFFIX", m_name.suffix );
00434     }
00435 
00436     if( m_PHOTO )
00437     {
00438       Tag* p = new Tag( v, "PHOTO" );
00439       if( !m_photo.extval.empty() )
00440       {
00441         new Tag( p, "EXTVAL", m_photo.extval );
00442       }
00443       else if( !m_photo.type.empty() && !m_photo.binval.empty() )
00444       {
00445         new Tag( p, "TYPE", m_photo.type );
00446         new Tag( p, "BINVAL", Base64::encode64( m_photo.binval ) );
00447       }
00448     }
00449 
00450     if( m_LOGO )
00451     {
00452       Tag* l = new Tag( v, "LOGO" );
00453       if( !m_logo.extval.empty() )
00454       {
00455         new Tag( l, "EXTVAL", m_logo.extval );
00456       }
00457       else if( !m_logo.type.empty() && !m_logo.binval.empty() )
00458       {
00459         new Tag( l, "TYPE", m_logo.type );
00460         new Tag( l, "BINVAL", Base64::encode64( m_logo.binval ) );
00461       }
00462     }
00463 
00464     EmailList::const_iterator ite = m_emailList.begin();
00465     for( ; ite != m_emailList.end(); ++ite )
00466     {
00467       Tag* e = new Tag( v, "EMAIL" );
00468       insertField( e, "INTERNET", (*ite).internet );
00469       insertField( e, "WORK", (*ite).work );
00470       insertField( e, "HOME", (*ite).home );
00471       insertField( e, "X400", (*ite).x400 );
00472       insertField( e, "PREF", (*ite).pref );
00473       insertField( e, "USERID", (*ite).userid );
00474     }
00475 
00476     AddressList::const_iterator ita = m_addressList.begin();
00477     for( ; ita != m_addressList.end(); ++ita )
00478     {
00479       Tag* a = new Tag( v, "ADR" );
00480       insertField( a, "POSTAL", (*ita).postal );
00481       insertField( a, "PARCEL", (*ita).parcel );
00482       insertField( a, "HOME", (*ita).home );
00483       insertField( a, "WORK", (*ita).work );
00484       insertField( a, "PREF", (*ita).pref );
00485       insertField( a, "DOM", (*ita).dom );
00486       if( !(*ita).dom )
00487         insertField( a, "INTL", (*ita).intl );
00488 
00489       insertField( a, "POBOX", (*ita).pobox );
00490       insertField( a, "EXTADD", (*ita).extadd );
00491       insertField( a, "STREET", (*ita).street );
00492       insertField( a, "LOCALITY", (*ita).locality );
00493       insertField( a, "REGION", (*ita).region );
00494       insertField( a, "PCODE", (*ita).pcode );
00495       insertField( a, "CTRY", (*ita).ctry );
00496     }
00497 
00498     TelephoneList::const_iterator itt = m_telephoneList.begin();
00499     for( ; itt != m_telephoneList.end(); ++itt )
00500     {
00501       Tag* t = new Tag( v, "TEL" );
00502       insertField( t, "NUMBER", (*itt).number );
00503       insertField( t, "HOME", (*itt).home );
00504       insertField( t, "WORK", (*itt).work );
00505       insertField( t, "VOICE", (*itt).voice );
00506       insertField( t, "FAX", (*itt).fax );
00507       insertField( t, "PAGER", (*itt).pager );
00508       insertField( t, "MSG", (*itt).msg );
00509       insertField( t, "CELL", (*itt).cell );
00510       insertField( t, "VIDEO", (*itt).video );
00511       insertField( t, "BBS", (*itt).bbs );
00512       insertField( t, "MODEM", (*itt).modem );
00513       insertField( t, "ISDN", (*itt).isdn );
00514       insertField( t, "PCS", (*itt).pcs );
00515       insertField( t, "PREF", (*itt).pref );
00516     }
00517 
00518     if( !m_geo.latitude.empty() && !m_geo.longitude.empty() )
00519     {
00520       Tag* g = new Tag( v, "GEO" );
00521       new Tag( g, "LAT", m_geo.latitude );
00522       new Tag( g, "LON", m_geo.longitude );
00523     }
00524 
00525     if( !m_org.name.empty() )
00526     {
00527       Tag* o = new Tag( v, "ORG" );
00528       new Tag( o, "ORGNAME", m_org.name );
00529       StringList::const_iterator ito = m_org.units.begin();
00530       for( ; ito != m_org.units.end(); ++ito )
00531         new Tag( o, "ORGUNIT", (*ito) );
00532     }
00533 
00534     if( m_class != ClassNone )
00535     {
00536       Tag* c = new Tag( v, "CLASS" );
00537       switch( m_class )
00538       {
00539         case ClassPublic:
00540           new Tag( c, "PUBLIC" );
00541           break;
00542         case ClassPrivate:
00543           new Tag( c, "PRIVATE" );
00544           break;
00545         case ClassConfidential:
00546           new Tag( c, "CONFIDENTIAL" );
00547           break;
00548         default:
00549           break;
00550       }
00551     }
00552 
00553     return v;
00554   }
00555 }