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 "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 // ---- SIManager::SI ---- 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 // ---- ~SIManager::SI ---- 00087 00088 // ---- SIManager ---- 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 /*|| si->profile().empty()*/ ) 00225 return; 00226 00227 // Tag* si = iq.query(); 00228 // Tag* ptag = 0; 00229 // Tag* fneg = 0; 00230 // if( si && si->name() == "si" && si->xmlns() == XMLNS_SI ) 00231 // { 00232 // ptag = si->findChildWithAttrib( XMLNS, (*it).second.profile ); 00233 // fneg = si->findChild( "feature", XMLNS, XMLNS_FEATURE_NEG ); 00234 // } 00235 00236 // FIXME: remove above commented code and 00237 // check corectness of last 3 params! 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 }