Fix verifying 'from' for IQ results.

Closes issue #278
This commit is contained in:
Lance Stout 2014-02-03 19:15:08 -06:00
parent 12995e280e
commit bd03f071c6
4 changed files with 61 additions and 5 deletions

View file

@ -9,7 +9,7 @@
from sleekxmpp.stanza.rootstanza import RootStanza
from sleekxmpp.xmlstream import StanzaBase, ET
from sleekxmpp.xmlstream.handler import Waiter, Callback
from sleekxmpp.xmlstream.matcher import MatcherId
from sleekxmpp.xmlstream.matcher import MatchIDSender
from sleekxmpp.exceptions import IqTimeout, IqError
@ -193,6 +193,13 @@ class Iq(RootStanza):
"""
if timeout is None:
timeout = self.stream.response_timeout
criteria = {
'id': self['id'],
'self': self.stream.boundjid,
'peer': self['to']
}
if callback is not None and self['type'] in ('get', 'set'):
handler_name = 'IqCallback_%s' % self['id']
if timeout_callback:
@ -203,19 +210,19 @@ class Iq(RootStanza):
self._fire_timeout,
repeat=False)
handler = Callback(handler_name,
MatcherId(self['id']),
MatchIDSender(criteria),
self._handle_result,
once=True)
else:
handler = Callback(handler_name,
MatcherId(self['id']),
MatchIDSender(criteria),
callback,
once=True)
self.stream.register_handler(handler)
StanzaBase.send(self, now=now)
return handler_name
elif block and self['type'] in ('get', 'set'):
waitfor = Waiter('IqWait_%s' % self['id'], MatcherId(self['id']))
waitfor = Waiter('IqWait_%s' % self['id'], MatchIDSender(criteria))
self.stream.register_handler(waitfor)
StanzaBase.send(self, now=now)
result = waitfor.wait(timeout)

View file

@ -16,7 +16,7 @@ from sleekxmpp.test import TestSocket, TestLiveSocket
from sleekxmpp.xmlstream import ET
from sleekxmpp.xmlstream import ElementBase
from sleekxmpp.xmlstream.tostring import tostring
from sleekxmpp.xmlstream.matcher import StanzaPath, MatcherId
from sleekxmpp.xmlstream.matcher import StanzaPath, MatcherId, MatchIDSender
from sleekxmpp.xmlstream.matcher import MatchXMLMask, MatchXPath
@ -212,6 +212,7 @@ class SleekTest(unittest.TestCase):
matchers = {'stanzapath': StanzaPath,
'xpath': MatchXPath,
'mask': MatchXMLMask,
'idsender': MatchIDSender,
'id': MatcherId}
Matcher = matchers.get(method, None)
if Matcher is None:

View file

@ -7,6 +7,7 @@
"""
from sleekxmpp.xmlstream.matcher.id import MatcherId
from sleekxmpp.xmlstream.matcher.idsender import MatchIDSender
from sleekxmpp.xmlstream.matcher.many import MatchMany
from sleekxmpp.xmlstream.matcher.stanzapath import StanzaPath
from sleekxmpp.xmlstream.matcher.xmlmask import MatchXMLMask

View file

@ -0,0 +1,47 @@
# -*- coding: utf-8 -*-
"""
sleekxmpp.xmlstream.matcher.id
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Part of SleekXMPP: The Sleek XMPP Library
:copyright: (c) 2011 Nathanael C. Fritz
:license: MIT, see LICENSE for more details
"""
from sleekxmpp.xmlstream.matcher.base import MatcherBase
class MatchIDSender(MatcherBase):
"""
The IDSender matcher selects stanzas that have the same stanza 'id'
interface value as the desired ID, and that the 'from' value is one
of a set of approved entities that can respond to a request.
"""
def match(self, xml):
"""Compare the given stanza's ``'id'`` attribute to the stored
``id`` value, and verify the sender's JID.
:param xml: The :class:`~sleekxmpp.xmlstream.stanzabase.ElementBase`
stanza to compare against.
"""
selfjid = self._criteria['self']
peerjid = self._criteria['peer']
allowed = {}
allowed[''] = True
allowed[selfjid.bare] = True
allowed[selfjid.host] = True
allowed[peerjid.full] = True
allowed[peerjid.bare] = True
allowed[peerjid.host] = True
_from = xml['from']
try:
return xml['id'] == self._criteria['id'] and allowed[_from]
except KeyError:
return False