aboutsummaryrefslogtreecommitdiffstats
path: root/libmproxy/console
diff options
context:
space:
mode:
authorAldo Cortesi <aldo@nullcube.com>2012-11-26 13:25:07 +1300
committerAldo Cortesi <aldo@nullcube.com>2012-11-26 13:25:07 +1300
commit8c976ac7f0f17f617d483827a8b53b01ddf5d398 (patch)
tree61f9f1c7a86ec2d33037b809c0ed5dea20730797 /libmproxy/console
parent64bf97bfb06dccf4d848468b65093330d5eaf63b (diff)
downloadmitmproxy-8c976ac7f0f17f617d483827a8b53b01ddf5d398.tar.gz
mitmproxy-8c976ac7f0f17f617d483827a8b53b01ddf5d398.tar.bz2
mitmproxy-8c976ac7f0f17f617d483827a8b53b01ddf5d398.zip
Substantially rewrite AMF decoding.
This is tricky, but we should now handle a lot more corner-cases.
Diffstat (limited to 'libmproxy/console')
-rw-r--r--libmproxy/console/contentview.py92
1 files changed, 68 insertions, 24 deletions
diff --git a/libmproxy/console/contentview.py b/libmproxy/console/contentview.py
index 2e93727a..2b46064a 100644
--- a/libmproxy/console/contentview.py
+++ b/libmproxy/console/contentview.py
@@ -15,11 +15,10 @@ from ..contrib import jsbeautifier, html2text
try:
import pyamf
- from pyamf import remoting
+ from pyamf import remoting, flex
except ImportError: # pragma nocover
pyamf = None
-
VIEW_CUTOFF = 1024*50
@@ -236,30 +235,75 @@ class ViewMultipart:
return "Multipart form", r
-class ViewAMF:
- name = "AMF"
- prompt = ("amf", "f")
- content_types = ["application/x-amf"]
- def __call__(self, hdrs, content, limit):
- envelope = remoting.decode(content)
- 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 pyamf:
+ class DummyObject(dict):
+ def __init__(self, alias):
+ dict.__init__(self)
+
+ def __readamf__(self, input):
+ data = input.readObject()
+ self["data"] = data
+
+ def pyamf_class_loader(s):
+ for i in pyamf.CLASS_LOADERS:
+ if i != pyamf_class_loader:
+ v = i(s)
+ if v:
+ return v
+ return DummyObject
+
+ pyamf.register_class_loader(pyamf_class_loader)
+
+ class ViewAMF:
+ name = "AMF"
+ prompt = ("amf", "f")
+ content_types = ["application/x-amf"]
+
+ def unpack(self, b, seen=set([])):
+ if hasattr(b, "body"):
+ return self.unpack(b.body, seen)
+ if isinstance(b, DummyObject):
+ if id(b) in seen:
+ return "<recursion>"
+ else:
+ seen.add(id(b))
+ for k, v in b.items():
+ b[k] = self.unpack(v, seen)
+ return b
+ elif isinstance(b, dict):
+ for k, v in b.items():
+ b[k] = self.unpack(v, seen)
+ return b
+ elif isinstance(b, list):
+ return [self.unpack(i) for i in b]
+ elif isinstance(b, flex.ArrayCollection):
+ return [self.unpack(i, seen) for i in b]
+ else:
+ return b
+
+ def __call__(self, hdrs, content, limit):
+ envelope = remoting.decode(content, strict=False)
+ if not envelope:
+ return None
- if hasattr(message, 'target'):
- one_message['target'] = message.target
- one_message['body'] = message.body
- data[target] = one_message
- s = json.dumps(data, indent=4)
- return "AMF", _view_text(s[:limit], len(s), limit)
+ txt = []
+ for target, message in iter(envelope):
+ if isinstance(message, pyamf.remoting.Request):
+ txt.append(urwid.Text([
+ ("header", "Request: "),
+ ("text", str(target)),
+ ]))
+ else:
+ txt.append(urwid.Text([
+ ("header", "Response: "),
+ ("text", "%s, code %s"%(target, message.status)),
+ ]))
+
+ s = json.dumps(self.unpack(message), indent=4)
+ txt.extend(_view_text(s[:limit], len(s), limit))
+
+ return "AMF v%s"%envelope.amfVersion, txt
class ViewJavaScript: