From 82a90511bc61b4ed98cd7ff2455b79dec015c45f Mon Sep 17 00:00:00 2001 From: Chris Czub Date: Mon, 9 Nov 2015 11:06:16 -0500 Subject: Add "add" ContentView method & test --- libmproxy/contentviews.py | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'libmproxy') diff --git a/libmproxy/contentviews.py b/libmproxy/contentviews.py index 9af08033..8d5aadfc 100644 --- a/libmproxy/contentviews.py +++ b/libmproxy/contentviews.py @@ -515,6 +515,14 @@ def get_by_shortcut(c): return i +def add(obj): + for i in views: + if i.name == obj.name: + raise ContentViewException("Duplicate view: " + obj.name) + + views.append(obj) + + def get(name): for i in views: if i.name == name: -- cgit v1.2.3 From d7239d665e6781d7b84ecfde3fd5d7d1831de284 Mon Sep 17 00:00:00 2001 From: Chris Czub Date: Mon, 9 Nov 2015 15:07:08 -0500 Subject: Add new contentviews' content type mappings --- libmproxy/contentviews.py | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'libmproxy') diff --git a/libmproxy/contentviews.py b/libmproxy/contentviews.py index 8d5aadfc..aa2082d1 100644 --- a/libmproxy/contentviews.py +++ b/libmproxy/contentviews.py @@ -520,8 +520,18 @@ def add(obj): if i.name == obj.name: raise ContentViewException("Duplicate view: " + obj.name) + for prompt in view_prompts: + if prompt[1] == obj.prompt[1]: + raise ContentViewException("Duplicate view shortcut: " + obj.prompt[1]) + views.append(obj) + for ct in obj.content_types: + l = content_types_map.setdefault(ct, []) + l.append(obj) + + view_prompts.append(obj.prompt) + def get(name): for i in views: -- cgit v1.2.3 From d3feaa3bc6e2d9c2c7ee8286038c69c0b9601869 Mon Sep 17 00:00:00 2001 From: Chris Czub Date: Mon, 9 Nov 2015 15:07:58 -0500 Subject: Add custom content view plugin support for mitmproxy/mitmdump --- libmproxy/flow.py | 46 +++++++++++++++++++++++++++++++++++++++++++++- libmproxy/script.py | 7 +++++++ 2 files changed, 52 insertions(+), 1 deletion(-) (limited to 'libmproxy') diff --git a/libmproxy/flow.py b/libmproxy/flow.py index 55a4dbcf..5acbebf2 100644 --- a/libmproxy/flow.py +++ b/libmproxy/flow.py @@ -9,7 +9,7 @@ import cookielib import os import re import urlparse - +import inspect from netlib import wsgi from netlib.exceptions import HttpException @@ -21,6 +21,11 @@ from .proxy.config import HostMatcher from .protocol.http_replay import RequestReplayThread from .protocol import Kill from .models import ClientConnection, ServerConnection, HTTPResponse, HTTPFlow, HTTPRequest +from . import contentviews as cv + + +class PluginError(Exception): + pass class AppRegistry: @@ -614,6 +619,43 @@ class State(object): self.flows.kill_all(master) +class Plugins(object): + def __init__(self): + self._view_plugins = {} + + def __iter__(self): + for plugin_type in ('view_plugins',): + yield (plugin_type, getattr(self, '_' + plugin_type)) + + def __getitem__(self, key): + if key in ('view_plugins',): + return getattr(self, '_' + key) + else: + return None + + def register_view(self, id, **kwargs): + if self._view_plugins.get(id): + raise PluginError("Duplicate view registration for %s" % (id, )) + + if not kwargs.get('class_ref') or not \ + callable(kwargs['class_ref']) or not \ + isinstance(kwargs['class_ref'], type): + raise PluginError("No custom content view class passed for view %s" % (id, )) + + script_path = inspect.stack()[1][1] + + view_plugin = { + 'title': kwargs.get('title') or id, + 'class_ref': kwargs['class_ref'], + 'script_path': script_path, + } + self._view_plugins[id] = view_plugin + + cv.add(kwargs['class_ref']()) + + print("Registered view plugin %s from script %s" % (kwargs['title'], script_path)) + + class FlowMaster(controller.Master): def __init__(self, server, state): controller.Master.__init__(self, server) @@ -643,6 +685,8 @@ class FlowMaster(controller.Master): self.stream = None self.apps = AppRegistry() + self.plugins = Plugins() + def start_app(self, host, port): self.apps.add( app.mapp, diff --git a/libmproxy/script.py b/libmproxy/script.py index 9d051c12..f11c5cd8 100644 --- a/libmproxy/script.py +++ b/libmproxy/script.py @@ -56,6 +56,13 @@ class ScriptContext: def app_registry(self): return self._master.apps + @property + def plugins(self): + if hasattr(self._master, 'plugins'): + return self._master.plugins + + return None + class Script: """ -- cgit v1.2.3 From e72a9a62a107ea3f53b6b26d1abe63c554448d17 Mon Sep 17 00:00:00 2001 From: Chris Czub Date: Fri, 13 Nov 2015 16:55:27 -0500 Subject: Feedback from PR #832 --- libmproxy/contentviews.py | 81 ++++++++++++++++++++++++++--------------------- libmproxy/flow.py | 43 ------------------------- libmproxy/script.py | 11 ++++--- 3 files changed, 51 insertions(+), 84 deletions(-) (limited to 'libmproxy') diff --git a/libmproxy/contentviews.py b/libmproxy/contentviews.py index aa2082d1..2f46ccca 100644 --- a/libmproxy/contentviews.py +++ b/libmproxy/contentviews.py @@ -479,34 +479,9 @@ class ViewWBXML(View): return None -views = [ - ViewAuto(), - ViewRaw(), - ViewHex(), - ViewJSON(), - ViewXML(), - ViewWBXML(), - ViewHTML(), - ViewHTMLOutline(), - ViewJavaScript(), - ViewCSS(), - ViewURLEncoded(), - ViewMultipart(), - ViewImage(), -] -if pyamf: - views.append(ViewAMF()) - -if ViewProtobuf.is_available(): - views.append(ViewProtobuf()) - +views = [] content_types_map = {} -for i in views: - for ct in i.content_types: - l = content_types_map.setdefault(ct, []) - l.append(i) - -view_prompts = [i.prompt for i in views] +view_prompts = [] def get_by_shortcut(c): @@ -515,23 +490,57 @@ def get_by_shortcut(c): return i -def add(obj): +def add(view): + # TODO: auto-select a different name (append an integer?) for i in views: - if i.name == obj.name: - raise ContentViewException("Duplicate view: " + obj.name) + if i.name == view.name: + raise ContentViewException("Duplicate view: " + view.name) + # TODO: the UI should auto-prompt for a replacement shortcut for prompt in view_prompts: - if prompt[1] == obj.prompt[1]: - raise ContentViewException("Duplicate view shortcut: " + obj.prompt[1]) + if prompt[1] == view.prompt[1]: + raise ContentViewException("Duplicate view shortcut: " + view.prompt[1]) + + views.append(view) + + for ct in view.content_types: + l = content_types_map.setdefault(ct, []) + l.append(view) + + view_prompts.append(view.prompt) - views.append(obj) - for ct in obj.content_types: +def remove(view): + for ct in view.content_types: l = content_types_map.setdefault(ct, []) - l.append(obj) + l.remove(view) + + if not len(l): + del content_types_map[ct] + + view_prompts.remove(view.prompt) + views.remove(view) - view_prompts.append(obj.prompt) +add(ViewAuto()) +add(ViewRaw()) +add(ViewHex()) +add(ViewJSON()) +add(ViewXML()) +add(ViewWBXML()) +add(ViewHTML()) +add(ViewHTMLOutline()) +add(ViewJavaScript()) +add(ViewCSS()) +add(ViewURLEncoded()) +add(ViewMultipart()) +add(ViewImage()) + +if pyamf: + add(ViewAMF()) + +if ViewProtobuf.is_available(): + add(ViewProtobuf()) def get(name): for i in views: diff --git a/libmproxy/flow.py b/libmproxy/flow.py index 5acbebf2..3343e694 100644 --- a/libmproxy/flow.py +++ b/libmproxy/flow.py @@ -24,10 +24,6 @@ from .models import ClientConnection, ServerConnection, HTTPResponse, HTTPFlow, from . import contentviews as cv -class PluginError(Exception): - pass - - class AppRegistry: def __init__(self): self.apps = {} @@ -619,43 +615,6 @@ class State(object): self.flows.kill_all(master) -class Plugins(object): - def __init__(self): - self._view_plugins = {} - - def __iter__(self): - for plugin_type in ('view_plugins',): - yield (plugin_type, getattr(self, '_' + plugin_type)) - - def __getitem__(self, key): - if key in ('view_plugins',): - return getattr(self, '_' + key) - else: - return None - - def register_view(self, id, **kwargs): - if self._view_plugins.get(id): - raise PluginError("Duplicate view registration for %s" % (id, )) - - if not kwargs.get('class_ref') or not \ - callable(kwargs['class_ref']) or not \ - isinstance(kwargs['class_ref'], type): - raise PluginError("No custom content view class passed for view %s" % (id, )) - - script_path = inspect.stack()[1][1] - - view_plugin = { - 'title': kwargs.get('title') or id, - 'class_ref': kwargs['class_ref'], - 'script_path': script_path, - } - self._view_plugins[id] = view_plugin - - cv.add(kwargs['class_ref']()) - - print("Registered view plugin %s from script %s" % (kwargs['title'], script_path)) - - class FlowMaster(controller.Master): def __init__(self, server, state): controller.Master.__init__(self, server) @@ -685,8 +644,6 @@ class FlowMaster(controller.Master): self.stream = None self.apps = AppRegistry() - self.plugins = Plugins() - def start_app(self, host, port): self.apps.add( app.mapp, diff --git a/libmproxy/script.py b/libmproxy/script.py index f11c5cd8..4da40c52 100644 --- a/libmproxy/script.py +++ b/libmproxy/script.py @@ -5,6 +5,8 @@ import threading import shlex import sys +from . import contentviews as cv + class ScriptError(Exception): pass @@ -56,12 +58,11 @@ class ScriptContext: def app_registry(self): return self._master.apps - @property - def plugins(self): - if hasattr(self._master, 'plugins'): - return self._master.plugins + def add_contentview(self, view_obj): + cv.add(view_obj) - return None + def remove_contentview(self, view_obj): + cv.remove(view_obj) class Script: -- cgit v1.2.3