gloox  0.9.9.12
disco.cpp
1 /*
2  Copyright (c) 2004-2008 by Jakob Schroeter <js@camaya.net>
3  This file is part of the gloox library. http://camaya.net/gloox
4 
5  This software is distributed under a license. The full license
6  agreement can be found in the file LICENSE in this distribution.
7  This software may not be copied, modified, sold or distributed
8  other than expressed in the named license agreement.
9 
10  This software is distributed without any warranty.
11 */
12 
13 
14 #include "disco.h"
15 #include "discohandler.h"
16 #include "clientbase.h"
17 #include "disconodehandler.h"
18 
19 
20 namespace gloox
21 {
22 
23  Disco::Disco( ClientBase *parent )
24  : m_parent( parent )
25  {
26  addFeature( XMLNS_VERSION );
27  addFeature( XMLNS_DISCO_INFO );
28  addFeature( XMLNS_DISCO_ITEMS );
29  if( m_parent )
30  {
31  m_parent->registerIqHandler( this, XMLNS_DISCO_INFO );
32  m_parent->registerIqHandler( this, XMLNS_DISCO_ITEMS );
33  m_parent->registerIqHandler( this, XMLNS_VERSION );
34  }
35  }
36 
37  Disco::~Disco()
38  {
39  if( m_parent )
40  {
41  m_parent->removeIqHandler( XMLNS_DISCO_INFO );
43  m_parent->removeIqHandler( XMLNS_VERSION );
44  m_parent->removeIDHandler( this );
45  }
46  }
47 
48  bool Disco::handleIq( Stanza *stanza )
49  {
50  switch( stanza->subtype() )
51  {
52  case StanzaIqGet:
53  if( stanza->xmlns() == XMLNS_VERSION )
54  {
55  Tag *iq = new Tag( "iq" );
56  iq->addAttribute( "id", stanza->id() );
57  iq->addAttribute( "from", m_parent->jid().full() );
58  iq->addAttribute( "to", stanza->from().full() );
59  iq->addAttribute( "type", "result" );
60  Tag *query = new Tag( iq, "query" );
61  query->addAttribute( "xmlns", XMLNS_VERSION );
62  new Tag( query, "name", m_versionName );
63  new Tag( query, "version", m_versionVersion );
64  new Tag( query, "os", m_versionOs );
65 
66  m_parent->send( iq );
67  }
68  else if( stanza->xmlns() == XMLNS_DISCO_INFO && stanza->hasChild( "query" ) )
69  {
70  Tag *iq = new Tag( "iq" );
71  iq->addAttribute( "id", stanza->id() );
72  iq->addAttribute( "from", m_parent->jid().full() );
73  iq->addAttribute( "to", stanza->from().full() );
74  iq->addAttribute( "type", "result" );
75  Tag *query = new Tag( iq, "query" );
76  query->addAttribute( "xmlns", XMLNS_DISCO_INFO );
77 
78  Tag *q = stanza->findChild( "query" );
79  const std::string& node = q->findAttribute( "node" );
80  if( !node.empty() )
81  {
82  query->addAttribute( "node", node );
83  new Tag( query, "feature", "var", XMLNS_DISCO_INFO );
84 
85  DiscoNodeHandlerMap::const_iterator it = m_nodeHandlers.find( node );
86  if( it != m_nodeHandlers.end() )
87  {
88  std::string name;
89  DiscoNodeHandlerList::const_iterator in = (*it).second.begin();
90  for( ; in != (*it).second.end(); ++in )
91  {
92  const StringMap& identities = (*in)->handleDiscoNodeIdentities( node, name );
93  StringMap::const_iterator im = identities.begin();
94  for( ; im != identities.end(); ++im )
95  {
96  Tag *i = new Tag( query, "identity" );
97  i->addAttribute( "category", (*im).first );
98  i->addAttribute( "type", (*im).second );
99  i->addAttribute( "name", name );
100  }
101  const StringList& features = (*in)->handleDiscoNodeFeatures( node );
102  StringList::const_iterator fi = features.begin();
103  for( ; fi != features.end(); ++fi )
104  {
105  Tag *f = new Tag( query, "feature" );
106  f->addAttribute( "var", (*fi) );
107  }
108  }
109  }
110  }
111  else
112  {
113  Tag *i = new Tag( query, "identity" );
114  i->addAttribute( "category", m_identityCategory );
115  i->addAttribute( "type", m_identityType );
116  i->addAttribute( "name", m_versionName );
117 
118  StringList::const_iterator it = m_features.begin();
119  for( ; it != m_features.end(); ++it )
120  {
121  Tag *f = new Tag( query, "feature" );
122  f->addAttribute( "var", (*it) );
123  }
124  }
125 
126  m_parent->send( iq );
127  }
128  else if( stanza->xmlns() == XMLNS_DISCO_ITEMS && stanza->hasChild( "query" ) )
129  {
130  Tag *iq = new Tag( "iq" );
131  iq->addAttribute( "id", stanza->id() );
132  iq->addAttribute( "to", stanza->from().full() );
133  iq->addAttribute( "from", m_parent->jid().full() );
134  iq->addAttribute( "type", "result" );
135  Tag *query = new Tag( iq, "query" );
136  query->addAttribute( "xmlns", XMLNS_DISCO_ITEMS );
137 
138  DiscoNodeHandlerMap::const_iterator it;
139  Tag *q = stanza->findChild( "query" );
140  const std::string& node = q->findAttribute( "node" );
141  query->addAttribute( "node", node );
142  it = m_nodeHandlers.find( node );
143  if( it != m_nodeHandlers.end() )
144  {
145  DiscoNodeHandlerList::const_iterator in = (*it).second.begin();
146  for( ; in != (*it).second.end(); ++in )
147  {
148  const DiscoNodeItemList& items = (*in)->handleDiscoNodeItems( node );
149  DiscoNodeItemList::const_iterator it = items.begin();
150  for( ; it != items.end(); ++it )
151  {
152  Tag *i = new Tag( query, "item" );
153  i->addAttribute( "jid", (*it).jid.empty() ? m_parent->jid().full() : (*it).jid );
154  i->addAttribute( "node", (*it).node );
155  i->addAttribute( "name", (*it).name );
156  }
157  }
158  }
159 
160  m_parent->send( iq );
161  }
162  return true;
163  break;
164 
165  case StanzaIqSet:
166  {
167  bool res = false;
168  DiscoHandlerList::const_iterator it = m_discoHandlers.begin();
169  for( ; it != m_discoHandlers.end(); ++it )
170  {
171  if( (*it)->handleDiscoSet( stanza ) )
172  res = true;
173  }
174  return res;
175  break;
176  }
177 
178  default:
179  break;
180  }
181  return false;
182  }
183 
184  bool Disco::handleIqID( Stanza *stanza, int context )
185  {
186  DiscoHandlerMap::iterator it = m_track.find( stanza->id() );
187  if( it != m_track.end() )
188  {
189  switch( stanza->subtype() )
190  {
191  case StanzaIqResult:
192  switch( context )
193  {
194  case GET_DISCO_INFO:
195  (*it).second.dh->handleDiscoInfoResult( stanza, (*it).second.context );
196  break;
197  case GET_DISCO_ITEMS:
198  (*it).second.dh->handleDiscoItemsResult( stanza, (*it).second.context );
199  break;
200  }
201  break;
202 
203  case StanzaIqError:
204  (*it).second.dh->handleDiscoError( stanza, (*it).second.context );
205  break;
206 
207  default:
208  break;
209  }
210 
211  m_track.erase( it );
212  }
213 
214  return false;
215  }
216 
217  void Disco::addFeature( const std::string& feature )
218  {
219  m_features.push_back( feature );
220  }
221 
222  void Disco::removeFeature( const std::string& feature )
223  {
224  m_features.remove( feature );
225  }
226 
227  void Disco::getDiscoInfo( const JID& to, const std::string& node, DiscoHandler *dh, int context,
228  const std::string& tid )
229  {
230  const std::string& id = tid.empty() ? m_parent->getID() : tid;
231 
232  Tag *iq = new Tag( "iq" );
233  iq->addAttribute( "id", id );
234  iq->addAttribute( "to", to.full() );
235  iq->addAttribute( "from", m_parent->jid().full() );
236  iq->addAttribute( "type", "get" );
237  Tag *q = new Tag( iq, "query" );
238  q->addAttribute( "xmlns", XMLNS_DISCO_INFO );
239  if( !node.empty() )
240  q->addAttribute( "node", node );
241 
242  DiscoHandlerContext ct;
243  ct.dh = dh;
244  ct.context = context;
245  m_track[id] = ct;
246  m_parent->trackID( this, id, GET_DISCO_INFO );
247  m_parent->send( iq );
248  }
249 
250  void Disco::getDiscoItems( const JID& to, const std::string& node, DiscoHandler *dh, int context,
251  const std::string& tid )
252  {
253  const std::string& id = tid.empty() ? m_parent->getID() : tid;
254 
255  Tag *iq = new Tag( "iq" );
256  iq->addAttribute( "id", id );
257  iq->addAttribute( "to", to.full() );
258  iq->addAttribute( "from", m_parent->jid().full() );
259  iq->addAttribute( "type", "get" );
260  Tag *q = new Tag( iq, "query" );
261  q->addAttribute( "xmlns", XMLNS_DISCO_ITEMS );
262  if( !node.empty() )
263  q->addAttribute( "node", node );
264 
265  DiscoHandlerContext ct;
266  ct.dh = dh;
267  ct.context = context;
268  m_track[id] = ct;
269  m_parent->trackID( this, id, GET_DISCO_ITEMS );
270  m_parent->send( iq );
271  }
272 
273  void Disco::setVersion( const std::string& name, const std::string& version, const std::string& os )
274  {
275  m_versionName = name;
276  m_versionVersion = version;
277  m_versionOs = os;
278  }
279 
280  void Disco::setIdentity( const std::string& category, const std::string& type )
281  {
282  m_identityCategory = category;
283  m_identityType = type;
284  }
285 
287  {
288  m_discoHandlers.push_back( dh );
289  }
290 
292  {
293  m_discoHandlers.remove( dh );
294  DiscoHandlerMap::iterator t;
295  DiscoHandlerMap::iterator it = m_track.begin();
296  while( it != m_track.end() )
297  {
298  t = it;
299  ++it;
300  if( dh == (*t).second.dh )
301  {
302  m_track.erase( t );
303  }
304  }
305  }
306 
307  void Disco::registerNodeHandler( DiscoNodeHandler *nh, const std::string& node )
308  {
309  m_nodeHandlers[node].push_back( nh );
310  }
311 
312  void Disco::removeNodeHandler( DiscoNodeHandler *nh, const std::string& node )
313  {
314  DiscoNodeHandlerMap::iterator it = m_nodeHandlers.find( node );
315  if( it != m_nodeHandlers.end() )
316  {
317  (*it).second.remove( nh );
318  if( !(*it).second.size() )
319  {
320  m_nodeHandlers.erase( it );
321  }
322  }
323  }
324 
325 }