From dfc033ab5f981eb97cda695e707acd590e5708e3 Mon Sep 17 00:00:00 2001 From: Clemens Date: Wed, 1 Jun 2016 00:52:37 +0200 Subject: added basic file up_download functionality (not finish yet) --- mitmproxy/web/__init__.py | 3 +++ mitmproxy/web/app.py | 23 +++++++++++++++++++++++ web/src/js/actions.js | 7 +++++++ web/src/js/components/header.js | 24 ++++++------------------ 4 files changed, 39 insertions(+), 18 deletions(-) diff --git a/mitmproxy/web/__init__.py b/mitmproxy/web/__init__.py index 80a65886..357718f1 100644 --- a/mitmproxy/web/__init__.py +++ b/mitmproxy/web/__init__.py @@ -87,6 +87,9 @@ class WebState(flow.State): data=[] ) + def load_flows(self, flows): + super(WebState, self).load_flows(flows) + class Options(object): attributes = [ diff --git a/mitmproxy/web/app.py b/mitmproxy/web/app.py index 43b2bad1..afeb7c00 100644 --- a/mitmproxy/web/app.py +++ b/mitmproxy/web/app.py @@ -8,6 +8,8 @@ import re import six import tornado.websocket +from six.moves import cStringIO as StringIO +from mitmproxy.flow import FlowWriter, FlowReader from mitmproxy import filt from mitmproxy import version @@ -159,6 +161,26 @@ class Flows(RequestHandler): data=[_strip_content(f.get_state()) for f in self.state.flows] )) +class DumpFlows(RequestHandler): + def get(self): + self.set_header("Content-Description", "File Transfer") + self.set_header("Cache-Control", "no-cache, no-store, must-revalidate") + self.set_header("Content-Disposition", "attachment; filename=flows") + self.set_header("Content-Type", "application/octet-stream") + self.set_header("Content-Transfer-Encoding", "binary") + + sio = StringIO() + fw = FlowWriter(sio) + for f in self.state.flows: + fw.add(f) + self.write(sio.getvalue()) + + sio.close() + + def post(self): + sio = StringIO(self.request.body) + self.state.load_flows(FlowReader(sio).stream()) + sio.close() class ClearAll(RequestHandler): @@ -356,6 +378,7 @@ class Application(tornado.web.Application): (r"/updates", ClientConnection), (r"/events", Events), (r"/flows", Flows), + (r"/flows/dump", DumpFlows), (r"/flows/accept", AcceptFlows), (r"/flows/(?P[0-9a-f\-]+)", FlowHandler), (r"/flows/(?P[0-9a-f\-]+)/accept", AcceptFlow), diff --git a/web/src/js/actions.js b/web/src/js/actions.js index 6ded4c44..0f81d7a3 100644 --- a/web/src/js/actions.js +++ b/web/src/js/actions.js @@ -117,6 +117,13 @@ export var FlowActions = { }, clear: function(){ $.post("/clear"); + }, + download: () => window.location = "/flows/dump", + upload: (file) => { + var filereader = new FileReader(); + filereader.file = file; + filereader.onload = (e) => $.post("/flows/dump", e.target.result); + filereader.readAsBinaryString(file); } }; diff --git a/web/src/js/components/header.js b/web/src/js/components/header.js index 0df29f51..4bb4622d 100644 --- a/web/src/js/components/header.js +++ b/web/src/js/components/header.js @@ -345,11 +345,14 @@ var FileMenu = React.createClass({ }, handleOpenClick: function (e) { e.preventDefault(); - console.error("unimplemented: handleOpenClick"); + }, + handleOpenChange: function (e) { + e.preventDefault(); + FlowActions.upload(e.target.files[0]); }, handleSaveClick: function (e) { e.preventDefault(); - console.error("unimplemented: handleSaveClick"); + FlowActions.download(); }, handleShutdownClick: function (e) { e.preventDefault(); @@ -369,10 +372,7 @@ var FileMenu = React.createClass({
  • - - - Open... - +
  • @@ -388,18 +388,6 @@ var FileMenu = React.createClass({
  • {/* -
  • - - - Open - -
  • -
  • - - - Save - -
  • -- cgit v1.2.3