siprofileft.cpp
/*
Copyright (c) 2007-2023 by Jakob Schröter <js@camaya.net>
This file is part of the gloox library. http://camaya.net/gloox
This software is distributed under a license. The full license
agreement can be found in the file LICENSE in this distribution.
This software may not be copied, modified, sold or distributed
other than expressed in the named license agreement.
This software is distributed without any warranty.
*/
#include "siprofileft.h"
#include "clientbase.h"
#include "siprofilefthandler.h"
#include "simanager.h"
#include "dataform.h"
#include "inbandbytestream.h"
#include "oob.h"
#include "socks5bytestream.h"
#include "socks5bytestreammanager.h"
#include <cstdlib>
#include <map>
namespace gloox
{
SIProfileFT::SIProfileFT( ClientBase* parent, SIProfileFTHandler* sipfth, SIManager* manager,
SOCKS5BytestreamManager* s5Manager )
: m_parent( parent ), m_manager( manager ), m_handler( sipfth ),
m_socks5Manager( s5Manager ), m_delManager( false ),
m_delS5Manager( false )
{
if( !m_manager )
{
m_delManager = true;
m_manager = new SIManager( m_parent );
}
m_manager->registerProfile( XMLNS_SI_FT, this );
if( !m_socks5Manager )
{
m_socks5Manager = new SOCKS5BytestreamManager( m_parent, this );
m_delS5Manager = true;
}
}
SIProfileFT::~SIProfileFT()
{
m_manager->removeProfile( XMLNS_SI_FT );
if( m_delManager )
delete m_manager;
if( m_socks5Manager && m_delS5Manager )
delete m_socks5Manager;
}
const std::string SIProfileFT::requestFT( const JID& to, const std::string& name, long size,
const std::string& hash, const std::string& desc,
const std::string& date, const std::string& mimetype,
int streamTypes, const JID& from,
const std::string& sid )
{
if( name.empty() || size <= 0 || !m_manager )
return EmptyString;
Tag* file = new Tag( "file", XMLNS, XMLNS_SI_FT );
file->addAttribute( "name", name );
file->addAttribute( "size", size );
if( !hash.empty() )
file->addAttribute( "hash", hash );
if( !date.empty() )
file->addAttribute( "date", date );
if( !desc.empty() )
new Tag( file, "desc", desc );
Tag* feature = new Tag( "feature", XMLNS, XMLNS_FEATURE_NEG );
DataForm df( TypeForm );
DataFormField* dff = df.addField( DataFormField::TypeListSingle, "stream-method" );
StringMultiMap sm;
if( streamTypes & FTTypeS5B )
sm.insert( std::make_pair( std::string( "s5b" ), XMLNS_BYTESTREAMS ) );
if( streamTypes & FTTypeIBB )
sm.insert( std::make_pair( std::string( "ibb" ), XMLNS_IBB ) );
if( streamTypes & FTTypeOOB )
sm.insert( std::make_pair( std::string( "oob" ), XMLNS_IQ_OOB ) );
dff->setOptions( sm );
feature->addChild( df.tag() );
return m_manager->requestSI( this, to, XMLNS_SI_FT, file, feature, mimetype, from, sid );
}
void SIProfileFT::acceptFT( const JID& to, const std::string& sid, StreamType type, const JID& from )
{
if( !m_manager )
return;
if( m_id2sid.find( sid ) == m_id2sid.end() )
return;
const std::string& id = m_id2sid[sid];
Tag* feature = new Tag( "feature", XMLNS, XMLNS_FEATURE_NEG );
DataFormField* dff = new DataFormField( "stream-method" );
switch( type )
{
case FTTypeAll:
case FTTypeS5B:
dff->setValue( XMLNS_BYTESTREAMS );
break;
case FTTypeIBB:
dff->setValue( XMLNS_IBB );
if( m_handler )
{
InBandBytestream* ibb = new InBandBytestream( m_parent, m_parent->logInstance(), to,
from ? from : m_parent->jid(), sid );
m_handler->handleFTBytestream( ibb );
}
break;
case FTTypeOOB:
dff->setValue( XMLNS_IQ_OOB );
break;
}
DataForm df( TypeSubmit );
df.addField( dff );
feature->addChild( df.tag() );
m_manager->acceptSI( to, id, 0, feature, from );
}
void SIProfileFT::declineFT( const JID& to, const std::string& sid, SIManager::SIError reason,
const std::string& text )
{
if( m_id2sid.find( sid ) == m_id2sid.end() || !m_manager )
return;
m_manager->declineSI( to, m_id2sid[sid], reason, text );
}
void SIProfileFT::dispose( Bytestream* bs )
{
if( bs )
{
if( bs->type() == Bytestream::S5B && m_socks5Manager )
m_socks5Manager->dispose( static_cast<SOCKS5Bytestream*>( bs ) );
else
delete bs;
}
}
void SIProfileFT::cancel( Bytestream* bs )
{
if( !bs )
return;
if( m_id2sid.find( bs->sid() ) == m_id2sid.end() || !m_manager )
return;
if( bs->type() == Bytestream::S5B && m_socks5Manager )
m_socks5Manager->rejectSOCKS5Bytestream( bs->sid(), StanzaErrorServiceUnavailable );
dispose( bs );
}
void SIProfileFT::setStreamHosts( StreamHostList hosts )
{
if( m_socks5Manager )
m_socks5Manager->setStreamHosts( hosts );
}
void SIProfileFT::addStreamHost( const JID& jid, const std::string& host, int port )
{
if( m_socks5Manager )
m_socks5Manager->addStreamHost( jid, host, port );
}
void SIProfileFT::handleSIRequest( const JID& from, const JID& to, const std::string& id,
const SIManager::SI& si )
{
if( si.profile() != XMLNS_SI_FT || !si.tag1() )
return;
if( m_handler )
{
const Tag* t = si.tag1()->findChild( "desc" );
const std::string& desc = t ? t->cdata() : EmptyString;
const std::string& mt = si.mimetype();
int types = 0;
if( si.tag2() )
{
const DataForm df( si.tag2()->findChild( "x", XMLNS, XMLNS_X_DATA ) );
const DataFormField* dff = df.field( "stream-method" );
if( dff )
{
const StringMultiMap& options = dff->options();
StringMultiMap::const_iterator it = options.begin();
for( ; it != options.end(); ++it )
{
if( (*it).second == XMLNS_BYTESTREAMS )
types |= FTTypeS5B;
else if( (*it).second == XMLNS_IBB )
types |= FTTypeIBB;
else if( (*it).second == XMLNS_IQ_OOB )
types |= FTTypeOOB;
}
}
}
const std::string& sid = si.id();
m_id2sid[sid] = id;
m_handler->handleFTRequest( from, to, sid, si.tag1()->findAttribute( "name" ),
atol( si.tag1()->findAttribute( "size" ).c_str() ),
si.tag1()->findAttribute( "hash" ),
si.tag1()->findAttribute( "date" ),
mt.empty() ? "binary/octet-stream" : mt,
desc, types );
}
}
void SIProfileFT::handleSIRequestResult( const JID& from, const JID& to, const std::string& sid,
const SIManager::SI& si )
{
if( si.tag2() )
{
const DataForm df( si.tag2()->findChild( "x", XMLNS, XMLNS_X_DATA ) );
const DataFormField* dff = df.field( "stream-method" );
if( dff )
{
if( m_socks5Manager && dff->value() == XMLNS_BYTESTREAMS )
{
// check return value:
m_socks5Manager->requestSOCKS5Bytestream( from, SOCKS5BytestreamManager::S5BTCP, sid, to );
}
else if( m_handler )
{
if( dff->value() == XMLNS_IBB )
{
InBandBytestream* ibb = new InBandBytestream( m_parent, m_parent->logInstance(),
to ? to : m_parent->jid(), from, sid );
m_handler->handleFTBytestream( ibb );
}
else if( dff->value() == XMLNS_IQ_OOB )
{
const std::string& url = m_handler->handleOOBRequestResult( from, to, sid );
if( !url.empty() )
{
const std::string& id = m_parent->getID();
IQ iq( IQ::Set, from, id );
if( to )
iq.setFrom( to );
iq.addExtension( new OOB( url, EmptyString, true ) );
m_parent->send( iq, this, OOBSent );
}
}
}
}
}
}
void SIProfileFT::handleIqID( const IQ& /*iq*/, int context )
{
switch( context )
{
case OOBSent:
// if( iq->subtype() == IQ::Error )
// m_handler->handleOOBError
break;
}
}
void SIProfileFT::handleSIRequestError( const IQ& iq, const std::string& sid )
{
if( m_handler )
m_handler->handleFTRequestError( iq, sid );
}
void SIProfileFT::handleIncomingBytestreamRequest( const std::string& sid, const JID& /*from*/ )
{
// TODO: check for valid sid/from tuple
m_socks5Manager->acceptSOCKS5Bytestream( sid );
}
void SIProfileFT::handleIncomingBytestream( Bytestream* bs )
{
if( m_handler )
m_handler->handleFTBytestream( bs );
}
void SIProfileFT::handleOutgoingBytestream( Bytestream* bs )
{
if( m_handler )
m_handler->handleFTBytestream( bs );
}
void SIProfileFT::handleBytestreamError( const IQ& iq, const std::string& sid )
{
if( m_handler )
m_handler->handleFTRequestError( iq, sid );
}
}
gloox::Bytestream
An abstraction of a single bytestream.
Definition bytestream.h:37
gloox::Bytestream::S5B
@ S5B
Definition bytestream.h:44
gloox::Bytestream::type
StreamType type() const
Definition bytestream.h:120
gloox::Bytestream::sid
const std::string & sid() const
Definition bytestream.h:114
gloox::ClientBase
This is the common base class for a Jabber/XMPP Client and a Jabber Component.
Definition clientbase.h:79
gloox::DataFormFieldContainer::addField
virtual void addField(DataFormField *field)
Definition dataformfieldcontainer.h:99
gloox::DataFormFieldContainer::field
DataFormField * field(const std::string &field) const
Definition dataformfieldcontainer.cpp:39
gloox::DataFormField
An abstraction of a single field in a XEP-0004 Data Form.
Definition dataformfield.h:34
gloox::DataFormField::setOptions
void setOptions(const StringMultiMap &options)
Definition dataformfield.h:138
gloox::DataFormField::options
const StringMultiMap & options() const
Definition dataformfield.h:108
gloox::DataFormField::value
const std::string & value() const
Definition dataformfield.h:189
gloox::DataFormField::TypeListSingle
@ TypeListSingle
Definition dataformfield.h:57
gloox::DataFormField::setValue
void setValue(const std::string &value)
Definition dataformfield.h:195
gloox::DataForm
An abstraction of a XEP-0004 Data Form.
Definition dataform.h:57
gloox::DataForm::tag
virtual Tag * tag() const
Definition dataform.cpp:106
gloox::IQ
An abstraction of an IQ stanza.
Definition iq.h:34
gloox::IQ::Set
@ Set
Definition iq.h:46
gloox::InBandBytestream
An implementation of a single In-Band Bytestream (XEP-0047).
Definition inbandbytestream.h:44
gloox::JID
An abstraction of a JID.
Definition jid.h:31
gloox::OOB
This is an abstraction of a jabber:x:oob namespace element or a jabber:iq:oob namespace element as sp...
Definition oob.h:36
gloox::SIManager
This class manages streams initiated using XEP-0095.
Definition simanager.h:35
gloox::SIManager::SIError
SIError
Definition simanager.h:42
gloox::SIProfileFTHandler
An abstract base class to handle file transfer (FT) requests.
Definition siprofilefthandler.h:37
gloox::SIProfileFT::setStreamHosts
void setStreamHosts(StreamHostList hosts)
Definition siprofileft.cpp:170
gloox::SIProfileFT::handleIncomingBytestream
virtual void handleIncomingBytestream(Bytestream *bs)
Definition siprofileft.cpp:294
gloox::SIProfileFT::handleIqID
virtual void handleIqID(const IQ &iq, int context)
Definition siprofileft.cpp:271
gloox::SIProfileFT::addStreamHost
void addStreamHost(const JID &jid, const std::string &host, int port)
Definition siprofileft.cpp:176
gloox::SIProfileFT::handleSIRequest
virtual void handleSIRequest(const JID &from, const JID &to, const std::string &id, const SIManager::SI &si)
Definition siprofileft.cpp:182
gloox::SIProfileFT::cancel
void cancel(Bytestream *bs)
Definition siprofileft.cpp:156
gloox::SIProfileFT::handleSIRequestError
virtual void handleSIRequestError(const IQ &iq, const std::string &sid)
Definition siprofileft.cpp:282
gloox::SIProfileFT::StreamType
StreamType
Definition siprofileft.h:158
gloox::SIProfileFT::FTTypeOOB
@ FTTypeOOB
Definition siprofileft.h:161
gloox::SIProfileFT::FTTypeAll
@ FTTypeAll
Definition siprofileft.h:162
gloox::SIProfileFT::FTTypeS5B
@ FTTypeS5B
Definition siprofileft.h:159
gloox::SIProfileFT::FTTypeIBB
@ FTTypeIBB
Definition siprofileft.h:160
gloox::SIProfileFT::handleIncomingBytestreamRequest
virtual void handleIncomingBytestreamRequest(const std::string &sid, const JID &from)
Definition siprofileft.cpp:288
gloox::SIProfileFT::~SIProfileFT
virtual ~SIProfileFT()
Definition siprofileft.cpp:52
gloox::SIProfileFT::handleOutgoingBytestream
virtual void handleOutgoingBytestream(Bytestream *bs)
Definition siprofileft.cpp:300
gloox::SIProfileFT::requestFT
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
gloox::SIProfileFT::dispose
void dispose(Bytestream *bs)
Definition siprofileft.cpp:145
gloox::SIProfileFT::acceptFT
void acceptFT(const JID &to, const std::string &sid, StreamType type=FTTypeS5B, const JID &from=JID())
Definition siprofileft.cpp:98
gloox::SIProfileFT::handleBytestreamError
virtual void handleBytestreamError(const IQ &iq, const std::string &sid)
Definition siprofileft.cpp:306
gloox::SIProfileFT::handleSIRequestResult
virtual void handleSIRequestResult(const JID &from, const JID &to, const std::string &sid, const SIManager::SI &si)
Definition siprofileft.cpp:228
gloox::SIProfileFT::SIProfileFT
SIProfileFT(ClientBase *parent, SIProfileFTHandler *sipfth, SIManager *manager=0, SOCKS5BytestreamManager *s5Manager=0)
Definition siprofileft.cpp:31
gloox::SIProfileFT::declineFT
void declineFT(const JID &to, const std::string &sid, SIManager::SIError reason, const std::string &text=EmptyString)
Definition siprofileft.cpp:136
gloox::SOCKS5BytestreamManager
An SOCKS5BytestreamManager dispatches SOCKS5 Bytestreams.
Definition socks5bytestreammanager.h:52
gloox::SOCKS5BytestreamManager::S5BTCP
@ S5BTCP
Definition socks5bytestreammanager.h:63
gloox::SOCKS5Bytestream
An implementation of a single SOCKS5 Bytestream (XEP-0065).
Definition socks5bytestream.h:43
gloox::Stanza::addExtension
void addExtension(const StanzaExtension *se)
Definition stanza.cpp:52
gloox::Stanza::setFrom
void setFrom(const JID &from)
Definition stanza.h:45
gloox::Tag
This is an abstraction of an XML element.
Definition tag.h:47
gloox::Tag::findChild
Tag * findChild(const std::string &name) const
Definition tag.cpp:624
gloox::Tag::addAttribute
bool addAttribute(Attribute *attr)
Definition tag.cpp:354
gloox::Tag::addChild
void addChild(Tag *child)
Definition tag.cpp:424
gloox::Tag::cdata
const std::string cdata() const
Definition tag.cpp:497
gloox::Tag::findAttribute
const std::string & findAttribute(const std::string &name) const
Definition tag.cpp:589
gloox
The namespace for the gloox library.
Definition adhoc.cpp:28
gloox::XMLNS_IQ_OOB
const std::string XMLNS_IQ_OOB
Definition gloox.cpp:48
gloox::StringMultiMap
std::multimap< std::string, std::string > StringMultiMap
Definition gloox.h:1266
gloox::XMLNS_IBB
const std::string XMLNS_IBB
Definition gloox.cpp:32
gloox::XMLNS_FEATURE_NEG
const std::string XMLNS_FEATURE_NEG
Definition gloox.cpp:33
gloox::XMLNS_X_DATA
const std::string XMLNS_X_DATA
Definition gloox.cpp:49
gloox::EmptyString
const std::string EmptyString
Definition gloox.cpp:124
gloox::XMLNS
const std::string XMLNS
Definition gloox.cpp:122
gloox::XMLNS_SI_FT
const std::string XMLNS_SI_FT
Definition gloox.cpp:65
gloox::StanzaErrorServiceUnavailable
@ StanzaErrorServiceUnavailable
Definition gloox.h:936
gloox::TypeSubmit
@ TypeSubmit
Definition dataform.h:37
gloox::TypeForm
@ TypeForm
Definition dataform.h:35
gloox::StreamHostList
std::list< StreamHost > StreamHostList
Definition socks5bytestreammanager.h:43
gloox::XMLNS_BYTESTREAMS
const std::string XMLNS_BYTESTREAMS
Definition gloox.cpp:66