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