aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--mitmproxy/console/help.py3
-rw-r--r--mitmproxy/console/master.py10
-rw-r--r--mitmproxy/console/window.py52
-rw-r--r--mitmproxy/web/static/images/favicon.icobin0 -> 365133 bytes
-rw-r--r--mitmproxy/web/templates/index.html3
-rw-r--r--release/setup.py2
-rw-r--r--setup.py8
-rw-r--r--tox.ini2
-rw-r--r--web/package.json1
-rw-r--r--web/src/images/favicon.icobin0 -> 365133 bytes
-rw-r--r--web/src/js/__tests__/ducks/flowViewSpec.js (renamed from web/src/js/__tests__/ducks/flowView.js)0
-rw-r--r--web/src/js/__tests__/ducks/flowsSpec.js (renamed from web/src/js/__tests__/ducks/flows.js)0
-rw-r--r--web/src/js/__tests__/ducks/ui/headerSpec.js (renamed from web/src/js/__tests__/ducks/ui.js)10
-rw-r--r--web/src/js/__tests__/ducks/utils/listSpec.js (renamed from web/src/js/__tests__/ducks/utils/list.js)0
-rw-r--r--web/src/js/__tests__/ducks/utils/viewSpec.js (renamed from web/src/js/__tests__/ducks/utils/view.js)6
-rwxr-xr-xweb/src/js/ducks/utils/view.js54
-rw-r--r--web/src/templates/index.html3
17 files changed, 103 insertions, 51 deletions
diff --git a/mitmproxy/console/help.py b/mitmproxy/console/help.py
index ff4a072f..8024dc31 100644
--- a/mitmproxy/console/help.py
+++ b/mitmproxy/console/help.py
@@ -49,12 +49,11 @@ class HelpView(urwid.ListBox):
text.append(urwid.Text([("head", "\n\nGlobal keys:\n")]))
keys = [
- ("c", "client replay of HTTP requests"),
("i", "set interception pattern"),
("o", "options"),
("q", "quit / return to previous page"),
("Q", "quit without confirm prompt"),
- ("S", "server replay of HTTP responses"),
+ ("R", "replay of HTTP requests/responses"),
]
text.extend(
common.format_keyvals(keys, key="key", val="text", indent=4)
diff --git a/mitmproxy/console/master.py b/mitmproxy/console/master.py
index 87c2cbf2..9a9addc5 100644
--- a/mitmproxy/console/master.py
+++ b/mitmproxy/console/master.py
@@ -13,6 +13,7 @@ import tempfile
import traceback
import weakref
+import six
import urwid
from typing import Optional # noqa
@@ -408,8 +409,13 @@ class ConsoleMaster(flow.FlowMaster):
def spawn_editor(self, data):
text = not isinstance(data, bytes)
fd, name = tempfile.mkstemp('', "mproxy", text=text)
- os.write(fd, data)
- os.close(fd)
+ if six.PY2:
+ os.close(fd)
+ with open(name, "w" if text else "wb") as f:
+ f.write(data)
+ else:
+ with open(fd, "w" if text else "wb") as f:
+ f.write(data)
# if no EDITOR is set, assume 'vi'
c = os.environ.get("EDITOR") or "vi"
cmd = shlex.split(c)
diff --git a/mitmproxy/console/window.py b/mitmproxy/console/window.py
index 25780daf..b24718be 100644
--- a/mitmproxy/console/window.py
+++ b/mitmproxy/console/window.py
@@ -38,15 +38,12 @@ class Window(urwid.Frame):
return False
return True
- def keypress(self, size, k):
- k = super(self.__class__, self).keypress(size, k)
- if k == "?":
- self.master.view_help(self.helpctx)
- elif k == "c":
+ def handle_replay(self, k):
+ if k == "c":
if not self.master.client_playback:
signals.status_prompt_path.send(
self,
- prompt = "Client replay",
+ prompt = "Client replay path",
callback = self.master.client_playback_path
)
else:
@@ -59,20 +56,7 @@ class Window(urwid.Frame):
),
callback = self.master.stop_client_playback_prompt,
)
- elif k == "i":
- signals.status_prompt.send(
- self,
- prompt = "Intercept filter",
- text = self.master.state.intercept_txt,
- callback = self.master.set_intercept
- )
- elif k == "o":
- self.master.view_options()
- elif k == "Q":
- raise urwid.ExitMainLoop
- elif k == "q":
- signals.pop_view_state.send(self)
- elif k == "S":
+ elif k == "s":
if not self.master.server_playback:
signals.status_prompt_path.send(
self,
@@ -89,5 +73,33 @@ class Window(urwid.Frame):
),
callback = self.master.stop_server_playback_prompt,
)
+
+ def keypress(self, size, k):
+ k = super(self.__class__, self).keypress(size, k)
+ if k == "?":
+ self.master.view_help(self.helpctx)
+ elif k == "i":
+ signals.status_prompt.send(
+ self,
+ prompt = "Intercept filter",
+ text = self.master.state.intercept_txt,
+ callback = self.master.set_intercept
+ )
+ elif k == "o":
+ self.master.view_options()
+ elif k == "Q":
+ raise urwid.ExitMainLoop
+ elif k == "q":
+ signals.pop_view_state.send(self)
+ elif k == "R":
+ signals.status_prompt_onekey.send(
+ self,
+ prompt = "Replay",
+ keys = (
+ ("client", "c"),
+ ("server", "s"),
+ ),
+ callback = self.handle_replay,
+ )
else:
return k
diff --git a/mitmproxy/web/static/images/favicon.ico b/mitmproxy/web/static/images/favicon.ico
new file mode 100644
index 00000000..bfd2fde7
--- /dev/null
+++ b/mitmproxy/web/static/images/favicon.ico
Binary files differ
diff --git a/mitmproxy/web/templates/index.html b/mitmproxy/web/templates/index.html
index 165d7d3d..db9d2ecb 100644
--- a/mitmproxy/web/templates/index.html
+++ b/mitmproxy/web/templates/index.html
@@ -6,10 +6,11 @@
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="/static/vendor.css"/>
<link rel="stylesheet" href="/static/app.css"/>
+ <link rel="icon" href="/static/images/favicon.ico" type="image/x-icon"/>
<script src="/static/vendor.js"></script>
<script src="/static/app.js"></script>
</head>
<body>
<div id="mitmproxy"></div>
</body>
-</html> \ No newline at end of file
+</html>
diff --git a/release/setup.py b/release/setup.py
index 601654e5..b8eb6eec 100644
--- a/release/setup.py
+++ b/release/setup.py
@@ -6,7 +6,7 @@ setup(
py_modules=["rtool"],
install_requires=[
"click>=6.2, <7.0",
- "twine>=1.6.5, <1.7",
+ "twine>=1.6.5, <1.8",
"virtualenv>=14.0.5, <15.1",
"wheel>=0.29.0, <0.30",
"six>=1.10.0, <1.11",
diff --git a/setup.py b/setup.py
index e0bd4545..23eb3b26 100644
--- a/setup.py
+++ b/setup.py
@@ -71,7 +71,7 @@ setup(
"h2>=2.4.0, <3",
"html2text>=2016.1.8, <=2016.5.29",
"hyperframe>=4.0.1, <5",
- "lxml>=3.5.0, <3.7",
+ "lxml>=3.5.0, <=3.6.0", # no wheels for 3.6.1 yet.
"Pillow>=3.2, <3.4",
"passlib>=1.6.5, <1.7",
"pyasn1>=0.1.9, <0.2",
@@ -80,7 +80,7 @@ setup(
"pyperclip>=1.5.22, <1.6",
"requests>=2.9.1, <2.11",
"six>=1.10, <1.11",
- "tornado>=4.3, <4.4",
+ "tornado>=4.3, <4.5",
"urwid>=1.3.1, <1.4",
"watchdog>=0.8.3, <0.9",
],
@@ -116,9 +116,9 @@ setup(
# "pyamf>=0.8.0, <0.9",
],
'examples': [
- "beautifulsoup4>=4.4.1, <4.5",
+ "beautifulsoup4>=4.4.1, <4.6",
"harparser>=0.2, <0.3",
- "pytz>=2015.07.0, <=2016.4",
+ "pytz>=2015.07.0, <=2016.6.1",
]
}
)
diff --git a/tox.ini b/tox.ini
index 9da23a2e..ff0e41c2 100644
--- a/tox.ini
+++ b/tox.ini
@@ -17,5 +17,5 @@ changedir = docs
commands = sphinx-build -W -b html -d {envtmpdir}/doctrees . {envtmpdir}/html
[testenv:lint]
-deps = flake8>=2.6.2, <3
+deps = flake8>=2.6.2, <3.1
commands = flake8 --jobs 8 --count mitmproxy netlib pathod examples test
diff --git a/web/package.json b/web/package.json
index 302803f2..fb2c8c30 100644
--- a/web/package.json
+++ b/web/package.json
@@ -7,6 +7,7 @@
"start": "gulp"
},
"jest": {
+ "testRegex": "__tests__/.*\\Spec.js$",
"testPathDirs": [
"<rootDir>/src/js"
],
diff --git a/web/src/images/favicon.ico b/web/src/images/favicon.ico
new file mode 100644
index 00000000..bfd2fde7
--- /dev/null
+++ b/web/src/images/favicon.ico
Binary files differ
diff --git a/web/src/js/__tests__/ducks/flowView.js b/web/src/js/__tests__/ducks/flowViewSpec.js
index d5d9a6d9..d5d9a6d9 100644
--- a/web/src/js/__tests__/ducks/flowView.js
+++ b/web/src/js/__tests__/ducks/flowViewSpec.js
diff --git a/web/src/js/__tests__/ducks/flows.js b/web/src/js/__tests__/ducks/flowsSpec.js
index 2b261cb1..2b261cb1 100644
--- a/web/src/js/__tests__/ducks/flows.js
+++ b/web/src/js/__tests__/ducks/flowsSpec.js
diff --git a/web/src/js/__tests__/ducks/ui.js b/web/src/js/__tests__/ducks/ui/headerSpec.js
index d3242815..8968e636 100644
--- a/web/src/js/__tests__/ducks/ui.js
+++ b/web/src/js/__tests__/ducks/ui/headerSpec.js
@@ -1,10 +1,10 @@
-jest.unmock('../../ducks/ui')
-jest.unmock('../../ducks/flows')
+jest.unmock('../../../ducks/ui/header')
+jest.unmock('../../../ducks/flows')
-import reducer, { setActiveMenu } from '../../ducks/ui'
-import * as flowActions from '../../ducks/flows'
+import reducer, { setActiveMenu } from '../../../ducks/ui/header'
+import * as flowActions from '../../../ducks/flows'
-describe('ui reducer', () => {
+describe('header reducer', () => {
it('should return the initial state', () => {
expect(reducer(undefined, {}).activeMenu).toEqual('Start')
})
diff --git a/web/src/js/__tests__/ducks/utils/list.js b/web/src/js/__tests__/ducks/utils/listSpec.js
index 72d162f2..72d162f2 100644
--- a/web/src/js/__tests__/ducks/utils/list.js
+++ b/web/src/js/__tests__/ducks/utils/listSpec.js
diff --git a/web/src/js/__tests__/ducks/utils/view.js b/web/src/js/__tests__/ducks/utils/viewSpec.js
index f0b147da..af3da173 100644
--- a/web/src/js/__tests__/ducks/utils/view.js
+++ b/web/src/js/__tests__/ducks/utils/viewSpec.js
@@ -66,11 +66,13 @@ describe('view reduce', () => {
it('should update item', () => {
const state = createState([
{ id: 1, val: 1 },
- { id: 2, val: 2 }
+ { id: 2, val: 2 },
+ { id: 3, val: 3 }
])
const result = createState([
{ id: 1, val: 1 },
- { id: 2, val: 3 }
+ { id: 2, val: 3 },
+ { id: 3, val: 3 }
])
expect(reduce(state, view.update({ id: 2, val: 3 }))).toEqual(result)
})
diff --git a/web/src/js/ducks/utils/view.js b/web/src/js/ducks/utils/view.js
index c00f00bd..6bf0a63e 100755
--- a/web/src/js/ducks/utils/view.js
+++ b/web/src/js/ducks/utils/view.js
@@ -54,21 +54,29 @@ export default function reduce(state = defaultState, action) {
}
case UPDATE:
- if (state.indexOf[action.item.id] == null) {
- return
+ let hasOldItem = state.indexOf[action.item.id] !== null && state.indexOf[action.item.id] !== undefined
+ let hasNewItem = action.filter(action.item)
+ if (!hasNewItem && !hasOldItem) {
+ return state
}
- const nextState = {
- ...state,
- ...sortedRemove(state, action.item.id),
+ if (hasNewItem && !hasOldItem) {
+ return {
+ ...state,
+ ...sortedInsert(state, action.item, action.sort)
+ }
}
- if (!action.filter(action.item)) {
- return nextState
+ if (!hasNewItem && hasOldItem) {
+ return {
+ ...state,
+ ...sortedRemove(state, action.item.id)
+ }
}
- return {
- ...nextState,
- ...sortedInsert(nextState, action.item, action.sort)
+ if (hasNewItem && hasOldItem) {
+ return {
+ ...state,
+ ...sortedUpdate(state, action.item, action.sort),
+ }
}
-
case RECEIVE:
{
const data = action.list.filter(action.filter).sort(action.sort)
@@ -110,7 +118,7 @@ export function receive(list, filter = defaultFilter, sort = defaultSort) {
function sortedInsert(state, item, sort) {
const index = sortedIndex(state.data, item, sort)
- const data = [...state.data]
+ const data = [ ...state.data ]
const indexOf = { ...state.indexOf }
data.splice(index, 0, item)
@@ -134,6 +142,28 @@ function sortedRemove(state, id) {
return { data, indexOf }
}
+function sortedUpdate(state, item, sort) {
+ let data = [ ...state.data ]
+ let indexOf = { ...state.indexOf }
+ let index = indexOf[item.id]
+ data[index] = item
+ while (index + 1 < data.length && sort(data[index], data[index + 1]) > 0) {
+ data[index] = data[index + 1]
+ data[index + 1] = item
+ indexOf[item.id] = index + 1
+ indexOf[data[index].id] = index
+ ++index
+ }
+ while (index > 0 && sort(data[index], data[index - 1]) < 0) {
+ data[index] = data[index - 1]
+ data[index - 1] = item
+ indexOf[item.id] = index - 1
+ indexOf[data[index].id] = index
+ --index
+ }
+ return { data, indexOf }
+}
+
function sortedIndex(list, item, sort) {
let low = 0
let high = list.length
diff --git a/web/src/templates/index.html b/web/src/templates/index.html
index 165d7d3d..db9d2ecb 100644
--- a/web/src/templates/index.html
+++ b/web/src/templates/index.html
@@ -6,10 +6,11 @@
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="/static/vendor.css"/>
<link rel="stylesheet" href="/static/app.css"/>
+ <link rel="icon" href="/static/images/favicon.ico" type="image/x-icon"/>
<script src="/static/vendor.js"></script>
<script src="/static/app.js"></script>
</head>
<body>
<div id="mitmproxy"></div>
</body>
-</html> \ No newline at end of file
+</html>