gloox  1.0.1
capabilities.cpp
1 /*
2  Copyright (c) 2007-2012 by Jakob Schroeter <js@camaya.net>
3  This file is part of the gloox library. http://camaya.net/gloox
4 
5  This software is distributed under a license. The full license
6  agreement can be found in the file LICENSE in this distribution.
7  This software may not be copied, modified, sold or distributed
8  other than expressed in the named license agreement.
9 
10  This software is distributed without any warranty.
11 */
12 
13 
14 #include "capabilities.h"
15 
16 #include "base64.h"
17 #include "disco.h"
18 #include "dataform.h"
19 #include "sha.h"
20 #include "tag.h"
21 
22 namespace gloox
23 {
24 
26  : StanzaExtension( ExtCaps ), m_disco( disco ), m_node( GLOOX_CAPS_NODE ),
27  m_hash( "sha-1" ), m_valid( false )
28  {
29  if( m_disco )
30  m_valid = true;
31  }
32 
34  : StanzaExtension( ExtCaps ), m_disco( 0 ), m_valid( false )
35  {
36  if( !tag || tag->name() != "c" || !tag->hasAttribute( XMLNS, XMLNS_CAPS )
37  || !tag->hasAttribute( "node" ) || !tag->hasAttribute( "ver" ) )
38  return;
39 
40  m_node = tag->findAttribute( "node" );
41  m_ver = tag->findAttribute( "ver" );
42  m_hash = tag->findAttribute( "hash" );
43  m_valid = true;
44  }
45 
47  {
48  if( m_disco )
49  m_disco->removeNodeHandlers( const_cast<Capabilities*>( this ) );
50  }
51 
52  const std::string Capabilities::ver() const
53  {
54  if( !m_disco )
55  return m_ver;
56 
57  SHA sha;
58  sha.feed( generate( m_disco->identities(), m_disco->features( true ), m_disco->form() ) );
59  const std::string& hash = Base64::encode64( sha.binary() );
60  m_disco->removeNodeHandlers( const_cast<Capabilities*>( this ) );
61  m_disco->registerNodeHandler( const_cast<Capabilities*>( this ), m_node + '#' + hash );
62  return hash;
63  }
64 
65  std::string Capabilities::generate( const Disco::IdentityList& il, const StringList& features, const DataForm* form )
66  {
67  StringList sl;
68  Disco::IdentityList::const_iterator it = il.begin();
69  for( ; it != il.end(); ++it )
70  {
71  std::string id = (*it)->category();
72  id += '/';
73  id += (*it)->type();
74  id += '/';
75  // FIXME add xml:lang caps here. see XEP-0115 Section 5
76  id += '/';
77  id += (*it)->name();
78  sl.push_back( id );
79  }
80  sl.sort();
81 
82  std::string s;
83  StringList::const_iterator it2 = sl.begin();
84  for( ; it2 != sl.end(); ++it2 )
85  {
86  s += (*it2);
87  s += '<';
88  }
89 
90  StringList f = features;
91  f.sort();
92  it2 = f.begin();
93  for( ; it2 != f.end(); ++it2 )
94  {
95  s += (*it2);
96  s += '<';
97  }
98 
99  if( form )
100  {
101  DataForm::FieldList::const_iterator it3 = form->fields().begin();
102  typedef std::map<std::string, StringList> MapSSL;
103 
104  MapSSL m;
105  for( ; it3 != form->fields().end(); ++it3 )
106  {
107  if( (*it3)->name() == "FORM_TYPE" )
108  {
109  s += (*it3)->value();
110  s += '<';
111  }
112  else
113  m.insert( std::make_pair( (*it3)->name(), (*it3)->values() ) );
114  }
115 
116  MapSSL::iterator it4 = m.begin();
117  for( ; it4 != m.end(); ++it4 )
118  {
119  s += it4->first;
120  s += '<';
121  it2 = it4->second.begin();
122  for( ; it2 != it4->second.end(); ++it2 )
123  {
124  s += (*it2);
125  s += '<';
126  }
127  }
128  }
129  return s;
130  }
131 
132  std::string Capabilities::generate( const Disco::Info* info )
133  {
134  return info ? generate( info->identities(), info->features(), info->form() ) : EmptyString;
135  }
136 
137  std::string Capabilities::generate( const Disco* disco )
138  {
139  return disco ? generate( disco->identities(), disco->features(), disco->form() ) : EmptyString;
140  }
141 
142  const std::string& Capabilities::filterString() const
143  {
144  static const std::string filter = "/presence/c[@xmlns='" + XMLNS_CAPS + "']";
145  return filter;
146  }
147 
149  {
150  if( !m_valid || m_node.empty() )
151  return 0;
152 
153  Tag* t = new Tag( "c" );
154  t->setXmlns( XMLNS_CAPS );
155  t->addAttribute( "hash", m_hash );
156  t->addAttribute( "node", m_node );
157  t->addAttribute( "ver", ver() );
158  return t;
159  }
160 
162  {
163  return m_disco->features();
164  }
165 
167  {
168  const Disco::IdentityList& il = m_disco->identities();
170  Disco::IdentityList::const_iterator it = il.begin();
171  for( ; it != il.end(); ++it )
172  {
173  ret.push_back( new Disco::Identity( *(*it) ) );
174  }
175  return ret;
176  }
177 
178  Disco::ItemList Capabilities::handleDiscoNodeItems( const JID&, const JID&, const std::string& )
179  {
180  return Disco::ItemList();
181  }
182 
183 }