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 util::clearList( m_roster );
00075 }
00076
00077 const std::string& RosterManager::Query::filterString() const
00078 {
00079 static const std::string filter = "/iq/query[@xmlns='" + XMLNS_ROSTER + "']";
00080 return filter;
00081 }
00082
00083 Tag* RosterManager::Query::tag() const
00084 {
00085 Tag* t = new Tag( "query" );
00086 t->setXmlns( XMLNS_ROSTER );
00087
00088 RosterData::const_iterator it = m_roster.begin();
00089 for( ; it != m_roster.end(); ++it )
00090 t->addChild( (*it)->tag() );
00091
00092 return t;
00093 }
00094
00095 StanzaExtension* RosterManager::Query::clone() const
00096 {
00097 Query* q = new Query();
00098 RosterData::const_iterator it = m_roster.begin();
00099 for( ; it != m_roster.end(); ++it )
00100 {
00101 q->m_roster.push_back( new RosterItemData( *(*it) ) );
00102 }
00103 return q;
00104 }
00105
00106
00107
00108 RosterManager::RosterManager( ClientBase* parent )
00109 : m_rosterListener( 0 ), m_parent( parent ), m_privateXML( 0 ),
00110 m_syncSubscribeReq( false )
00111 {
00112 if( m_parent )
00113 {
00114 m_parent->registerIqHandler( this, ExtRoster );
00115 m_parent->registerPresenceHandler( this );
00116 m_parent->registerSubscriptionHandler( this );
00117 m_parent->registerStanzaExtension( new Query() );
00118
00119 m_self = new RosterItem( m_parent->jid().bare() );
00120 m_privateXML = new PrivateXML( m_parent );
00121 }
00122 }
00123
00124 RosterManager::~RosterManager()
00125 {
00126 if( m_parent )
00127 {
00128 m_parent->removeIqHandler( this, ExtRoster );
00129 m_parent->removeIDHandler( this );
00130 m_parent->removePresenceHandler( this );
00131 m_parent->removeSubscriptionHandler( this );
00132 m_parent->removeStanzaExtension( ExtRoster );
00133 delete m_self;
00134 delete m_privateXML;
00135 }
00136
00137 util::clearMap( m_roster );
00138 }
00139
00140 Roster* RosterManager::roster()
00141 {
00142 return &m_roster;
00143 }
00144
00145 void RosterManager::fill()
00146 {
00147 if( !m_parent )
00148 return;
00149
00150 util::clearMap( m_roster );
00151 m_privateXML->requestXML( "roster", XMLNS_ROSTER_DELIMITER, this );
00152 IQ iq( IQ::Get, JID(), m_parent->getID() );
00153 iq.addExtension( new Query() );
00154 m_parent->send( iq, this, RequestRoster );
00155 }
00156
00157 bool RosterManager::handleIq( const IQ& iq )
00158 {
00159 if( iq.subtype() != IQ::Set )
00160 return false;
00161
00162
00163 const Query* q = iq.findExtension<Query>( ExtRoster );
00164 if( q && q->roster().size() )
00165 mergePush( q->roster() );
00166
00167 IQ re( IQ::Result, JID(), iq.id() );
00168 m_parent->send( re );
00169 return true;
00170 }
00171
00172 void RosterManager::handleIqID( const IQ& iq, int context )
00173 {
00174 if( iq.subtype() == IQ::Result )
00175 {
00176 const Query* q = iq.findExtension<Query>( ExtRoster );
00177 if( q )
00178 mergeRoster( q->roster() );
00179
00180 if( context == RequestRoster )
00181 {
00182 if( m_parent )
00183 m_parent->rosterFilled();
00184
00185 if( m_rosterListener )
00186 m_rosterListener->handleRoster( m_roster );
00187 }
00188 }
00189 else if( iq.subtype() == IQ::Error )
00190 {
00191 if( context == RequestRoster && m_parent )
00192 m_parent->rosterFilled();
00193
00194 if( m_rosterListener )
00195 m_rosterListener->handleRosterError( iq );
00196 }
00197 }
00198
00199 void RosterManager::handlePresence( const Presence& presence )
00200 {
00201 if( presence.subtype() == Presence::Error )
00202 return;
00203
00204 bool self = false;
00205 Roster::iterator it = m_roster.find( presence.from().bare() );
00206 if( it != m_roster.end() || ( self = ( presence.from().bare() == m_self->jid() ) ) )
00207 {
00208 RosterItem* ri = self ? m_self : (*it).second;
00209 const std::string& resource = presence.from().resource();
00210
00211 if( presence.presence() == Presence::Unavailable )
00212 ri->removeResource( resource );
00213 else
00214 {
00215 ri->setPresence( resource, presence.presence() );
00216 ri->setStatus( resource, presence.status() );
00217 ri->setPriority( resource, presence.priority() );
00218 ri->setExtensions( resource, presence.extensions() );
00219 }
00220
00221 if( m_rosterListener && !self )
00222 m_rosterListener->handleRosterPresence( *ri, resource,
00223 presence.presence(), presence.status() );
00224 else if( m_rosterListener && self )
00225 m_rosterListener->handleSelfPresence( *ri, resource,
00226 presence.presence(), presence.status() );
00227 }
00228 else
00229 {
00230 if( m_rosterListener )
00231 m_rosterListener->handleNonrosterPresence( presence );
00232 }
00233 }
00234
00235 void RosterManager::subscribe( const JID& jid, const std::string& name,
00236 const StringList& groups, const std::string& msg )
00237 {
00238 if( !jid )
00239 return;
00240
00241 add( jid, name, groups );
00242
00243 Subscription s( Subscription::Subscribe, jid.bareJID(), msg );
00244 m_parent->send( s );
00245 }
00246
00247
00248 void RosterManager::add( const JID& jid, const std::string& name, const StringList& groups )
00249 {
00250 if( !jid )
00251 return;
00252
00253 IQ iq( IQ::Set, JID(), m_parent->getID() );
00254 iq.addExtension( new Query( jid, name, groups) );
00255
00256 m_parent->send( iq, this, AddRosterItem );
00257 }
00258
00259 void RosterManager::unsubscribe( const JID& jid, const std::string& msg )
00260 {
00261 Subscription p( Subscription::Unsubscribe, jid.bareJID(), msg );
00262 m_parent->send( p );
00263 }
00264
00265 void RosterManager::cancel( const JID& jid, const std::string& msg )
00266 {
00267 Subscription p( Subscription::Unsubscribed, jid.bareJID(), msg );
00268 m_parent->send( p );
00269 }
00270
00271 void RosterManager::remove( const JID& jid )
00272 {
00273 if( !jid )
00274 return;
00275
00276 IQ iq( IQ::Set, JID(), m_parent->getID() );
00277 iq.addExtension( new Query( jid ) );
00278
00279 m_parent->send( iq, this, RemoveRosterItem );
00280 }
00281
00282 void RosterManager::synchronize()
00283 {
00284 Roster::const_iterator it = m_roster.begin();
00285 for( ; it != m_roster.end(); ++it )
00286 {
00287 if( !(*it).second->changed() )
00288 continue;
00289
00290 IQ iq( IQ::Set, JID(), m_parent->getID() );
00291 iq.addExtension( new Query( (*it).second->jid(), (*it).second->name(), (*it).second->groups() ) );
00292 m_parent->send( iq, this, SynchronizeRoster );
00293 }
00294 }
00295
00296 void RosterManager::ackSubscriptionRequest( const JID& to, bool ack )
00297 {
00298 Subscription p( ack ? Subscription::Subscribed
00299 : Subscription::Unsubscribed, to.bareJID() );
00300 m_parent->send( p );
00301 }
00302
00303 void RosterManager::handleSubscription( const Subscription& s10n )
00304 {
00305 if( !m_rosterListener )
00306 return;
00307
00308 switch( s10n.subtype() )
00309 {
00310 case Subscription::Subscribe:
00311 {
00312 bool answer = m_rosterListener->handleSubscriptionRequest( s10n.from(), s10n.status() );
00313 if( m_syncSubscribeReq )
00314 {
00315 ackSubscriptionRequest( s10n.from(), answer );
00316 }
00317 break;
00318 }
00319 case Subscription::Subscribed:
00320 {
00321 m_rosterListener->handleItemSubscribed( s10n.from() );
00322 break;
00323 }
00324
00325 case Subscription::Unsubscribe:
00326 {
00327 Subscription p( Subscription::Unsubscribed, s10n.from().bareJID() );
00328 m_parent->send( p );
00329
00330 bool answer = m_rosterListener->handleUnsubscriptionRequest( s10n.from(), s10n.status() );
00331 if( m_syncSubscribeReq && answer )
00332 remove( s10n.from().bare() );
00333 break;
00334 }
00335
00336 case Subscription::Unsubscribed:
00337 {
00338 m_rosterListener->handleItemUnsubscribed( s10n.from() );
00339 break;
00340 }
00341
00342 default:
00343 break;
00344 }
00345 }
00346
00347 void RosterManager::registerRosterListener( RosterListener* rl, bool syncSubscribeReq )
00348 {
00349 m_syncSubscribeReq = syncSubscribeReq;
00350 m_rosterListener = rl;
00351 }
00352
00353 void RosterManager::removeRosterListener()
00354 {
00355 m_syncSubscribeReq = false;
00356 m_rosterListener = 0;
00357 }
00358
00359 void RosterManager::setDelimiter( const std::string& delimiter )
00360 {
00361 m_delimiter = delimiter;
00362 Tag* t = new Tag( "roster", m_delimiter );
00363 t->addAttribute( XMLNS, XMLNS_ROSTER_DELIMITER );
00364 m_privateXML->storeXML( t, this );
00365 }
00366
00367 void RosterManager::handlePrivateXML( const Tag* xml )
00368 {
00369 if( xml )
00370 m_delimiter = xml->cdata();
00371 }
00372
00373 void RosterManager::handlePrivateXMLResult( const std::string& , PrivateXMLResult )
00374 {
00375 }
00376
00377 RosterItem* RosterManager::getRosterItem( const JID& jid )
00378 {
00379 Roster::const_iterator it = m_roster.find( jid.bare() );
00380 return it != m_roster.end() ? (*it).second : 0;
00381 }
00382
00383 void RosterManager::mergePush( const RosterData& data )
00384 {
00385 RosterData::const_iterator it = data.begin();
00386 for( ; it != data.end(); ++it )
00387 {
00388 Roster::iterator itr = m_roster.find( (*it)->jid() );
00389 if( itr != m_roster.end() )
00390 {
00391 if( (*it)->remove() )
00392 {
00393 if( m_rosterListener )
00394 m_rosterListener->handleItemRemoved( (*it)->jid() );
00395 delete (*itr).second;
00396 m_roster.erase( itr );
00397 }
00398 else
00399 {
00400 (*itr).second->setData( *(*it) );
00401 if( m_rosterListener )
00402 m_rosterListener->handleItemUpdated( (*it)->jid() );
00403 }
00404 }
00405 else if( !(*it)->remove() )
00406 {
00407 m_roster.insert( std::make_pair( (*it)->jid(), new RosterItem( *(*it) ) ) );
00408 if( m_rosterListener )
00409 m_rosterListener->handleItemAdded( (*it)->jid() );
00410 }
00411 }
00412 }
00413
00414 void RosterManager::mergeRoster( const RosterData& data )
00415 {
00416 RosterData::const_iterator it = data.begin();
00417 for( ; it != data.end(); ++it )
00418 m_roster.insert( std::make_pair( (*it)->jid(), new RosterItem( *(*it) ) ) );
00419 }
00420
00421 }