From 3189d144a521fcc98695dd079fb3dd4304de2eee Mon Sep 17 00:00:00 2001 From: Sahn Lam Date: Thu, 16 Aug 2012 23:27:47 -0700 Subject: [PATCH] Optional AMF decoding support If PyAMF is installed, enable AMF decoding. --- libmproxy/console/contentview.py | 28 ++++++++++++++++++++++-- libmproxy/console/help.py | 4 ++++ libmproxy/utils.py | 36 +++++++++++++++++++++++++++++++ test/data/test.amf | Bin 0 -> 432 bytes test/test_console_contentview.py | 23 ++++++++++++++++++++ 5 files changed, 89 insertions(+), 2 deletions(-) create mode 100644 test/data/test.amf diff --git a/libmproxy/console/contentview.py b/libmproxy/console/contentview.py index 2443c188c..4efbb2b1c 100644 --- a/libmproxy/console/contentview.py +++ b/libmproxy/console/contentview.py @@ -20,6 +20,7 @@ VIEW_RAW = 7 VIEW_HEX = 8 VIEW_HTML = 9 VIEW_OUTLINE = 10 +VIEW_AMF = 11 VIEW_NAMES = { VIEW_AUTO: "Auto", @@ -36,7 +37,7 @@ VIEW_NAMES = { } -VIEW_PROMPT = ( +VIEW_PROMPT = [ ("auto detect", "a"), ("hex", "e"), ("html", "h"), @@ -48,7 +49,7 @@ VIEW_PROMPT = ( ("multipart", "m"), ("urlencoded", "u"), ("xml", "x"), -) +] VIEW_SHORTCUTS = { "a": VIEW_AUTO, @@ -285,6 +286,10 @@ def view_image(hdrs, content, limit): ) return "%s image"%img.format, fmt +def view_amf(hdrs, content, limit): + s = utils.pretty_amf(content) + if s: + return "AMF", _view_text(s[:limit], len(s), limit) PRETTY_FUNCTION_MAP = { VIEW_XML: view_xml, @@ -344,3 +349,22 @@ def get_content_view(viewmode, hdrItems, content, limit): else: msg.append(ret[0]) return " ".join(msg), ret[1] + + +# +# Enable optional decoding methods at runtime +# + +# AMF decoding requires pyamf +try: + import pyamf + + VIEW_SHORTCUTS["f"] = VIEW_AMF + VIEW_PROMPT.append(("amf", "f")) + VIEW_NAMES[VIEW_AMF] = "AMF" + CONTENT_TYPES_MAP["application/x-amf"] = VIEW_AMF + PRETTY_FUNCTION_MAP[VIEW_AMF] = view_amf +except ImportError: + pass + + diff --git a/libmproxy/console/help.py b/libmproxy/console/help.py index 64428fcce..e278e7633 100644 --- a/libmproxy/console/help.py +++ b/libmproxy/console/help.py @@ -83,6 +83,10 @@ class HelpView(urwid.ListBox): common.highlight_key("xml", "x") + [("text", ": XML")] ), + (None, + common.highlight_key("amf", "f") + + [("text", ": AMF (requires PyAMF)")] + ), ("o", "toggle options:"), (None, common.highlight_key("anticache", "a") + diff --git a/libmproxy/utils.py b/libmproxy/utils.py index 871beb355..a89419a91 100644 --- a/libmproxy/utils.py +++ b/libmproxy/utils.py @@ -81,6 +81,42 @@ def pretty_json(s): return json.dumps(p, sort_keys=True, indent=4).split("\n") +def pretty_amf(s): + """ + Takes an AMF encoded string, decodes it and returns a nicely indented + string in JSON format. + + Reqires pyamf module. The function returns None if pyamf is not + installed. + """ + try: + import pyamf + from pyamf import remoting + except ImportError: + return None + + envelope = remoting.decode(s) + if not envelope: + return None + + data = {} + data['amfVersion'] = envelope.amfVersion + for target, message in iter(envelope): + + one_message = {} + + if hasattr(message, 'status'): + one_message['status'] = message.status + + if hasattr(message, 'target'): + one_message['target'] = message.target + + one_message['body'] = message.body + data[target] = one_message + + return json.dumps(data, indent=4) + + def urldecode(s): """ Takes a urlencoded string and returns a list of (key, value) tuples. diff --git a/test/data/test.amf b/test/data/test.amf new file mode 100644 index 0000000000000000000000000000000000000000..c8fc261d264825ad8da8351743fd9e3a2cf8f085 GIT binary patch literal 432 zcmX|8&riZI7+u*IVUrMImW3F@!RS%>VFDfjQHjPF(X%P*H)yhTv+Y3eV2p|W0p7g$ zcX;&b*+0gk-3<27etCWGd+%#CUDGtAReM;#2>6V8uuG_jvGk_BbklNsZN+%86i=^M zHgcAWZX%~ASWL|V9(x;ppvp^_Q9&bSmfK@Yz(25;ixHie1yz?+$tW=pN}HgHgz2@tv~1t|0C=3hzH~xhft2@4ET_2X2>DLzz8tu_5-Sp zk;D=l53>v4e#FDtYMueZ;{Zr5XF8eiCd8DPZnNHKw(9$hPN$W#`lvXG0#X8HFj?g9 z;-aUfGv0n2