capabilities.cpp
00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014 #include "capabilities.h"
00015
00016 #include "base64.h"
00017 #include "disco.h"
00018 #include "dataform.h"
00019 #include "sha.h"
00020 #include "tag.h"
00021
00022 namespace gloox
00023 {
00024
00025 Capabilities::Capabilities( Disco* disco )
00026 : StanzaExtension( ExtCaps ), m_disco( disco ), m_node( GLOOX_CAPS_NODE ),
00027 m_hash( "sha-1" ), m_valid( false )
00028 {
00029 if( m_disco )
00030 m_valid = true;
00031 }
00032
00033 Capabilities::Capabilities( const Tag* tag )
00034 : StanzaExtension( ExtCaps ), m_disco( 0 ), m_valid( false )
00035 {
00036 if( !tag || tag->name() != "c" || !tag->hasAttribute( XMLNS, XMLNS_CAPS )
00037 || !tag->hasAttribute( "node" ) || !tag->hasAttribute( "ver" ) )
00038 return;
00039
00040 m_node = tag->findAttribute( "node" );
00041 m_ver = tag->findAttribute( "ver" );
00042 m_hash = tag->findAttribute( "hash" );
00043 m_valid = true;
00044 }
00045
00046 Capabilities::~Capabilities()
00047 {
00048 if( m_disco )
00049 m_disco->removeNodeHandlers( const_cast<Capabilities*>( this ) );
00050 }
00051
00052 const std::string Capabilities::ver() const
00053 {
00054 if( !m_disco )
00055 return m_ver;
00056
00057 SHA sha;
00058 sha.feed( generate( m_disco->identities(), m_disco->features( true ), m_disco->form() ) );
00059 const std::string& hash = Base64::encode64( sha.binary() );
00060 m_disco->removeNodeHandlers( const_cast<Capabilities*>( this ) );
00061 m_disco->registerNodeHandler( const_cast<Capabilities*>( this ), m_node + '#' + hash );
00062 return hash;
00063 }
00064
00065 std::string Capabilities::generate( const Disco::IdentityList& il, const StringList& features, const DataForm* form )
00066 {
00067 StringList sl;
00068 Disco::IdentityList::const_iterator it = il.begin();
00069 for( ; it != il.end(); ++it )
00070 {
00071 std::string id = (*it)->category();
00072 id += '/';
00073 id += (*it)->type();
00074 id += '/';
00075
00076 id += '/';
00077 id += (*it)->name();
00078 sl.push_back( id );
00079 }
00080 sl.sort();
00081
00082 std::string s;
00083 StringList::const_iterator it2 = sl.begin();
00084 for( ; it2 != sl.end(); ++it2 )
00085 {
00086 s += (*it2);
00087 s += '<';
00088 }
00089
00090 StringList f = features;
00091 f.sort();
00092 it2 = f.begin();
00093 for( ; it2 != f.end(); ++it2 )
00094 {
00095 s += (*it2);
00096 s += '<';
00097 }
00098
00099 if( form )
00100 {
00101 DataForm::FieldList::const_iterator it3 = form->fields().begin();
00102 typedef std::map<std::string, StringList> MapSSL;
00103
00104 MapSSL m;
00105 for( ; it3 != form->fields().end(); ++it3 )
00106 {
00107 if( (*it3)->name() == "FORM_TYPE" )
00108 {
00109 s += (*it3)->value();
00110 s += '<';
00111 }
00112 else
00113 m.insert( std::make_pair( (*it3)->name(), (*it3)->values() ) );
00114 }
00115
00116 MapSSL::iterator it4 = m.begin();
00117 for( ; it4 != m.end(); ++it4 )
00118 {
00119 s += it4->first;
00120 s += '<';
00121 it2 = it4->second.begin();
00122 for( ; it2 != it4->second.end(); ++it2 )
00123 {
00124 s += (*it2);
00125 s += '<';
00126 }
00127 }
00128 }
00129 return s;
00130 }
00131
00132 std::string Capabilities::generate( const Disco::Info* info )
00133 {
00134 return info ? generate( info->identities(), info->features(), info->form() ) : EmptyString;
00135 }
00136
00137 std::string Capabilities::generate( const Disco* disco )
00138 {
00139 return disco ? generate( disco->identities(), disco->features(), disco->form() ) : EmptyString;
00140 }
00141
00142 const std::string& Capabilities::filterString() const
00143 {
00144 static const std::string filter = "/presence/c[@xmlns='" + XMLNS_CAPS + "']";
00145 return filter;
00146 }
00147
00148 Tag* Capabilities::tag() const
00149 {
00150 if( !m_valid || m_node.empty() )
00151 return 0;
00152
00153 Tag* t = new Tag( "c" );
00154 t->setXmlns( XMLNS_CAPS );
00155 t->addAttribute( "hash", m_hash );
00156 t->addAttribute( "node", m_node );
00157 t->addAttribute( "ver", ver() );
00158 return t;
00159 }
00160
00161 StringList Capabilities::handleDiscoNodeFeatures( const JID&, const std::string& )
00162 {
00163 return m_disco->features();
00164 }
00165
00166 Disco::IdentityList Capabilities::handleDiscoNodeIdentities( const JID&, const std::string& )
00167 {
00168 const Disco::IdentityList& il = m_disco->identities();
00169 Disco::IdentityList ret;
00170 Disco::IdentityList::const_iterator it = il.begin();
00171 for( ; it != il.end(); ++it )
00172 {
00173 ret.push_back( new Disco::Identity( *(*it) ) );
00174 }
00175 return ret;
00176 }
00177
00178 Disco::ItemList Capabilities::handleDiscoNodeItems( const JID&, const JID&, const std::string& )
00179 {
00180 return Disco::ItemList();
00181 }
00182
00183 }