gloox
1.0
|
00001 /* 00002 Copyright (c) 2007-2009 by Jakob Schroeter <js@camaya.net> 00003 This file is part of the gloox library. http://camaya.net/gloox 00004 00005 This software is distributed under a license. The full license 00006 agreement can be found in the file LICENSE in this distribution. 00007 This software may not be copied, modified, sold or distributed 00008 other than expressed in the named license agreement. 00009 00010 This software is distributed without any warranty. 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 // check return value: 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& /*iq*/, int context ) 00272 { 00273 switch( context ) 00274 { 00275 case OOBSent: 00276 // if( iq->subtype() == IQ::Error ) 00277 // m_handler->handleOOBError 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& /*from*/ ) 00289 { 00290 // TODO: check for valid sid/from tuple 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 }