00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "siprofileft.h"
00015
00016 #include "clientbase.h"
00017 #include "siprofilefthandler.h"
00018 #include "simanager.h"
00019 #include "dataform.h"
00020 #include "inbandbytestream.h"
00021 #include "oob.h"
00022 #include "socks5bytestream.h"
00023 #include "socks5bytestreammanager.h"
00024
00025 #include <cstdlib>
00026 #include <map>
00027
00028 namespace gloox
00029 {
00030
00031 SIProfileFT::SIProfileFT( ClientBase* parent, SIProfileFTHandler* sipfth, SIManager* manager,
00032 SOCKS5BytestreamManager* s5Manager )
00033 : m_parent( parent ), m_manager( manager ), m_handler( sipfth ),
00034 m_socks5Manager( s5Manager ), m_delManager( false ),
00035 m_delS5Manager( false )
00036 {
00037 if( !m_manager )
00038 {
00039 m_delManager = true;
00040 m_manager = new SIManager( m_parent );
00041 }
00042
00043 m_manager->registerProfile( XMLNS_SI_FT, this );
00044
00045 if( !m_socks5Manager )
00046 {
00047 m_socks5Manager = new SOCKS5BytestreamManager( m_parent, this );
00048 m_delS5Manager = true;
00049 }
00050 }
00051
00052 SIProfileFT::~SIProfileFT()
00053 {
00054 m_manager->removeProfile( XMLNS_SI_FT );
00055
00056 if( m_delManager )
00057 delete m_manager;
00058
00059 if( m_socks5Manager && m_delS5Manager )
00060 delete m_socks5Manager;
00061 }
00062
00063 const std::string SIProfileFT::requestFT( const JID& to, const std::string& name, long size,
00064 const std::string& hash, const std::string& desc,
00065 const std::string& date, const std::string& mimetype,
00066 int streamTypes, const JID& from,
00067 const std::string& sid )
00068 {
00069 if( name.empty() || size <= 0 || !m_manager )
00070 return EmptyString;
00071
00072 Tag* file = new Tag( "file", XMLNS, XMLNS_SI_FT );
00073 file->addAttribute( "name", name );
00074 file->addAttribute( "size", size );
00075 if( !hash.empty() )
00076 file->addAttribute( "hash", hash );
00077 if( !date.empty() )
00078 file->addAttribute( "date", date );
00079 if( !desc.empty() )
00080 new Tag( file, "desc", desc );
00081
00082 Tag* feature = new Tag( "feature", XMLNS, XMLNS_FEATURE_NEG );
00083 DataForm df( TypeForm );
00084 DataFormField* dff = df.addField( DataFormField::TypeListSingle, "stream-method" );
00085 StringMultiMap sm;
00086 if( streamTypes & FTTypeS5B )
00087 sm.insert( std::make_pair( "s5b", XMLNS_BYTESTREAMS ) );
00088 if( streamTypes & FTTypeIBB )
00089 sm.insert( std::make_pair( "ibb", XMLNS_IBB ) );
00090 if( streamTypes & FTTypeOOB )
00091 sm.insert( std::make_pair( "oob", XMLNS_IQ_OOB ) );
00092 dff->setOptions( sm );
00093 feature->addChild( df.tag() );
00094
00095 return m_manager->requestSI( this, to, XMLNS_SI_FT, file, feature, mimetype, from, sid );
00096 }
00097
00098 void SIProfileFT::acceptFT( const JID& to, const std::string& sid, StreamType type, const JID& from )
00099 {
00100 if( !m_manager )
00101 return;
00102
00103 if( m_id2sid.find( sid ) == m_id2sid.end() )
00104 return;
00105
00106 const std::string& id = m_id2sid[sid];
00107
00108 Tag* feature = new Tag( "feature", XMLNS, XMLNS_FEATURE_NEG );
00109 DataFormField* dff = new DataFormField( "stream-method" );
00110 switch( type )
00111 {
00112 case FTTypeAll:
00113 case FTTypeS5B:
00114 dff->setValue( XMLNS_BYTESTREAMS );
00115 break;
00116 case FTTypeIBB:
00117 dff->setValue( XMLNS_IBB );
00118 if( m_handler )
00119 {
00120 InBandBytestream* ibb = new InBandBytestream( m_parent, m_parent->logInstance(), to,
00121 from ? from : m_parent->jid(), sid );
00122 m_handler->handleFTBytestream( ibb );
00123 }
00124 break;
00125 case FTTypeOOB:
00126 dff->setValue( XMLNS_IQ_OOB );
00127 break;
00128 }
00129 DataForm df( TypeSubmit );
00130 df.addField( dff );
00131 feature->addChild( df.tag() );
00132
00133 m_manager->acceptSI( to, id, 0, feature, from );
00134 }
00135
00136 void SIProfileFT::declineFT( const JID& to, const std::string& sid, SIManager::SIError reason,
00137 const std::string& text )
00138 {
00139 if( m_id2sid.find( sid ) == m_id2sid.end() || !m_manager )
00140 return;
00141
00142 m_manager->declineSI( to, m_id2sid[sid], reason, text );
00143 }
00144
00145 void SIProfileFT::dispose( Bytestream* bs )
00146 {
00147 if( bs )
00148 {
00149 if( bs->type() == Bytestream::S5B && m_socks5Manager )
00150 m_socks5Manager->dispose( static_cast<SOCKS5Bytestream*>( bs ) );
00151 else
00152 delete bs;
00153 }
00154 }
00155
00156 void SIProfileFT::cancel( Bytestream* bs )
00157 {
00158 if( !bs )
00159 return;
00160
00161 if( m_id2sid.find( bs->sid() ) == m_id2sid.end() || !m_manager )
00162 return;
00163
00164 if( bs->type() == Bytestream::S5B && m_socks5Manager )
00165 m_socks5Manager->rejectSOCKS5Bytestream( bs->sid(), StanzaErrorServiceUnavailable );
00166
00167 dispose( bs );
00168 }
00169
00170 void SIProfileFT::setStreamHosts( StreamHostList hosts )
00171 {
00172 if( m_socks5Manager )
00173 m_socks5Manager->setStreamHosts( hosts );
00174 }
00175
00176 void SIProfileFT::addStreamHost( const JID& jid, const std::string& host, int port )
00177 {
00178 if( m_socks5Manager )
00179 m_socks5Manager->addStreamHost( jid, host, port );
00180 }
00181
00182 void SIProfileFT::handleSIRequest( const JID& from, const JID& to, const std::string& id,
00183 const SIManager::SI& si )
00184 {
00185 if( si.profile() != XMLNS_SI_FT || !si.tag1() )
00186 return;
00187
00188 if( m_handler )
00189 {
00190 const Tag* t = si.tag1()->findChild( "desc" );
00191 const std::string& desc = t ? t->cdata() : EmptyString;
00192
00193 const std::string& mt = si.mimetype();
00194 int types = 0;
00195
00196 if( si.tag2() )
00197 {
00198 const DataForm df( si.tag2()->findChild( "x", XMLNS, XMLNS_X_DATA ) );
00199 const DataFormField* dff = df.field( "stream-method" );
00200
00201 if( dff )
00202 {
00203 const StringMultiMap& options = dff->options();
00204 StringMultiMap::const_iterator it = options.begin();
00205 for( ; it != options.end(); ++it )
00206 {
00207 if( (*it).second == XMLNS_BYTESTREAMS )
00208 types |= FTTypeS5B;
00209 else if( (*it).second == XMLNS_IBB )
00210 types |= FTTypeIBB;
00211 else if( (*it).second == XMLNS_IQ_OOB )
00212 types |= FTTypeOOB;
00213 }
00214 }
00215 }
00216
00217 const std::string& sid = si.id();
00218 m_id2sid[sid] = id;
00219 m_handler->handleFTRequest( from, to, sid, si.tag1()->findAttribute( "name" ),
00220 atol( si.tag1()->findAttribute( "size" ).c_str() ),
00221 si.tag1()->findAttribute( "hash" ),
00222 si.tag1()->findAttribute( "date" ),
00223 mt.empty() ? "binary/octet-stream" : mt,
00224 desc, types );
00225 }
00226 }
00227
00228 void SIProfileFT::handleSIRequestResult( const JID& from, const JID& to, const std::string& sid,
00229 const SIManager::SI& si )
00230 {
00231 if( si.tag2() )
00232 {
00233 const DataForm df( si.tag2()->findChild( "x", XMLNS, XMLNS_X_DATA ) );
00234 const DataFormField* dff = df.field( "stream-method" );
00235
00236 if( dff )
00237 {
00238 if( m_socks5Manager && dff->value() == XMLNS_BYTESTREAMS )
00239 {
00240
00241 m_socks5Manager->requestSOCKS5Bytestream( from, SOCKS5BytestreamManager::S5BTCP, sid, to );
00242 }
00243 else if( m_handler )
00244 {
00245 if( dff->value() == XMLNS_IBB )
00246 {
00247 InBandBytestream* ibb = new InBandBytestream( m_parent, m_parent->logInstance(),
00248 to ? to : m_parent->jid(), from, sid );
00249
00250 m_handler->handleFTBytestream( ibb );
00251 }
00252 else if( dff->value() == XMLNS_IQ_OOB )
00253 {
00254 const std::string& url = m_handler->handleOOBRequestResult( from, to, sid );
00255 if( !url.empty() )
00256 {
00257 const std::string& id = m_parent->getID();
00258 IQ iq( IQ::Set, from, id );
00259 if( to )
00260 iq.setFrom( to );
00261
00262 iq.addExtension( new OOB( url, EmptyString, true ) );
00263 m_parent->send( iq, this, OOBSent );
00264 }
00265 }
00266 }
00267 }
00268 }
00269 }
00270
00271 void SIProfileFT::handleIqID( const IQ& , int context )
00272 {
00273 switch( context )
00274 {
00275 case OOBSent:
00276
00277
00278 break;
00279 }
00280 }
00281
00282 void SIProfileFT::handleSIRequestError( const IQ& iq, const std::string& sid )
00283 {
00284 if( m_handler )
00285 m_handler->handleFTRequestError( iq, sid );
00286 }
00287
00288 void SIProfileFT::handleIncomingBytestreamRequest( const std::string& sid, const JID& )
00289 {
00290
00291 m_socks5Manager->acceptSOCKS5Bytestream( sid );
00292 }
00293
00294 void SIProfileFT::handleIncomingBytestream( Bytestream* bs )
00295 {
00296 if( m_handler )
00297 m_handler->handleFTBytestream( bs );
00298 }
00299
00300 void SIProfileFT::handleOutgoingBytestream( Bytestream* bs )
00301 {
00302 if( m_handler )
00303 m_handler->handleFTBytestream( bs );
00304 }
00305
00306 void SIProfileFT::handleBytestreamError( const IQ& iq, const std::string& sid )
00307 {
00308 if( m_handler )
00309 m_handler->handleFTRequestError( iq, sid );
00310 }
00311
00312 }