gloox  1.0.28
siprofileft.cpp
1 /*
2  Copyright (c) 2007-2023 by Jakob Schröter <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 "siprofileft.h"
15 
16 #include "clientbase.h"
17 #include "siprofilefthandler.h"
18 #include "simanager.h"
19 #include "dataform.h"
20 #include "inbandbytestream.h"
21 #include "oob.h"
22 #include "socks5bytestream.h"
23 #include "socks5bytestreammanager.h"
24 
25 #include <cstdlib>
26 #include <map>
27 
28 namespace gloox
29 {
30 
32  SOCKS5BytestreamManager* s5Manager )
33  : m_parent( parent ), m_manager( manager ), m_handler( sipfth ),
34  m_socks5Manager( s5Manager ), m_delManager( false ),
35  m_delS5Manager( false )
36  {
37  if( !m_manager )
38  {
39  m_delManager = true;
40  m_manager = new SIManager( m_parent );
41  }
42 
43  m_manager->registerProfile( XMLNS_SI_FT, this );
44 
45  if( !m_socks5Manager )
46  {
47  m_socks5Manager = new SOCKS5BytestreamManager( m_parent, this );
48  m_delS5Manager = true;
49  }
50  }
51 
53  {
54  m_manager->removeProfile( XMLNS_SI_FT );
55 
56  if( m_delManager )
57  delete m_manager;
58 
59  if( m_socks5Manager && m_delS5Manager )
60  delete m_socks5Manager;
61  }
62 
63  const std::string SIProfileFT::requestFT( const JID& to, const std::string& name, long size,
64  const std::string& hash, const std::string& desc,
65  const std::string& date, const std::string& mimetype,
66  int streamTypes, const JID& from,
67  const std::string& sid )
68  {
69  if( name.empty() || size <= 0 || !m_manager )
70  return EmptyString;
71 
72  Tag* file = new Tag( "file", XMLNS, XMLNS_SI_FT );
73  file->addAttribute( "name", name );
74  file->addAttribute( "size", size );
75  if( !hash.empty() )
76  file->addAttribute( "hash", hash );
77  if( !date.empty() )
78  file->addAttribute( "date", date );
79  if( !desc.empty() )
80  new Tag( file, "desc", desc );
81 
82  Tag* feature = new Tag( "feature", XMLNS, XMLNS_FEATURE_NEG );
83  DataForm df( TypeForm );
84  DataFormField* dff = df.addField( DataFormField::TypeListSingle, "stream-method" );
85  StringMultiMap sm;
86  if( streamTypes & FTTypeS5B )
87  sm.insert( std::make_pair( std::string( "s5b" ), XMLNS_BYTESTREAMS ) );
88  if( streamTypes & FTTypeIBB )
89  sm.insert( std::make_pair( std::string( "ibb" ), XMLNS_IBB ) );
90  if( streamTypes & FTTypeOOB )
91  sm.insert( std::make_pair( std::string( "oob" ), XMLNS_IQ_OOB ) );
92  dff->setOptions( sm );
93  feature->addChild( df.tag() );
94 
95  return m_manager->requestSI( this, to, XMLNS_SI_FT, file, feature, mimetype, from, sid );
96  }
97 
98  void SIProfileFT::acceptFT( const JID& to, const std::string& sid, StreamType type, const JID& from )
99  {
100  if( !m_manager )
101  return;
102 
103  if( m_id2sid.find( sid ) == m_id2sid.end() )
104  return;
105 
106  const std::string& id = m_id2sid[sid];
107 
108  Tag* feature = new Tag( "feature", XMLNS, XMLNS_FEATURE_NEG );
109  DataFormField* dff = new DataFormField( "stream-method" );
110  switch( type )
111  {
112  case FTTypeAll:
113  case FTTypeS5B:
114  dff->setValue( XMLNS_BYTESTREAMS );
115  break;
116  case FTTypeIBB:
117  dff->setValue( XMLNS_IBB );
118  if( m_handler )
119  {
120  InBandBytestream* ibb = new InBandBytestream( m_parent, m_parent->logInstance(), to,
121  from ? from : m_parent->jid(), sid );
122  m_handler->handleFTBytestream( ibb );
123  }
124  break;
125  case FTTypeOOB:
126  dff->setValue( XMLNS_IQ_OOB );
127  break;
128  }
129  DataForm df( TypeSubmit );
130  df.addField( dff );
131  feature->addChild( df.tag() );
132 
133  m_manager->acceptSI( to, id, 0, feature, from );
134  }
135 
136  void SIProfileFT::declineFT( const JID& to, const std::string& sid, SIManager::SIError reason,
137  const std::string& text )
138  {
139  if( m_id2sid.find( sid ) == m_id2sid.end() || !m_manager )
140  return;
141 
142  m_manager->declineSI( to, m_id2sid[sid], reason, text );
143  }
144 
146  {
147  if( bs )
148  {
149  if( bs->type() == Bytestream::S5B && m_socks5Manager )
150  m_socks5Manager->dispose( static_cast<SOCKS5Bytestream*>( bs ) );
151  else
152  delete bs;
153  }
154  }
155 
157  {
158  if( !bs )
159  return;
160 
161  if( m_id2sid.find( bs->sid() ) == m_id2sid.end() || !m_manager )
162  return;
163 
164  if( bs->type() == Bytestream::S5B && m_socks5Manager )
165  m_socks5Manager->rejectSOCKS5Bytestream( bs->sid(), StanzaErrorServiceUnavailable );
166 
167  dispose( bs );
168  }
169 
171  {
172  if( m_socks5Manager )
173  m_socks5Manager->setStreamHosts( hosts );
174  }
175 
176  void SIProfileFT::addStreamHost( const JID& jid, const std::string& host, int port )
177  {
178  if( m_socks5Manager )
179  m_socks5Manager->addStreamHost( jid, host, port );
180  }
181 
182  void SIProfileFT::handleSIRequest( const JID& from, const JID& to, const std::string& id,
183  const SIManager::SI& si )
184  {
185  if( si.profile() != XMLNS_SI_FT || !si.tag1() )
186  return;
187 
188  if( m_handler )
189  {
190  const Tag* t = si.tag1()->findChild( "desc" );
191  const std::string& desc = t ? t->cdata() : EmptyString;
192 
193  const std::string& mt = si.mimetype();
194  int types = 0;
195 
196  if( si.tag2() )
197  {
198  const DataForm df( si.tag2()->findChild( "x", XMLNS, XMLNS_X_DATA ) );
199  const DataFormField* dff = df.field( "stream-method" );
200 
201  if( dff )
202  {
203  const StringMultiMap& options = dff->options();
204  StringMultiMap::const_iterator it = options.begin();
205  for( ; it != options.end(); ++it )
206  {
207  if( (*it).second == XMLNS_BYTESTREAMS )
208  types |= FTTypeS5B;
209  else if( (*it).second == XMLNS_IBB )
210  types |= FTTypeIBB;
211  else if( (*it).second == XMLNS_IQ_OOB )
212  types |= FTTypeOOB;
213  }
214  }
215  }
216 
217  const std::string& sid = si.id();
218  m_id2sid[sid] = id;
219  m_handler->handleFTRequest( from, to, sid, si.tag1()->findAttribute( "name" ),
220  atol( si.tag1()->findAttribute( "size" ).c_str() ),
221  si.tag1()->findAttribute( "hash" ),
222  si.tag1()->findAttribute( "date" ),
223  mt.empty() ? "binary/octet-stream" : mt,
224  desc, types );
225  }
226  }
227 
228  void SIProfileFT::handleSIRequestResult( const JID& from, const JID& to, const std::string& sid,
229  const SIManager::SI& si )
230  {
231  if( si.tag2() )
232  {
233  const DataForm df( si.tag2()->findChild( "x", XMLNS, XMLNS_X_DATA ) );
234  const DataFormField* dff = df.field( "stream-method" );
235 
236  if( dff )
237  {
238  if( m_socks5Manager && dff->value() == XMLNS_BYTESTREAMS )
239  {
240  // check return value:
241  m_socks5Manager->requestSOCKS5Bytestream( from, SOCKS5BytestreamManager::S5BTCP, sid, to );
242  }
243  else if( m_handler )
244  {
245  if( dff->value() == XMLNS_IBB )
246  {
247  InBandBytestream* ibb = new InBandBytestream( m_parent, m_parent->logInstance(),
248  to ? to : m_parent->jid(), from, sid );
249 
250  m_handler->handleFTBytestream( ibb );
251  }
252  else if( dff->value() == XMLNS_IQ_OOB )
253  {
254  const std::string& url = m_handler->handleOOBRequestResult( from, to, sid );
255  if( !url.empty() )
256  {
257  const std::string& id = m_parent->getID();
258  IQ iq( IQ::Set, from, id );
259  if( to )
260  iq.setFrom( to );
261 
262  iq.addExtension( new OOB( url, EmptyString, true ) );
263  m_parent->send( iq, this, OOBSent );
264  }
265  }
266  }
267  }
268  }
269  }
270 
271  void SIProfileFT::handleIqID( const IQ& /*iq*/, int context )
272  {
273  switch( context )
274  {
275  case OOBSent:
276 // if( iq->subtype() == IQ::Error )
277 // m_handler->handleOOBError
278  break;
279  }
280  }
281 
282  void SIProfileFT::handleSIRequestError( const IQ& iq, const std::string& sid )
283  {
284  if( m_handler )
285  m_handler->handleFTRequestError( iq, sid );
286  }
287 
288  void SIProfileFT::handleIncomingBytestreamRequest( const std::string& sid, const JID& /*from*/ )
289  {
290 // TODO: check for valid sid/from tuple
291  m_socks5Manager->acceptSOCKS5Bytestream( sid );
292  }
293 
295  {
296  if( m_handler )
297  m_handler->handleFTBytestream( bs );
298  }
299 
301  {
302  if( m_handler )
303  m_handler->handleFTBytestream( bs );
304  }
305 
306  void SIProfileFT::handleBytestreamError( const IQ& iq, const std::string& sid )
307  {
308  if( m_handler )
309  m_handler->handleFTRequestError( iq, sid );
310  }
311 
312 }
An abstraction of a single bytestream.
Definition: bytestream.h:37
const std::string & sid() const
Definition: bytestream.h:114
StreamType type() const
Definition: bytestream.h:120
This is the common base class for a Jabber/XMPP Client and a Jabber Component.
Definition: clientbase.h:79
const std::string getID()
const JID & jid()
Definition: clientbase.h:147
LogSink & logInstance()
Definition: clientbase.h:599
void send(Tag *tag)
virtual void addField(DataFormField *field)
DataFormField * field(const std::string &field) const
An abstraction of a single field in a XEP-0004 Data Form.
Definition: dataformfield.h:34
void setOptions(const StringMultiMap &options)
const std::string & value() const
const StringMultiMap & options() const
void setValue(const std::string &value)
An abstraction of a XEP-0004 Data Form.
Definition: dataform.h:57
virtual Tag * tag() const
Definition: dataform.cpp:106
An abstraction of an IQ stanza.
Definition: iq.h:34
@ Set
Definition: iq.h:46
An implementation of a single In-Band Bytestream (XEP-0047).
An abstraction of a JID.
Definition: jid.h:31
This is an abstraction of a jabber:x:oob namespace element or a jabber:iq:oob namespace element as sp...
Definition: oob.h:36
This class manages streams initiated using XEP-0095.
Definition: simanager.h:35
void acceptSI(const JID &to, const std::string &id, Tag *child1, Tag *child2=0, const JID &from=JID())
Definition: simanager.cpp:137
void registerProfile(const std::string &profile, SIProfileHandler *sih)
Definition: simanager.cpp:171
void declineSI(const JID &to, const std::string &id, SIError reason, const std::string &text=EmptyString)
Definition: simanager.cpp:147
void removeProfile(const std::string &profile)
Definition: simanager.cpp:182
const std::string requestSI(SIHandler *sih, const JID &to, const std::string &profile, Tag *child1, Tag *child2=0, const std::string &mimetype="binary/octet-stream", const JID &from=JID(), const std::string &sid=EmptyString)
Definition: simanager.cpp:112
An abstract base class to handle file transfer (FT) requests.
virtual void handleFTRequestError(const IQ &iq, const std::string &sid)=0
virtual void handleFTBytestream(Bytestream *bs)=0
virtual void handleFTRequest(const JID &from, const JID &to, const std::string &sid, const std::string &name, long size, const std::string &hash, const std::string &date, const std::string &mimetype, const std::string &desc, int stypes)=0
virtual const std::string handleOOBRequestResult(const JID &from, const JID &to, const std::string &sid)=0
void setStreamHosts(StreamHostList hosts)
virtual void handleIncomingBytestream(Bytestream *bs)
virtual void handleIqID(const IQ &iq, int context)
void addStreamHost(const JID &jid, const std::string &host, int port)
virtual void handleSIRequest(const JID &from, const JID &to, const std::string &id, const SIManager::SI &si)
void cancel(Bytestream *bs)
virtual void handleSIRequestError(const IQ &iq, const std::string &sid)
virtual void handleIncomingBytestreamRequest(const std::string &sid, const JID &from)
virtual ~SIProfileFT()
Definition: siprofileft.cpp:52
virtual void handleOutgoingBytestream(Bytestream *bs)
const std::string requestFT(const JID &to, const std::string &name, long size, const std::string &hash=EmptyString, const std::string &desc=EmptyString, const std::string &date=EmptyString, const std::string &mimetype=EmptyString, int streamTypes=FTTypeAll, const JID &from=JID(), const std::string &sid=EmptyString)
Definition: siprofileft.cpp:63
void dispose(Bytestream *bs)
void acceptFT(const JID &to, const std::string &sid, StreamType type=FTTypeS5B, const JID &from=JID())
Definition: siprofileft.cpp:98
virtual void handleBytestreamError(const IQ &iq, const std::string &sid)
virtual void handleSIRequestResult(const JID &from, const JID &to, const std::string &sid, const SIManager::SI &si)
SIProfileFT(ClientBase *parent, SIProfileFTHandler *sipfth, SIManager *manager=0, SOCKS5BytestreamManager *s5Manager=0)
Definition: siprofileft.cpp:31
void declineFT(const JID &to, const std::string &sid, SIManager::SIError reason, const std::string &text=EmptyString)
An SOCKS5BytestreamManager dispatches SOCKS5 Bytestreams.
void setStreamHosts(StreamHostList hosts)
void addStreamHost(const JID &jid, const std::string &host, int port)
void rejectSOCKS5Bytestream(const std::string &sid, StanzaError reason=StanzaErrorNotAcceptable)
bool requestSOCKS5Bytestream(const JID &to, S5BMode mode, const std::string &sid=EmptyString, const JID &from=JID())
bool dispose(SOCKS5Bytestream *s5b)
void acceptSOCKS5Bytestream(const std::string &sid)
An implementation of a single SOCKS5 Bytestream (XEP-0065).
void addExtension(const StanzaExtension *se)
Definition: stanza.cpp:52
void setFrom(const JID &from)
Definition: stanza.h:45
This is an abstraction of an XML element.
Definition: tag.h:47
Tag * findChild(const std::string &name) const
Definition: tag.cpp:624
bool addAttribute(Attribute *attr)
Definition: tag.cpp:354
void addChild(Tag *child)
Definition: tag.cpp:424
const std::string cdata() const
Definition: tag.cpp:497
The namespace for the gloox library.
Definition: adhoc.cpp:28
const std::string XMLNS_IQ_OOB
Definition: gloox.cpp:48
std::multimap< std::string, std::string > StringMultiMap
Definition: gloox.h:1266
const std::string XMLNS_IBB
Definition: gloox.cpp:32
const std::string XMLNS_FEATURE_NEG
Definition: gloox.cpp:33
const std::string XMLNS_X_DATA
Definition: gloox.cpp:49
const std::string EmptyString
Definition: gloox.cpp:124
const std::string XMLNS
Definition: gloox.cpp:122
const std::string XMLNS_SI_FT
Definition: gloox.cpp:65
@ StanzaErrorServiceUnavailable
Definition: gloox.h:936
@ TypeSubmit
Definition: dataform.h:37
@ TypeForm
Definition: dataform.h:35
std::list< StreamHost > StreamHostList
const std::string XMLNS_BYTESTREAMS
Definition: gloox.cpp:66