gloox  0.9.9.12
siprofileft.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 "siprofileft.h"
15 
16 #include "siprofilefthandler.h"
17 #include "simanager.h"
18 #include "dataform.h"
19 #include "socks5bytestream.h"
20 #include "socks5bytestreammanager.h"
21 
22 #include <cstdlib>
23 
24 namespace gloox
25 {
26 
28  SOCKS5BytestreamManager* s5Manager )
29  : m_parent( parent ), m_manager( manager ), m_handler( sipfth ),
30  m_socks5Manager( s5Manager ), m_delManager( false ), m_delS5Manager( false ), m_ranged( false )
31  {
32  if( !m_manager )
33  {
34  m_delManager = true;
35  m_manager = new SIManager( m_parent );
36  }
37 
38  m_manager->registerProfile( XMLNS_SI_FT, this );
39 
40  if( !m_socks5Manager )
41  {
42  m_socks5Manager = new SOCKS5BytestreamManager( m_parent, this );
43  m_delS5Manager = true;
44  }
45  }
46 
48  {
49  m_manager->removeProfile( XMLNS_SI_FT );
50 
51  if( m_delManager )
52  delete m_manager;
53 
54  if( m_socks5Manager && m_delS5Manager )
55  delete m_socks5Manager;
56  }
57 
58  const std::string SIProfileFT::requestFT( const JID& to, const std::string& name, long size,
59  const std::string& hash, const std::string& desc,
60  const std::string& date, const std::string& mimetype )
61  {
62  if( name.empty() || size <= 0 || !m_manager )
63  return std::string();
64 
65  Tag* file = new Tag( "file", "xmlns", XMLNS_SI_FT );
66  file->addAttribute( "name", name );
67  file->addAttribute( "size", size );
68  if( !hash.empty() )
69  file->addAttribute( "hash", hash );
70  if( !date.empty() )
71  file->addAttribute( "date", date );
72  if( !desc.empty() )
73  new Tag( file, "desc", desc );
74  if( m_ranged )
75  new Tag( file, "range" );
76 
77  Tag* feature = new Tag( "feature", "xmlns", XMLNS_FEATURE_NEG );
78  DataFormField* dff = new DataFormField( "stream-method", "", "", DataFormField::FieldTypeListSingle );
79  StringMap sm;
80  sm["s5b"] = XMLNS_BYTESTREAMS;
81 // sm["ibb"] = XMLNS_IBB;
82 // sm["oob"] = XMLNS_IQ_OOB;
83  dff->setOptions( sm );
85  df.addField( dff );
86  feature->addChild( df.tag() );
87 
88  return m_manager->requestSI( this, to, XMLNS_SI_FT, file, feature, mimetype );;
89  }
90 
91  void SIProfileFT::acceptFT( const JID& to, const std::string& id, StreamType type )
92  {
93  if( !m_manager )
94  return;
95 
96  Tag* feature = new Tag( "feature", "xmlns", XMLNS_FEATURE_NEG );
97  DataFormField* dff = new DataFormField( "stream-method" );
98  switch( type )
99  {
100  case FTTypeS5B:
101  dff->setValue( XMLNS_BYTESTREAMS );
102  break;
103 /* case FTTypeIBB:
104  dff->setValue( XMLNS_IBB );
105  break;
106  case FTTypeOOB:
107  dff->setValue( XMLNS_IQ_OOB );
108  break;*/
109  }
111  df.addField( dff );
112  feature->addChild( df.tag() );
113 
114  m_manager->acceptSI( to, id, 0, feature );
115  }
116 
117  void SIProfileFT::declineFT( const JID& to, const std::string& id, SIManager::SIError reason,
118  const std::string& text )
119  {
120  if( !m_manager )
121  return;
122 
123  m_manager->declineSI( to, id, reason, text );
124  }
125 
127  {
128  if( m_socks5Manager )
129  m_socks5Manager->dispose( s5b );
130  }
131 
133  {
134  if( m_socks5Manager )
135  m_socks5Manager->setStreamHosts( hosts );
136  }
137 
138  void SIProfileFT::addStreamHost( const JID& jid, const std::string& host, int port )
139  {
140  if( m_socks5Manager )
141  m_socks5Manager->addStreamHost( jid, host, port );
142  }
143 
144  void SIProfileFT::handleSIRequest( const JID& from, const std::string& id, const std::string& profile,
145  Tag* si, Tag* ptag, Tag* /*fneg*/ )
146  {
147  if( profile != XMLNS_SI_FT || !ptag || !si )
148  return;
149 
150  if( m_handler )
151  {
152  std::string desc;
153  long offset = 0;
154  long length = -1;
155  if( ptag->hasChild( "desc" ) )
156  desc = ptag->findChild( "desc" )->cdata();
157  Tag* r = ptag->findChild( "range" );
158  if( r )
159  {
160  if( r->hasAttribute( "offset" ) )
161  offset = atol( r->findAttribute( "offset" ).c_str() );
162  if( r->hasAttribute( "length" ) )
163  length = atol( r->findAttribute( "length" ).c_str() );
164  }
165  const std::string& mt = si->findAttribute( "mime-type" );
166  m_handler->handleFTRequest( from, id, si->findAttribute( "id" ), ptag->findAttribute( "name" ),
167  atol( ptag->findAttribute( "size" ).c_str() ),
168  ptag->findAttribute( "hash" ), ptag->findAttribute( "date" ),
169  mt.empty() ? "binary/octet-stream" : mt, desc, FTTypeS5B, offset, length );
170  }
171  }
172 
173  void SIProfileFT::handleSIRequestResult( const JID& from, const std::string& sid,
174  Tag* /*si*/, Tag* /*ptag*/, Tag* fneg )
175  {
176 
177  if( m_socks5Manager && fneg && fneg->hasChild( "x", "xmlns", XMLNS_X_DATA ) )
178  {
179  DataForm df( fneg->findChild( "x", "xmlns", XMLNS_X_DATA ) );
180  DataFormField* dff = df.field( "stream-method" );
181  if( dff && dff->value() == XMLNS_BYTESTREAMS )
182  {
183  // check return value:
184  m_socks5Manager->requestSOCKS5Bytestream( from, SOCKS5BytestreamManager::S5BTCP, sid );
185  }
186  }
187 
188 // if( m_handler )
189 // m_handler->handleFTRequestResult( from, sid );
190  }
191 
192  void SIProfileFT::handleSIRequestError( Stanza* stanza, const std::string& sid )
193  {
194  if( m_handler )
195  m_handler->handleFTRequestError( stanza, sid );
196  }
197 
198  void SIProfileFT::handleIncomingSOCKS5BytestreamRequest( const std::string& sid, const JID& /*from*/ )
199  {
200 // TODO: check for valid sid/from tuple
201  m_socks5Manager->acceptSOCKS5Bytestream( sid );
202  }
203 
205  {
206  if( m_handler )
207  m_handler->handleFTSOCKS5Bytestream( s5b );
208  }
209 
211  {
212  if( m_handler )
213  m_handler->handleFTSOCKS5Bytestream( s5b );
214  }
215 
216  void SIProfileFT::handleSOCKS5BytestreamError( Stanza* stanza, const std::string& sid )
217  {
218  if( m_handler )
219  m_handler->handleFTRequestError( stanza, sid );
220  }
221 
222 }