Commit 0d52344a authored by mathieui's avatar mathieui

Merge branch 'fix-component-handshake' into 'master'

Fix component handshake

Closes #3464

See merge request !156
parents 7057773d 768089d4
Pipeline #3920 passed with stages
in 6 minutes and 42 seconds
......@@ -22,7 +22,8 @@ class TestPrivateStorage(SlixIntegration):
el,
)
result = await self.clients[0]['xep_0049'].retrieve('bookmarks')
self.assertEqual(str(result['private']['bookmarks']), str(el))
self.assertEqual(result['private']['bookmarks'], el)
# Purge bookmarks
await self.clients[0]['xep_0049'].store(
......
......@@ -10,6 +10,7 @@ import logging
import hashlib
from slixmpp.basexmpp import BaseXMPP
from slixmpp.stanza import Handshake
from slixmpp.xmlstream import XMLStream
from slixmpp.xmlstream import ET
from slixmpp.xmlstream.matcher import MatchXPath
......@@ -123,9 +124,10 @@ class ComponentXMPP(BaseXMPP):
sid = xml.get('id', '')
pre_hash = bytes('%s%s' % (sid, self.secret), 'utf-8')
handshake = ET.Element('{jabber:component:accept}handshake')
handshake.text = hashlib.sha1(pre_hash).hexdigest().lower()
self.send_xml(handshake)
handshake = Handshake()
handshake['value'] = hashlib.sha1(pre_hash).hexdigest().lower()
self.send(handshake)
def _handle_handshake(self, xml):
"""The handshake has been accepted.
......
# Slixmpp: The Slick XMPP Library
# Copyright (C) 2010 Nathanael C. Fritz
# This file is part of Slixmpp.
......@@ -10,3 +9,9 @@ from slixmpp.stanza.message import Message
from slixmpp.stanza.presence import Presence
from slixmpp.stanza.stream_features import StreamFeatures
from slixmpp.stanza.stream_error import StreamError
from slixmpp.stanza.handshake import Handshake
__all__ = [
'Error', 'Iq', 'Message', 'Presence', 'StreamFeatures', 'StreamError',
'Handshake'
]
# Slixmpp: The Slick XMPP Library
# Copyright (C) 2021 Mathieu Pasquet
# This file is part of Slixmpp.
# See the file LICENSE for copying permission.
from slixmpp.xmlstream import StanzaBase
class Handshake(StanzaBase):
"""
Jabber Component protocol handshake
"""
namespace = 'jabber:component:accept'
name = 'handshake'
interfaces = {'value'}
def set_value(self, value: str):
self.xml.text = value
def get_value(self) -> str:
return self.xml.text
def del_value(self):
self.xml.text = ''
......@@ -487,7 +487,7 @@ class ElementBase(object):
else:
return None if check else self.init_plugin(name, lang)
def init_plugin(self, attrib, lang=None, existing_xml=None, reuse=True):
def init_plugin(self, attrib, lang=None, existing_xml=None, element=None, reuse=True):
"""Enable and initialize a stanza plugin.
:param string attrib: The :attr:`plugin_attrib` value of the
......@@ -504,7 +504,10 @@ class ElementBase(object):
if reuse and (attrib, lang) in self.plugins:
return self.plugins[(attrib, lang)]
plugin = plugin_class(parent=self, xml=existing_xml)
if element is not None:
plugin = element
else:
plugin = plugin_class(parent=self, xml=existing_xml)
if plugin.is_extension:
self.plugins[(attrib, None)] = plugin
......@@ -1172,14 +1175,18 @@ class ElementBase(object):
else:
raise TypeError
self.xml.append(item.xml)
self.iterables.append(item)
if item.__class__ in self.plugin_iterables:
if item.__class__.plugin_multi_attrib:
self.init_plugin(item.__class__.plugin_multi_attrib)
elif item.__class__ == self.plugin_tag_map.get(item.tag_name(), None):
if item.__class__ == self.plugin_tag_map.get(item.tag_name(), None):
self.init_plugin(item.plugin_attrib,
existing_xml=item.xml,
element=item,
reuse=False)
elif item.__class__ in self.plugin_iterables:
self.iterables.append(item)
if item.__class__.plugin_multi_attrib:
self.init_plugin(item.__class__.plugin_multi_attrib)
else:
self.iterables.append(item)
return self
def appendxml(self, xml):
......@@ -1269,14 +1276,14 @@ class ElementBase(object):
# Check that this stanza is a superset of the other stanza.
values = self.values
other_values = other.values
for key in other.keys():
if key not in values or values[key] != other[key]:
if key not in values or values.get(key) != other_values.get(key):
return False
# Check that the other stanza is a superset of this stanza.
values = other.values
for key in self.keys():
if key not in values or values[key] != self[key]:
if key not in values or other_values.get(key) != values.get(key):
return False
# Both stanzas are supersets of each other, therefore they
......
......@@ -1140,9 +1140,12 @@ class XMLStream(asyncio.BaseProtocol):
if not self._always_send_everything and not self._session_started:
# Avoid circular imports
from slixmpp.stanza.rootstanza import RootStanza
from slixmpp.stanza import Iq
is_bind = isinstance(data, Iq) and data.get_plugin('bind', check=True)
if isinstance(data, (RootStanza, str)) and not is_bind:
from slixmpp.stanza import Iq, Handshake
passthrough = (
(isinstance(data, Iq) and data.get_plugin('bind', check=True))
or isinstance(data, Handshake)
)
if isinstance(data, (RootStanza, str)) and not passthrough:
self.__queued_stanzas.append(data)
log.debug('NOT SENT: %s %s', type(data), data)
return
......
......@@ -456,6 +456,7 @@ class TestElementBase(SlixTest):
class TestSubStanza(ElementBase):
name = "sub"
plugin_attrib = name
namespace = "baz"
interfaces = {'attrib'}
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment