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() | 
