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 "rosteritemdata.h"
00019 #include "rosterlistener.h"
00020 #include "privatexml.h"
00021 #include "util.h"
00022 #include "stanzaextension.h"
00023 #include "capabilities.h"
00024
00025
00026 namespace gloox
00027 {
00028
00029
00030 RosterManager::Query::Query( const JID& jid, const std::string& name, const StringList& groups )
00031 : StanzaExtension( ExtRoster )
00032 {
00033 m_roster.push_back( new RosterItemData( jid.bare(), name, groups ) );
00034 }
00035
00036 RosterManager::Query::Query( const JID& jid )
00037 : StanzaExtension( ExtRoster )
00038 {
00039 m_roster.push_back( new RosterItemData( jid.bare() ) );
00040 }
00041
00042 RosterManager::Query::Query( const Tag* tag )
00043 : StanzaExtension( ExtRoster )
00044 {
00045 if( !tag || tag->name() != "query" || tag->xmlns() != XMLNS_ROSTER )
00046 return;
00047
00048 const ConstTagList& l = tag->findTagList( "query/item" );
00049 ConstTagList::const_iterator it = l.begin();
00050 for( ; it != l.end(); ++it )
00051 {
00052 StringList groups;
00053 const ConstTagList& g = (*it)->findTagList( "item/group" );
00054 ConstTagList::const_iterator it_g = g.begin();
00055 for( ; it_g != g.end(); ++it_g )
00056 groups.push_back( (*it_g)->cdata() );
00057
00058 const std::string sub = (*it)->findAttribute( "subscription" );
00059 if( sub == "remove" )
00060 m_roster.push_back( new RosterItemData( (*it)->findAttribute( "jid" ) ) );
00061 else
00062 {
00063 RosterItemData* rid = new RosterItemData( (*it)->findAttribute( "jid" ),
00064 (*it)->findAttribute( "name" ),
00065 groups );
00066 rid->setSubscription( sub, (*it)->findAttribute( "ask" ) );
00067 m_roster.push_back( rid );
00068 }
00069 }
00070 }
00071
00072 RosterManager::Query::~Query()
00073 {
00074
00075
00076 RosterData::iterator it = m_roster.begin();
00077 RosterData::iterator it2;
00078 while( it != m_roster.end() )
00079 {
00080 it2 = it++;
00081 delete (*it2);
00082 m_roster.erase( it2 );
00083 }
00084
00085 }
00086
00087 const std::string& RosterManager::Query::filterString() const
00088 {
00089 static const std::string filter = "/iq/query[@xmlns='" + XMLNS_ROSTER + "']";
00090 return filter;
00091 }
00092
00093 Tag* RosterManager::Query::tag() const
00094 {
00095 Tag* t = new Tag( "query" );
00096 t->setXmlns( XMLNS_ROSTER );
00097
00098 RosterData::const_iterator it = m_roster.begin();
00099 for( ; it != m_roster.end(); ++it )
00100 t->addChild( (*it)->tag() );
00101
00102 return t;
00103 }
00104
00105
00106
00107 RosterManager::RosterManager( ClientBase* parent )
00108 : m_rosterListener( 0 ), m_parent( parent ), m_privateXML( 0 ),
00109 m_syncSubscribeReq( false )
00110 {
00111 if( m_parent )
00112 {
00113 m_parent->registerIqHandler( this, ExtRoster );
00114 m_parent->registerPresenceHandler( this );
00115 m_parent->registerSubscriptionHandler( this );
00116 m_parent->registerStanzaExtension( new Query() );
00117
00118 m_self = new RosterItem( m_parent->jid().bare() );
00119 m_privateXML = new PrivateXML( m_parent );
00120 }
00121 }
00122
00123 RosterManager::~RosterManager()
00124 {
00125 if( m_parent )
00126 {
00127 m_parent->removeIqHandler( this, ExtRoster );
00128 m_parent->removeIDHandler( this );
00129 m_parent->removePresenceHandler( this );
00130 m_parent->removeSubscriptionHandler( this );
00131 m_parent->removeStanzaExtension( ExtRoster );
00132 delete m_self;
00133 delete m_privateXML;
00134 }
00135
00136
00137
00138 Roster::iterator it = m_roster.begin();
00139 Roster::iterator it2;
00140 while( it != m_roster.end() )
00141 {
00142 it2 = it++;
00143 delete (*it2).second;
00144 m_roster.erase( it2 );
00145 }
00146
00147 }
00148
00149 Roster* RosterManager::roster()
00150 {
00151 return &m_roster;
00152 }
00153
00154 void RosterManager::fill()
00155 {
00156 if( !m_parent )
00157 return;
00158
00159 m_privateXML->requestXML( "roster", XMLNS_ROSTER_DELIMITER, this );
00160 IQ iq( IQ::Get, JID(), m_parent->getID() );
00161 iq.addExtension( new Query() );
00162 m_parent->send( iq, this, 0 );
00163 }
00164
00165 bool RosterManager::handleIq( const IQ& iq )
00166 {
00167 if( iq.subtype() != IQ::Set )
00168 return false;
00169
00170
00171 const Query* q = iq.findExtension<Query>( ExtRoster );
00172 if( q && q->roster().size() )
00173 mergePush( q->roster() );
00174
00175
00176
00177
00178 IQ re( IQ::Result, JID(), iq.id() );
00179 m_parent->send( re );
00180 return true;
00181 }
00182
00183 void RosterManager::handleIqID( const IQ& iq, int )
00184 {
00185 if( iq.subtype() == IQ::Result )
00186 {
00187 const Query* q = iq.findExtension<Query>( ExtRoster );
00188 if( q )
00189 mergeRoster( q->roster() );
00190
00191 m_parent->rosterFilled();
00192
00193 if( m_rosterListener )
00194 m_rosterListener->handleRoster( m_roster );
00195 }
00196 else if( iq.subtype() == IQ::Error )
00197 {
00198 if( m_rosterListener )
00199 m_rosterListener->handleRosterError( iq );
00200 }
00201 }
00202
00203 void RosterManager::handlePresence( const Presence& presence )
00204 {
00205 if( presence.subtype() == Presence::Error )
00206 return;
00207
00208 bool self = false;
00209 Roster::iterator it = m_roster.find( presence.from().bare() );
00210 if( it != m_roster.end() || ( self = ( presence.from().bare() == m_self->jid() ) ) )
00211 {
00212 RosterItem* ri = self ? m_self : (*it).second;
00213 const std::string& resource = presence.from().resource();
00214
00215 if( presence.presence() == Presence::Unavailable )
00216 ri->removeResource( resource );
00217 else
00218 {
00219 ri->setPresence( resource, presence.presence() );
00220 ri->setStatus( resource, presence.status() );
00221 ri->setPriority( resource, presence.priority() );
00222 ri->setExtensions( resource, presence.extensions() );
00223 }
00224
00225 if( m_rosterListener && !self )
00226 m_rosterListener->handleRosterPresence( *ri, resource,
00227 presence.presence(), presence.status() );
00228 else if( m_rosterListener && self )
00229 m_rosterListener->handleSelfPresence( *ri, resource,
00230 presence.presence(), presence.status() );
00231 }
00232 else
00233 {
00234 if( m_rosterListener )
00235 m_rosterListener->handleNonrosterPresence( presence );
00236 }
00237 }
00238
00239 void RosterManager::subscribe( const JID& jid, const std::string& name,
00240 const StringList& groups, const std::string& msg )
00241 {
00242 if( !jid )
00243 return;
00244
00245 add( jid, name, groups );
00246
00247 Subscription s( Subscription::Subscribe, jid.bareJID(), msg );
00248 m_parent->send( s );
00249 }
00250
00251
00252 void RosterManager::add( const JID& jid, const std::string& name, const StringList& groups )
00253 {
00254 if( !jid )
00255 return;
00256
00257 IQ iq( IQ::Set, JID(), m_parent->getID() );
00258 iq.addExtension( new Query( jid, name, groups) );
00259
00260
00261
00262
00263
00264
00265
00266
00267 m_parent->send( iq, this, 0 );
00268 }
00269
00270 void RosterManager::unsubscribe( const JID& jid, const std::string& msg )
00271 {
00272 Subscription p( Subscription::Unsubscribe, jid.bareJID(), msg );
00273 m_parent->send( p );
00274 }
00275
00276 void RosterManager::cancel( const JID& jid, const std::string& msg )
00277 {
00278 Subscription p( Subscription::Unsubscribed, jid.bareJID(), msg );
00279 m_parent->send( p );
00280 }
00281
00282 void RosterManager::remove( const JID& jid )
00283 {
00284 if( !jid )
00285 return;
00286
00287 IQ iq( IQ::Set, JID(), m_parent->getID() );
00288 iq.addExtension( new Query( jid ) );
00289
00290 m_parent->send( iq, this, 0 );
00291 }
00292
00293 void RosterManager::synchronize()
00294 {
00295 Roster::const_iterator it = m_roster.begin();
00296 for( ; it != m_roster.end(); ++it )
00297 {
00298 if( !(*it).second->changed() )
00299 continue;
00300
00301 IQ iq( IQ::Set, JID(), m_parent->getID() );
00302 iq.addExtension( new Query( (*it).second->jid(), (*it).second->name(), (*it).second->groups() ) );
00303 m_parent->send( iq, this, 0 );
00304 }
00305 }
00306
00307 void RosterManager::ackSubscriptionRequest( const JID& to, bool ack )
00308 {
00309 Subscription p( ack ? Subscription::Subscribed
00310 : Subscription::Unsubscribed, to.bareJID() );
00311 m_parent->send( p );
00312 }
00313
00314 void RosterManager::handleSubscription( const Subscription& s10n )
00315 {
00316 if( !m_rosterListener )
00317 return;
00318
00319 switch( s10n.subtype() )
00320 {
00321 case Subscription::Subscribe:
00322 {
00323 bool answer = m_rosterListener->handleSubscriptionRequest( s10n.from(), s10n.status() );
00324 if( m_syncSubscribeReq )
00325 {
00326 ackSubscriptionRequest( s10n.from(), answer );
00327 }
00328 break;
00329 }
00330 case Subscription::Subscribed:
00331 {
00332
00333
00334
00335 m_rosterListener->handleItemSubscribed( s10n.from() );
00336 break;
00337 }
00338
00339 case Subscription::Unsubscribe:
00340 {
00341 Subscription p( Subscription::Unsubscribed, s10n.from().bareJID() );
00342 m_parent->send( p );
00343
00344 bool answer = m_rosterListener->handleUnsubscriptionRequest( s10n.from(), s10n.status() );
00345 if( m_syncSubscribeReq && answer )
00346 remove( s10n.from().bare() );
00347 break;
00348 }
00349
00350 case Subscription::Unsubscribed:
00351 {
00352
00353
00354
00355 m_rosterListener->handleItemUnsubscribed( s10n.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::setDelimiter( const std::string& delimiter )
00377 {
00378 m_delimiter = delimiter;
00379 Tag* t = new Tag( "roster", m_delimiter );
00380 t->addAttribute( XMLNS, XMLNS_ROSTER_DELIMITER );
00381 m_privateXML->storeXML( t, this );
00382 }
00383
00384 void RosterManager::handlePrivateXML( const Tag* xml )
00385 {
00386 if( xml )
00387 m_delimiter = xml->cdata();
00388 }
00389
00390 void RosterManager::handlePrivateXMLResult( const std::string& , PrivateXMLResult )
00391 {
00392 }
00393
00394 RosterItem* RosterManager::getRosterItem( const JID& jid )
00395 {
00396 Roster::const_iterator it = m_roster.find( jid.bare() );
00397 return it != m_roster.end() ? (*it).second : 0;
00398 }
00399
00400 void RosterManager::mergePush( const RosterData& data )
00401 {
00402 RosterData::const_iterator it = data.begin();
00403 for( ; it != data.end(); ++it )
00404 {
00405 Roster::iterator itr = m_roster.find( (*it)->jid() );
00406 if( itr != m_roster.end() )
00407 {
00408 if( (*it)->remove() )
00409 {
00410 if( m_rosterListener )
00411 m_rosterListener->handleItemRemoved( (*it)->jid() );
00412 delete (*itr).second;
00413 m_roster.erase( itr );
00414 }
00415 else
00416 {
00417 (*itr).second->setData( *(*it) );
00418
00419 if( m_rosterListener )
00420 m_rosterListener->handleItemUpdated( (*it)->jid() );
00421 }
00422 }
00423 else if( !(*it)->remove() )
00424 {
00425 m_roster.insert( std::make_pair( (*it)->jid(), new RosterItem( *(*it) ) ) );
00426 if( m_rosterListener )
00427 m_rosterListener->handleItemAdded( (*it)->jid() );
00428 }
00429 }
00430 }
00431
00432 void RosterManager::mergeRoster( const RosterData& data )
00433 {
00434 RosterData::const_iterator it = data.begin();
00435 for( ; it != data.end(); ++it )
00436 m_roster.insert( std::make_pair( (*it)->jid(), new RosterItem( *(*it) ) ) );
00437 }
00438
00439 }