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 "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 // FIXME add xml:lang caps here. see XEP-0115 Section 5 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 }