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