diff options
-rw-r--r-- | mitmproxy/addons/cut.py | 25 | ||||
-rw-r--r-- | mitmproxy/tools/console/master.py | 1 | ||||
-rw-r--r-- | test/mitmproxy/addons/test_cut.py | 21 |
3 files changed, 47 insertions, 0 deletions
diff --git a/mitmproxy/addons/cut.py b/mitmproxy/addons/cut.py index 19d99bc4..a4a2107b 100644 --- a/mitmproxy/addons/cut.py +++ b/mitmproxy/addons/cut.py @@ -1,3 +1,4 @@ +import io import csv import typing from mitmproxy import command @@ -7,6 +8,8 @@ from mitmproxy import ctx from mitmproxy import certs from mitmproxy.utils import strutils +import pyperclip + def headername(spec: str): if not (spec.startswith("header[") and spec.endswith("]")): @@ -124,3 +127,25 @@ class Cut: [strutils.always_str(c) or "" for c in r] # type: ignore ) ctx.log.alert("Saved %s cuts as CSV." % len(cuts)) + + @command.command("cut.clip") + def clip(self, cuts: command.Cuts) -> None: + """ + Send cuts to the system clipboard. + """ + fp = io.StringIO(newline="") + if len(cuts) == 1 and len(cuts[0]) == 1: + v = cuts[0][0] + if isinstance(v, bytes): + fp.write(strutils.always_str(v)) + else: + fp.write("utf8") + ctx.log.alert("Clipped single cut.") + else: + writer = csv.writer(fp) + for r in cuts: + writer.writerow( + [strutils.always_str(c) or "" for c in r] # type: ignore + ) + ctx.log.alert("Clipped %s cuts as CSV." % len(cuts)) + pyperclip.copy(fp.getvalue()) diff --git a/mitmproxy/tools/console/master.py b/mitmproxy/tools/console/master.py index b86be7e1..b9de2733 100644 --- a/mitmproxy/tools/console/master.py +++ b/mitmproxy/tools/console/master.py @@ -152,6 +152,7 @@ def default_keymap(km): km.add("A", "flow.resume @all", context="flowlist") km.add("a", "flow.resume @focus", context="flowlist") km.add("b", "console.command 'cut.save s.content|@focus '", context="flowlist") + km.add("C", "console.command 'cut.clip '", context="flowlist") km.add("d", "view.remove @focus", context="flowlist") km.add("D", "view.duplicate @focus", context="flowlist") km.add("e", "set console_eventlog=toggle", context="flowlist") diff --git a/test/mitmproxy/addons/test_cut.py b/test/mitmproxy/addons/test_cut.py index b4c0f66b..e028331f 100644 --- a/test/mitmproxy/addons/test_cut.py +++ b/test/mitmproxy/addons/test_cut.py @@ -7,6 +7,7 @@ from mitmproxy.test import taddons from mitmproxy.test import tflow from mitmproxy.test import tutils import pytest +from unittest import mock def test_extract(): @@ -101,6 +102,26 @@ def qr(f): return fp.read() +def test_cut_clip(): + v = view.View() + c = cut.Cut() + with taddons.context() as tctx: + tctx.master.addons.add(v, c) + v.add([tflow.tflow(resp=True)]) + + with mock.patch('pyperclip.copy') as pc: + tctx.command(c.clip, "q.method|@all") + assert pc.called + + with mock.patch('pyperclip.copy') as pc: + tctx.command(c.clip, "q.content|@all") + assert pc.called + + with mock.patch('pyperclip.copy') as pc: + tctx.command(c.clip, "q.method,q.content|@all") + assert pc.called + + def test_cut_file(tmpdir): f = str(tmpdir.join("path")) v = view.View() |