00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "siprofileft.h"
00015
00016 #include "siprofilefthandler.h"
00017 #include "simanager.h"
00018 #include "dataform.h"
00019 #include "socks5bytestream.h"
00020 #include "socks5bytestreammanager.h"
00021
00022 #include <cstdlib>
00023
00024 namespace gloox
00025 {
00026
00027 SIProfileFT::SIProfileFT( ClientBase* parent, SIProfileFTHandler* sipfth, SIManager* manager,
00028 SOCKS5BytestreamManager* s5Manager )
00029 : m_parent( parent ), m_manager( manager ), m_handler( sipfth ),
00030 m_socks5Manager( s5Manager ), m_delManager( false ), m_delS5Manager( false ), m_ranged( false )
00031 {
00032 if( !m_manager )
00033 {
00034 m_delManager = true;
00035 m_manager = new SIManager( m_parent );
00036 }
00037
00038 m_manager->registerProfile( XMLNS_SI_FT, this );
00039
00040 if( !m_socks5Manager )
00041 {
00042 m_socks5Manager = new SOCKS5BytestreamManager( m_parent, this );
00043 m_delS5Manager = true;
00044 }
00045 }
00046
00047 SIProfileFT::~SIProfileFT()
00048 {
00049 m_manager->removeProfile( XMLNS_SI_FT );
00050
00051 if( m_delManager )
00052 delete m_manager;
00053
00054 if( m_socks5Manager && m_delS5Manager )
00055 delete m_socks5Manager;
00056 }
00057
00058 const std::string SIProfileFT::requestFT( const JID& to, const std::string& name, long size,
00059 const std::string& hash, const std::string& desc,
00060 const std::string& date, const std::string& mimetype )
00061 {
00062 if( name.empty() || size <= 0 || !m_manager )
00063 return std::string();
00064
00065 Tag* file = new Tag( "file", "xmlns", XMLNS_SI_FT );
00066 file->addAttribute( "name", name );
00067 file->addAttribute( "size", size );
00068 if( !hash.empty() )
00069 file->addAttribute( "hash", hash );
00070 if( !date.empty() )
00071 file->addAttribute( "date", date );
00072 if( !desc.empty() )
00073 new Tag( file, "desc", desc );
00074 if( m_ranged )
00075 new Tag( file, "range" );
00076
00077 Tag* feature = new Tag( "feature", "xmlns", XMLNS_FEATURE_NEG );
00078 DataFormField* dff = new DataFormField( "stream-method", "", "", DataFormField::FieldTypeListSingle );
00079 StringMap sm;
00080 sm["s5b"] = XMLNS_BYTESTREAMS;
00081
00082
00083 dff->setOptions( sm );
00084 DataForm df( DataForm::FormTypeForm );
00085 df.addField( dff );
00086 feature->addChild( df.tag() );
00087
00088 return m_manager->requestSI( this, to, XMLNS_SI_FT, file, feature, mimetype );;
00089 }
00090
00091 void SIProfileFT::acceptFT( const JID& to, const std::string& id, StreamType type )
00092 {
00093 if( !m_manager )
00094 return;
00095
00096 Tag* feature = new Tag( "feature", "xmlns", XMLNS_FEATURE_NEG );
00097 DataFormField* dff = new DataFormField( "stream-method" );
00098 switch( type )
00099 {
00100 case FTTypeS5B:
00101 dff->setValue( XMLNS_BYTESTREAMS );
00102 break;
00103
00104
00105
00106
00107
00108
00109 }
00110 DataForm df( DataForm::FormTypeSubmit );
00111 df.addField( dff );
00112 feature->addChild( df.tag() );
00113
00114 m_manager->acceptSI( to, id, 0, feature );
00115 }
00116
00117 void SIProfileFT::declineFT( const JID& to, const std::string& id, SIManager::SIError reason,
00118 const std::string& text )
00119 {
00120 if( !m_manager )
00121 return;
00122
00123 m_manager->declineSI( to, id, reason, text );
00124 }
00125
00126 void SIProfileFT::dispose( SOCKS5Bytestream* s5b )
00127 {
00128 if( m_socks5Manager )
00129 m_socks5Manager->dispose( s5b );
00130 }
00131
00132 void SIProfileFT::setStreamHosts( StreamHostList hosts )
00133 {
00134 if( m_socks5Manager )
00135 m_socks5Manager->setStreamHosts( hosts );
00136 }
00137
00138 void SIProfileFT::addStreamHost( const JID& jid, const std::string& host, int port )
00139 {
00140 if( m_socks5Manager )
00141 m_socks5Manager->addStreamHost( jid, host, port );
00142 }
00143
00144 void SIProfileFT::handleSIRequest( const JID& from, const std::string& id, const std::string& profile,
00145 Tag* si, Tag* ptag, Tag* )
00146 {
00147 if( profile != XMLNS_SI_FT || !ptag || !si )
00148 return;
00149
00150 if( m_handler )
00151 {
00152 std::string desc;
00153 long offset = 0;
00154 long length = -1;
00155 if( ptag->hasChild( "desc" ) )
00156 desc = ptag->findChild( "desc" )->cdata();
00157 Tag* r = ptag->findChild( "range" );
00158 if( r )
00159 {
00160 if( r->hasAttribute( "offset" ) )
00161 offset = atol( r->findAttribute( "offset" ).c_str() );
00162 if( r->hasAttribute( "length" ) )
00163 length = atol( r->findAttribute( "length" ).c_str() );
00164 }
00165 const std::string& mt = si->findAttribute( "mime-type" );
00166 m_handler->handleFTRequest( from, id, si->findAttribute( "id" ), ptag->findAttribute( "name" ),
00167 atol( ptag->findAttribute( "size" ).c_str() ),
00168 ptag->findAttribute( "hash" ), ptag->findAttribute( "date" ),
00169 mt.empty() ? "binary/octet-stream" : mt, desc, FTTypeS5B, offset, length );
00170 }
00171 }
00172
00173 void SIProfileFT::handleSIRequestResult( const JID& from, const std::string& sid,
00174 Tag* , Tag* , Tag* fneg )
00175 {
00176
00177 if( m_socks5Manager && fneg && fneg->hasChild( "x", "xmlns", XMLNS_X_DATA ) )
00178 {
00179 DataForm df( fneg->findChild( "x", "xmlns", XMLNS_X_DATA ) );
00180 DataFormField* dff = df.field( "stream-method" );
00181 if( dff && dff->value() == XMLNS_BYTESTREAMS )
00182 {
00183
00184 m_socks5Manager->requestSOCKS5Bytestream( from, SOCKS5BytestreamManager::S5BTCP, sid );
00185 }
00186 }
00187
00188
00189
00190 }
00191
00192 void SIProfileFT::handleSIRequestError( Stanza* stanza, const std::string& sid )
00193 {
00194 if( m_handler )
00195 m_handler->handleFTRequestError( stanza, sid );
00196 }
00197
00198 void SIProfileFT::handleIncomingSOCKS5BytestreamRequest( const std::string& sid, const JID& )
00199 {
00200
00201 m_socks5Manager->acceptSOCKS5Bytestream( sid );
00202 }
00203
00204 void SIProfileFT::handleIncomingSOCKS5Bytestream( SOCKS5Bytestream* s5b )
00205 {
00206 if( m_handler )
00207 m_handler->handleFTSOCKS5Bytestream( s5b );
00208 }
00209
00210 void SIProfileFT::handleOutgoingSOCKS5Bytestream( SOCKS5Bytestream *s5b )
00211 {
00212 if( m_handler )
00213 m_handler->handleFTSOCKS5Bytestream( s5b );
00214 }
00215
00216 void SIProfileFT::handleSOCKS5BytestreamError( Stanza* stanza, const std::string& sid )
00217 {
00218 if( m_handler )
00219 m_handler->handleFTRequestError( stanza, sid );
00220 }
00221
00222 }