aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAldo Cortesi <aldo@corte.si>2017-04-30 14:42:37 +1200
committerAldo Cortesi <aldo@corte.si>2017-04-30 14:42:37 +1200
commitbefbe88d96865bb69134af2c7019d66e3a7a09fa (patch)
tree4d72b6e0b5032114a4254e1939946507803bd9a2
parented62bbad1d7b0e7f3f948e2cc1503687edafc811 (diff)
downloadmitmproxy-befbe88d96865bb69134af2c7019d66e3a7a09fa.tar.gz
mitmproxy-befbe88d96865bb69134af2c7019d66e3a7a09fa.tar.bz2
mitmproxy-befbe88d96865bb69134af2c7019d66e3a7a09fa.zip
commands: cut.clip copies cuts to system clipboard
-rw-r--r--mitmproxy/addons/cut.py25
-rw-r--r--mitmproxy/tools/console/master.py1
-rw-r--r--test/mitmproxy/addons/test_cut.py21
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()