00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
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 )
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 )
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 * , int )
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
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
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
00329
00330
00331
00332
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
00355
00356
00357
00358
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
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 *xml )
00468 {
00469 m_delimiter = xml->cdata();
00470 }
00471
00472 void RosterManager::handlePrivateXMLResult( const std::string& , PrivateXMLResult )
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 }