aboutsummaryrefslogtreecommitdiffstats
path: root/mitmproxy/tools
diff options
context:
space:
mode:
Diffstat (limited to 'mitmproxy/tools')
-rw-r--r--mitmproxy/tools/console/flowview.py4
-rw-r--r--mitmproxy/tools/console/master.py15
-rw-r--r--mitmproxy/tools/console/statusbar.py43
-rw-r--r--mitmproxy/tools/console/window.py2
-rw-r--r--mitmproxy/tools/main.py9
-rw-r--r--mitmproxy/tools/web/master.py4
-rw-r--r--mitmproxy/tools/web/static/app.js4
7 files changed, 56 insertions, 25 deletions
diff --git a/mitmproxy/tools/console/flowview.py b/mitmproxy/tools/console/flowview.py
index 9420c105..650a9366 100644
--- a/mitmproxy/tools/console/flowview.py
+++ b/mitmproxy/tools/console/flowview.py
@@ -30,12 +30,14 @@ class FlowViewHeader(urwid.WidgetWrap):
self.focus_changed()
def focus_changed(self):
+ cols, _ = self.master.ui.get_cols_rows()
if self.master.view.focus.flow:
self._w = common.format_flow(
self.master.view.focus.flow,
False,
extended=True,
- hostheader=self.master.options.showhost
+ hostheader=self.master.options.showhost,
+ max_url_len=cols,
)
else:
self._w = urwid.Pile([])
diff --git a/mitmproxy/tools/console/master.py b/mitmproxy/tools/console/master.py
index 5da6ef0b..de660b17 100644
--- a/mitmproxy/tools/console/master.py
+++ b/mitmproxy/tools/console/master.py
@@ -1,3 +1,4 @@
+import asyncio
import mailcap
import mimetypes
import os
@@ -94,7 +95,9 @@ class ConsoleMaster(master.Master):
self.start_err = entry
else:
signals.status_message.send(
- message=(entry.level, "{}: {}".format(entry.level.title(), entry.msg)),
+ message=(entry.level,
+ "{}: {}".format(entry.level.title(),
+ str(entry.msg).lstrip())),
expire=5
)
@@ -180,12 +183,6 @@ class ConsoleMaster(master.Master):
)
self.ui.clear()
- def ticker(self, *userdata):
- changed = self.tick(timeout=0)
- if changed:
- self.loop.draw_screen()
- self.loop.set_alarm_in(0.01, self.ticker)
-
def inject_key(self, key):
self.loop.process_input([key])
@@ -204,6 +201,7 @@ class ConsoleMaster(master.Master):
)
self.loop = urwid.MainLoop(
urwid.SolidFill("x"),
+ event_loop=urwid.AsyncioEventLoop(loop=asyncio.get_event_loop()),
screen = self.ui,
handle_mouse = self.options.console_mouse,
)
@@ -212,8 +210,6 @@ class ConsoleMaster(master.Master):
self.loop.widget = self.window
self.window.refresh()
- self.loop.set_alarm_in(0.01, self.ticker)
-
if self.start_err:
def display_err(*_):
self.sig_add_log(None, self.start_err)
@@ -234,6 +230,7 @@ class ConsoleMaster(master.Master):
finally:
sys.stderr.flush()
super().shutdown()
+ self.addons.trigger("done")
def shutdown(self):
raise urwid.ExitMainLoop
diff --git a/mitmproxy/tools/console/statusbar.py b/mitmproxy/tools/console/statusbar.py
index 8553a66f..fa987e94 100644
--- a/mitmproxy/tools/console/statusbar.py
+++ b/mitmproxy/tools/console/statusbar.py
@@ -49,7 +49,8 @@ class ActionBar(urwid.WidgetWrap):
def sig_message(self, sender, message, expire=1):
if self.prompting:
return
- w = urwid.Text(message)
+ cols, _ = self.master.ui.get_cols_rows()
+ w = urwid.Text(self.shorten_message(message, cols))
self._w = w
if expire:
def cb(*args):
@@ -60,6 +61,36 @@ class ActionBar(urwid.WidgetWrap):
def prep_prompt(self, p):
return p.strip() + ": "
+ def shorten_message(self, msg, max_width):
+ """
+ Shorten message so that it fits into a single line in the statusbar.
+ """
+ if isinstance(msg, tuple):
+ disp_attr, msg_text = msg
+ elif isinstance(msg, str):
+ disp_attr, msg_text = None, msg
+ else:
+ return msg
+ msg_end = "\u2026" # unicode ellipsis for the end of shortened message
+ prompt = "(more in eventlog)"
+
+ msg_lines = msg_text.split("\n")
+ first_line = msg_lines[0]
+ if len(msg_lines) > 1:
+ # First line of messages with a few lines must end with prompt.
+ line_length = len(first_line) + len(prompt)
+ else:
+ line_length = len(first_line)
+
+ if line_length > max_width:
+ shortening_index = max(0, max_width - len(prompt) - len(msg_end))
+ first_line = first_line[:shortening_index] + msg_end
+ else:
+ if len(msg_lines) == 1:
+ prompt = ""
+
+ return [(disp_attr, first_line), ("warn", prompt)]
+
def sig_prompt(self, sender, prompt, text, callback, args=()):
signals.focus.send(self, section="footer")
self._w = urwid.Edit(self.prep_prompt(prompt), text or "")
@@ -160,9 +191,7 @@ class StatusBar(urwid.WidgetWrap):
r.append(("heading_key", "H"))
r.append("eaders]")
if len(self.master.options.replacements):
- r.append("[")
- r.append(("heading_key", "R"))
- r.append("eplacing]")
+ r.append("[%d replacements]" % len(self.master.options.replacements))
if creplay.count():
r.append("[")
r.append(("heading_key", "cplayback"))
@@ -197,10 +226,8 @@ class StatusBar(urwid.WidgetWrap):
r.append("[")
r.append(("heading_key", "u"))
r.append(":%s]" % self.master.options.stickyauth)
- if self.master.options.console_default_contentview != "auto":
- r.append("[")
- r.append(("heading_key", "M"))
- r.append(":%s]" % self.master.options.console_default_contentview)
+ if self.master.options.console_default_contentview != 'auto':
+ r.append("[contentview:%s]" % (self.master.options.console_default_contentview))
if self.master.options.has_changed("view_order"):
r.append("[")
r.append(("heading_key", "o"))
diff --git a/mitmproxy/tools/console/window.py b/mitmproxy/tools/console/window.py
index f2b6d3f4..7669299c 100644
--- a/mitmproxy/tools/console/window.py
+++ b/mitmproxy/tools/console/window.py
@@ -294,7 +294,7 @@ class Window(urwid.Frame):
if not k:
if args[1] == "mouse drag":
signals.status_message.send(
- message = "Hold down fn, shift, alt or ctrl to select text or use the --no-mouse parameter.",
+ message = "Hold down fn, shift, alt or ctrl to select text or use the --set console_mouse=false parameter.",
expire = 1
)
elif args[1] == "mouse press" and args[2] == 4:
diff --git a/mitmproxy/tools/main.py b/mitmproxy/tools/main.py
index 330060f7..53c236bb 100644
--- a/mitmproxy/tools/main.py
+++ b/mitmproxy/tools/main.py
@@ -1,12 +1,13 @@
from __future__ import print_function # this is here for the version check to work on Python 2.
+import asyncio
import sys
-if sys.version_info < (3, 5):
+if sys.version_info < (3, 6):
# This must be before any mitmproxy imports, as they already break!
# Keep all other imports below with the 'noqa' magic comment.
print("#" * 49, file=sys.stderr)
- print("# mitmproxy only supports Python 3.5 and above! #", file=sys.stderr)
+ print("# mitmproxy requires Python 3.6 or higher! #", file=sys.stderr)
print("#" * 49, file=sys.stderr)
import argparse # noqa
@@ -117,8 +118,10 @@ def run(
def cleankill(*args, **kwargs):
master.shutdown()
-
signal.signal(signal.SIGTERM, cleankill)
+ loop = asyncio.get_event_loop()
+ for signame in ('SIGINT', 'SIGTERM'):
+ loop.add_signal_handler(getattr(signal, signame), master.shutdown)
master.run()
except exceptions.OptionsError as e:
print("%s: %s" % (sys.argv[0], e), file=sys.stderr)
diff --git a/mitmproxy/tools/web/master.py b/mitmproxy/tools/web/master.py
index 4c597f0e..b7eddcce 100644
--- a/mitmproxy/tools/web/master.py
+++ b/mitmproxy/tools/web/master.py
@@ -2,6 +2,8 @@ import webbrowser
import tornado.httpserver
import tornado.ioloop
+from tornado.platform.asyncio import AsyncIOMainLoop
+
from mitmproxy import addons
from mitmproxy import log
from mitmproxy import master
@@ -102,6 +104,7 @@ class WebMaster(master.Master):
)
def run(self): # pragma: no cover
+ AsyncIOMainLoop().install()
iol = tornado.ioloop.IOLoop.instance()
@@ -109,7 +112,6 @@ class WebMaster(master.Master):
http_server.listen(self.options.web_port, self.options.web_iface)
iol.add_callback(self.start)
- tornado.ioloop.PeriodicCallback(lambda: self.tick(timeout=0), 5).start()
web_url = "http://{}:{}/".format(self.options.web_iface, self.options.web_port)
self.add_log(
diff --git a/mitmproxy/tools/web/static/app.js b/mitmproxy/tools/web/static/app.js
index ace3106d..ac3be38c 100644
--- a/mitmproxy/tools/web/static/app.js
+++ b/mitmproxy/tools/web/static/app.js
@@ -86,7 +86,7 @@
"use strict";function _interopRequireWildcard(e){if(e&&e.__esModule)return e;var t={};if(null!=e)for(var r in e)Object.prototype.hasOwnProperty.call(e,r)&&(t[r]=e[r]);return t.default=e,t}function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}function FileMenu(e){var t=e.clearFlows,r=e.loadFlows,a=e.saveFlows,l=e.openModal;return _react2.default.createElement(_Dropdown2.default,{className:"pull-left",btnClass:"special",text:"mitmproxy"},_react2.default.createElement("a",{href:"#",onClick:function(e){return FileMenu.onNewClick(e,t)}},_react2.default.createElement("i",{className:"fa fa-fw fa-file"})," New"),_react2.default.createElement(_FileChooser2.default,{icon:"fa-folder-open",text:" Open...",onOpenFile:function(e){return r(e)}}),_react2.default.createElement("a",{href:"#",onClick:function(e){e.preventDefault(),a()}},_react2.default.createElement("i",{className:"fa fa-fw fa-floppy-o"})," Save..."),_react2.default.createElement(_HideInStatic2.default,null,_react2.default.createElement("a",{href:"#",onClick:function(e){e.preventDefault(),l()}},_react2.default.createElement("i",{className:"fa fa-fw fa-cog"})," Options"),_react2.default.createElement(_Dropdown.Divider,null),_react2.default.createElement("a",{href:"http://mitm.it/",target:"_blank"},_react2.default.createElement("i",{className:"fa fa-fw fa-external-link"})," Install Certificates...")))}Object.defineProperty(exports,"__esModule",{value:!0}),exports.FileMenu=FileMenu;var _react=require("react"),_react2=_interopRequireDefault(_react),_propTypes=require("prop-types"),_propTypes2=_interopRequireDefault(_propTypes),_reactRedux=require("react-redux"),_FileChooser=require("../common/FileChooser"),_FileChooser2=_interopRequireDefault(_FileChooser),_Dropdown=require("../common/Dropdown"),_Dropdown2=_interopRequireDefault(_Dropdown),_flows=require("../../ducks/flows"),flowsActions=_interopRequireWildcard(_flows),_modal=require("../../ducks/ui/modal"),modalActions=_interopRequireWildcard(_modal),_HideInStatic=require("../common/HideInStatic"),_HideInStatic2=_interopRequireDefault(_HideInStatic);FileMenu.propTypes={clearFlows:_propTypes2.default.func.isRequired,loadFlows:_propTypes2.default.func.isRequired,saveFlows:_propTypes2.default.func.isRequired,openModal:_propTypes2.default.func.isRequired},FileMenu.onNewClick=function(e,t){e.preventDefault(),confirm("Delete all flows?")&&t()},exports.default=(0,_reactRedux.connect)(null,{clearFlows:flowsActions.clear,loadFlows:flowsActions.upload,saveFlows:flowsActions.download,openModal:function(){return modalActions.setActiveModal("OptionModal")}})(FileMenu);
},{"../../ducks/flows":57,"../../ducks/ui/modal":65,"../common/Dropdown":48,"../common/FileChooser":49,"../common/HideInStatic":50,"prop-types":"prop-types","react":"react","react-redux":"react-redux"}],30:[function(require,module,exports){
-"use strict";function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}function _classCallCheck(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function _possibleConstructorReturn(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function _inherits(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}Object.defineProperty(exports,"__esModule",{value:!0});var _createClass=function(){function e(e,t){for(var r=0;r<t.length;r++){var n=t[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}return function(t,r,n){return r&&e(t.prototype,r),n&&e(t,n),t}}(),_react=require("react"),_react2=_interopRequireDefault(_react),_utils=require("../../utils"),FilterDocs=function(e){function t(e,r){_classCallCheck(this,t);var n=_possibleConstructorReturn(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e,r));return n.state={doc:t.doc},n}return _inherits(t,e),_createClass(t,[{key:"componentWillMount",value:function(){var e=this;t.xhr||(t.xhr=(0,_utils.fetchApi)("/filter-help").then(function(e){return e.json()}),t.xhr.catch(function(){t.xhr=null})),this.state.doc||t.xhr.then(function(r){t.doc=r,e.setState({doc:r})})}},{key:"render",value:function(){var e=this,t=this.state.doc;return t?_react2.default.createElement("table",{className:"table table-condensed"},_react2.default.createElement("tbody",null,t.commands.map(function(t){return _react2.default.createElement("tr",{key:t[1],onClick:function(r){return e.props.selectHandler(t[0].split(" ")[0]+" ")}},_react2.default.createElement("td",null,t[0].replace(" "," ")),_react2.default.createElement("td",null,t[1]))}),_react2.default.createElement("tr",{key:"docs-link"},_react2.default.createElement("td",{colSpan:"2"},_react2.default.createElement("a",{href:"http://docs.mitmproxy.org/en/stable/features/filters.html",target:"_blank"},_react2.default.createElement("i",{className:"fa fa-external-link"}),"  mitmproxy docs"))))):_react2.default.createElement("i",{className:"fa fa-spinner fa-spin"})}}]),t}(_react.Component);FilterDocs.xhr=null,FilterDocs.doc=null,exports.default=FilterDocs;
+"use strict";function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}function _classCallCheck(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function _possibleConstructorReturn(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function _inherits(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}Object.defineProperty(exports,"__esModule",{value:!0});var _createClass=function(){function e(e,t){for(var r=0;r<t.length;r++){var n=t[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}return function(t,r,n){return r&&e(t.prototype,r),n&&e(t,n),t}}(),_react=require("react"),_react2=_interopRequireDefault(_react),_utils=require("../../utils"),FilterDocs=function(e){function t(e,r){_classCallCheck(this,t);var n=_possibleConstructorReturn(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e,r));return n.state={doc:t.doc},n}return _inherits(t,e),_createClass(t,[{key:"componentWillMount",value:function(){var e=this;t.xhr||(t.xhr=(0,_utils.fetchApi)("/filter-help").then(function(e){return e.json()}),t.xhr.catch(function(){t.xhr=null})),this.state.doc||t.xhr.then(function(r){t.doc=r,e.setState({doc:r})})}},{key:"render",value:function(){var e=this,t=this.state.doc;return t?_react2.default.createElement("table",{className:"table table-condensed"},_react2.default.createElement("tbody",null,t.commands.map(function(t){return _react2.default.createElement("tr",{key:t[1],onClick:function(r){return e.props.selectHandler(t[0].split(" ")[0]+" ")}},_react2.default.createElement("td",null,t[0].replace(" "," ")),_react2.default.createElement("td",null,t[1]))}),_react2.default.createElement("tr",{key:"docs-link"},_react2.default.createElement("td",{colSpan:"2"},_react2.default.createElement("a",{href:"https://mitmproxy.org/docs/latest/concepts-filters/",target:"_blank"},_react2.default.createElement("i",{className:"fa fa-external-link"}),"  mitmproxy docs"))))):_react2.default.createElement("i",{className:"fa fa-spinner fa-spin"})}}]),t}(_react.Component);FilterDocs.xhr=null,FilterDocs.doc=null,exports.default=FilterDocs;
},{"../../utils":71,"react":"react"}],31:[function(require,module,exports){
"use strict";function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}function _classCallCheck(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function _possibleConstructorReturn(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function _inherits(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}Object.defineProperty(exports,"__esModule",{value:!0});var _createClass=function(){function e(e,t){for(var r=0;r<t.length;r++){var o=t[r];o.enumerable=o.enumerable||!1,o.configurable=!0,"value"in o&&(o.writable=!0),Object.defineProperty(e,o.key,o)}}return function(t,r,o){return r&&e(t.prototype,r),o&&e(t,o),t}}(),_react=require("react"),_react2=_interopRequireDefault(_react),_propTypes=require("prop-types"),_propTypes2=_interopRequireDefault(_propTypes),_reactDom=require("react-dom"),_reactDom2=_interopRequireDefault(_reactDom),_classnames=require("classnames"),_classnames2=_interopRequireDefault(_classnames),_utils=require("../../utils.js"),_filt=require("../../filt/filt"),_filt2=_interopRequireDefault(_filt),_FilterDocs=require("./FilterDocs"),_FilterDocs2=_interopRequireDefault(_FilterDocs),FilterInput=function(e){function t(e,r){_classCallCheck(this,t);var o=_possibleConstructorReturn(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e,r));return o.state={value:o.props.value,focus:!1,mousefocus:!1},o.onChange=o.onChange.bind(o),o.onFocus=o.onFocus.bind(o),o.onBlur=o.onBlur.bind(o),o.onKeyDown=o.onKeyDown.bind(o),o.onMouseEnter=o.onMouseEnter.bind(o),o.onMouseLeave=o.onMouseLeave.bind(o),o.selectFilter=o.selectFilter.bind(o),o}return _inherits(t,e),_createClass(t,[{key:"componentWillReceiveProps",value:function(e){this.setState({value:e.value})}},{key:"isValid",value:function(e){try{var t=null==e?this.state.value:e;return t&&_filt2.default.parse(t),!0}catch(e){return!1}}},{key:"getDesc",value:function(){if(!this.state.value)return _react2.default.createElement(_FilterDocs2.default,{selectHandler:this.selectFilter});try{return _filt2.default.parse(this.state.value).desc}catch(e){return""+e}}},{key:"onChange",value:function(e){var t=e.target.value;this.setState({value:t}),this.isValid(t)&&this.props.onChange(t)}},{key:"onFocus",value:function(){this.setState({focus:!0})}},{key:"onBlur",value:function(){this.setState({focus:!1})}},{key:"onMouseEnter",value:function(){this.setState({mousefocus:!0})}},{key:"onMouseLeave",value:function(){this.setState({mousefocus:!1})}},{key:"onKeyDown",value:function(e){e.keyCode!==_utils.Key.ESC&&e.keyCode!==_utils.Key.ENTER||(this.blur(),this.setState({mousefocus:!1})),e.stopPropagation()}},{key:"selectFilter",value:function(e){this.setState({value:e}),_reactDom2.default.findDOMNode(this.refs.input).focus()}},{key:"blur",value:function(){_reactDom2.default.findDOMNode(this.refs.input).blur()}},{key:"select",value:function(){_reactDom2.default.findDOMNode(this.refs.input).select()}},{key:"render",value:function(){var e=this.props,t=e.type,r=e.color,o=e.placeholder,n=this.state,a=n.value,s=n.focus,u=n.mousefocus;return _react2.default.createElement("div",{className:(0,_classnames2.default)("filter-input input-group",{"has-error":!this.isValid()})},_react2.default.createElement("span",{className:"input-group-addon"},_react2.default.createElement("i",{className:"fa fa-fw fa-"+t,style:{color:r}})),_react2.default.createElement("input",{type:"text",ref:"input",placeholder:o,className:"form-control",value:a,onChange:this.onChange,onFocus:this.onFocus,onBlur:this.onBlur,onKeyDown:this.onKeyDown}),(s||u)&&_react2.default.createElement("div",{className:"popover bottom",onMouseEnter:this.onMouseEnter,onMouseLeave:this.onMouseLeave},_react2.default.createElement("div",{className:"arrow"}),_react2.default.createElement("div",{className:"popover-content"},this.getDesc())))}}]),t}(_react.Component);exports.default=FilterInput;
@@ -137,7 +137,7 @@
"use strict";function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}function Button(e){var t=e.onClick,r=e.children,a=e.icon,s=e.disabled,l=e.className,i=e.title;return _react2.default.createElement("div",{className:(0,_classnames2.default)(l,"btn btn-default"),onClick:!s&&t,disabled:s,title:i},a&&_react2.default.createElement("i",{className:"fa fa-fw "+a}),r)}Object.defineProperty(exports,"__esModule",{value:!0}),exports.default=Button;var _react=require("react"),_react2=_interopRequireDefault(_react),_propTypes=require("prop-types"),_propTypes2=_interopRequireDefault(_propTypes),_classnames=require("classnames"),_classnames2=_interopRequireDefault(_classnames);Button.propTypes={onClick:_propTypes2.default.func.isRequired,children:_propTypes2.default.node.isRequired,icon:_propTypes2.default.string,title:_propTypes2.default.string};
},{"classnames":"classnames","prop-types":"prop-types","react":"react"}],47:[function(require,module,exports){
-"use strict";function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}function DocsLink(e){var r=e.children,t=e.resource,a="http://docs.mitmproxy.org/en/stable/"+t;return _react2.default.createElement("a",{target:"_blank",href:a},r||_react2.default.createElement("i",{className:"fa fa-question-circle"}))}Object.defineProperty(exports,"__esModule",{value:!0}),exports.default=DocsLink;var _react=require("react"),_react2=_interopRequireDefault(_react),_propTypes=require("prop-types"),_propTypes2=_interopRequireDefault(_propTypes);DocsLink.propTypes={resource:_propTypes2.default.string.isRequired};
+"use strict";function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}function DocsLink(e){var r=e.children,t=e.resource,a="https://mitmproxy.org/docs/latest"+t;return _react2.default.createElement("a",{target:"_blank",href:a},r||_react2.default.createElement("i",{className:"fa fa-question-circle"}))}Object.defineProperty(exports,"__esModule",{value:!0}),exports.default=DocsLink;var _react=require("react"),_react2=_interopRequireDefault(_react),_propTypes=require("prop-types"),_propTypes2=_interopRequireDefault(_propTypes);DocsLink.propTypes={resource:_propTypes2.default.string.isRequired};
},{"prop-types":"prop-types","react":"react"}],48:[function(require,module,exports){
"use strict";function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}function _classCallCheck(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}function _possibleConstructorReturn(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function _inherits(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}Object.defineProperty(exports,"__esModule",{value:!0}),exports.Divider=void 0;var _createClass=function(){function e(e,t){for(var r=0;r<t.length;r++){var n=t[r];n.enumerable=n.enumerable||!1,n.configurable=!0,"value"in n&&(n.writable=!0),Object.defineProperty(e,n.key,n)}}return function(t,r,n){return r&&e(t.prototype,r),n&&e(t,n),t}}(),_react=require("react"),_react2=_interopRequireDefault(_react),_propTypes=require("prop-types"),_propTypes2=_interopRequireDefault(_propTypes),_classnames=require("classnames"),_classnames2=_interopRequireDefault(_classnames),Divider=exports.Divider=function(){return _react2.default.createElement("hr",{className:"divider"})},Dropdown=function(e){function t(e,r){_classCallCheck(this,t);var n=_possibleConstructorReturn(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,e,r));return n.state={open:!1},n.close=n.close.bind(n),n.open=n.open.bind(n),n}return _inherits(t,e),_createClass(t,[{key:"close",value:function(){this.setState({open:!1}),document.removeEventListener("click",this.close)}},{key:"open",value:function(e){e.preventDefault(),this.state.open||(this.setState({open:!this.state.open}),document.addEventListener("click",this.close))}},{key:"render",value:function(){var e=this.props,t=e.dropup,r=e.className,n=e.btnClass,o=e.text,s=e.children;return _react2.default.createElement("div",{className:(0,_classnames2.default)(t?"dropup":"dropdown",r,{open:this.state.open})},_react2.default.createElement("a",{href:"#",className:n,onClick:this.open},o),_react2.default.createElement("ul",{className:"dropdown-menu",role:"menu"},s.map(function(e,t){return _react2.default.createElement("li",{key:t}," ",e," ")})))}}]),t}(_react.Component);Dropdown.propTypes={dropup:_propTypes2.default.bool,className:_propTypes2.default.string,btnClass:_propTypes2.default.string.isRequired},Dropdown.defaultProps={dropup:!1},exports.default=Dropdown;