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