Hi, I realized that I did not quote the original message. Also, my reply was written too hastily at the end of the day. Here is the correct patch, tested with a pre and post deep_base64 client. -Adam git-diff /home/func-cermaster/func/func/overlord/client.py overlord/client.py diff --git a/home/func-cermaster/func/func/overlord/client.py b/overlord/client.py index b9f8d76..4e924c6 100644 --- a/home/func-cermaster/func/func/overlord/client.py +++ b/overlord/client.py @@ -786,7 +786,7 @@ class Overlord(object): if self.interactive: print retval - retval = func_utils.deep_base64(retval) + retval = func_utils.deep_base64(retval,1) except Exception, e: (t, v, tb) = sys.exc_info() git-diff /home/func-cermaster/func/func/utils.py utils.py diff --git a/home/func-cermaster/func/func/utils.py b/utils.py index 011b902..b6e8a6f 100644 --- a/home/func-cermaster/func/func/utils.py +++ b/utils.py @@ -168,22 +168,29 @@ def should_log(args): return True return False -def deep_base64(ds): +def deep_base64(ds, mode = 0): """ Run through an arbitrary datastructure of dicts / lists / tuples to find all strings and base 64 encode/decode them with xmlrpclib.Binary objects. + + mode 0 - flip, 1 - force decode, 2 - force encode + """ from xmlrpclib import Binary if isinstance(ds, Binary): + if mode == 2: + return ds return ds.data if isinstance(ds, basestring): + if mode == 1: + return ds return Binary(ds) if isinstance(ds, list) or isinstance(ds, tuple): - cleaned = map(lambda x: deep_base64(x), ds) + cleaned = map(lambda x: deep_base64(x,mode), ds) if isinstance(ds, tuple): cleaned = tuple(cleaned) return cleaned @@ -191,7 +198,7 @@ def deep_base64(ds): if isinstance(ds, dict): cleaned = {} for k,v in ds.iteritems(): - cleaned[deep_base64(k)] = deep_base64(v) + cleaned[deep_base64(k)] = deep_base64(v,mode) return cleaned return ds From: John Eckersberg <jeckersb redhat com> ------------------------------------- >From http://docs.python.org/library/xmlrpclib.html: When passing strings, characters special to XML such as <, >, and & will be automatically escaped. However, it’s the caller’s responsibility to ensure that the string is free of characters that aren’t allowed in XML, such as the control characters with ASCII values between 0 and 31 (except, of course, tab, newline and carriage return); failing to do this will result in an XML-RPC request that isn’t well-formed XML. If you have to pass arbitrary strings via XML-RPC, use the Binary wrapper class --- func/minion/server.py | 9 ++++++++- func/overlord/client.py | 4 +++- func/utils.py | 28 ++++++++++++++++++++++++++++ 3 files changed, 39 insertions(+), 2 deletions(-) diff --git a/func/minion/server.py b/func/minion/server.py index fbe5c4b..27b4181 100644 --- a/func/minion/server.py +++ b/func/minion/server.py @@ -201,7 +201,14 @@ class FuncApiMethod: rc = utils.nice_exception(t,v,tb) self.logger.debug("Return code for %s: %s" % (self.__name, rc)) - return rc + if self.__name == 'jobs.job_status': + # don't double-encode (which ultimately ends up being a no-op, + # since deep_base64(deep_base64(foo)) == foo + # the return value stored by jobthing is already encoded at this + # point + return rc + else: + return futils.deep_base64(rc) def serve(): diff --git a/func/overlord/client.py b/func/overlord/client.py index e011929..4b8c689 100644 --- a/func/overlord/client.py +++ b/func/overlord/client.py @@ -649,7 +649,9 @@ class Overlord(object): if self.interactive: print retval - + + retval = func_utils.deep_base64(retval) + except Exception, e: (t, v, tb) = sys.exc_info() retval = utils.nice_exception(t,v,tb) diff --git a/func/utils.py b/func/utils.py index 75ac368..011b902 100644 --- a/func/utils.py +++ b/func/utils.py @@ -168,6 +168,34 @@ def should_log(args): return True return False +def deep_base64(ds): + """ + Run through an arbitrary datastructure of dicts / lists / tuples + to find all strings and base 64 encode/decode them with + xmlrpclib.Binary objects. + """ + from xmlrpclib import Binary + + if isinstance(ds, Binary): + return ds.data + + if isinstance(ds, basestring): + return Binary(ds) + + if isinstance(ds, list) or isinstance(ds, tuple): + cleaned = map(lambda x: deep_base64(x), ds) + if isinstance(ds, tuple): + cleaned = tuple(cleaned) + return cleaned + + if isinstance(ds, dict): + cleaned = {} + for k,v in ds.iteritems(): + cleaned[deep_base64(k)] = deep_base64(v) + return cleaned + + return ds + #################### PROGRESS BAR ################################## # The code below can be used for progress bar purposes as we will do #it is a combination of http://code.activestate.com/recipes/168639/ and -- 1.6.6 _______________________________________________ Func-list mailing list Func-list@xxxxxxxxxx https://www.redhat.com/mailman/listinfo/func-list