Fix the xep_0009 import (no more relatives)
Also, remove trailing spaces in all files of this plugin
This commit is contained in:
parent
1ed06bebcd
commit
4b71fba64c
@ -11,11 +11,9 @@ import base64
|
|||||||
import logging
|
import logging
|
||||||
import time
|
import time
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
_namespace = 'jabber:iq:rpc'
|
_namespace = 'jabber:iq:rpc'
|
||||||
|
|
||||||
def fault2xml(fault):
|
def fault2xml(fault):
|
||||||
value = dict()
|
value = dict()
|
||||||
@ -25,7 +23,7 @@ def fault2xml(fault):
|
|||||||
fault.append(_py2xml((value)))
|
fault.append(_py2xml((value)))
|
||||||
return fault
|
return fault
|
||||||
|
|
||||||
def xml2fault(params):
|
def xml2fault(params):
|
||||||
vals = []
|
vals = []
|
||||||
for value in params.findall('{%s}value' % _namespace):
|
for value in params.findall('{%s}value' % _namespace):
|
||||||
vals.append(_xml2py(value))
|
vals.append(_xml2py(value))
|
||||||
@ -101,7 +99,7 @@ def xml2py(params):
|
|||||||
def _xml2py(value):
|
def _xml2py(value):
|
||||||
namespace = 'jabber:iq:rpc'
|
namespace = 'jabber:iq:rpc'
|
||||||
if value.find('{%s}nil' % namespace) is not None:
|
if value.find('{%s}nil' % namespace) is not None:
|
||||||
return None
|
return None
|
||||||
if value.find('{%s}i4' % namespace) is not None:
|
if value.find('{%s}i4' % namespace) is not None:
|
||||||
return int(value.find('{%s}i4' % namespace).text)
|
return int(value.find('{%s}i4' % namespace).text)
|
||||||
if value.find('{%s}int' % namespace) is not None:
|
if value.find('{%s}int' % namespace) is not None:
|
||||||
@ -131,7 +129,7 @@ def _xml2py(value):
|
|||||||
|
|
||||||
|
|
||||||
class rpcbase64(object):
|
class rpcbase64(object):
|
||||||
|
|
||||||
def __init__(self, data):
|
def __init__(self, data):
|
||||||
#base 64 encoded string
|
#base 64 encoded string
|
||||||
self.data = data
|
self.data = data
|
||||||
@ -148,7 +146,7 @@ class rpcbase64(object):
|
|||||||
|
|
||||||
|
|
||||||
class rpctime(object):
|
class rpctime(object):
|
||||||
|
|
||||||
def __init__(self,data=None):
|
def __init__(self,data=None):
|
||||||
#assume string data is in iso format YYYYMMDDTHH:MM:SS
|
#assume string data is in iso format YYYYMMDDTHH:MM:SS
|
||||||
if type(data) is str:
|
if type(data) is str:
|
||||||
|
@ -16,19 +16,15 @@ import sys
|
|||||||
import threading
|
import threading
|
||||||
import traceback
|
import traceback
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
def _intercept(method, name, public):
|
def _intercept(method, name, public):
|
||||||
def _resolver(instance, *args, **kwargs):
|
def _resolver(instance, *args, **kwargs):
|
||||||
log.debug("Locally calling %s.%s with arguments %s." % (instance.FQN(), method.__name__, args))
|
log.debug("Locally calling %s.%s with arguments %s." % (instance.FQN(), method.__name__, args))
|
||||||
try:
|
try:
|
||||||
value = method(instance, *args, **kwargs)
|
value = method(instance, *args, **kwargs)
|
||||||
if value == NotImplemented:
|
if value == NotImplemented:
|
||||||
raise InvocationException("Local handler does not implement %s.%s!" % (instance.FQN(), method.__name__))
|
raise InvocationException("Local handler does not implement %s.%s!" % (instance.FQN(), method.__name__))
|
||||||
return value
|
return value
|
||||||
except InvocationException:
|
except InvocationException:
|
||||||
raise
|
raise
|
||||||
@ -43,50 +39,49 @@ def remote(function_argument, public = True):
|
|||||||
Decorator for methods which are remotely callable. This decorator
|
Decorator for methods which are remotely callable. This decorator
|
||||||
works in conjunction with classes which extend ABC Endpoint.
|
works in conjunction with classes which extend ABC Endpoint.
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
@remote
|
@remote
|
||||||
def remote_method(arg1, arg2)
|
def remote_method(arg1, arg2)
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
function_argument -- a stand-in for either the actual method
|
function_argument -- a stand-in for either the actual method
|
||||||
OR a new name (string) for the method. In that case the
|
OR a new name (string) for the method. In that case the
|
||||||
method is considered mapped:
|
method is considered mapped:
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
@remote("new_name")
|
@remote("new_name")
|
||||||
def remote_method(arg1, arg2)
|
def remote_method(arg1, arg2)
|
||||||
|
|
||||||
public -- A flag which indicates if this method should be part
|
public -- A flag which indicates if this method should be part
|
||||||
of the known dictionary of remote methods. Defaults to True.
|
of the known dictionary of remote methods. Defaults to True.
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
@remote(False)
|
@remote(False)
|
||||||
def remote_method(arg1, arg2)
|
def remote_method(arg1, arg2)
|
||||||
|
|
||||||
Note: renaming and revising (public vs. private) can be combined.
|
Note: renaming and revising (public vs. private) can be combined.
|
||||||
Example:
|
Example:
|
||||||
|
|
||||||
@remote("new_name", False)
|
@remote("new_name", False)
|
||||||
def remote_method(arg1, arg2)
|
def remote_method(arg1, arg2)
|
||||||
'''
|
'''
|
||||||
if hasattr(function_argument, '__call__'):
|
if hasattr(function_argument, '__call__'):
|
||||||
return _intercept(function_argument, None, public)
|
return _intercept(function_argument, None, public)
|
||||||
else:
|
else:
|
||||||
if not isinstance(function_argument, basestring):
|
if not isinstance(function_argument, basestring):
|
||||||
if not isinstance(function_argument, bool):
|
if not isinstance(function_argument, bool):
|
||||||
raise Exception('Expected an RPC method name or visibility modifier!')
|
raise Exception('Expected an RPC method name or visibility modifier!')
|
||||||
else:
|
else:
|
||||||
def _wrap_revised(function):
|
def _wrap_revised(function):
|
||||||
function = _intercept(function, None, function_argument)
|
function = _intercept(function, None, function_argument)
|
||||||
return function
|
return function
|
||||||
return _wrap_revised
|
return _wrap_revised
|
||||||
def _wrap_remapped(function):
|
def _wrap_remapped(function):
|
||||||
function = _intercept(function, function_argument, public)
|
function = _intercept(function, function_argument, public)
|
||||||
return function
|
return function
|
||||||
return _wrap_remapped
|
return _wrap_remapped
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class ACL:
|
class ACL:
|
||||||
'''
|
'''
|
||||||
An Access Control List (ACL) is a list of rules, which are evaluated
|
An Access Control List (ACL) is a list of rules, which are evaluated
|
||||||
@ -102,7 +97,7 @@ class ACL:
|
|||||||
[ (ACL.ALLOW, 'test@xmpp.org/unit', 'test.*'),
|
[ (ACL.ALLOW, 'test@xmpp.org/unit', 'test.*'),
|
||||||
(ACL.DENY, '*', '*') ] deny everyone everything, except named
|
(ACL.DENY, '*', '*') ] deny everyone everything, except named
|
||||||
JID, which is allowed access to endpoint 'test' only.
|
JID, which is allowed access to endpoint 'test' only.
|
||||||
|
|
||||||
The use of wildcards is allowed in expressions, as follows:
|
The use of wildcards is allowed in expressions, as follows:
|
||||||
'*' everyone, or everything (= all endpoints and methods)
|
'*' everyone, or everything (= all endpoints and methods)
|
||||||
'test@xmpp.org/*' every JID regardless of JID resource
|
'test@xmpp.org/*' every JID regardless of JID resource
|
||||||
@ -113,7 +108,7 @@ class ACL:
|
|||||||
'''
|
'''
|
||||||
ALLOW = True
|
ALLOW = True
|
||||||
DENY = False
|
DENY = False
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def check(cls, rules, jid, resource):
|
def check(cls, rules, jid, resource):
|
||||||
if rules is None:
|
if rules is None:
|
||||||
@ -121,9 +116,9 @@ class ACL:
|
|||||||
for rule in rules:
|
for rule in rules:
|
||||||
policy = cls._check(rule, jid, resource)
|
policy = cls._check(rule, jid, resource)
|
||||||
if policy is not None:
|
if policy is not None:
|
||||||
return policy
|
return policy
|
||||||
return cls.DENY # By default if not rule matches, deny access.
|
return cls.DENY # By default if not rule matches, deny access.
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _check(cls, rule, jid, resource):
|
def _check(cls, rule, jid, resource):
|
||||||
if cls._match(jid, rule[1]) and cls._match(resource, rule[2]):
|
if cls._match(jid, rule[1]) and cls._match(resource, rule[2]):
|
||||||
@ -138,13 +133,13 @@ class ACL:
|
|||||||
return ''
|
return ''
|
||||||
else:
|
else:
|
||||||
if new_index == -1:
|
if new_index == -1:
|
||||||
return expression[index : ]
|
return expression[index : ]
|
||||||
else:
|
else:
|
||||||
return expression[index : new_index]
|
return expression[index : new_index]
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def _match(cls, value, expression):
|
def _match(cls, value, expression):
|
||||||
#! print "_match [VALUE] %s [EXPR] %s" % (value, expression)
|
#! print "_match [VALUE] %s [EXPR] %s" % (value, expression)
|
||||||
index = 0
|
index = 0
|
||||||
position = 0
|
position = 0
|
||||||
while index < len(expression):
|
while index < len(expression):
|
||||||
@ -169,24 +164,23 @@ class ACL:
|
|||||||
ANY_ALL = [ (ACL.ALLOW, '*', '*') ]
|
ANY_ALL = [ (ACL.ALLOW, '*', '*') ]
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class RemoteException(Exception):
|
class RemoteException(Exception):
|
||||||
'''
|
'''
|
||||||
Base exception for RPC. This exception is raised when a problem
|
Base exception for RPC. This exception is raised when a problem
|
||||||
occurs in the network layer.
|
occurs in the network layer.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
def __init__(self, message="", cause=None):
|
def __init__(self, message="", cause=None):
|
||||||
'''
|
'''
|
||||||
Initializes a new RemoteException.
|
Initializes a new RemoteException.
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
message -- The message accompanying this exception.
|
message -- The message accompanying this exception.
|
||||||
cause -- The underlying cause of this exception.
|
cause -- The underlying cause of this exception.
|
||||||
'''
|
'''
|
||||||
self._message = message
|
self._message = message
|
||||||
self._cause = cause
|
self._cause = cause
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
return repr(self._message)
|
return repr(self._message)
|
||||||
@ -202,7 +196,7 @@ class RemoteException(Exception):
|
|||||||
class InvocationException(RemoteException):
|
class InvocationException(RemoteException):
|
||||||
'''
|
'''
|
||||||
Exception raised when a problem occurs during the remote invocation
|
Exception raised when a problem occurs during the remote invocation
|
||||||
of a method.
|
of a method.
|
||||||
'''
|
'''
|
||||||
pass
|
pass
|
||||||
|
|
||||||
@ -216,48 +210,45 @@ class AuthorizationException(RemoteException):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class TimeoutException(Exception):
|
class TimeoutException(Exception):
|
||||||
'''
|
'''
|
||||||
Exception raised when the synchronous execution of a method takes
|
Exception raised when the synchronous execution of a method takes
|
||||||
longer than the given threshold because an underlying asynchronous
|
longer than the given threshold because an underlying asynchronous
|
||||||
reply did not arrive in time.
|
reply did not arrive in time.
|
||||||
'''
|
'''
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Callback(object):
|
class Callback(object):
|
||||||
'''
|
'''
|
||||||
A base class for callback handlers.
|
A base class for callback handlers.
|
||||||
'''
|
'''
|
||||||
__metaclass__ = abc.ABCMeta
|
__metaclass__ = abc.ABCMeta
|
||||||
|
|
||||||
|
|
||||||
@abc.abstractproperty
|
@abc.abstractproperty
|
||||||
def set_value(self, value):
|
def set_value(self, value):
|
||||||
return NotImplemented
|
return NotImplemented
|
||||||
|
|
||||||
@abc.abstractproperty
|
@abc.abstractproperty
|
||||||
def cancel_with_error(self, exception):
|
def cancel_with_error(self, exception):
|
||||||
return NotImplemented
|
return NotImplemented
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Future(Callback):
|
class Future(Callback):
|
||||||
'''
|
'''
|
||||||
Represents the result of an asynchronous computation.
|
Represents the result of an asynchronous computation.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
'''
|
'''
|
||||||
Initializes a new Future.
|
Initializes a new Future.
|
||||||
'''
|
'''
|
||||||
self._value = None
|
self._value = None
|
||||||
self._exception = None
|
self._exception = None
|
||||||
self._event = threading.Event()
|
self._event = threading.Event()
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def set_value(self, value):
|
def set_value(self, value):
|
||||||
'''
|
'''
|
||||||
Sets the value of this Future. Once the value is set, a caller
|
Sets the value of this Future. Once the value is set, a caller
|
||||||
@ -265,13 +256,13 @@ class Future(Callback):
|
|||||||
'''
|
'''
|
||||||
self._value = value
|
self._value = value
|
||||||
self._event.set()
|
self._event.set()
|
||||||
|
|
||||||
def get_value(self, timeout=None):
|
def get_value(self, timeout=None):
|
||||||
'''
|
'''
|
||||||
Gets the value of this Future. This call will block until
|
Gets the value of this Future. This call will block until
|
||||||
the result is available, or until an optional timeout expires.
|
the result is available, or until an optional timeout expires.
|
||||||
When this Future is cancelled with an error,
|
When this Future is cancelled with an error,
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
timeout -- The maximum waiting time to obtain the value.
|
timeout -- The maximum waiting time to obtain the value.
|
||||||
'''
|
'''
|
||||||
@ -281,7 +272,7 @@ class Future(Callback):
|
|||||||
if not self._event.is_set():
|
if not self._event.is_set():
|
||||||
raise TimeoutException
|
raise TimeoutException
|
||||||
return self._value
|
return self._value
|
||||||
|
|
||||||
def is_done(self):
|
def is_done(self):
|
||||||
'''
|
'''
|
||||||
Returns true if a value has been returned.
|
Returns true if a value has been returned.
|
||||||
@ -290,23 +281,23 @@ class Future(Callback):
|
|||||||
|
|
||||||
def cancel_with_error(self, exception):
|
def cancel_with_error(self, exception):
|
||||||
'''
|
'''
|
||||||
Cancels the Future because of an error. Once cancelled, a
|
Cancels the Future because of an error. Once cancelled, a
|
||||||
caller blocked on get_value will be able to continue.
|
caller blocked on get_value will be able to continue.
|
||||||
'''
|
'''
|
||||||
self._exception = exception
|
self._exception = exception
|
||||||
self._event.set()
|
self._event.set()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Endpoint(object):
|
class Endpoint(object):
|
||||||
'''
|
'''
|
||||||
The Endpoint class is an abstract base class for all objects
|
The Endpoint class is an abstract base class for all objects
|
||||||
participating in an RPC-enabled XMPP network.
|
participating in an RPC-enabled XMPP network.
|
||||||
|
|
||||||
A user subclassing this class is required to implement the method:
|
A user subclassing this class is required to implement the method:
|
||||||
FQN(self)
|
FQN(self)
|
||||||
where FQN stands for Fully Qualified Name, an unambiguous name
|
where FQN stands for Fully Qualified Name, an unambiguous name
|
||||||
which specifies which object an RPC call refers to. It is the
|
which specifies which object an RPC call refers to. It is the
|
||||||
first part in a RPC method name '<fqn>.<method>'.
|
first part in a RPC method name '<fqn>.<method>'.
|
||||||
'''
|
'''
|
||||||
__metaclass__ = abc.ABCMeta
|
__metaclass__ = abc.ABCMeta
|
||||||
@ -317,38 +308,38 @@ class Endpoint(object):
|
|||||||
Initialize a new Endpoint. This constructor should never be
|
Initialize a new Endpoint. This constructor should never be
|
||||||
invoked by a user, instead it will be called by the factories
|
invoked by a user, instead it will be called by the factories
|
||||||
which instantiate the RPC-enabled objects, of which only
|
which instantiate the RPC-enabled objects, of which only
|
||||||
the classes are provided by the user.
|
the classes are provided by the user.
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
session -- An RPC session instance.
|
session -- An RPC session instance.
|
||||||
target_jid -- the identity of the remote XMPP entity.
|
target_jid -- the identity of the remote XMPP entity.
|
||||||
'''
|
'''
|
||||||
self.session = session
|
self.session = session
|
||||||
self.target_jid = target_jid
|
self.target_jid = target_jid
|
||||||
|
|
||||||
@abc.abstractproperty
|
@abc.abstractproperty
|
||||||
def FQN(self):
|
def FQN(self):
|
||||||
return NotImplemented
|
return NotImplemented
|
||||||
|
|
||||||
def get_methods(self):
|
def get_methods(self):
|
||||||
'''
|
'''
|
||||||
Returns a dictionary of all RPC method names provided by this
|
Returns a dictionary of all RPC method names provided by this
|
||||||
class. This method returns the actual method names as found
|
class. This method returns the actual method names as found
|
||||||
in the class definition which have been decorated with:
|
in the class definition which have been decorated with:
|
||||||
|
|
||||||
@remote
|
@remote
|
||||||
def some_rpc_method(arg1, arg2)
|
def some_rpc_method(arg1, arg2)
|
||||||
|
|
||||||
|
|
||||||
Unless:
|
Unless:
|
||||||
(1) the name has been remapped, in which case the new
|
(1) the name has been remapped, in which case the new
|
||||||
name will be returned.
|
name will be returned.
|
||||||
|
|
||||||
@remote("new_name")
|
@remote("new_name")
|
||||||
def some_rpc_method(arg1, arg2)
|
def some_rpc_method(arg1, arg2)
|
||||||
|
|
||||||
(2) the method is set to hidden
|
(2) the method is set to hidden
|
||||||
|
|
||||||
@remote(False)
|
@remote(False)
|
||||||
def some_hidden_method(arg1, arg2)
|
def some_hidden_method(arg1, arg2)
|
||||||
'''
|
'''
|
||||||
@ -360,7 +351,7 @@ class Endpoint(object):
|
|||||||
result[test_attr._rpc_name] = test_attr
|
result[test_attr._rpc_name] = test_attr
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
pass
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -374,13 +365,13 @@ class Proxy(Endpoint):
|
|||||||
def __init__(self, endpoint, callback = None):
|
def __init__(self, endpoint, callback = None):
|
||||||
'''
|
'''
|
||||||
Initializes a new Proxy.
|
Initializes a new Proxy.
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
endpoint -- The endpoint which is proxified.
|
endpoint -- The endpoint which is proxified.
|
||||||
'''
|
'''
|
||||||
self._endpoint = endpoint
|
self._endpoint = endpoint
|
||||||
self._callback = callback
|
self._callback = callback
|
||||||
|
|
||||||
def __getattribute__(self, name, *args):
|
def __getattribute__(self, name, *args):
|
||||||
if name in ('__dict__', '_endpoint', 'async', '_callback'):
|
if name in ('__dict__', '_endpoint', 'async', '_callback'):
|
||||||
return object.__getattribute__(self, name)
|
return object.__getattribute__(self, name)
|
||||||
@ -389,31 +380,30 @@ class Proxy(Endpoint):
|
|||||||
if hasattr(attribute, '__call__'):
|
if hasattr(attribute, '__call__'):
|
||||||
try:
|
try:
|
||||||
if attribute._rpc:
|
if attribute._rpc:
|
||||||
def _remote_call(*args, **kwargs):
|
def _remote_call(*args, **kwargs):
|
||||||
log.debug("Remotely calling '%s.%s' with arguments %s." % (self._endpoint.FQN(), attribute._rpc_name, args))
|
log.debug("Remotely calling '%s.%s' with arguments %s." % (self._endpoint.FQN(), attribute._rpc_name, args))
|
||||||
return self._endpoint.session._call_remote(self._endpoint.target_jid, "%s.%s" % (self._endpoint.FQN(), attribute._rpc_name), self._callback, *args, **kwargs)
|
return self._endpoint.session._call_remote(self._endpoint.target_jid, "%s.%s" % (self._endpoint.FQN(), attribute._rpc_name), self._callback, *args, **kwargs)
|
||||||
return _remote_call
|
return _remote_call
|
||||||
except:
|
except:
|
||||||
pass # If the attribute doesn't exist, don't care!
|
pass # If the attribute doesn't exist, don't care!
|
||||||
return attribute
|
return attribute
|
||||||
|
|
||||||
def async(self, callback):
|
def async(self, callback):
|
||||||
return Proxy(self._endpoint, callback)
|
return Proxy(self._endpoint, callback)
|
||||||
|
|
||||||
def get_endpoint(self):
|
def get_endpoint(self):
|
||||||
'''
|
'''
|
||||||
Returns the proxified endpoint.
|
Returns the proxified endpoint.
|
||||||
'''
|
'''
|
||||||
return self._endpoint
|
return self._endpoint
|
||||||
|
|
||||||
def FQN(self):
|
def FQN(self):
|
||||||
return self._endpoint.FQN()
|
return self._endpoint.FQN()
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class JabberRPCEntry(object):
|
class JabberRPCEntry(object):
|
||||||
|
|
||||||
|
|
||||||
def __init__(self, endpoint_FQN, call):
|
def __init__(self, endpoint_FQN, call):
|
||||||
self._endpoint_FQN = endpoint_FQN
|
self._endpoint_FQN = endpoint_FQN
|
||||||
self._call = call
|
self._call = call
|
||||||
@ -424,28 +414,27 @@ class JabberRPCEntry(object):
|
|||||||
return return_value
|
return return_value
|
||||||
else:
|
else:
|
||||||
return self._return(return_value)
|
return self._return(return_value)
|
||||||
|
|
||||||
def get_endpoint_FQN(self):
|
def get_endpoint_FQN(self):
|
||||||
return self._endpoint_FQN
|
return self._endpoint_FQN
|
||||||
|
|
||||||
def _return(self, *args):
|
def _return(self, *args):
|
||||||
return args
|
return args
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class RemoteSession(object):
|
class RemoteSession(object):
|
||||||
'''
|
'''
|
||||||
A context object for a Jabber-RPC session.
|
A context object for a Jabber-RPC session.
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
|
||||||
def __init__(self, client, session_close_callback):
|
def __init__(self, client, session_close_callback):
|
||||||
'''
|
'''
|
||||||
Initializes a new RPC session.
|
Initializes a new RPC session.
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
client -- The SleekXMPP client associated with this session.
|
client -- The SleekXMPP client associated with this session.
|
||||||
session_close_callback -- A callback called when the
|
session_close_callback -- A callback called when the
|
||||||
session is closed.
|
session is closed.
|
||||||
'''
|
'''
|
||||||
self._client = client
|
self._client = client
|
||||||
@ -455,16 +444,16 @@ class RemoteSession(object):
|
|||||||
self._callbacks = {}
|
self._callbacks = {}
|
||||||
self._acls = {}
|
self._acls = {}
|
||||||
self._lock = RLock()
|
self._lock = RLock()
|
||||||
|
|
||||||
def _wait(self):
|
def _wait(self):
|
||||||
self._event.wait()
|
self._event.wait()
|
||||||
|
|
||||||
def _notify(self, event):
|
def _notify(self, event):
|
||||||
log.debug("RPC Session as %s started." % self._client.boundjid.full)
|
log.debug("RPC Session as %s started." % self._client.boundjid.full)
|
||||||
self._client.sendPresence()
|
self._client.sendPresence()
|
||||||
self._event.set()
|
self._event.set()
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def _register_call(self, endpoint, method, name=None):
|
def _register_call(self, endpoint, method, name=None):
|
||||||
'''
|
'''
|
||||||
Registers a method from an endpoint as remotely callable.
|
Registers a method from an endpoint as remotely callable.
|
||||||
@ -487,8 +476,8 @@ class RemoteSession(object):
|
|||||||
def _register_callback(self, pid, callback):
|
def _register_callback(self, pid, callback):
|
||||||
with self._lock:
|
with self._lock:
|
||||||
self._callbacks[pid] = callback
|
self._callbacks[pid] = callback
|
||||||
|
|
||||||
def forget_callback(self, callback):
|
def forget_callback(self, callback):
|
||||||
with self._lock:
|
with self._lock:
|
||||||
pid = self._find_key(self._callbacks, callback)
|
pid = self._find_key(self._callbacks, callback)
|
||||||
if pid is not None:
|
if pid is not None:
|
||||||
@ -496,7 +485,7 @@ class RemoteSession(object):
|
|||||||
else:
|
else:
|
||||||
raise ValueError("Unknown callback!")
|
raise ValueError("Unknown callback!")
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def _find_key(self, dict, value):
|
def _find_key(self, dict, value):
|
||||||
"""return the key of dictionary dic given the value"""
|
"""return the key of dictionary dic given the value"""
|
||||||
search = [k for k, v in dict.iteritems() if v == value]
|
search = [k for k, v in dict.iteritems() if v == value]
|
||||||
@ -504,7 +493,7 @@ class RemoteSession(object):
|
|||||||
return None
|
return None
|
||||||
else:
|
else:
|
||||||
return search[0]
|
return search[0]
|
||||||
|
|
||||||
def _unregister_call(self, key):
|
def _unregister_call(self, key):
|
||||||
#removes the registered call
|
#removes the registered call
|
||||||
with self._lock:
|
with self._lock:
|
||||||
@ -512,18 +501,18 @@ class RemoteSession(object):
|
|||||||
del self._entries[key]
|
del self._entries[key]
|
||||||
else:
|
else:
|
||||||
raise ValueError()
|
raise ValueError()
|
||||||
|
|
||||||
def new_proxy(self, target_jid, endpoint_cls):
|
def new_proxy(self, target_jid, endpoint_cls):
|
||||||
'''
|
'''
|
||||||
Instantiates a new proxy object, which proxies to a remote
|
Instantiates a new proxy object, which proxies to a remote
|
||||||
endpoint. This method uses a class reference without
|
endpoint. This method uses a class reference without
|
||||||
constructor arguments to instantiate the proxy.
|
constructor arguments to instantiate the proxy.
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
target_jid -- the XMPP entity ID hosting the endpoint.
|
target_jid -- the XMPP entity ID hosting the endpoint.
|
||||||
endpoint_cls -- The remote (duck) type.
|
endpoint_cls -- The remote (duck) type.
|
||||||
'''
|
'''
|
||||||
try:
|
try:
|
||||||
argspec = inspect.getargspec(endpoint_cls.__init__)
|
argspec = inspect.getargspec(endpoint_cls.__init__)
|
||||||
args = [None] * (len(argspec[0]) - 1)
|
args = [None] * (len(argspec[0]) - 1)
|
||||||
result = endpoint_cls(*args)
|
result = endpoint_cls(*args)
|
||||||
@ -531,7 +520,7 @@ class RemoteSession(object):
|
|||||||
return Proxy(result)
|
return Proxy(result)
|
||||||
except:
|
except:
|
||||||
traceback.print_exc(file=sys.stdout)
|
traceback.print_exc(file=sys.stdout)
|
||||||
|
|
||||||
def new_handler(self, acl, handler_cls, *args, **kwargs):
|
def new_handler(self, acl, handler_cls, *args, **kwargs):
|
||||||
'''
|
'''
|
||||||
Instantiates a new handler object, which is called remotely
|
Instantiates a new handler object, which is called remotely
|
||||||
@ -539,7 +528,7 @@ class RemoteSession(object):
|
|||||||
implementing the remote method in the local endpoint class. The
|
implementing the remote method in the local endpoint class. The
|
||||||
returned reference can be called locally and will behave as a
|
returned reference can be called locally and will behave as a
|
||||||
regular instance.
|
regular instance.
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
acl -- Access control list (see ACL class)
|
acl -- Access control list (see ACL class)
|
||||||
handler_clss -- The local (duck) type.
|
handler_clss -- The local (duck) type.
|
||||||
@ -556,11 +545,11 @@ class RemoteSession(object):
|
|||||||
Endpoint.__init__(result, self, self._client.boundjid.full)
|
Endpoint.__init__(result, self, self._client.boundjid.full)
|
||||||
method_dict = result.get_methods()
|
method_dict = result.get_methods()
|
||||||
for method_name, method in method_dict.iteritems():
|
for method_name, method in method_dict.iteritems():
|
||||||
#!!! self._client.plugin['xep_0009'].register_call(result.FQN(), method, method_name)
|
#!!! self._client.plugin['xep_0009'].register_call(result.FQN(), method, method_name)
|
||||||
self._register_call(result.FQN(), method, method_name)
|
self._register_call(result.FQN(), method, method_name)
|
||||||
self._register_acl(result.FQN(), acl)
|
self._register_acl(result.FQN(), acl)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
# def is_available(self, targetCls, pto):
|
# def is_available(self, targetCls, pto):
|
||||||
# return self._client.is_available(pto)
|
# return self._client.is_available(pto)
|
||||||
|
|
||||||
@ -571,19 +560,19 @@ class RemoteSession(object):
|
|||||||
future = Future()
|
future = Future()
|
||||||
self._register_callback(pid, future)
|
self._register_callback(pid, future)
|
||||||
iq.send()
|
iq.send()
|
||||||
return future.get_value(30)
|
return future.get_value(30)
|
||||||
else:
|
else:
|
||||||
print "[RemoteSession] _call_remote %s" % callback
|
print "[RemoteSession] _call_remote %s" % callback
|
||||||
self._register_callback(pid, callback)
|
self._register_callback(pid, callback)
|
||||||
iq.send()
|
iq.send()
|
||||||
|
|
||||||
def close(self):
|
def close(self):
|
||||||
'''
|
'''
|
||||||
Closes this session.
|
Closes this session.
|
||||||
'''
|
'''
|
||||||
self._client.disconnect(False)
|
self._client.disconnect(False)
|
||||||
self._session_close_callback()
|
self._session_close_callback()
|
||||||
|
|
||||||
def _on_jabber_rpc_method_call(self, iq):
|
def _on_jabber_rpc_method_call(self, iq):
|
||||||
iq.enable('rpc_query')
|
iq.enable('rpc_query')
|
||||||
params = iq['rpc_query']['method_call']['params']
|
params = iq['rpc_query']['method_call']['params']
|
||||||
@ -609,15 +598,15 @@ class RemoteSession(object):
|
|||||||
except AuthorizationException as ae:
|
except AuthorizationException as ae:
|
||||||
log.error(ae.get_message())
|
log.error(ae.get_message())
|
||||||
error = self._client.plugin['xep_0009']._forbidden(iq)
|
error = self._client.plugin['xep_0009']._forbidden(iq)
|
||||||
error.send()
|
error.send()
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
if isinstance(e, KeyError):
|
if isinstance(e, KeyError):
|
||||||
log.error("No handler available for %s!" % pmethod)
|
log.error("No handler available for %s!" % pmethod)
|
||||||
error = self._client.plugin['xep_0009']._item_not_found(iq)
|
error = self._client.plugin['xep_0009']._item_not_found(iq)
|
||||||
else:
|
else:
|
||||||
traceback.print_exc(file=sys.stderr)
|
traceback.print_exc(file=sys.stderr)
|
||||||
log.error("An unexpected problem occurred invoking method %s!" % pmethod)
|
log.error("An unexpected problem occurred invoking method %s!" % pmethod)
|
||||||
error = self._client.plugin['xep_0009']._undefined_condition(iq)
|
error = self._client.plugin['xep_0009']._undefined_condition(iq)
|
||||||
#! print "[REMOTE.PY] _handle_remote_procedure_call AN ERROR SHOULD BE SENT NOW %s " % e
|
#! print "[REMOTE.PY] _handle_remote_procedure_call AN ERROR SHOULD BE SENT NOW %s " % e
|
||||||
error.send()
|
error.send()
|
||||||
|
|
||||||
@ -632,7 +621,7 @@ class RemoteSession(object):
|
|||||||
callback.set_value(args[0])
|
callback.set_value(args[0])
|
||||||
else:
|
else:
|
||||||
callback.set_value(None)
|
callback.set_value(None)
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def _on_jabber_rpc_method_response2(self, iq):
|
def _on_jabber_rpc_method_response2(self, iq):
|
||||||
iq.enable('rpc_query')
|
iq.enable('rpc_query')
|
||||||
@ -648,41 +637,40 @@ class RemoteSession(object):
|
|||||||
callback.set_value(args[0])
|
callback.set_value(args[0])
|
||||||
else:
|
else:
|
||||||
callback.set_value(None)
|
callback.set_value(None)
|
||||||
pass
|
pass
|
||||||
|
|
||||||
def _on_jabber_rpc_method_fault(self, iq):
|
def _on_jabber_rpc_method_fault(self, iq):
|
||||||
iq.enable('rpc_query')
|
iq.enable('rpc_query')
|
||||||
fault = xml2fault(iq['rpc_query']['method_response']['fault'])
|
fault = xml2fault(iq['rpc_query']['method_response']['fault'])
|
||||||
pid = iq['id']
|
pid = iq['id']
|
||||||
with self._lock:
|
with self._lock:
|
||||||
callback = self._callbacks[pid]
|
callback = self._callbacks[pid]
|
||||||
del self._callbacks[pid]
|
del self._callbacks[pid]
|
||||||
e = {
|
e = {
|
||||||
500: InvocationException
|
500: InvocationException
|
||||||
}[fault['code']](fault['string'])
|
}[fault['code']](fault['string'])
|
||||||
callback.cancel_with_error(e)
|
callback.cancel_with_error(e)
|
||||||
|
|
||||||
def _on_jabber_rpc_error(self, iq):
|
def _on_jabber_rpc_error(self, iq):
|
||||||
pid = iq['id']
|
pid = iq['id']
|
||||||
pmethod = self._client.plugin['xep_0009']._extract_method(iq['rpc_query'])
|
pmethod = self._client.plugin['xep_0009']._extract_method(iq['rpc_query'])
|
||||||
code = iq['error']['code']
|
code = iq['error']['code']
|
||||||
type = iq['error']['type']
|
type = iq['error']['type']
|
||||||
condition = iq['error']['condition']
|
condition = iq['error']['condition']
|
||||||
#! print("['REMOTE.PY']._BINDING_handle_remote_procedure_error -> ERROR! ERROR! ERROR! Condition is '%s'" % condition)
|
#! print("['REMOTE.PY']._BINDING_handle_remote_procedure_error -> ERROR! ERROR! ERROR! Condition is '%s'" % condition)
|
||||||
with self._lock:
|
with self._lock:
|
||||||
callback = self._callbacks[pid]
|
callback = self._callbacks[pid]
|
||||||
del self._callbacks[pid]
|
del self._callbacks[pid]
|
||||||
e = {
|
e = {
|
||||||
'item-not-found': RemoteException("No remote handler available for %s at %s!" % (pmethod, iq['from'])),
|
'item-not-found': RemoteException("No remote handler available for %s at %s!" % (pmethod, iq['from'])),
|
||||||
'forbidden': AuthorizationException("Forbidden to invoke remote handler for %s at %s!" % (pmethod, iq['from'])),
|
'forbidden': AuthorizationException("Forbidden to invoke remote handler for %s at %s!" % (pmethod, iq['from'])),
|
||||||
'undefined-condition': RemoteException("An unexpected problem occured trying to invoke %s at %s!" % (pmethod, iq['from'])),
|
'undefined-condition': RemoteException("An unexpected problem occured trying to invoke %s at %s!" % (pmethod, iq['from'])),
|
||||||
}[condition]
|
}[condition]
|
||||||
if e is None:
|
if e is None:
|
||||||
RemoteException("An unexpected exception occurred at %s!" % iq['from'])
|
RemoteException("An unexpected exception occurred at %s!" % iq['from'])
|
||||||
callback.cancel_with_error(e)
|
callback.cancel_with_error(e)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class Remote(object):
|
class Remote(object):
|
||||||
'''
|
'''
|
||||||
Bootstrap class for Jabber-RPC sessions. New sessions are openend
|
Bootstrap class for Jabber-RPC sessions. New sessions are openend
|
||||||
@ -691,18 +679,18 @@ class Remote(object):
|
|||||||
_instance = None
|
_instance = None
|
||||||
_sessions = dict()
|
_sessions = dict()
|
||||||
_lock = threading.RLock()
|
_lock = threading.RLock()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def new_session_with_client(cls, client, callback=None):
|
def new_session_with_client(cls, client, callback=None):
|
||||||
'''
|
'''
|
||||||
Opens a new session with a given client.
|
Opens a new session with a given client.
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
client -- An XMPP client.
|
client -- An XMPP client.
|
||||||
callback -- An optional callback which can be used to track
|
callback -- An optional callback which can be used to track
|
||||||
the starting state of the session.
|
the starting state of the session.
|
||||||
'''
|
'''
|
||||||
with Remote._lock:
|
with Remote._lock:
|
||||||
if(client.boundjid.bare in cls._sessions):
|
if(client.boundjid.bare in cls._sessions):
|
||||||
raise RemoteException("There already is a session associated with these credentials!")
|
raise RemoteException("There already is a session associated with these credentials!")
|
||||||
else:
|
else:
|
||||||
@ -710,21 +698,21 @@ class Remote(object):
|
|||||||
def _session_close_callback():
|
def _session_close_callback():
|
||||||
with Remote._lock:
|
with Remote._lock:
|
||||||
del cls._sessions[client.boundjid.bare]
|
del cls._sessions[client.boundjid.bare]
|
||||||
result = RemoteSession(client, _session_close_callback)
|
result = RemoteSession(client, _session_close_callback)
|
||||||
client.plugin['xep_0009'].xmpp.add_event_handler('jabber_rpc_method_call', result._on_jabber_rpc_method_call)
|
client.plugin['xep_0009'].xmpp.add_event_handler('jabber_rpc_method_call', result._on_jabber_rpc_method_call)
|
||||||
client.plugin['xep_0009'].xmpp.add_event_handler('jabber_rpc_method_response', result._on_jabber_rpc_method_response)
|
client.plugin['xep_0009'].xmpp.add_event_handler('jabber_rpc_method_response', result._on_jabber_rpc_method_response)
|
||||||
client.plugin['xep_0009'].xmpp.add_event_handler('jabber_rpc_method_fault', result._on_jabber_rpc_method_fault)
|
client.plugin['xep_0009'].xmpp.add_event_handler('jabber_rpc_method_fault', result._on_jabber_rpc_method_fault)
|
||||||
client.plugin['xep_0009'].xmpp.add_event_handler('jabber_rpc_error', result._on_jabber_rpc_error)
|
client.plugin['xep_0009'].xmpp.add_event_handler('jabber_rpc_error', result._on_jabber_rpc_error)
|
||||||
if callback is None:
|
if callback is None:
|
||||||
start_event_handler = result._notify
|
start_event_handler = result._notify
|
||||||
else:
|
else:
|
||||||
start_event_handler = callback
|
start_event_handler = callback
|
||||||
client.add_event_handler("session_start", start_event_handler)
|
client.add_event_handler("session_start", start_event_handler)
|
||||||
if client.connect():
|
if client.connect():
|
||||||
client.process(threaded=True)
|
client.process(threaded=True)
|
||||||
else:
|
else:
|
||||||
raise RemoteException("Could not connect to XMPP server!")
|
raise RemoteException("Could not connect to XMPP server!")
|
||||||
pass
|
pass
|
||||||
if callback is None:
|
if callback is None:
|
||||||
result._wait()
|
result._wait()
|
||||||
return result
|
return result
|
||||||
@ -733,20 +721,19 @@ class Remote(object):
|
|||||||
def new_session(cls, jid, password, callback=None):
|
def new_session(cls, jid, password, callback=None):
|
||||||
'''
|
'''
|
||||||
Opens a new session and instantiates a new XMPP client.
|
Opens a new session and instantiates a new XMPP client.
|
||||||
|
|
||||||
Arguments:
|
Arguments:
|
||||||
jid -- The XMPP JID for logging in.
|
jid -- The XMPP JID for logging in.
|
||||||
password -- The password for logging in.
|
password -- The password for logging in.
|
||||||
callback -- An optional callback which can be used to track
|
callback -- An optional callback which can be used to track
|
||||||
the starting state of the session.
|
the starting state of the session.
|
||||||
'''
|
'''
|
||||||
client = sleekxmpp.ClientXMPP(jid, password)
|
client = sleekxmpp.ClientXMPP(jid, password)
|
||||||
#? Register plug-ins.
|
#? Register plug-ins.
|
||||||
client.registerPlugin('xep_0004') # Data Forms
|
client.registerPlugin('xep_0004') # Data Forms
|
||||||
client.registerPlugin('xep_0009') # Jabber-RPC
|
client.registerPlugin('xep_0009') # Jabber-RPC
|
||||||
client.registerPlugin('xep_0030') # Service Discovery
|
client.registerPlugin('xep_0030') # Service Discovery
|
||||||
client.registerPlugin('xep_0060') # PubSub
|
client.registerPlugin('xep_0060') # PubSub
|
||||||
client.registerPlugin('xep_0199') # XMPP Ping
|
client.registerPlugin('xep_0199') # XMPP Ping
|
||||||
return cls.new_session_with_client(client, callback)
|
return cls.new_session_with_client(client, callback)
|
||||||
|
|
||||||
|
|
@ -6,8 +6,8 @@
|
|||||||
See the file LICENSE for copying permission.
|
See the file LICENSE for copying permission.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from .. import base
|
from sleekxmpp.plugins import base
|
||||||
from stanza.RPC import RPCQuery, MethodCall, MethodResponse
|
from sleekxmpp.plugins.xep_0009.stanza.RPC import RPCQuery, MethodCall, MethodResponse
|
||||||
from sleekxmpp.stanza.iq import Iq
|
from sleekxmpp.stanza.iq import Iq
|
||||||
from sleekxmpp.xmlstream.handler.callback import Callback
|
from sleekxmpp.xmlstream.handler.callback import Callback
|
||||||
from sleekxmpp.xmlstream.matcher.xpath import MatchXPath
|
from sleekxmpp.xmlstream.matcher.xpath import MatchXPath
|
||||||
@ -27,15 +27,15 @@ class xep_0009(base.base_plugin):
|
|||||||
self.xep = '0009'
|
self.xep = '0009'
|
||||||
self.description = 'Jabber-RPC'
|
self.description = 'Jabber-RPC'
|
||||||
#self.stanza = sleekxmpp.plugins.xep_0009.stanza
|
#self.stanza = sleekxmpp.plugins.xep_0009.stanza
|
||||||
|
|
||||||
register_stanza_plugin(Iq, RPCQuery)
|
register_stanza_plugin(Iq, RPCQuery)
|
||||||
register_stanza_plugin(RPCQuery, MethodCall)
|
register_stanza_plugin(RPCQuery, MethodCall)
|
||||||
register_stanza_plugin(RPCQuery, MethodResponse)
|
register_stanza_plugin(RPCQuery, MethodResponse)
|
||||||
|
|
||||||
self.xmpp.registerHandler(
|
self.xmpp.registerHandler(
|
||||||
Callback('RPC Call', MatchXPath('{%s}iq/{%s}query/{%s}methodCall' % (self.xmpp.default_ns, RPCQuery.namespace, RPCQuery.namespace)),
|
Callback('RPC Call', MatchXPath('{%s}iq/{%s}query/{%s}methodCall' % (self.xmpp.default_ns, RPCQuery.namespace, RPCQuery.namespace)),
|
||||||
self._handle_method_call)
|
self._handle_method_call)
|
||||||
)
|
)
|
||||||
self.xmpp.registerHandler(
|
self.xmpp.registerHandler(
|
||||||
Callback('RPC Call', MatchXPath('{%s}iq/{%s}query/{%s}methodResponse' % (self.xmpp.default_ns, RPCQuery.namespace, RPCQuery.namespace)),
|
Callback('RPC Call', MatchXPath('{%s}iq/{%s}query/{%s}methodResponse' % (self.xmpp.default_ns, RPCQuery.namespace, RPCQuery.namespace)),
|
||||||
self._handle_method_response)
|
self._handle_method_response)
|
||||||
@ -46,7 +46,7 @@ class xep_0009(base.base_plugin):
|
|||||||
)
|
)
|
||||||
self.xmpp.add_event_handler('jabber_rpc_method_call', self._on_jabber_rpc_method_call)
|
self.xmpp.add_event_handler('jabber_rpc_method_call', self._on_jabber_rpc_method_call)
|
||||||
self.xmpp.add_event_handler('jabber_rpc_method_response', self._on_jabber_rpc_method_response)
|
self.xmpp.add_event_handler('jabber_rpc_method_response', self._on_jabber_rpc_method_response)
|
||||||
self.xmpp.add_event_handler('jabber_rpc_method_fault', self._on_jabber_rpc_method_fault)
|
self.xmpp.add_event_handler('jabber_rpc_method_fault', self._on_jabber_rpc_method_fault)
|
||||||
self.xmpp.add_event_handler('jabber_rpc_error', self._on_jabber_rpc_error)
|
self.xmpp.add_event_handler('jabber_rpc_error', self._on_jabber_rpc_error)
|
||||||
self.xmpp.add_event_handler('error', self._handle_error)
|
self.xmpp.add_event_handler('error', self._handle_error)
|
||||||
#self.activeCalls = []
|
#self.activeCalls = []
|
||||||
@ -54,7 +54,7 @@ class xep_0009(base.base_plugin):
|
|||||||
def post_init(self):
|
def post_init(self):
|
||||||
base.base_plugin.post_init(self)
|
base.base_plugin.post_init(self)
|
||||||
self.xmpp.plugin['xep_0030'].add_feature('jabber:iq:rpc')
|
self.xmpp.plugin['xep_0030'].add_feature('jabber:iq:rpc')
|
||||||
self.xmpp.plugin['xep_0030'].add_identity('automation','rpc')
|
self.xmpp.plugin['xep_0030'].add_identity('automation','rpc')
|
||||||
|
|
||||||
def make_iq_method_call(self, pto, pmethod, params):
|
def make_iq_method_call(self, pto, pmethod, params):
|
||||||
iq = self.xmpp.makeIqSet()
|
iq = self.xmpp.makeIqSet()
|
||||||
@ -64,7 +64,7 @@ class xep_0009(base.base_plugin):
|
|||||||
iq['rpc_query']['method_call']['method_name'] = pmethod
|
iq['rpc_query']['method_call']['method_name'] = pmethod
|
||||||
iq['rpc_query']['method_call']['params'] = params
|
iq['rpc_query']['method_call']['params'] = params
|
||||||
return iq;
|
return iq;
|
||||||
|
|
||||||
def make_iq_method_response(self, pid, pto, params):
|
def make_iq_method_response(self, pid, pto, params):
|
||||||
iq = self.xmpp.makeIqResult(pid)
|
iq = self.xmpp.makeIqResult(pid)
|
||||||
iq.attrib['to'] = pto
|
iq.attrib['to'] = pto
|
||||||
@ -78,7 +78,7 @@ class xep_0009(base.base_plugin):
|
|||||||
iq.attrib['to'] = pto
|
iq.attrib['to'] = pto
|
||||||
iq.attrib['from'] = self.xmpp.boundjid.full
|
iq.attrib['from'] = self.xmpp.boundjid.full
|
||||||
iq.enable('rpc_query')
|
iq.enable('rpc_query')
|
||||||
iq['rpc_query']['method_response']['params'] = None
|
iq['rpc_query']['method_response']['params'] = None
|
||||||
iq['rpc_query']['method_response']['fault'] = params
|
iq['rpc_query']['method_response']['fault'] = params
|
||||||
return iq
|
return iq
|
||||||
|
|
||||||
@ -100,58 +100,58 @@ class xep_0009(base.base_plugin):
|
|||||||
iq['error']['type'] = 'cancel'
|
iq['error']['type'] = 'cancel'
|
||||||
iq['error']['condition'] = 'item-not-found'
|
iq['error']['condition'] = 'item-not-found'
|
||||||
return iq
|
return iq
|
||||||
|
|
||||||
def _undefined_condition(self, iq):
|
def _undefined_condition(self, iq):
|
||||||
payload = iq.get_payload()
|
payload = iq.get_payload()
|
||||||
iq.reply().error().set_payload(payload)
|
iq.reply().error().set_payload(payload)
|
||||||
iq['error']['code'] = '500'
|
iq['error']['code'] = '500'
|
||||||
iq['error']['type'] = 'cancel'
|
iq['error']['type'] = 'cancel'
|
||||||
iq['error']['condition'] = 'undefined-condition'
|
iq['error']['condition'] = 'undefined-condition'
|
||||||
return iq
|
return iq
|
||||||
|
|
||||||
def _forbidden(self, iq):
|
def _forbidden(self, iq):
|
||||||
payload = iq.get_payload()
|
payload = iq.get_payload()
|
||||||
iq.reply().error().set_payload(payload)
|
iq.reply().error().set_payload(payload)
|
||||||
iq['error']['code'] = '403'
|
iq['error']['code'] = '403'
|
||||||
iq['error']['type'] = 'auth'
|
iq['error']['type'] = 'auth'
|
||||||
iq['error']['condition'] = 'forbidden'
|
iq['error']['condition'] = 'forbidden'
|
||||||
return iq
|
return iq
|
||||||
|
|
||||||
def _recipient_unvailable(self, iq):
|
def _recipient_unvailable(self, iq):
|
||||||
payload = iq.get_payload()
|
payload = iq.get_payload()
|
||||||
iq.reply().error().set_payload(payload)
|
iq.reply().error().set_payload(payload)
|
||||||
iq['error']['code'] = '404'
|
iq['error']['code'] = '404'
|
||||||
iq['error']['type'] = 'wait'
|
iq['error']['type'] = 'wait'
|
||||||
iq['error']['condition'] = 'recipient-unavailable'
|
iq['error']['condition'] = 'recipient-unavailable'
|
||||||
return iq
|
return iq
|
||||||
|
|
||||||
def _handle_method_call(self, iq):
|
def _handle_method_call(self, iq):
|
||||||
type = iq['type']
|
type = iq['type']
|
||||||
if type == 'set':
|
if type == 'set':
|
||||||
log.debug("Incoming Jabber-RPC call from %s" % iq['from'])
|
log.debug("Incoming Jabber-RPC call from %s" % iq['from'])
|
||||||
self.xmpp.event('jabber_rpc_method_call', iq)
|
self.xmpp.event('jabber_rpc_method_call', iq)
|
||||||
else:
|
else:
|
||||||
if type == 'error' and ['rpc_query'] is None:
|
if type == 'error' and ['rpc_query'] is None:
|
||||||
self.handle_error(iq)
|
self.handle_error(iq)
|
||||||
else:
|
else:
|
||||||
log.debug("Incoming Jabber-RPC error from %s" % iq['from'])
|
log.debug("Incoming Jabber-RPC error from %s" % iq['from'])
|
||||||
self.xmpp.event('jabber_rpc_error', iq)
|
self.xmpp.event('jabber_rpc_error', iq)
|
||||||
|
|
||||||
def _handle_method_response(self, iq):
|
def _handle_method_response(self, iq):
|
||||||
if iq['rpc_query']['method_response']['fault'] is not None:
|
if iq['rpc_query']['method_response']['fault'] is not None:
|
||||||
log.debug("Incoming Jabber-RPC fault from %s" % iq['from'])
|
log.debug("Incoming Jabber-RPC fault from %s" % iq['from'])
|
||||||
#self._on_jabber_rpc_method_fault(iq)
|
#self._on_jabber_rpc_method_fault(iq)
|
||||||
self.xmpp.event('jabber_rpc_method_fault', iq)
|
self.xmpp.event('jabber_rpc_method_fault', iq)
|
||||||
else:
|
else:
|
||||||
log.debug("Incoming Jabber-RPC response from %s" % iq['from'])
|
log.debug("Incoming Jabber-RPC response from %s" % iq['from'])
|
||||||
self.xmpp.event('jabber_rpc_method_response', iq)
|
self.xmpp.event('jabber_rpc_method_response', iq)
|
||||||
|
|
||||||
def _handle_error(self, iq):
|
def _handle_error(self, iq):
|
||||||
print("['XEP-0009']._handle_error -> ERROR! Iq is '%s'" % iq)
|
print("['XEP-0009']._handle_error -> ERROR! Iq is '%s'" % iq)
|
||||||
print("#######################")
|
print("#######################")
|
||||||
print("### NOT IMPLEMENTED ###")
|
print("### NOT IMPLEMENTED ###")
|
||||||
print("#######################")
|
print("#######################")
|
||||||
|
|
||||||
def _on_jabber_rpc_method_call(self, iq, forwarded=False):
|
def _on_jabber_rpc_method_call(self, iq, forwarded=False):
|
||||||
"""
|
"""
|
||||||
A default handler for Jabber-RPC method call. If another
|
A default handler for Jabber-RPC method call. If another
|
||||||
@ -161,7 +161,7 @@ class xep_0009(base.base_plugin):
|
|||||||
forwarded set to True, then it will run as normal.
|
forwarded set to True, then it will run as normal.
|
||||||
"""
|
"""
|
||||||
if not forwarded and self.xmpp.event_handled('jabber_rpc_method_call') > 1:
|
if not forwarded and self.xmpp.event_handled('jabber_rpc_method_call') > 1:
|
||||||
return
|
return
|
||||||
# Reply with error by default
|
# Reply with error by default
|
||||||
error = self.client.plugin['xep_0009']._item_not_found(iq)
|
error = self.client.plugin['xep_0009']._item_not_found(iq)
|
||||||
error.send()
|
error.send()
|
||||||
@ -175,7 +175,7 @@ class xep_0009(base.base_plugin):
|
|||||||
forwarded set to True, then it will run as normal.
|
forwarded set to True, then it will run as normal.
|
||||||
"""
|
"""
|
||||||
if not forwarded and self.xmpp.event_handled('jabber_rpc_method_response') > 1:
|
if not forwarded and self.xmpp.event_handled('jabber_rpc_method_response') > 1:
|
||||||
return
|
return
|
||||||
error = self.client.plugin['xep_0009']._recpient_unavailable(iq)
|
error = self.client.plugin['xep_0009']._recpient_unavailable(iq)
|
||||||
error.send()
|
error.send()
|
||||||
|
|
||||||
@ -186,12 +186,12 @@ class xep_0009(base.base_plugin):
|
|||||||
|
|
||||||
If this handler is called by your own custom handler with
|
If this handler is called by your own custom handler with
|
||||||
forwarded set to True, then it will run as normal.
|
forwarded set to True, then it will run as normal.
|
||||||
"""
|
"""
|
||||||
if not forwarded and self.xmpp.event_handled('jabber_rpc_method_fault') > 1:
|
if not forwarded and self.xmpp.event_handled('jabber_rpc_method_fault') > 1:
|
||||||
return
|
return
|
||||||
error = self.client.plugin['xep_0009']._recpient_unavailable(iq)
|
error = self.client.plugin['xep_0009']._recpient_unavailable(iq)
|
||||||
error.send()
|
error.send()
|
||||||
|
|
||||||
def _on_jabber_rpc_error(self, iq, forwarded=False):
|
def _on_jabber_rpc_error(self, iq, forwarded=False):
|
||||||
"""
|
"""
|
||||||
A default handler for Jabber-RPC error response. If another
|
A default handler for Jabber-RPC error response. If another
|
||||||
@ -199,23 +199,23 @@ class xep_0009(base.base_plugin):
|
|||||||
|
|
||||||
If this handler is called by your own custom handler with
|
If this handler is called by your own custom handler with
|
||||||
forwarded set to True, then it will run as normal.
|
forwarded set to True, then it will run as normal.
|
||||||
"""
|
"""
|
||||||
if not forwarded and self.xmpp.event_handled('jabber_rpc_error') > 1:
|
if not forwarded and self.xmpp.event_handled('jabber_rpc_error') > 1:
|
||||||
return
|
return
|
||||||
error = self.client.plugin['xep_0009']._recpient_unavailable(iq, iq.get_payload())
|
error = self.client.plugin['xep_0009']._recpient_unavailable(iq, iq.get_payload())
|
||||||
error.send()
|
error.send()
|
||||||
|
|
||||||
def _send_fault(self, iq, fault_xml): #
|
def _send_fault(self, iq, fault_xml): #
|
||||||
fault = self.make_iq_method_response_fault(iq['id'], iq['from'], fault_xml)
|
fault = self.make_iq_method_response_fault(iq['id'], iq['from'], fault_xml)
|
||||||
fault.send()
|
fault.send()
|
||||||
|
|
||||||
def _send_error(self, iq):
|
def _send_error(self, iq):
|
||||||
print("['XEP-0009']._send_error -> ERROR! Iq is '%s'" % iq)
|
print("['XEP-0009']._send_error -> ERROR! Iq is '%s'" % iq)
|
||||||
print("#######################")
|
print("#######################")
|
||||||
print("### NOT IMPLEMENTED ###")
|
print("### NOT IMPLEMENTED ###")
|
||||||
print("#######################")
|
print("#######################")
|
||||||
|
|
||||||
def _extract_method(self, stanza):
|
def _extract_method(self, stanza):
|
||||||
xml = ET.fromstring("%s" % stanza)
|
xml = ET.fromstring("%s" % stanza)
|
||||||
return xml.find("./methodCall/methodName").text
|
return xml.find("./methodCall/methodName").text
|
||||||
|
|
||||||
|
@ -14,55 +14,51 @@ class RPCQuery(ElementBase):
|
|||||||
name = 'query'
|
name = 'query'
|
||||||
namespace = 'jabber:iq:rpc'
|
namespace = 'jabber:iq:rpc'
|
||||||
plugin_attrib = 'rpc_query'
|
plugin_attrib = 'rpc_query'
|
||||||
interfaces = set(())
|
interfaces = set(())
|
||||||
subinterfaces = set(())
|
subinterfaces = set(())
|
||||||
plugin_attrib_map = {}
|
plugin_attrib_map = {}
|
||||||
plugin_tag_map = {}
|
plugin_tag_map = {}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class MethodCall(ElementBase):
|
class MethodCall(ElementBase):
|
||||||
name = 'methodCall'
|
name = 'methodCall'
|
||||||
namespace = 'jabber:iq:rpc'
|
namespace = 'jabber:iq:rpc'
|
||||||
plugin_attrib = 'method_call'
|
plugin_attrib = 'method_call'
|
||||||
interfaces = set(('method_name', 'params'))
|
interfaces = set(('method_name', 'params'))
|
||||||
subinterfaces = set(())
|
subinterfaces = set(())
|
||||||
plugin_attrib_map = {}
|
plugin_attrib_map = {}
|
||||||
plugin_tag_map = {}
|
plugin_tag_map = {}
|
||||||
|
|
||||||
|
|
||||||
def get_method_name(self):
|
def get_method_name(self):
|
||||||
return self._get_sub_text('methodName')
|
return self._get_sub_text('methodName')
|
||||||
|
|
||||||
def set_method_name(self, value):
|
def set_method_name(self, value):
|
||||||
return self._set_sub_text('methodName', value)
|
return self._set_sub_text('methodName', value)
|
||||||
|
|
||||||
def get_params(self):
|
def get_params(self):
|
||||||
return self.xml.find('{%s}params' % self.namespace)
|
return self.xml.find('{%s}params' % self.namespace)
|
||||||
|
|
||||||
def set_params(self, params):
|
def set_params(self, params):
|
||||||
self.append(params)
|
self.append(params)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class MethodResponse(ElementBase):
|
class MethodResponse(ElementBase):
|
||||||
name = 'methodResponse'
|
name = 'methodResponse'
|
||||||
namespace = 'jabber:iq:rpc'
|
namespace = 'jabber:iq:rpc'
|
||||||
plugin_attrib = 'method_response'
|
plugin_attrib = 'method_response'
|
||||||
interfaces = set(('params', 'fault'))
|
interfaces = set(('params', 'fault'))
|
||||||
subinterfaces = set(())
|
subinterfaces = set(())
|
||||||
plugin_attrib_map = {}
|
plugin_attrib_map = {}
|
||||||
plugin_tag_map = {}
|
plugin_tag_map = {}
|
||||||
|
|
||||||
|
|
||||||
def get_params(self):
|
def get_params(self):
|
||||||
return self.xml.find('{%s}params' % self.namespace)
|
return self.xml.find('{%s}params' % self.namespace)
|
||||||
|
|
||||||
def set_params(self, params):
|
def set_params(self, params):
|
||||||
self.append(params)
|
self.append(params)
|
||||||
|
|
||||||
def get_fault(self):
|
def get_fault(self):
|
||||||
return self.xml.find('{%s}fault' % self.namespace)
|
return self.xml.find('{%s}fault' % self.namespace)
|
||||||
|
|
||||||
def set_fault(self, fault):
|
def set_fault(self, fault):
|
||||||
self.append(fault)
|
self.append(fault)
|
||||||
|
@ -6,4 +6,4 @@
|
|||||||
See the file LICENSE for copying permission.
|
See the file LICENSE for copying permission.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
from RPC import RPCQuery, MethodCall, MethodResponse
|
from sleekxmpp.plugins.xep_0009.stanza.RPC import RPCQuery, MethodCall, MethodResponse
|
||||||
|
Loading…
Reference in New Issue
Block a user