rostermanager.cpp

00001 /*
00002   Copyright (c) 2004-2007 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 "clientbase.h"
00015 #include "rostermanager.h"
00016 #include "disco.h"
00017 #include "rosteritem.h"
00018 #include "rosterlistener.h"
00019 #include "privatexml.h"
00020 
00021 
00022 namespace gloox
00023 {
00024 
00025   RosterManager::RosterManager( ClientBase *parent )
00026     : m_rosterListener( 0 ), m_parent( parent ), m_privateXML( 0 ),
00027       m_syncSubscribeReq( false )
00028   {
00029     if( m_parent )
00030     {
00031       m_parent->registerIqHandler( this, XMLNS_ROSTER );
00032       m_parent->registerPresenceHandler( this );
00033       m_parent->registerSubscriptionHandler( this );
00034 
00035       m_self = new RosterItem( m_parent->jid().bare() );
00036 
00037       m_privateXML = new PrivateXML( m_parent );
00038     }
00039   }
00040 
00041   RosterManager::~RosterManager()
00042   {
00043     if( m_parent )
00044     {
00045       m_parent->removeIqHandler( XMLNS_ROSTER );
00046       m_parent->removePresenceHandler( this );
00047       m_parent->removeSubscriptionHandler( this );
00048       delete m_self;
00049       delete m_privateXML;
00050     }
00051 
00052     Roster::iterator it = m_roster.begin();
00053     for( ; it != m_roster.end(); ++it )
00054       delete (*it).second;
00055     m_roster.clear();
00056   }
00057 
00058   Roster* RosterManager::roster()
00059   {
00060     return &m_roster;
00061   }
00062 
00063   void RosterManager::fill()
00064   {
00065     m_privateXML->requestXML( "roster", XMLNS_ROSTER_DELIMITER, this );
00066 
00067     Tag *iq = new Tag( "iq" );
00068     iq->addAttribute( "type", "get" );
00069     iq->addAttribute( "id", m_parent->getID() );
00070     Tag *q = new Tag( iq, "query" );
00071     q->addAttribute( "xmlns", XMLNS_ROSTER );
00072     m_parent->send( iq );
00073   }
00074 
00075   bool RosterManager::handleIq( Stanza *stanza )
00076   {
00077     if( stanza->subtype() == StanzaIqResult ) // initial roster
00078     {
00079       extractItems( stanza, false );
00080 
00081       if( m_rosterListener )
00082         m_rosterListener->handleRoster( m_roster );
00083 
00084       m_parent->rosterFilled();
00085 
00086       return true;
00087     }
00088     else if( stanza->subtype() == StanzaIqSet ) // roster item push
00089     {
00090       extractItems( stanza, true );
00091 
00092       Tag *iq = new Tag( "iq" );
00093       iq->addAttribute( "id", stanza->id() );
00094       iq->addAttribute( "type", "result" );
00095       m_parent->send( iq );
00096 
00097       return true;
00098     }
00099     else if( stanza->subtype() == StanzaIqError )
00100     {
00101       if( m_rosterListener )
00102         m_rosterListener->handleRosterError( stanza );
00103     }
00104 
00105     return false;
00106   }
00107 
00108   bool RosterManager::handleIqID( Stanza * /*stanza*/, int /*context*/ )
00109   {
00110     return false;
00111   }
00112 
00113   void RosterManager::handlePresence( Stanza *stanza )
00114   {
00115     if( stanza->subtype() == StanzaPresenceError )
00116       return;
00117 
00118     StringList caps;
00119     const Tag::TagList& l = stanza->children();
00120     Tag::TagList::const_iterator it_c = l.begin();
00121     for( ; it_c != l.end(); ++it_c )
00122     {
00123       if( (*it_c)->name() == "c" )
00124       {
00125         std::string cap;
00126         cap.append( (*it_c)->findAttribute( "node" ).c_str() );
00127         cap.append( "#" );
00128         cap.append( (*it_c)->findAttribute( "ver" ).c_str() );
00129         if( (*it_c)->findAttribute( "ext" ).size ())
00130         {
00131           cap.append( "#" );
00132           cap.append( (*it_c)->findAttribute( "ext" ).c_str() );
00133         }
00134         caps.push_back( cap );
00135       }
00136     }
00137 
00138     Roster::iterator it = m_roster.find( stanza->from().bare() );
00139     if( it != m_roster.end() )
00140     {
00141       if( stanza->presence() == PresenceUnavailable )
00142         (*it).second->removeResource( stanza->from().resource() );
00143       else
00144       {
00145         (*it).second->setPresence( stanza->from().resource(), stanza->presence() );
00146         (*it).second->setStatus( stanza->from().resource(), stanza->status() );
00147         (*it).second->setPriority( stanza->from().resource(), stanza->priority() );
00148   //       (*it).second->setCaps ( caps );
00149       }
00150 
00151       if( m_rosterListener )
00152         m_rosterListener->handleRosterPresence( (*(*it).second), stanza->from().resource(),
00153                                                 stanza->presence(), stanza->status() );
00154     }
00155     else if( stanza->from().bare() == m_self->jid() )
00156     {
00157       if( stanza->presence() == PresenceUnavailable )
00158         m_self->removeResource( stanza->from().resource() );
00159       else
00160       {
00161         m_self->setPresence( stanza->from().resource(), stanza->presence() );
00162         m_self->setStatus( stanza->from().resource(), stanza->status() );
00163         m_self->setPriority( stanza->from().resource(), stanza->priority() );
00164   //       (*it).second->setCaps ( caps );
00165       }
00166 
00167       if( m_rosterListener )
00168         m_rosterListener->handleSelfPresence( *m_self, stanza->from().resource(),
00169                                               stanza->presence(), stanza->status() );
00170     }
00171     else
00172     {
00173       if( m_rosterListener )
00174         m_rosterListener->handleNonrosterPresence( stanza );
00175     }
00176   }
00177 
00178   void RosterManager::subscribe( const JID& jid, const std::string& name,
00179                                  const StringList& groups, const std::string& msg )
00180   {
00181     if( !jid )
00182       return;
00183 
00184     add( jid, name, groups );
00185 
00186     Tag *s = new Tag( "presence" );
00187     s->addAttribute( "type", "subscribe" );
00188     s->addAttribute( "to", jid.bare() );
00189     s->addAttribute( "from", m_parent->jid().full() );
00190     if( !msg.empty() )
00191       new Tag( s, "status", msg );
00192 
00193     m_parent->send( s );
00194   }
00195 
00196 
00197   void RosterManager::add( const JID& jid, const std::string& name, const StringList& groups )
00198   {
00199     if( !jid )
00200       return;
00201 
00202     const std::string& id = m_parent->getID();
00203 
00204     Tag *iq = new Tag( "iq" );
00205     iq->addAttribute( "type", "set" );
00206     iq->addAttribute( "id", id );
00207     Tag *q = new Tag( iq, "query" );
00208     q->addAttribute( "xmlns", XMLNS_ROSTER );
00209     Tag *i = new Tag( q, "item" );
00210     i->addAttribute( "jid", jid.bare() );
00211     if( !name.empty() )
00212       i->addAttribute( "name", name );
00213 
00214     if( groups.size() != 0 )
00215     {
00216       StringList::const_iterator it = groups.begin();
00217       for( ; it != groups.end(); ++it )
00218         new Tag( i, "group", (*it) );
00219     }
00220 
00221     m_parent->send( iq );
00222   }
00223 
00224   void RosterManager::unsubscribe( const JID& jid, const std::string& msg )
00225   {
00226     Tag *s = new Tag( "presence" );
00227     s->addAttribute( "type", "unsubscribe" );
00228     s->addAttribute( "from", m_parent->jid().bare() );
00229     s->addAttribute( "to", jid.bare() );
00230     if( !msg.empty() )
00231       new Tag( s, "status", msg );
00232 
00233     m_parent->send( s );
00234 
00235   }
00236 
00237   void RosterManager::cancel( const JID& jid, const std::string& msg )
00238   {
00239     Tag *s = new Tag( "presence" );
00240     s->addAttribute( "type", "unsubscribed" );
00241     s->addAttribute( "from", m_parent->jid().bare() );
00242     s->addAttribute( "to", jid.bare() );
00243     if( !msg.empty() )
00244       new Tag( s, "status", msg );
00245 
00246     m_parent->send( s );
00247 
00248   }
00249 
00250   void RosterManager::remove( const JID& jid )
00251   {
00252     const std::string& id = m_parent->getID();
00253 
00254     Tag *iq = new Tag( "iq" );
00255     iq->addAttribute( "type", "set" );
00256     iq->addAttribute( "id", id );
00257     Tag *q = new Tag( iq, "query" );
00258     q->addAttribute( "xmlns", XMLNS_ROSTER );
00259     Tag *i = new Tag( q, "item" );
00260     i->addAttribute( "jid", jid.bare() );
00261     i->addAttribute( "subscription", "remove" );
00262 
00263     m_parent->send( iq );
00264   }
00265 
00266   void RosterManager::synchronize()
00267   {
00268     Roster::const_iterator it = m_roster.begin();
00269     for( ; it != m_roster.end(); ++it )
00270     {
00271       if( (*it).second->changed() )
00272       {
00273         const std::string& id = m_parent->getID();
00274 
00275         Tag *iq = new Tag( "iq" );
00276         iq->addAttribute( "type", "set" );
00277         iq->addAttribute( "id", id );
00278         Tag *q = new Tag( iq, "query" );
00279         q->addAttribute( "xmlns", XMLNS_ROSTER );
00280         Tag *i = new Tag( q, "item" );
00281         i->addAttribute( "jid", (*it).second->jid() );
00282         if( !(*it).second->name().empty() )
00283           i->addAttribute( "name", (*it).second->name() );
00284 
00285         if( (*it).second->groups().size() != 0 )
00286         {
00287           StringList::const_iterator g_it = (*it).second->groups().begin();
00288           for( ; g_it != (*it).second->groups().end(); ++g_it )
00289             new Tag( i, "group", (*g_it) );
00290         }
00291 
00292         m_parent->send( iq );
00293       }
00294     }
00295   }
00296 
00297   void RosterManager::ackSubscriptionRequest( const JID& to, bool ack )
00298   {
00299     Tag *p = new Tag( "presence" );
00300     if( ack )
00301       p->addAttribute( "type", "subscribed" );
00302     else
00303       p->addAttribute( "type", "unsubscribed" );
00304 
00305     p->addAttribute( "from", m_parent->jid().bare() );
00306     p->addAttribute( "to", to.bare() );
00307     m_parent->send( p );
00308   }
00309 
00310   void RosterManager::handleSubscription( Stanza *stanza )
00311   {
00312     if( !m_rosterListener )
00313       return;
00314 
00315     switch( stanza->subtype() )
00316     {
00317       case StanzaS10nSubscribe:
00318       {
00319         bool answer = m_rosterListener->handleSubscriptionRequest( stanza->from(), stanza->status() );
00320         if( m_syncSubscribeReq )
00321         {
00322           ackSubscriptionRequest( stanza->from(), answer );
00323         }
00324         break;
00325       }
00326       case StanzaS10nSubscribed:
00327       {
00328 //         Tag *p = new Tag( "presence" );
00329 //         p->addAttribute( "type", "subscribe" );
00330 //         p->addAttribute( "from", m_parent->jid().bare() );
00331 //         p->addAttribute( "to", stanza->from().bare() );
00332 //         m_parent->send( p );
00333 
00334         m_rosterListener->handleItemSubscribed( stanza->from() );
00335         break;
00336       }
00337 
00338       case StanzaS10nUnsubscribe:
00339       {
00340         Tag *p = new Tag( "presence" );
00341         p->addAttribute( "type", "unsubscribed" );
00342         p->addAttribute( "from", m_parent->jid().bare() );
00343         p->addAttribute( "to", stanza->from().bare() );
00344         m_parent->send( p );
00345 
00346         bool answer = m_rosterListener->handleUnsubscriptionRequest( stanza->from(), stanza->status() );
00347         if( m_syncSubscribeReq && answer )
00348           remove( stanza->from().bare() );
00349         break;
00350       }
00351 
00352       case StanzaS10nUnsubscribed:
00353       {
00354 //         Tag *p = new Tag( "presence" );
00355 //         p->addAttribute( "type", "unsubscribe" );
00356 //         p->addAttribute( "from", m_parent->jid().bare() );
00357 //         p->addAttribute( "to", stanza->from().bare() );
00358 //         m_parent->send( p );
00359 
00360         m_rosterListener->handleItemUnsubscribed( stanza->from() );
00361         break;
00362       }
00363 
00364       default:
00365         break;
00366     }
00367   }
00368 
00369   void RosterManager::registerRosterListener( RosterListener *rl, bool syncSubscribeReq )
00370   {
00371     m_syncSubscribeReq = syncSubscribeReq;
00372     m_rosterListener = rl;
00373   }
00374 
00375   void RosterManager::removeRosterListener()
00376   {
00377     m_syncSubscribeReq = false;
00378     m_rosterListener = 0;
00379   }
00380 
00381   void RosterManager::extractItems( Tag *tag, bool isPush )
00382   {
00383     Tag *t = tag->findChild( "query" );
00384     const Tag::TagList& l = t->children();
00385     Tag::TagList::const_iterator it = l.begin();
00386     for( ; it != l.end(); ++it )
00387     {
00388       if( (*it)->name() == "item" )
00389       {
00390         StringList gl;
00391         if( (*it)->hasChild( "group" ) )
00392         {
00393           const Tag::TagList& g = (*it)->children();
00394           Tag::TagList::const_iterator it_g = g.begin();
00395           for( ; it_g != g.end(); ++it_g )
00396           {
00397             gl.push_back( (*it_g)->cdata() );
00398           }
00399         }
00400 
00401         const JID& jid = (*it)->findAttribute( "jid" );
00402         Roster::iterator it_d = m_roster.find( jid.bare() );
00403         if( it_d != m_roster.end() )
00404         {
00405           (*it_d).second->setName( (*it)->findAttribute( "name" ) );
00406           const std::string& sub = (*it)->findAttribute( "subscription" );
00407           if( sub == "remove" )
00408           {
00409             delete (*it_d).second;
00410             m_roster.erase( it_d );
00411             if( m_rosterListener )
00412               m_rosterListener->handleItemRemoved( jid );
00413             continue;
00414           }
00415           const std::string& ask = (*it)->findAttribute( "ask" );
00416           bool a = false;
00417           if( !ask.empty() )
00418             a = true;
00419           (*it_d).second->setSubscription( sub, a );
00420           (*it_d).second->setGroups( gl );
00421           (*it_d).second->setSynchronized();
00422 
00423           if( isPush && m_rosterListener )
00424             m_rosterListener->handleItemUpdated( jid );
00425         }
00426         else
00427         {
00428           const std::string& sub = (*it)->findAttribute( "subscription" );
00429           if( sub == "remove" )
00430             continue;
00431           const std::string& name = (*it)->findAttribute( "name" );
00432           const std::string& ask = (*it)->findAttribute( "ask" );
00433           bool a = false;
00434           if( !ask.empty() )
00435             a = true;
00436 
00437           StringList caps;
00438           add( jid.bare(), name, gl, caps, sub, a );
00439           if( isPush && m_rosterListener )
00440             m_rosterListener->handleItemAdded( jid );
00441         }
00442       }
00443     }
00444   }
00445 
00446   void RosterManager::add( const std::string& jid, const std::string& name,
00447                            const StringList& groups, const StringList& caps,
00448                            const std::string& sub, bool ask )
00449   {
00450     if( m_roster.find( jid ) == m_roster.end() )
00451       m_roster[jid] = new RosterItem( jid, name );
00452 
00453     m_roster[jid]->setSubscription( sub, ask );
00454     m_roster[jid]->setGroups( groups );
00455 //     m_roster[jid]->setCaps( caps );
00456     m_roster[jid]->setSynchronized();
00457   }
00458 
00459   void RosterManager::setDelimiter( const std::string& delimiter )
00460   {
00461     m_delimiter = delimiter;
00462     Tag *t = new Tag( "roster", m_delimiter );
00463     t->addAttribute( "xmlns", XMLNS_ROSTER_DELIMITER );
00464     m_privateXML->storeXML( t, this );
00465   }
00466 
00467   void RosterManager::handlePrivateXML( const std::string& /*tag*/, Tag *xml )
00468   {
00469     m_delimiter = xml->cdata();
00470   }
00471 
00472   void RosterManager::handlePrivateXMLResult( const std::string& /*uid*/, PrivateXMLResult /*result*/ )
00473   {
00474   }
00475 
00476   RosterItem* RosterManager::getRosterItem( const JID& jid )
00477   {
00478     Roster::const_iterator it = m_roster.find( jid.bare() );
00479     if( it != m_roster.end() )
00480       return (*it).second;
00481     else
00482       return 0;
00483   }
00484 
00485 }

Generated on Sat Nov 10 08:50:27 2007 for gloox by  doxygen 1.5.3-20071008