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 ), m_delimiterFetched( false ),
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 m_roster[m_parent->jid().bare()] = i;
00039 }
00040
00041 m_privateXML = new PrivateXML( m_parent );
00042 }
00043 }
00044
00045 RosterManager::~RosterManager()
00046 {
00047 if( m_parent )
00048 {
00049 m_parent->removeIqHandler( XMLNS_ROSTER );
00050 m_parent->removePresenceHandler( this );
00051 m_parent->removeSubscriptionHandler( this );
00052 }
00053
00054 RosterListener::Roster::iterator it = m_roster.begin();
00055 for( ; it != m_roster.end(); ++it )
00056 delete( (*it).second );
00057 m_roster.clear();
00058
00059 if( m_privateXML )
00060 delete m_privateXML;
00061 }
00062
00063 RosterListener::Roster* RosterManager::roster()
00064 {
00065 return &m_roster;
00066 }
00067
00068 void RosterManager::fill()
00069 {
00070 if( !m_delimiterFetched )
00071 {
00072 m_privateXML->requestXML( "roster", XMLNS_ROSTER_DELIMITER, this );
00073 return;
00074 }
00075
00076 Tag *iq = new Tag( "iq" );
00077 iq->addAttrib( "type", "get" );
00078 iq->addAttrib( "id", m_parent->getID() );
00079 Tag *q = new Tag( "query" );
00080 q->addAttrib( "xmlns", XMLNS_ROSTER );
00081 iq->addChild( q );
00082 m_parent->send( iq );
00083 }
00084
00085 bool RosterManager::handleIq( Stanza *stanza )
00086 {
00087 if( stanza->subtype() == STANZA_IQ_RESULT )
00088 {
00089 extractItems( stanza, false );
00090
00091 if( m_rosterListener )
00092 m_rosterListener->roster( m_roster );
00093
00094 return true;
00095 }
00096 else if( stanza->subtype() == STANZA_IQ_SET )
00097 {
00098 extractItems( stanza, true );
00099
00100 Tag *iq = new Tag( "iq" );
00101 iq->addAttrib( "id", stanza->id() );
00102 iq->addAttrib( "type", "result" );
00103 m_parent->send( iq );
00104
00105 return true;
00106 }
00107 return false;
00108 }
00109
00110 void RosterManager::handlePresence( Stanza *stanza )
00111 {
00112 RosterListener::Roster::iterator it = m_roster.find( stanza->from().bare() );
00113 if( it != m_roster.end() )
00114 {
00115 PresenceStatus oldStat = (*it).second->status();
00116
00117 (*it).second->setStatus( stanza->show() );
00118 (*it).second->setStatusMsg( stanza->status() );
00119
00120 if( m_rosterListener )
00121 {
00122 if( stanza->show() == PRESENCE_AVAILABLE )
00123 {
00124 if( oldStat == PRESENCE_UNAVAILABLE )
00125 m_rosterListener->itemAvailable( (*(*it).second), stanza->status() );
00126 else
00127 m_rosterListener->itemChanged( (*(*it).second), stanza->show(), stanza->status() );
00128 }
00129 else if( stanza->show() == PRESENCE_UNAVAILABLE )
00130 m_rosterListener->itemUnavailable( (*(*it).second), stanza->status() );
00131 else
00132 m_rosterListener->itemChanged( (*(*it).second), stanza->show(), stanza->status() );
00133 }
00134 }
00135 else
00136 {
00137 StringList sl;
00138 add( stanza->from().bare(), std::string(), sl, "none", false );
00139 m_roster[stanza->from().bare()]->setStatus( stanza->show() );
00140 m_roster[stanza->from().bare()]->setStatusMsg( stanza->status() );
00141 }
00142 }
00143
00144 void RosterManager::subscribe( const std::string& jid, const std::string& name,
00145 StringList& groups, const std::string& msg )
00146 {
00147 if( jid.empty() )
00148 return;
00149
00150 add( jid, name, groups );
00151
00152 Tag *s = new Tag( "presence" );
00153 s->addAttrib( "type", "subscribe" );
00154 s->addAttrib( "to", jid );
00155 s->addAttrib( "from", m_parent->jid().full() );
00156 if( !msg.empty() )
00157 new Tag( s, "status", msg );
00158
00159 m_parent->send( s );
00160 }
00161
00162
00163 void RosterManager::add( const std::string& jid, const std::string& name, StringList& groups )
00164 {
00165 if( jid.empty() )
00166 return;
00167
00168 std::string id = m_parent->getID();
00169
00170 Tag *iq = new Tag( "iq" );
00171 iq->addAttrib( "type", "set" );
00172 iq->addAttrib( "id", id );
00173 Tag *q = new Tag( "query" );
00174 q->addAttrib( "xmlns", XMLNS_ROSTER );
00175 Tag *i = new Tag( "item" );
00176 i->addAttrib( "jid", jid );
00177 if( !name.empty() )
00178 i->addAttrib( "name", name );
00179
00180 if( groups.size() != 0 )
00181 {
00182 StringList::const_iterator it = groups.begin();
00183 for( ; it != groups.end(); ++it )
00184 {
00185 Tag *g = new Tag( "group", (*it) );
00186 i->addChild( g );
00187 }
00188 }
00189 q->addChild( i );
00190 iq->addChild( q );
00191 m_parent->send( iq );
00192 }
00193
00194 void RosterManager::unsubscribe( const std::string& jid, const std::string& msg, bool remove )
00195 {
00196 Tag *s = new Tag( "presence" );
00197 s->addAttrib( "type", "unsubscribe" );
00198 s->addAttrib( "from", m_parent->jid().bare() );
00199 s->addAttrib( "to", jid );
00200 if( !msg.empty() )
00201 new Tag( s, "status", msg );
00202
00203 m_parent->send( s );
00204
00205 if( remove )
00206 {
00207 std::string id = m_parent->getID();
00208
00209 Tag *iq = new Tag( "iq" );
00210 iq->addAttrib( "type", "set" );
00211 iq->addAttrib( "id", id );
00212 Tag *q = new Tag( "query" );
00213 q->addAttrib( "xmlns", XMLNS_ROSTER );
00214 Tag *i = new Tag( "item" );
00215 i->addAttrib( "jid", jid );
00216 i->addAttrib( "subscription", "remove" );
00217 q->addChild( i );
00218 iq->addChild( q );
00219
00220 m_parent->send( iq );
00221 }
00222 }
00223
00224 void RosterManager::synchronize()
00225 {
00226 RosterListener::Roster::const_iterator it = m_roster.begin();
00227 for( ; it != m_roster.end(); ++it )
00228 {
00229 if( (*it).second->changed() )
00230 {
00231 std::string id = m_parent->getID();
00232
00233 Tag *iq = new Tag( "iq" );
00234 iq->addAttrib( "type", "set" );
00235 iq->addAttrib( "id", id );
00236 Tag *q = new Tag( "query" );
00237 q->addAttrib( "xmlns", XMLNS_ROSTER );
00238 Tag *i = new Tag( "item" );
00239 i->addAttrib( "jid", (*it).second->jid() );
00240 if( !(*it).second->name().empty() )
00241 i->addAttrib( "name", (*it).second->name() );
00242
00243 if( (*it).second->groups().size() != 0 )
00244 {
00245 StringList::const_iterator g_it = (*it).second->groups().begin();
00246 for( ; g_it != (*it).second->groups().end(); ++g_it )
00247 {
00248 i->addChild( new Tag( "group", (*g_it) ) );
00249 }
00250 }
00251 q->addChild( i );
00252 iq->addChild( q );
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->addAttrib( "type", "subscribed" );
00264 else
00265 p->addAttrib( "type", "unsubscribed" );
00266
00267 p->addAttrib( "from", m_parent->jid().bare() );
00268 p->addAttrib( "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 STANZA_S10N_SUBSCRIBE:
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 STANZA_S10N_SUBSCRIBED:
00289 {
00290
00291
00292
00293
00294
00295
00296 m_rosterListener->itemSubscribed( stanza->from().bare() );
00297 break;
00298 }
00299
00300 case STANZA_S10N_UNSUBSCRIBE:
00301 {
00302 Tag *p = new Tag( "presence" );
00303 p->addAttrib( "type", "unsubscribed" );
00304 p->addAttrib( "from", m_parent->jid().bare() );
00305 p->addAttrib( "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 STANZA_S10N_UNSUBSCRIBED:
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
00384 if( m_rosterListener )
00385 m_rosterListener->itemUpdated( jid );
00386 }
00387 else
00388 {
00389 const std::string sub = (*it)->findAttribute( "subscription" );
00390 if( sub == "remove" )
00391 continue;
00392 const std::string name = (*it)->findAttribute( "name" );
00393 const std::string ask = (*it)->findAttribute( "ask" );
00394 bool a = false;
00395 if( !ask.empty() )
00396 a = true;
00397
00398 add( jid, name, gl, sub, a );
00399 if( isPush && m_rosterListener )
00400 m_rosterListener->itemAdded( jid );
00401 }
00402 }
00403 }
00404 }
00405
00406 void RosterManager::add( const std::string& jid, const std::string& name,
00407 StringList& groups, const std::string& sub, bool ask )
00408 {
00409 if( m_roster.find( jid ) == m_roster.end() )
00410 m_roster[jid] = new RosterItem( jid, name );
00411
00412 m_roster[jid]->setStatus( PRESENCE_UNAVAILABLE );
00413 m_roster[jid]->setSubscription( sub, ask );
00414 m_roster[jid]->setGroups( groups );
00415 }
00416
00417 void RosterManager::setDelimiter( const std::string& delimiter )
00418 {
00419 m_delimiter = delimiter;
00420 Tag *t = new Tag( "roster", m_delimiter );
00421 t->addAttrib( "xmlns", XMLNS_ROSTER_DELIMITER );
00422 m_privateXML->storeXML( t, this );
00423 }
00424
00425 void RosterManager::handlePrivateXML( const std::string& , Tag *xml )
00426 {
00427 m_delimiterFetched = true;
00428 m_delimiter = xml->cdata();
00429 fill();
00430 }
00431
00432 void RosterManager::handlePrivateXMLResult( const std::string , PrivateXMLResult result )
00433 {
00434 m_delimiterFetched = true;
00435 if( result == PrivateXMLHandler::PXML_REQUEST_ERROR )
00436 fill();
00437 }
00438
00439 }