00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "disco.h"
00015 #include "discohandler.h"
00016 #include "clientbase.h"
00017 #include "disconodehandler.h"
00018
00019
00020 namespace gloox
00021 {
00022
00023 Disco::Disco( ClientBase *parent )
00024 : m_parent( parent )
00025 {
00026 addFeature( XMLNS_VERSION );
00027 addFeature( XMLNS_DISCO_INFO );
00028 addFeature( XMLNS_DISCO_ITEMS );
00029 if( m_parent )
00030 {
00031 m_parent->registerIqHandler( this, XMLNS_DISCO_INFO );
00032 m_parent->registerIqHandler( this, XMLNS_DISCO_ITEMS );
00033 m_parent->registerIqHandler( this, XMLNS_VERSION );
00034 }
00035 }
00036
00037 Disco::~Disco()
00038 {
00039 if( m_parent )
00040 {
00041 m_parent->removeIqHandler( XMLNS_DISCO_INFO );
00042 m_parent->removeIqHandler( XMLNS_DISCO_ITEMS );
00043 m_parent->removeIqHandler( XMLNS_VERSION );
00044 }
00045 }
00046
00047 bool Disco::handleIq( Stanza *stanza )
00048 {
00049 switch( stanza->subtype() )
00050 {
00051 case StanzaIqGet:
00052 if( stanza->xmlns() == XMLNS_VERSION )
00053 {
00054 Tag *iq = new Tag( "iq" );
00055 iq->addAttribute( "id", stanza->id() );
00056 iq->addAttribute( "from", m_parent->jid().full() );
00057 iq->addAttribute( "to", stanza->from().full() );
00058 iq->addAttribute( "type", "result" );
00059 Tag *query = new Tag( iq, "query" );
00060 query->addAttribute( "xmlns", XMLNS_VERSION );
00061 new Tag( query, "name", m_versionName );
00062 new Tag( query, "version", m_versionVersion );
00063 new Tag( query, "os", m_versionOs );
00064
00065 m_parent->send( iq );
00066 }
00067 else if( stanza->xmlns() == XMLNS_DISCO_INFO && stanza->hasChild( "query" ) )
00068 {
00069 Tag *iq = new Tag( "iq" );
00070 iq->addAttribute( "id", stanza->id() );
00071 iq->addAttribute( "from", m_parent->jid().full() );
00072 iq->addAttribute( "to", stanza->from().full() );
00073 iq->addAttribute( "type", "result" );
00074 Tag *query = new Tag( iq, "query" );
00075 query->addAttribute( "xmlns", XMLNS_DISCO_INFO );
00076
00077 Tag *q = stanza->findChild( "query" );
00078 const std::string& node = q->findAttribute( "node" );
00079 if( !node.empty() )
00080 {
00081 query->addAttribute( "node", node );
00082 new Tag( query, "feature", "var", XMLNS_DISCO_INFO );
00083
00084 DiscoNodeHandlerMap::const_iterator it = m_nodeHandlers.find( node );
00085 if( it != m_nodeHandlers.end() )
00086 {
00087 std::string name;
00088 DiscoNodeHandlerList::const_iterator in = (*it).second.begin();
00089 for( ; in != (*it).second.end(); ++in )
00090 {
00091 const StringMap& identities = (*in)->handleDiscoNodeIdentities( node, name );
00092 StringMap::const_iterator im = identities.begin();
00093 for( ; im != identities.end(); ++im )
00094 {
00095 Tag *i = new Tag( query, "identity" );
00096 i->addAttribute( "category", (*im).first );
00097 i->addAttribute( "type", (*im).second );
00098 i->addAttribute( "name", name );
00099 }
00100 const StringList& features = (*in)->handleDiscoNodeFeatures( node );
00101 StringList::const_iterator fi = features.begin();
00102 for( ; fi != features.end(); ++fi )
00103 {
00104 Tag *f = new Tag( query, "feature" );
00105 f->addAttribute( "var", (*fi) );
00106 }
00107 }
00108 }
00109 }
00110 else
00111 {
00112 Tag *i = new Tag( query, "identity" );
00113 i->addAttribute( "category", m_identityCategory );
00114 i->addAttribute( "type", m_identityType );
00115 i->addAttribute( "name", m_versionName );
00116
00117 StringList::const_iterator it = m_features.begin();
00118 for( ; it != m_features.end(); ++it )
00119 {
00120 Tag *f = new Tag( query, "feature" );
00121 f->addAttribute( "var", (*it) );
00122 }
00123 }
00124
00125 m_parent->send( iq );
00126 }
00127 else if( stanza->xmlns() == XMLNS_DISCO_ITEMS && stanza->hasChild( "query" ) )
00128 {
00129 Tag *iq = new Tag( "iq" );
00130 iq->addAttribute( "id", stanza->id() );
00131 iq->addAttribute( "to", stanza->from().full() );
00132 iq->addAttribute( "from", m_parent->jid().full() );
00133 iq->addAttribute( "type", "result" );
00134 Tag *query = new Tag( iq, "query" );
00135 query->addAttribute( "xmlns", XMLNS_DISCO_ITEMS );
00136
00137 DiscoNodeHandlerMap::const_iterator it;
00138 Tag *q = stanza->findChild( "query" );
00139 const std::string& node = q->findAttribute( "node" );
00140 query->addAttribute( "node", node );
00141 it = m_nodeHandlers.find( node );
00142 if( it != m_nodeHandlers.end() )
00143 {
00144 DiscoNodeHandlerList::const_iterator in = (*it).second.begin();
00145 for( ; in != (*it).second.end(); ++in )
00146 {
00147 const DiscoNodeItemList& items = (*in)->handleDiscoNodeItems( node );
00148 DiscoNodeItemList::const_iterator it = items.begin();
00149 for( ; it != items.end(); ++it )
00150 {
00151 Tag *i = new Tag( query, "item" );
00152 i->addAttribute( "jid", (*it).jid.empty() ? m_parent->jid().full() : (*it).jid );
00153 i->addAttribute( "node", (*it).node );
00154 i->addAttribute( "name", (*it).name );
00155 }
00156 }
00157 }
00158
00159 m_parent->send( iq );
00160 }
00161 return true;
00162 break;
00163
00164 case StanzaIqSet:
00165 {
00166 bool res = false;
00167 DiscoHandlerList::const_iterator it = m_discoHandlers.begin();
00168 for( ; it != m_discoHandlers.end(); ++it )
00169 {
00170 if( (*it)->handleDiscoSet( stanza ) )
00171 res = true;
00172 }
00173 return res;
00174 break;
00175 }
00176
00177 default:
00178 break;
00179 }
00180 return false;
00181 }
00182
00183 bool Disco::handleIqID( Stanza *stanza, int context )
00184 {
00185 DiscoHandlerMap::iterator it = m_track.find( stanza->id() );
00186 if( it != m_track.end() )
00187 {
00188 switch( stanza->subtype() )
00189 {
00190 case StanzaIqResult:
00191 switch( context )
00192 {
00193 case GET_DISCO_INFO:
00194 (*it).second.dh->handleDiscoInfoResult( stanza, (*it).second.context );
00195 break;
00196 case GET_DISCO_ITEMS:
00197 (*it).second.dh->handleDiscoItemsResult( stanza, (*it).second.context );
00198 break;
00199 }
00200 break;
00201
00202 case StanzaIqError:
00203 (*it).second.dh->handleDiscoError( stanza, (*it).second.context );
00204 break;
00205
00206 default:
00207 break;
00208 }
00209
00210 m_track.erase( it );
00211 }
00212
00213 return false;
00214 }
00215
00216 void Disco::addFeature( const std::string& feature )
00217 {
00218 m_features.push_back( feature );
00219 }
00220
00221 void Disco::removeFeature( const std::string& feature )
00222 {
00223 m_features.remove( feature );
00224 }
00225
00226 void Disco::getDiscoInfo( const JID& to, const std::string& node, DiscoHandler *dh, int context,
00227 const std::string& tid )
00228 {
00229 const std::string& id = tid.empty() ? m_parent->getID() : tid;
00230
00231 Tag *iq = new Tag( "iq" );
00232 iq->addAttribute( "id", id );
00233 iq->addAttribute( "to", to.full() );
00234 iq->addAttribute( "from", m_parent->jid().full() );
00235 iq->addAttribute( "type", "get" );
00236 Tag *q = new Tag( iq, "query" );
00237 q->addAttribute( "xmlns", XMLNS_DISCO_INFO );
00238 if( !node.empty() )
00239 q->addAttribute( "node", node );
00240
00241 DiscoHandlerContext ct;
00242 ct.dh = dh;
00243 ct.context = context;
00244 m_track[id] = ct;
00245 m_parent->trackID( this, id, GET_DISCO_INFO );
00246 m_parent->send( iq );
00247 }
00248
00249 void Disco::getDiscoItems( const JID& to, const std::string& node, DiscoHandler *dh, int context,
00250 const std::string& tid )
00251 {
00252 const std::string& id = tid.empty() ? m_parent->getID() : tid;
00253
00254 Tag *iq = new Tag( "iq" );
00255 iq->addAttribute( "id", id );
00256 iq->addAttribute( "to", to.full() );
00257 iq->addAttribute( "from", m_parent->jid().full() );
00258 iq->addAttribute( "type", "get" );
00259 Tag *q = new Tag( iq, "query" );
00260 q->addAttribute( "xmlns", XMLNS_DISCO_ITEMS );
00261 if( !node.empty() )
00262 q->addAttribute( "node", node );
00263
00264 DiscoHandlerContext ct;
00265 ct.dh = dh;
00266 ct.context = context;
00267 m_track[id] = ct;
00268 m_parent->trackID( this, id, GET_DISCO_ITEMS );
00269 m_parent->send( iq );
00270 }
00271
00272 void Disco::setVersion( const std::string& name, const std::string& version, const std::string& os )
00273 {
00274 m_versionName = name;
00275 m_versionVersion = version;
00276 m_versionOs = os;
00277 }
00278
00279 void Disco::setIdentity( const std::string& category, const std::string& type )
00280 {
00281 m_identityCategory = category;
00282 m_identityType = type;
00283 }
00284
00285 void Disco::registerDiscoHandler( DiscoHandler *dh )
00286 {
00287 m_discoHandlers.push_back( dh );
00288 }
00289
00290 void Disco::removeDiscoHandler( DiscoHandler *dh )
00291 {
00292 m_discoHandlers.remove( dh );
00293 }
00294
00295 void Disco::registerNodeHandler( DiscoNodeHandler *nh, const std::string& node )
00296 {
00297 m_nodeHandlers[node].push_back( nh );
00298 }
00299
00300 void Disco::removeNodeHandler( DiscoNodeHandler *nh, const std::string& node )
00301 {
00302 DiscoNodeHandlerMap::iterator it = m_nodeHandlers.find( node );
00303 if( it != m_nodeHandlers.end() )
00304 {
00305 (*it).second.remove( nh );
00306 if( !(*it).second.size() )
00307 {
00308 m_nodeHandlers.erase( it );
00309 }
00310 }
00311 }
00312
00313 }