00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "simanager.h"
00015
00016 #include "siprofilehandler.h"
00017 #include "sihandler.h"
00018 #include "clientbase.h"
00019 #include "disco.h"
00020 #include "error.h"
00021
00022 namespace gloox
00023 {
00024
00025
00026 SIManager::SI::SI( const Tag* tag )
00027 : StanzaExtension( ExtSI ), m_tag1( 0 ), m_tag2( 0 )
00028 {
00029 if( !tag || tag->name() != "si" || tag->xmlns() != XMLNS_SI )
00030 return;
00031
00032 m_valid = true;
00033
00034 m_id = tag->findAttribute( "id" );
00035 m_mimetype = tag->findAttribute( "mime-type" );
00036 m_profile = tag->findAttribute( "profile" );
00037
00038 Tag* c = tag->findChild( "file", "xmlns", XMLNS_SI_FT );
00039 if ( c )
00040 m_tag1 = c->clone();
00041 c = tag->findChild( "feature", "xmlns", XMLNS_FEATURE_NEG );
00042 if( c )
00043 m_tag2 = c->clone();
00044 }
00045
00046 SIManager::SI::SI( Tag* tag1, Tag* tag2, const std::string& id,
00047 const std::string& mimetype, const std::string& profile )
00048 : StanzaExtension( ExtSI ), m_tag1( tag1 ), m_tag2( tag2 ),
00049 m_id( id ), m_mimetype( mimetype ), m_profile( profile )
00050 {
00051 m_valid = true;
00052 }
00053
00054 SIManager::SI::~SI()
00055 {
00056 delete m_tag1;
00057 delete m_tag2;
00058 }
00059
00060 const std::string& SIManager::SI::filterString() const
00061 {
00062 static const std::string filter = "/iq/si[@xmlns='" + XMLNS_SI + "']";
00063 return filter;
00064 }
00065
00066 Tag* SIManager::SI::tag() const
00067 {
00068 if( !m_valid )
00069 return 0;
00070
00071 Tag* t = new Tag( "si" );
00072 t->setXmlns( XMLNS_SI );
00073 if( !m_id.empty() )
00074 t->addAttribute( "id", m_id );
00075 if( !m_mimetype.empty() )
00076 t->addAttribute( "mime-type", m_mimetype.empty() ? "binary/octet-stream" : m_mimetype );
00077 if( !m_profile.empty() )
00078 t->addAttribute( "profile", m_profile );
00079 if( m_tag1 )
00080 t->addChildCopy( m_tag1 );
00081 if( m_tag2 )
00082 t->addChildCopy( m_tag2 );
00083
00084 return t;
00085 }
00086
00087
00088
00089 SIManager::SIManager( ClientBase* parent, bool advertise )
00090 : m_parent( parent ), m_advertise( advertise )
00091 {
00092 if( m_parent )
00093 {
00094 m_parent->registerStanzaExtension( new SI() );
00095 m_parent->registerIqHandler( this, ExtSI );
00096 if( m_parent->disco() && m_advertise )
00097 m_parent->disco()->addFeature( XMLNS_SI );
00098 }
00099 }
00100
00101 SIManager::~SIManager()
00102 {
00103 if( m_parent )
00104 {
00105 m_parent->removeIqHandler( this, ExtSI );
00106 m_parent->removeIDHandler( this );
00107 if( m_parent->disco() && m_advertise )
00108 m_parent->disco()->removeFeature( XMLNS_SI );
00109 }
00110 }
00111
00112 const std::string SIManager::requestSI( SIHandler* sih, const JID& to, const std::string& profile,
00113 Tag* child1, Tag* child2, const std::string& mimetype,
00114 const JID& from, const std::string& sid )
00115 {
00116 if( !m_parent || !sih )
00117 return EmptyString;
00118
00119 const std::string& id = m_parent->getID();
00120 const std::string& sidToUse = sid.empty() ? m_parent->getID() : sid;
00121
00122 IQ iq( IQ::Set, to, id );
00123 iq.addExtension( new SI( child1, child2, sidToUse, mimetype, profile ) );
00124 if( from )
00125 iq.setFrom( from );
00126
00127 TrackStruct t;
00128 t.sid = sidToUse;
00129 t.profile = profile;
00130 t.sih = sih;
00131 m_track[id] = t;
00132 m_parent->send( iq, this, OfferSI );
00133
00134 return sidToUse;
00135 }
00136
00137 void SIManager::acceptSI( const JID& to, const std::string& id, Tag* child1, Tag* child2, const JID& from )
00138 {
00139 IQ iq( IQ::Result, to, id );
00140 iq.addExtension( new SI( child1, child2 ) );
00141 if( from )
00142 iq.setFrom( from );
00143
00144 m_parent->send( iq );
00145 }
00146
00147 void SIManager::declineSI( const JID& to, const std::string& id, SIError reason, const std::string& text )
00148 {
00149 IQ iq( IQ::Error, to, id );
00150 Error* error;
00151 if( reason == NoValidStreams || reason == BadProfile )
00152 {
00153 Tag* appError = 0;
00154 if( reason == NoValidStreams )
00155 appError = new Tag( "no-valid-streams", XMLNS, XMLNS_SI );
00156 else if( reason == BadProfile )
00157 appError = new Tag( "bad-profile", XMLNS, XMLNS_SI );
00158 error = new Error( StanzaErrorTypeCancel, StanzaErrorBadRequest, appError );
00159 }
00160 else
00161 {
00162 error = new Error( StanzaErrorTypeCancel, StanzaErrorForbidden );
00163 if( !text.empty() )
00164 error->text( text );
00165 }
00166
00167 iq.addExtension( error );
00168 m_parent->send( iq );
00169 }
00170
00171 void SIManager::registerProfile( const std::string& profile, SIProfileHandler* sih )
00172 {
00173 if( !sih || profile.empty() )
00174 return;
00175
00176 m_handlers[profile] = sih;
00177
00178 if( m_parent && m_advertise && m_parent->disco() )
00179 m_parent->disco()->addFeature( profile );
00180 }
00181
00182 void SIManager::removeProfile( const std::string& profile )
00183 {
00184 if( profile.empty() )
00185 return;
00186
00187 m_handlers.erase( profile );
00188
00189 if( m_parent && m_advertise && m_parent->disco() )
00190 m_parent->disco()->removeFeature( profile );
00191 }
00192
00193 bool SIManager::handleIq( const IQ& iq )
00194 {
00195 TrackMap::iterator itt = m_track.find( iq.id() );
00196 if( itt != m_track.end() )
00197 return false;
00198
00199 const SI* si = iq.findExtension<SI>( ExtSI );
00200 if( !si || si->profile().empty() )
00201 return false;
00202
00203 HandlerMap::const_iterator it = m_handlers.find( si->profile() );
00204 if( it != m_handlers.end() && (*it).second )
00205 {
00206 (*it).second->handleSIRequest( iq.from(), iq.to(), iq.id(), *si );
00207 return true;
00208 }
00209
00210 return false;
00211 }
00212
00213 void SIManager::handleIqID( const IQ& iq, int context )
00214 {
00215 switch( iq.subtype() )
00216 {
00217 case IQ::Result:
00218 if( context == OfferSI )
00219 {
00220 TrackMap::iterator it = m_track.find( iq.id() );
00221 if( it != m_track.end() )
00222 {
00223 const SI* si = iq.findExtension<SI>( ExtSI );
00224 if( !si )
00225 return;
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238 (*it).second.sih->handleSIRequestResult( iq.from(), iq.to(), (*it).second.sid, *si );
00239 m_track.erase( it );
00240 }
00241 }
00242 break;
00243 case IQ::Error:
00244 if( context == OfferSI )
00245 {
00246 TrackMap::iterator it = m_track.find( iq.id() );
00247 if( it != m_track.end() )
00248 {
00249 (*it).second.sih->handleSIRequestError( iq, (*it).second.sid );
00250 m_track.erase( it );
00251 }
00252 }
00253 break;
00254 default:
00255 break;
00256 }
00257 }
00258
00259 }