gloox  0.9.9.12
simanager.cpp
1 /*
2  Copyright (c) 2007-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 "simanager.h"
15 
16 #include "siprofilehandler.h"
17 #include "sihandler.h"
18 #include "clientbase.h"
19 #include "disco.h"
20 
21 namespace gloox
22 {
23 
24  SIManager::SIManager( ClientBase* parent, bool advertise )
25  : m_parent( parent ), m_advertise( advertise )
26  {
27  if( m_parent && m_advertise )
28  {
29  m_parent->registerIqHandler( this, XMLNS_SI );
30  if( m_parent->disco() )
31  m_parent->disco()->addFeature( XMLNS_SI );
32  }
33  }
34 
36  {
37  if( m_parent && m_advertise )
38  {
39  m_parent->removeIqHandler( XMLNS_SI );
40  m_parent->removeIDHandler( this );
41  if( m_parent->disco() )
42  m_parent->disco()->removeFeature( XMLNS_SI );
43  }
44  }
45 
46  const std::string SIManager::requestSI( SIHandler* sih, const JID& to, const std::string& profile,
47  Tag* child1, Tag* child2, const std::string& mimetype )
48  {
49  if( !m_parent || !sih )
50  return std::string();
51 
52  const std::string& id = m_parent->getID();
53  const std::string& id2 = m_parent->getID();
54 
55  Tag* iq = new Tag( "iq" );
56  iq->addAttribute( "type", "set" );
57  iq->addAttribute( "id", id );
58  iq->addAttribute( "to", to.full() );
59  Tag* si = new Tag( iq, "si" );
60  si->addAttribute( "xmlns", XMLNS_SI );
61  si->addAttribute( "id", id2 );
62  if( mimetype.empty() )
63  si->addAttribute( "mime-type", "binary/octet-stream" );
64  else
65  si->addAttribute( "mime-type", mimetype );
66  si->addAttribute( "profile", profile );
67 
68  si->addChild( child1 );
69  si->addChild( child2 );
70 
71  TrackStruct t;
72  t.sid = id2;
73  t.profile = profile;
74  t.sih = sih;
75  m_track[id] = t;
76  m_parent->trackID( this, id, OfferSI );
77  m_parent->send( iq );
78 
79  return id2;
80  }
81 
82  void SIManager::acceptSI( const JID& to, const std::string& id, Tag* child1, Tag* child2 )
83  {
84  Tag* iq = new Tag( "iq" );
85  iq->addAttribute( "id", id );
86  iq->addAttribute( "to", to.full() );
87  iq->addAttribute( "type", "result" );
88  Tag* si = new Tag( iq, "si" );
89  si->addAttribute( "xmlns", XMLNS_SI );
90 
91  si->addChild( child1 );
92  si->addChild( child2 );
93 
94  m_parent->send( iq );
95  }
96 
97  void SIManager::declineSI( const JID& to, const std::string& id, SIError reason, const std::string& text )
98  {
99  Tag* iq = new Tag( "iq" );
100  iq->addAttribute( "id", id );
101  iq->addAttribute( "to", to.full() );
102  iq->addAttribute( "type", "error" );
103  Tag* error = new Tag( iq, "error" );
104  if( reason == NoValidStreams || reason == BadProfile )
105  {
106  error->addAttribute( "code", "400" );
107  error->addAttribute( "type", "cancel" );
108  new Tag( error, "bad-request", "xmlns", XMLNS_XMPP_STANZAS );
109  if( reason == NoValidStreams )
110  new Tag( error, "no-valid-streams", "xmlns", XMLNS_SI );
111  else if( reason == BadProfile )
112  new Tag( error, "bad-profile", "xmlns", XMLNS_SI );
113  }
114  else
115  {
116  error->addAttribute( "code", "403" );
117  error->addAttribute( "type", "cancel" );
118  new Tag( error, "forbidden", "xmlns", XMLNS_XMPP_STANZAS );
119  if( !text.empty() )
120  {
121  Tag* t = new Tag( error, "text", "xmlns", XMLNS_XMPP_STANZAS );
122  t->setCData( text );
123  }
124  }
125 
126  m_parent->send( iq );
127  }
128 
129  void SIManager::registerProfile( const std::string& profile, SIProfileHandler* sih )
130  {
131  if( !sih || profile.empty() )
132  return;
133 
134  m_handlers[profile] = sih;
135 
136  if( m_parent && m_advertise && m_parent->disco() )
137  m_parent->disco()->addFeature( profile );
138  }
139 
140  void SIManager::removeProfile( const std::string& profile )
141  {
142  if( profile.empty() )
143  return;
144 
145  m_handlers.erase( profile );
146 
147  if( m_parent && m_advertise && m_parent->disco() )
148  m_parent->disco()->removeFeature( profile );
149  }
150 
151  bool SIManager::handleIq( Stanza *stanza )
152  {
153  TrackMap::iterator it = m_track.find( stanza->id() );
154  if( it != m_track.end() )
155  return false;
156 
157  Tag *si = stanza->findChild( "si", "xmlns", XMLNS_SI );
158  if( si && si->hasAttribute( "profile" ) )
159  {
160  const std::string& profile = si->findAttribute( "profile" );
161  HandlerMap::const_iterator it = m_handlers.find( profile );
162  if( it != m_handlers.end() && (*it).second )
163  {
164  Tag* p = si->findChildWithAttrib( "xmlns", profile );
165  Tag* f = si->findChild( "feature", "xmlns", XMLNS_FEATURE_NEG );
166  (*it).second->handleSIRequest( stanza->from(), stanza->id(), profile, si, p, f );
167  return true;
168  }
169  }
170 
171  return false;
172  }
173 
174  bool SIManager::handleIqID( Stanza *stanza, int context )
175  {
176  switch( stanza->subtype() )
177  {
178  case StanzaIqResult:
179  if( context == OfferSI )
180  {
181  TrackMap::iterator it = m_track.find( stanza->id() );
182  if( it != m_track.end() )
183  {
184  Tag* si = stanza->findChild( "si", "xmlns", XMLNS_SI );
185  Tag* ptag = 0;
186  Tag* fneg = 0;
187  if( si )
188  {
189  ptag = si->findChildWithAttrib( "xmlns", (*it).second.profile );
190  fneg = si->findChild( "feature", "xmlns", XMLNS_FEATURE_NEG );
191  }
192  (*it).second.sih->handleSIRequestResult( stanza->from(), (*it).second.sid, si, ptag, fneg );
193  m_track.erase( it );
194  }
195  return true;
196  }
197  break;
198  case StanzaIqError:
199  if( context == OfferSI )
200  {
201  TrackMap::iterator it = m_track.find( stanza->id() );
202  if( it != m_track.end() )
203  {
204  (*it).second.sih->handleSIRequestError( stanza, (*it).second.sid );
205  m_track.erase( it );
206  }
207  return true;
208  }
209  break;
210  default:
211  break;
212  }
213 
214  return false;
215  }
216 
217 }