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