From 202d50656ea8e733d37e2d953b99706bd44e6206 Mon Sep 17 00:00:00 2001 From: Glenn Maynard Date: Thu, 28 Apr 2011 00:53:59 -0400 Subject: [PATCH] Report the original stream:error stanza to clients. When a stream:error was received, the error was parsed, converted to a StreamError exception, then XML was recreated from that. This is roundabout and lossy: it's parsing the XML, then attempting to recreate the same XML that it already had. Instead, keep the original XML node in the exception, and use it directly. This ensures that the node in remote-stream-error is unchanged from what we received from the remote server. Any extensions will be passed through unchanged, as should happen for all stanzas. For example, the node reported by Jabber14 now correctly reproduces its xmlns='jabber:client' attribute. The simple patch in patches.py should eventually be sent upstream. --- punjab/__init__.py | 1 + punjab/patches.py | 24 ++++++++++++++++++++++++ punjab/session.py | 6 +----- 3 files changed, 26 insertions(+), 5 deletions(-) create mode 100644 punjab/patches.py diff --git a/punjab/__init__.py b/punjab/__init__.py index 70bf013..d932699 100644 --- a/punjab/__init__.py +++ b/punjab/__init__.py @@ -4,6 +4,7 @@ Punjab - multiple http interfaces to jabber. """ from twisted.python import log from twisted.application import service +import twisted_patches def uriCheck(elem, uri): diff --git a/punjab/patches.py b/punjab/patches.py new file mode 100644 index 0000000..73f71a3 --- /dev/null +++ b/punjab/patches.py @@ -0,0 +1,24 @@ +# XXX: All monkey patches should be sent upstream and eventually removed. + +import functools + +def patch(cls, attr): + """Patch the function named attr in the object cls with the decorated function.""" + orig_func = getattr(cls, attr) + @wraps(orig_func) + def decorator(func): + def wrapped_func(*args, **kwargs): + return func(orig_func, *args, **kwargs) + setattr(cls, attr, wrapped_func) + return orig_func + return decorator + +# Modify jabber.error.exceptionFromStreamError to include the XML element in +# the exception. +from twisted.words.protocols.jabber import error as jabber_error +@patch(jabber_error, "exceptionFromStreamError") +def exceptionFromStreamError(orig, element): + exception = orig(element) + exception.element = element + return exception + diff --git a/punjab/session.py b/punjab/session.py index de49f20..0bb58a5 100644 --- a/punjab/session.py +++ b/punjab/session.py @@ -517,11 +517,7 @@ class Session(jabber.JabberClientFactory, server.Session): def streamError(self, streamerror): """called when we get a stream:error stanza""" - try: # a workaround for a bug in twisted.words.protocols.jabber.error - err_elem = streamerror.value.getElement() - err_elem.toXml() - except: # no matter what the exception we just return None - err_elem = None + err_elem = getattr(streamerror.value, "element") e = self.buildRemoteError(err_elem) do_expire = True -- 1.7.10.4