aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--docs/install.rst5
-rw-r--r--mitmproxy/addons/__init__.py28
-rw-r--r--mitmproxy/addons/check_alpn.py17
-rw-r--r--mitmproxy/addons/check_ca.py24
-rw-r--r--mitmproxy/addons/termlog.py4
-rw-r--r--mitmproxy/certs.py4
-rw-r--r--mitmproxy/test/tflow.py56
-rw-r--r--mitmproxy/tools/console/master.py12
-rw-r--r--mitmproxy/tools/dump.py18
-rw-r--r--test/mitmproxy/addons/test_check_alpn.py23
-rw-r--r--test/mitmproxy/addons/test_check_ca.py19
-rw-r--r--test/mitmproxy/addons/test_disable_h2c_upgrade.py17
-rw-r--r--test/mitmproxy/addons/test_dumper.py20
-rw-r--r--test/mitmproxy/test_tools_dump.py21
-rw-r--r--test/mitmproxy/test_web_master.py5
-rw-r--r--web/src/js/filt/filt.js971
-rw-r--r--web/src/js/filt/filt.peg58
17 files changed, 790 insertions, 512 deletions
diff --git a/docs/install.rst b/docs/install.rst
index bcf07023..9a2aca0a 100644
--- a/docs/install.rst
+++ b/docs/install.rst
@@ -20,7 +20,7 @@ You can use Homebrew to install everything:
brew install mitmproxy
-Or you can download the pre-built binary packages from `mitmproxy.org`_.
+Or you can download the pre-built binary packages from our `releases`_.
.. _install-windows:
@@ -44,7 +44,7 @@ Installation on Linux
---------------------
The recommended way to run mitmproxy on Linux is to use the pre-built binaries
-provided at `mitmproxy.org`_.
+provided at `releases`_.
Our pre-built binaries provide you with the latest version of mitmproxy, a
self-contained Python 3.5 environment and a recent version of OpenSSL that
@@ -144,6 +144,7 @@ by running: ``mitmproxy --version``
.. _Hacking: https://github.com/mitmproxy/mitmproxy/blob/master/README.rst#hacking
+.. _releases: https://github.com/mitmproxy/mitmproxy/releases
.. _mitmproxy.org: https://mitmproxy.org/
.. _`Python website`: https://www.python.org/downloads/windows/
.. _pip: https://pip.pypa.io/en/latest/installing.html
diff --git a/mitmproxy/addons/__init__.py b/mitmproxy/addons/__init__.py
index 8a2f2974..2e1d1c67 100644
--- a/mitmproxy/addons/__init__.py
+++ b/mitmproxy/addons/__init__.py
@@ -1,35 +1,39 @@
from mitmproxy.addons import anticache
from mitmproxy.addons import anticomp
+from mitmproxy.addons import check_alpn
+from mitmproxy.addons import check_ca
from mitmproxy.addons import clientplayback
-from mitmproxy.addons import streamfile
+from mitmproxy.addons import disable_h2c_upgrade
from mitmproxy.addons import onboarding
from mitmproxy.addons import proxyauth
from mitmproxy.addons import replace
from mitmproxy.addons import script
-from mitmproxy.addons import setheaders
from mitmproxy.addons import serverplayback
+from mitmproxy.addons import setheaders
from mitmproxy.addons import stickyauth
from mitmproxy.addons import stickycookie
from mitmproxy.addons import streambodies
+from mitmproxy.addons import streamfile
from mitmproxy.addons import upstream_auth
-from mitmproxy.addons import disable_h2c_upgrade
def default_addons():
return [
- onboarding.Onboarding(),
- proxyauth.ProxyAuth(),
anticache.AntiCache(),
anticomp.AntiComp(),
+ check_alpn.CheckALPN(),
+ check_ca.CheckCA(),
+ clientplayback.ClientPlayback(),
+ disable_h2c_upgrade.DisableH2CleartextUpgrade(),
+ onboarding.Onboarding(),
+ proxyauth.ProxyAuth(),
+ replace.Replace(),
+ script.ScriptLoader(),
+ serverplayback.ServerPlayback(),
+ setheaders.SetHeaders(),
stickyauth.StickyAuth(),
stickycookie.StickyCookie(),
- script.ScriptLoader(),
- streamfile.StreamFile(),
streambodies.StreamBodies(),
- replace.Replace(),
- setheaders.SetHeaders(),
- serverplayback.ServerPlayback(),
- clientplayback.ClientPlayback(),
+ streamfile.StreamFile(),
upstream_auth.UpstreamAuth(),
- disable_h2c_upgrade.DisableH2CleartextUpgrade(),
]
diff --git a/mitmproxy/addons/check_alpn.py b/mitmproxy/addons/check_alpn.py
new file mode 100644
index 00000000..c288d788
--- /dev/null
+++ b/mitmproxy/addons/check_alpn.py
@@ -0,0 +1,17 @@
+import mitmproxy
+from mitmproxy.net import tcp
+
+
+class CheckALPN:
+ def __init__(self):
+ self.failed = False
+
+ def configure(self, options, updated):
+ self.failed = mitmproxy.ctx.master.options.http2 and not tcp.HAS_ALPN
+ if self.failed:
+ mitmproxy.ctx.master.add_log(
+ "HTTP/2 is disabled because ALPN support missing!\n"
+ "OpenSSL 1.0.2+ required to support HTTP/2 connections.\n"
+ "Use --no-http2 to silence this warning.",
+ "warn",
+ )
diff --git a/mitmproxy/addons/check_ca.py b/mitmproxy/addons/check_ca.py
new file mode 100644
index 00000000..a83ab8e1
--- /dev/null
+++ b/mitmproxy/addons/check_ca.py
@@ -0,0 +1,24 @@
+import mitmproxy
+
+
+class CheckCA:
+ def __init__(self):
+ self.failed = False
+
+ def configure(self, options, updated):
+ has_ca = (
+ mitmproxy.ctx.master.server and
+ mitmproxy.ctx.master.server.config and
+ mitmproxy.ctx.master.server.config.certstore and
+ mitmproxy.ctx.master.server.config.certstore.default_ca
+ )
+ if has_ca:
+ self.failed = mitmproxy.ctx.master.server.config.certstore.default_ca.has_expired()
+ if self.failed:
+ mitmproxy.ctx.master.add_log(
+ "The mitmproxy certificate authority has expired!\n"
+ "Please delete all CA-related files in your ~/.mitmproxy folder.\n"
+ "The CA will be regenerated automatically after restarting mitmproxy.\n"
+ "Then make sure all your clients have the new CA installed.",
+ "warn",
+ )
diff --git a/mitmproxy/addons/termlog.py b/mitmproxy/addons/termlog.py
index b75f5f5a..f7739efe 100644
--- a/mitmproxy/addons/termlog.py
+++ b/mitmproxy/addons/termlog.py
@@ -5,9 +5,9 @@ from mitmproxy import log
class TermLog:
- def __init__(self, outfile=sys.stdout):
+ def __init__(self, outfile=None):
self.options = None
- self.outfile = outfile
+ self.outfile = outfile or sys.stdout
def configure(self, options, updated):
self.options = options
diff --git a/mitmproxy/certs.py b/mitmproxy/certs.py
index 4e4eb4d1..4b939c80 100644
--- a/mitmproxy/certs.py
+++ b/mitmproxy/certs.py
@@ -3,8 +3,8 @@ import ssl
import time
import datetime
import ipaddress
-
import sys
+
from pyasn1.type import univ, constraint, char, namedtype, tag
from pyasn1.codec.der.decoder import decode
from pyasn1.error import PyAsn1Error
@@ -13,8 +13,8 @@ import OpenSSL
from mitmproxy.types import serializable
# Default expiry must not be too long: https://github.com/mitmproxy/mitmproxy/issues/815
-
DEFAULT_EXP = 94608000 # = 24 * 60 * 60 * 365 * 3
+
# Generated with "openssl dhparam". It's too slow to generate this on startup.
DEFAULT_DHPARAM = b"""
-----BEGIN DH PARAMETERS-----
diff --git a/mitmproxy/test/tflow.py b/mitmproxy/test/tflow.py
index 959c9a2c..edf4d7a7 100644
--- a/mitmproxy/test/tflow.py
+++ b/mitmproxy/test/tflow.py
@@ -1,9 +1,11 @@
from mitmproxy.test import tutils
from mitmproxy import tcp
+from mitmproxy import websocket
from mitmproxy import controller
from mitmproxy import http
from mitmproxy import connections
from mitmproxy import flow
+from mitmproxy.net import http as net_http
def ttcpflow(client_conn=True, server_conn=True, messages=True, err=None):
@@ -26,6 +28,60 @@ def ttcpflow(client_conn=True, server_conn=True, messages=True, err=None):
return f
+def twebsocketflow(client_conn=True, server_conn=True, messages=True, err=None, handshake_flow=True):
+
+ if client_conn is True:
+ client_conn = tclient_conn()
+ if server_conn is True:
+ server_conn = tserver_conn()
+ if handshake_flow is True:
+ req = http.HTTPRequest(
+ "relative",
+ "GET",
+ "http",
+ "example.com",
+ "80",
+ "/ws",
+ "HTTP/1.1",
+ headers=net_http.Headers(
+ connection="upgrade",
+ upgrade="websocket",
+ sec_websocket_version="13",
+ sec_websocket_key="1234",
+ ),
+ content=b''
+ )
+ resp = http.HTTPResponse(
+ "HTTP/1.1",
+ 101,
+ reason=net_http.status_codes.RESPONSES.get(101),
+ headers=net_http.Headers(
+ connection='upgrade',
+ upgrade='websocket',
+ sec_websocket_accept=b'',
+ ),
+ content=b'',
+ )
+ handshake_flow = http.HTTPFlow(client_conn, server_conn)
+ handshake_flow.request = req
+ handshake_flow.response = resp
+
+ f = websocket.WebSocketFlow(client_conn, server_conn, handshake_flow)
+
+ if messages is True:
+ messages = [
+ websocket.WebSocketBinaryMessage(f, True, b"hello binary"),
+ websocket.WebSocketTextMessage(f, False, "hello text".encode()),
+ ]
+ if err is True:
+ err = terr()
+
+ f.messages = messages
+ f.error = err
+ f.reply = controller.DummyReply()
+ return f
+
+
def tflow(client_conn=True, server_conn=True, req=True, resp=None, err=None):
"""
@type client_conn: bool | None | mitmproxy.proxy.connection.ClientConnection
diff --git a/mitmproxy/tools/console/master.py b/mitmproxy/tools/console/master.py
index 8afdce2c..10f8cbf5 100644
--- a/mitmproxy/tools/console/master.py
+++ b/mitmproxy/tools/console/master.py
@@ -33,8 +33,6 @@ from mitmproxy.tools.console import statusbar
from mitmproxy.tools.console import window
from mitmproxy.utils import strutils
-from mitmproxy.net import tcp
-
EVENTLOG_SIZE = 10000
@@ -272,16 +270,6 @@ class ConsoleMaster(master.Master):
print("Could not load file: {}".format(ret), file=sys.stderr)
sys.exit(1)
- self.loop.set_alarm_in(0.01, self.ticker)
- if self.options.http2 and not tcp.HAS_ALPN: # pragma: no cover
- def http2err(*args, **kwargs):
- signals.status_message.send(
- message = "HTTP/2 disabled - OpenSSL 1.0.2+ required."
- " Use --no-http2 to silence this warning.",
- expire=5
- )
- self.loop.set_alarm_in(0.01, http2err)
-
self.loop.set_alarm_in(
0.0001,
lambda *args: self.view_flowlist()
diff --git a/mitmproxy/tools/dump.py b/mitmproxy/tools/dump.py
index 4e2844a1..e1e40fb0 100644
--- a/mitmproxy/tools/dump.py
+++ b/mitmproxy/tools/dump.py
@@ -6,7 +6,6 @@ from mitmproxy import addons
from mitmproxy import options
from mitmproxy import master
from mitmproxy.addons import dumper, termlog
-from mitmproxy.net import tcp
class DumpError(Exception):
@@ -30,7 +29,13 @@ class Options(options.Options):
class DumpMaster(master.Master):
- def __init__(self, options, server, with_termlog=True, with_dumper=True):
+ def __init__(
+ self,
+ options: Options,
+ server,
+ with_termlog=True,
+ with_dumper=True,
+ ) -> None:
master.Master.__init__(self, options, server)
self.has_errored = False
if with_termlog:
@@ -38,8 +43,6 @@ class DumpMaster(master.Master):
self.addons.add(*addons.default_addons())
if with_dumper:
self.addons.add(dumper.Dumper())
- # This line is just for type hinting
- self.options = self.options # type: Options
if not self.options.no_server:
self.add_log(
@@ -47,13 +50,6 @@ class DumpMaster(master.Master):
"info"
)
- if self.server and self.options.http2 and not tcp.HAS_ALPN: # pragma: no cover
- self.add_log(
- "ALPN support missing (OpenSSL 1.0.2+ required)!\n"
- "HTTP/2 is disabled. Use --no-http2 to silence this warning.",
- "error"
- )
-
if options.rfile:
try:
self.load_flows_file(options.rfile)
diff --git a/test/mitmproxy/addons/test_check_alpn.py b/test/mitmproxy/addons/test_check_alpn.py
new file mode 100644
index 00000000..2dc0c835
--- /dev/null
+++ b/test/mitmproxy/addons/test_check_alpn.py
@@ -0,0 +1,23 @@
+from mitmproxy.addons import check_alpn
+from mitmproxy.test import taddons
+from ...conftest import requires_alpn
+
+
+class TestCheckALPN:
+
+ @requires_alpn
+ def test_check_alpn(self):
+ msg = 'ALPN support missing'
+
+ with taddons.context() as tctx:
+ a = check_alpn.CheckALPN()
+ tctx.configure(a)
+ assert not any(msg in m for l, m in tctx.master.event_log)
+
+ def test_check_no_alpn(self, disable_alpn):
+ msg = 'ALPN support missing'
+
+ with taddons.context() as tctx:
+ a = check_alpn.CheckALPN()
+ tctx.configure(a)
+ assert any(msg in m for l, m in tctx.master.event_log)
diff --git a/test/mitmproxy/addons/test_check_ca.py b/test/mitmproxy/addons/test_check_ca.py
new file mode 100644
index 00000000..fc64621c
--- /dev/null
+++ b/test/mitmproxy/addons/test_check_ca.py
@@ -0,0 +1,19 @@
+import pytest
+from unittest import mock
+
+from mitmproxy.addons import check_ca
+from mitmproxy.test import taddons
+
+
+class TestCheckCA:
+
+ @pytest.mark.parametrize('expired', [False, True])
+ def test_check_ca(self, expired):
+ msg = 'The mitmproxy certificate authority has expired!'
+
+ with taddons.context() as tctx:
+ tctx.master.server = mock.MagicMock()
+ tctx.master.server.config.certstore.default_ca.has_expired = mock.MagicMock(return_value=expired)
+ a = check_ca.CheckCA()
+ tctx.configure(a)
+ assert any(msg in m for l, m in tctx.master.event_log) is expired
diff --git a/test/mitmproxy/addons/test_disable_h2c_upgrade.py b/test/mitmproxy/addons/test_disable_h2c_upgrade.py
new file mode 100644
index 00000000..6cab713d
--- /dev/null
+++ b/test/mitmproxy/addons/test_disable_h2c_upgrade.py
@@ -0,0 +1,17 @@
+from mitmproxy.addons import disable_h2c_upgrade
+from mitmproxy.test import tflow
+
+
+class TestTermLog:
+ def test_simple(self):
+ a = disable_h2c_upgrade.DisableH2CleartextUpgrade()
+
+ f = tflow.tflow()
+ f.request.headers['upgrade'] = 'h2c'
+ f.request.headers['connection'] = 'foo'
+ f.request.headers['http2-settings'] = 'bar'
+
+ a.request(f)
+ assert 'upgrade' not in f.request.headers
+ assert 'connection' not in f.request.headers
+ assert 'http2-settings' not in f.request.headers
diff --git a/test/mitmproxy/addons/test_dumper.py b/test/mitmproxy/addons/test_dumper.py
index 7ac17a7c..8fa8a22a 100644
--- a/test/mitmproxy/addons/test_dumper.py
+++ b/test/mitmproxy/addons/test_dumper.py
@@ -157,7 +157,7 @@ def test_tcp():
d = dumper.Dumper(sio)
with taddons.context(options=dump.Options()) as ctx:
ctx.configure(d, flow_detail=3, showhost=True)
- f = tflow.ttcpflow(client_conn=True, server_conn=True)
+ f = tflow.ttcpflow()
d.tcp_message(f)
assert "it's me" in sio.getvalue()
sio.truncate(0)
@@ -165,3 +165,21 @@ def test_tcp():
f = tflow.ttcpflow(client_conn=True, err=True)
d.tcp_error(f)
assert "Error in TCP" in sio.getvalue()
+
+
+def test_websocket():
+ sio = io.StringIO()
+ d = dumper.Dumper(sio)
+ with taddons.context(options=dump.Options()) as ctx:
+ ctx.configure(d, flow_detail=3, showhost=True)
+ f = tflow.twebsocketflow()
+ d.websocket_message(f)
+ assert "hello text" in sio.getvalue()
+ sio.truncate(0)
+
+ d.websocket_end(f)
+ assert "WebSocket connection closed by" in sio.getvalue()
+
+ f = tflow.twebsocketflow(client_conn=True, err=True)
+ d.websocket_error(f)
+ assert "Error in WebSocket" in sio.getvalue()
diff --git a/test/mitmproxy/test_tools_dump.py b/test/mitmproxy/test_tools_dump.py
index 2e64d2d2..505f514b 100644
--- a/test/mitmproxy/test_tools_dump.py
+++ b/test/mitmproxy/test_tools_dump.py
@@ -1,10 +1,13 @@
import os
+import pytest
+from unittest import mock
-from mitmproxy.tools import dump
from mitmproxy import proxy
-from mitmproxy.test import tutils
from mitmproxy import log
from mitmproxy import controller
+from mitmproxy.tools import dump
+
+from mitmproxy.test import tutils
from . import mastertest
@@ -37,3 +40,17 @@ class TestDumpMaster(mastertest.MasterTest):
ent.reply = controller.DummyReply()
m.log(ent)
assert m.has_errored
+
+ @pytest.mark.parametrize("termlog", [False, True])
+ def test_addons_termlog(self, termlog):
+ with mock.patch('sys.stdout'):
+ o = dump.Options()
+ m = dump.DumpMaster(o, proxy.DummyServer(), with_termlog=termlog)
+ assert (m.addons.get('termlog') is not None) == termlog
+
+ @pytest.mark.parametrize("dumper", [False, True])
+ def test_addons_dumper(self, dumper):
+ with mock.patch('sys.stdout'):
+ o = dump.Options()
+ m = dump.DumpMaster(o, proxy.DummyServer(), with_dumper=dumper)
+ assert (m.addons.get('dumper') is not None) == dumper
diff --git a/test/mitmproxy/test_web_master.py b/test/mitmproxy/test_web_master.py
index 08dce8f3..3591284d 100644
--- a/test/mitmproxy/test_web_master.py
+++ b/test/mitmproxy/test_web_master.py
@@ -1,13 +1,16 @@
from mitmproxy.tools.web import master
from mitmproxy import proxy
from mitmproxy import options
+from mitmproxy.proxy.config import ProxyConfig
+
from . import mastertest
class TestWebMaster(mastertest.MasterTest):
def mkmaster(self, **opts):
o = options.Options(**opts)
- return master.WebMaster(o, proxy.DummyServer(o))
+ c = ProxyConfig(o)
+ return master.WebMaster(o, proxy.DummyServer(c))
def test_basic(self):
m = self.mkmaster()
diff --git a/web/src/js/filt/filt.js b/web/src/js/filt/filt.js
index f2c5ded2..a15f5f9f 100644
--- a/web/src/js/filt/filt.js
+++ b/web/src/js/filt/filt.js
@@ -59,94 +59,100 @@ module.exports = (function() {
peg$c20 = ")",
peg$c21 = { type: "literal", value: ")", description: "\")\"" },
peg$c22 = function(expr) { return binding(expr); },
- peg$c23 = "~a",
- peg$c24 = { type: "literal", value: "~a", description: "\"~a\"" },
- peg$c25 = function() { return assetFilter; },
- peg$c26 = "~e",
- peg$c27 = { type: "literal", value: "~e", description: "\"~e\"" },
- peg$c28 = function() { return errorFilter; },
- peg$c29 = "~http",
- peg$c30 = { type: "literal", value: "~http", description: "\"~http\"" },
- peg$c31 = function() { return httpFilter; },
- peg$c32 = "~marked",
- peg$c33 = { type: "literal", value: "~marked", description: "\"~marked\"" },
- peg$c34 = function() { return markedFilter; },
- peg$c35 = "~q",
- peg$c36 = { type: "literal", value: "~q", description: "\"~q\"" },
- peg$c37 = function() { return noResponseFilter; },
- peg$c38 = "~s",
- peg$c39 = { type: "literal", value: "~s", description: "\"~s\"" },
- peg$c40 = function() { return responseFilter; },
- peg$c41 = "~tcp",
- peg$c42 = { type: "literal", value: "~tcp", description: "\"~tcp\"" },
- peg$c43 = function() { return tcpFilter; },
- peg$c44 = "true",
- peg$c45 = { type: "literal", value: "true", description: "\"true\"" },
- peg$c46 = function() { return trueFilter; },
- peg$c47 = "false",
- peg$c48 = { type: "literal", value: "false", description: "\"false\"" },
- peg$c49 = function() { return falseFilter; },
- peg$c50 = "~c",
- peg$c51 = { type: "literal", value: "~c", description: "\"~c\"" },
- peg$c52 = function(s) { return responseCode(s); },
- peg$c53 = "~d",
- peg$c54 = { type: "literal", value: "~d", description: "\"~d\"" },
- peg$c55 = function(s) { return domain(s); },
- peg$c56 = "~h",
- peg$c57 = { type: "literal", value: "~h", description: "\"~h\"" },
- peg$c58 = function(s) { return header(s); },
- peg$c59 = "~hq",
- peg$c60 = { type: "literal", value: "~hq", description: "\"~hq\"" },
- peg$c61 = function(s) { return requestHeader(s); },
- peg$c62 = "~hs",
- peg$c63 = { type: "literal", value: "~hs", description: "\"~hs\"" },
- peg$c64 = function(s) { return responseHeader(s); },
- peg$c65 = "~m",
- peg$c66 = { type: "literal", value: "~m", description: "\"~m\"" },
- peg$c67 = function(s) { return method(s); },
- peg$c68 = "~t",
- peg$c69 = { type: "literal", value: "~t", description: "\"~t\"" },
- peg$c70 = function(s) { return contentType(s); },
- peg$c71 = "~tq",
- peg$c72 = { type: "literal", value: "~tq", description: "\"~tq\"" },
- peg$c73 = function(s) { return requestContentType(s); },
- peg$c74 = "~ts",
- peg$c75 = { type: "literal", value: "~ts", description: "\"~ts\"" },
- peg$c76 = function(s) { return responseContentType(s); },
- peg$c77 = "~u",
- peg$c78 = { type: "literal", value: "~u", description: "\"~u\"" },
- peg$c79 = function(s) { return url(s); },
- peg$c80 = { type: "other", description: "integer" },
- peg$c81 = /^['"]/,
- peg$c82 = { type: "class", value: "['\"]", description: "['\"]" },
- peg$c83 = /^[0-9]/,
- peg$c84 = { type: "class", value: "[0-9]", description: "[0-9]" },
- peg$c85 = function(digits) { return parseInt(digits.join(""), 10); },
- peg$c86 = { type: "other", description: "string" },
- peg$c87 = "\"",
- peg$c88 = { type: "literal", value: "\"", description: "\"\\\"\"" },
- peg$c89 = function(chars) { return chars.join(""); },
- peg$c90 = "'",
- peg$c91 = { type: "literal", value: "'", description: "\"'\"" },
- peg$c92 = /^["\\]/,
- peg$c93 = { type: "class", value: "[\"\\\\]", description: "[\"\\\\]" },
- peg$c94 = { type: "any", description: "any character" },
- peg$c95 = function(char) { return char; },
- peg$c96 = "\\",
- peg$c97 = { type: "literal", value: "\\", description: "\"\\\\\"" },
- peg$c98 = /^['\\]/,
- peg$c99 = { type: "class", value: "['\\\\]", description: "['\\\\]" },
- peg$c100 = /^['"\\]/,
- peg$c101 = { type: "class", value: "['\"\\\\]", description: "['\"\\\\]" },
- peg$c102 = "n",
- peg$c103 = { type: "literal", value: "n", description: "\"n\"" },
- peg$c104 = function() { return "\n"; },
- peg$c105 = "r",
- peg$c106 = { type: "literal", value: "r", description: "\"r\"" },
- peg$c107 = function() { return "\r"; },
- peg$c108 = "t",
- peg$c109 = { type: "literal", value: "t", description: "\"t\"" },
- peg$c110 = function() { return "\t"; },
+ peg$c23 = "true",
+ peg$c24 = { type: "literal", value: "true", description: "\"true\"" },
+ peg$c25 = function() { return trueFilter; },
+ peg$c26 = "false",
+ peg$c27 = { type: "literal", value: "false", description: "\"false\"" },
+ peg$c28 = function() { return falseFilter; },
+ peg$c29 = "~a",
+ peg$c30 = { type: "literal", value: "~a", description: "\"~a\"" },
+ peg$c31 = function() { return assetFilter; },
+ peg$c32 = "~c",
+ peg$c33 = { type: "literal", value: "~c", description: "\"~c\"" },
+ peg$c34 = function(s) { return responseCode(s); },
+ peg$c35 = "~d",
+ peg$c36 = { type: "literal", value: "~d", description: "\"~d\"" },
+ peg$c37 = function(s) { return domain(s); },
+ peg$c38 = "~dst",
+ peg$c39 = { type: "literal", value: "~dst", description: "\"~dst\"" },
+ peg$c40 = function(s) { return destination(s); },
+ peg$c41 = "~e",
+ peg$c42 = { type: "literal", value: "~e", description: "\"~e\"" },
+ peg$c43 = function() { return errorFilter; },
+ peg$c44 = "~h",
+ peg$c45 = { type: "literal", value: "~h", description: "\"~h\"" },
+ peg$c46 = function(s) { return header(s); },
+ peg$c47 = "~hq",
+ peg$c48 = { type: "literal", value: "~hq", description: "\"~hq\"" },
+ peg$c49 = function(s) { return requestHeader(s); },
+ peg$c50 = "~hs",
+ peg$c51 = { type: "literal", value: "~hs", description: "\"~hs\"" },
+ peg$c52 = function(s) { return responseHeader(s); },
+ peg$c53 = "~http",
+ peg$c54 = { type: "literal", value: "~http", description: "\"~http\"" },
+ peg$c55 = function() { return httpFilter; },
+ peg$c56 = "~m",
+ peg$c57 = { type: "literal", value: "~m", description: "\"~m\"" },
+ peg$c58 = function(s) { return method(s); },
+ peg$c59 = "~marked",
+ peg$c60 = { type: "literal", value: "~marked", description: "\"~marked\"" },
+ peg$c61 = function() { return markedFilter; },
+ peg$c62 = "~q",
+ peg$c63 = { type: "literal", value: "~q", description: "\"~q\"" },
+ peg$c64 = function() { return noResponseFilter; },
+ peg$c65 = "~src",
+ peg$c66 = { type: "literal", value: "~src", description: "\"~src\"" },
+ peg$c67 = function(s) { return source(s); },
+ peg$c68 = "~s",
+ peg$c69 = { type: "literal", value: "~s", description: "\"~s\"" },
+ peg$c70 = function() { return responseFilter; },
+ peg$c71 = "~t",
+ peg$c72 = { type: "literal", value: "~t", description: "\"~t\"" },
+ peg$c73 = function(s) { return contentType(s); },
+ peg$c74 = "~tcp",
+ peg$c75 = { type: "literal", value: "~tcp", description: "\"~tcp\"" },
+ peg$c76 = function() { return tcpFilter; },
+ peg$c77 = "~tq",
+ peg$c78 = { type: "literal", value: "~tq", description: "\"~tq\"" },
+ peg$c79 = function(s) { return requestContentType(s); },
+ peg$c80 = "~ts",
+ peg$c81 = { type: "literal", value: "~ts", description: "\"~ts\"" },
+ peg$c82 = function(s) { return responseContentType(s); },
+ peg$c83 = "~u",
+ peg$c84 = { type: "literal", value: "~u", description: "\"~u\"" },
+ peg$c85 = function(s) { return url(s); },
+ peg$c86 = { type: "other", description: "integer" },
+ peg$c87 = /^['"]/,
+ peg$c88 = { type: "class", value: "['\"]", description: "['\"]" },
+ peg$c89 = /^[0-9]/,
+ peg$c90 = { type: "class", value: "[0-9]", description: "[0-9]" },
+ peg$c91 = function(digits) { return parseInt(digits.join(""), 10); },
+ peg$c92 = { type: "other", description: "string" },
+ peg$c93 = "\"",
+ peg$c94 = { type: "literal", value: "\"", description: "\"\\\"\"" },
+ peg$c95 = function(chars) { return chars.join(""); },
+ peg$c96 = "'",
+ peg$c97 = { type: "literal", value: "'", description: "\"'\"" },
+ peg$c98 = /^["\\]/,
+ peg$c99 = { type: "class", value: "[\"\\\\]", description: "[\"\\\\]" },
+ peg$c100 = { type: "any", description: "any character" },
+ peg$c101 = function(char) { return char; },
+ peg$c102 = "\\",
+ peg$c103 = { type: "literal", value: "\\", description: "\"\\\\\"" },
+ peg$c104 = /^['\\]/,
+ peg$c105 = { type: "class", value: "['\\\\]", description: "['\\\\]" },
+ peg$c106 = /^['"\\]/,
+ peg$c107 = { type: "class", value: "['\"\\\\]", description: "['\"\\\\]" },
+ peg$c108 = "n",
+ peg$c109 = { type: "literal", value: "n", description: "\"n\"" },
+ peg$c110 = function() { return "\n"; },
+ peg$c111 = "r",
+ peg$c112 = { type: "literal", value: "r", description: "\"r\"" },
+ peg$c113 = function() { return "\r"; },
+ peg$c114 = "t",
+ peg$c115 = { type: "literal", value: "t", description: "\"t\"" },
+ peg$c116 = function() { return "\t"; },
peg$currPos = 0,
peg$savedPos = 0,
@@ -655,288 +661,57 @@ module.exports = (function() {
}
function peg$parseExpr() {
- var s0;
-
- s0 = peg$parseNullaryExpr();
- if (s0 === peg$FAILED) {
- s0 = peg$parseUnaryExpr();
- }
-
- return s0;
- }
-
- function peg$parseNullaryExpr() {
- var s0, s1;
-
- s0 = peg$parseBooleanLiteral();
- if (s0 === peg$FAILED) {
- s0 = peg$currPos;
- if (input.substr(peg$currPos, 2) === peg$c23) {
- s1 = peg$c23;
- peg$currPos += 2;
- } else {
- s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c24); }
- }
- if (s1 !== peg$FAILED) {
- peg$savedPos = s0;
- s1 = peg$c25();
- }
- s0 = s1;
- if (s0 === peg$FAILED) {
- s0 = peg$currPos;
- if (input.substr(peg$currPos, 2) === peg$c26) {
- s1 = peg$c26;
- peg$currPos += 2;
- } else {
- s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c27); }
- }
- if (s1 !== peg$FAILED) {
- peg$savedPos = s0;
- s1 = peg$c28();
- }
- s0 = s1;
- if (s0 === peg$FAILED) {
- s0 = peg$currPos;
- if (input.substr(peg$currPos, 5) === peg$c29) {
- s1 = peg$c29;
- peg$currPos += 5;
- } else {
- s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c30); }
- }
- if (s1 !== peg$FAILED) {
- peg$savedPos = s0;
- s1 = peg$c31();
- }
- s0 = s1;
- if (s0 === peg$FAILED) {
- s0 = peg$currPos;
- if (input.substr(peg$currPos, 7) === peg$c32) {
- s1 = peg$c32;
- peg$currPos += 7;
- } else {
- s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c33); }
- }
- if (s1 !== peg$FAILED) {
- peg$savedPos = s0;
- s1 = peg$c34();
- }
- s0 = s1;
- if (s0 === peg$FAILED) {
- s0 = peg$currPos;
- if (input.substr(peg$currPos, 2) === peg$c35) {
- s1 = peg$c35;
- peg$currPos += 2;
- } else {
- s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c36); }
- }
- if (s1 !== peg$FAILED) {
- peg$savedPos = s0;
- s1 = peg$c37();
- }
- s0 = s1;
- if (s0 === peg$FAILED) {
- s0 = peg$currPos;
- if (input.substr(peg$currPos, 2) === peg$c38) {
- s1 = peg$c38;
- peg$currPos += 2;
- } else {
- s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c39); }
- }
- if (s1 !== peg$FAILED) {
- peg$savedPos = s0;
- s1 = peg$c40();
- }
- s0 = s1;
- if (s0 === peg$FAILED) {
- s0 = peg$currPos;
- if (input.substr(peg$currPos, 4) === peg$c41) {
- s1 = peg$c41;
- peg$currPos += 4;
- } else {
- s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c42); }
- }
- if (s1 !== peg$FAILED) {
- peg$savedPos = s0;
- s1 = peg$c43();
- }
- s0 = s1;
- }
- }
- }
- }
- }
- }
- }
-
- return s0;
- }
-
- function peg$parseBooleanLiteral() {
- var s0, s1;
+ var s0, s1, s2, s3;
s0 = peg$currPos;
- if (input.substr(peg$currPos, 4) === peg$c44) {
- s1 = peg$c44;
+ if (input.substr(peg$currPos, 4) === peg$c23) {
+ s1 = peg$c23;
peg$currPos += 4;
} else {
s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c45); }
+ if (peg$silentFails === 0) { peg$fail(peg$c24); }
}
if (s1 !== peg$FAILED) {
peg$savedPos = s0;
- s1 = peg$c46();
+ s1 = peg$c25();
}
s0 = s1;
if (s0 === peg$FAILED) {
s0 = peg$currPos;
- if (input.substr(peg$currPos, 5) === peg$c47) {
- s1 = peg$c47;
+ if (input.substr(peg$currPos, 5) === peg$c26) {
+ s1 = peg$c26;
peg$currPos += 5;
} else {
s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c48); }
+ if (peg$silentFails === 0) { peg$fail(peg$c27); }
}
if (s1 !== peg$FAILED) {
peg$savedPos = s0;
- s1 = peg$c49();
+ s1 = peg$c28();
}
s0 = s1;
- }
-
- return s0;
- }
-
- function peg$parseUnaryExpr() {
- var s0, s1, s2, s3;
-
- s0 = peg$currPos;
- if (input.substr(peg$currPos, 2) === peg$c50) {
- s1 = peg$c50;
- peg$currPos += 2;
- } else {
- s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c51); }
- }
- if (s1 !== peg$FAILED) {
- s2 = [];
- s3 = peg$parsews();
- if (s3 !== peg$FAILED) {
- while (s3 !== peg$FAILED) {
- s2.push(s3);
- s3 = peg$parsews();
- }
- } else {
- s2 = peg$FAILED;
- }
- if (s2 !== peg$FAILED) {
- s3 = peg$parseIntegerLiteral();
- if (s3 !== peg$FAILED) {
- peg$savedPos = s0;
- s1 = peg$c52(s3);
- s0 = s1;
- } else {
- peg$currPos = s0;
- s0 = peg$FAILED;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$FAILED;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$FAILED;
- }
- if (s0 === peg$FAILED) {
- s0 = peg$currPos;
- if (input.substr(peg$currPos, 2) === peg$c53) {
- s1 = peg$c53;
- peg$currPos += 2;
- } else {
- s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c54); }
- }
- if (s1 !== peg$FAILED) {
- s2 = [];
- s3 = peg$parsews();
- if (s3 !== peg$FAILED) {
- while (s3 !== peg$FAILED) {
- s2.push(s3);
- s3 = peg$parsews();
- }
- } else {
- s2 = peg$FAILED;
- }
- if (s2 !== peg$FAILED) {
- s3 = peg$parseStringLiteral();
- if (s3 !== peg$FAILED) {
- peg$savedPos = s0;
- s1 = peg$c55(s3);
- s0 = s1;
- } else {
- peg$currPos = s0;
- s0 = peg$FAILED;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$FAILED;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$FAILED;
- }
if (s0 === peg$FAILED) {
s0 = peg$currPos;
- if (input.substr(peg$currPos, 2) === peg$c56) {
- s1 = peg$c56;
+ if (input.substr(peg$currPos, 2) === peg$c29) {
+ s1 = peg$c29;
peg$currPos += 2;
} else {
s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c57); }
+ if (peg$silentFails === 0) { peg$fail(peg$c30); }
}
if (s1 !== peg$FAILED) {
- s2 = [];
- s3 = peg$parsews();
- if (s3 !== peg$FAILED) {
- while (s3 !== peg$FAILED) {
- s2.push(s3);
- s3 = peg$parsews();
- }
- } else {
- s2 = peg$FAILED;
- }
- if (s2 !== peg$FAILED) {
- s3 = peg$parseStringLiteral();
- if (s3 !== peg$FAILED) {
- peg$savedPos = s0;
- s1 = peg$c58(s3);
- s0 = s1;
- } else {
- peg$currPos = s0;
- s0 = peg$FAILED;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$FAILED;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$FAILED;
+ peg$savedPos = s0;
+ s1 = peg$c31();
}
+ s0 = s1;
if (s0 === peg$FAILED) {
s0 = peg$currPos;
- if (input.substr(peg$currPos, 3) === peg$c59) {
- s1 = peg$c59;
- peg$currPos += 3;
+ if (input.substr(peg$currPos, 2) === peg$c32) {
+ s1 = peg$c32;
+ peg$currPos += 2;
} else {
s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c60); }
+ if (peg$silentFails === 0) { peg$fail(peg$c33); }
}
if (s1 !== peg$FAILED) {
s2 = [];
@@ -950,10 +725,10 @@ module.exports = (function() {
s2 = peg$FAILED;
}
if (s2 !== peg$FAILED) {
- s3 = peg$parseStringLiteral();
+ s3 = peg$parseIntegerLiteral();
if (s3 !== peg$FAILED) {
peg$savedPos = s0;
- s1 = peg$c61(s3);
+ s1 = peg$c34(s3);
s0 = s1;
} else {
peg$currPos = s0;
@@ -969,12 +744,12 @@ module.exports = (function() {
}
if (s0 === peg$FAILED) {
s0 = peg$currPos;
- if (input.substr(peg$currPos, 3) === peg$c62) {
- s1 = peg$c62;
- peg$currPos += 3;
+ if (input.substr(peg$currPos, 2) === peg$c35) {
+ s1 = peg$c35;
+ peg$currPos += 2;
} else {
s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c63); }
+ if (peg$silentFails === 0) { peg$fail(peg$c36); }
}
if (s1 !== peg$FAILED) {
s2 = [];
@@ -991,7 +766,7 @@ module.exports = (function() {
s3 = peg$parseStringLiteral();
if (s3 !== peg$FAILED) {
peg$savedPos = s0;
- s1 = peg$c64(s3);
+ s1 = peg$c37(s3);
s0 = s1;
} else {
peg$currPos = s0;
@@ -1007,12 +782,12 @@ module.exports = (function() {
}
if (s0 === peg$FAILED) {
s0 = peg$currPos;
- if (input.substr(peg$currPos, 2) === peg$c65) {
- s1 = peg$c65;
- peg$currPos += 2;
+ if (input.substr(peg$currPos, 4) === peg$c38) {
+ s1 = peg$c38;
+ peg$currPos += 4;
} else {
s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c66); }
+ if (peg$silentFails === 0) { peg$fail(peg$c39); }
}
if (s1 !== peg$FAILED) {
s2 = [];
@@ -1029,7 +804,7 @@ module.exports = (function() {
s3 = peg$parseStringLiteral();
if (s3 !== peg$FAILED) {
peg$savedPos = s0;
- s1 = peg$c67(s3);
+ s1 = peg$c40(s3);
s0 = s1;
} else {
peg$currPos = s0;
@@ -1045,50 +820,26 @@ module.exports = (function() {
}
if (s0 === peg$FAILED) {
s0 = peg$currPos;
- if (input.substr(peg$currPos, 2) === peg$c68) {
- s1 = peg$c68;
+ if (input.substr(peg$currPos, 2) === peg$c41) {
+ s1 = peg$c41;
peg$currPos += 2;
} else {
s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c69); }
+ if (peg$silentFails === 0) { peg$fail(peg$c42); }
}
if (s1 !== peg$FAILED) {
- s2 = [];
- s3 = peg$parsews();
- if (s3 !== peg$FAILED) {
- while (s3 !== peg$FAILED) {
- s2.push(s3);
- s3 = peg$parsews();
- }
- } else {
- s2 = peg$FAILED;
- }
- if (s2 !== peg$FAILED) {
- s3 = peg$parseStringLiteral();
- if (s3 !== peg$FAILED) {
- peg$savedPos = s0;
- s1 = peg$c70(s3);
- s0 = s1;
- } else {
- peg$currPos = s0;
- s0 = peg$FAILED;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$FAILED;
- }
- } else {
- peg$currPos = s0;
- s0 = peg$FAILED;
+ peg$savedPos = s0;
+ s1 = peg$c43();
}
+ s0 = s1;
if (s0 === peg$FAILED) {
s0 = peg$currPos;
- if (input.substr(peg$currPos, 3) === peg$c71) {
- s1 = peg$c71;
- peg$currPos += 3;
+ if (input.substr(peg$currPos, 2) === peg$c44) {
+ s1 = peg$c44;
+ peg$currPos += 2;
} else {
s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c72); }
+ if (peg$silentFails === 0) { peg$fail(peg$c45); }
}
if (s1 !== peg$FAILED) {
s2 = [];
@@ -1105,7 +856,7 @@ module.exports = (function() {
s3 = peg$parseStringLiteral();
if (s3 !== peg$FAILED) {
peg$savedPos = s0;
- s1 = peg$c73(s3);
+ s1 = peg$c46(s3);
s0 = s1;
} else {
peg$currPos = s0;
@@ -1121,12 +872,12 @@ module.exports = (function() {
}
if (s0 === peg$FAILED) {
s0 = peg$currPos;
- if (input.substr(peg$currPos, 3) === peg$c74) {
- s1 = peg$c74;
+ if (input.substr(peg$currPos, 3) === peg$c47) {
+ s1 = peg$c47;
peg$currPos += 3;
} else {
s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c75); }
+ if (peg$silentFails === 0) { peg$fail(peg$c48); }
}
if (s1 !== peg$FAILED) {
s2 = [];
@@ -1143,7 +894,7 @@ module.exports = (function() {
s3 = peg$parseStringLiteral();
if (s3 !== peg$FAILED) {
peg$savedPos = s0;
- s1 = peg$c76(s3);
+ s1 = peg$c49(s3);
s0 = s1;
} else {
peg$currPos = s0;
@@ -1159,12 +910,12 @@ module.exports = (function() {
}
if (s0 === peg$FAILED) {
s0 = peg$currPos;
- if (input.substr(peg$currPos, 2) === peg$c77) {
- s1 = peg$c77;
- peg$currPos += 2;
+ if (input.substr(peg$currPos, 3) === peg$c50) {
+ s1 = peg$c50;
+ peg$currPos += 3;
} else {
s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c78); }
+ if (peg$silentFails === 0) { peg$fail(peg$c51); }
}
if (s1 !== peg$FAILED) {
s2 = [];
@@ -1181,7 +932,7 @@ module.exports = (function() {
s3 = peg$parseStringLiteral();
if (s3 !== peg$FAILED) {
peg$savedPos = s0;
- s1 = peg$c79(s3);
+ s1 = peg$c52(s3);
s0 = s1;
} else {
peg$currPos = s0;
@@ -1197,12 +948,321 @@ module.exports = (function() {
}
if (s0 === peg$FAILED) {
s0 = peg$currPos;
- s1 = peg$parseStringLiteral();
+ if (input.substr(peg$currPos, 5) === peg$c53) {
+ s1 = peg$c53;
+ peg$currPos += 5;
+ } else {
+ s1 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c54); }
+ }
if (s1 !== peg$FAILED) {
peg$savedPos = s0;
- s1 = peg$c79(s1);
+ s1 = peg$c55();
}
s0 = s1;
+ if (s0 === peg$FAILED) {
+ s0 = peg$currPos;
+ if (input.substr(peg$currPos, 2) === peg$c56) {
+ s1 = peg$c56;
+ peg$currPos += 2;
+ } else {
+ s1 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c57); }
+ }
+ if (s1 !== peg$FAILED) {
+ s2 = [];
+ s3 = peg$parsews();
+ if (s3 !== peg$FAILED) {
+ while (s3 !== peg$FAILED) {
+ s2.push(s3);
+ s3 = peg$parsews();
+ }
+ } else {
+ s2 = peg$FAILED;
+ }
+ if (s2 !== peg$FAILED) {
+ s3 = peg$parseStringLiteral();
+ if (s3 !== peg$FAILED) {
+ peg$savedPos = s0;
+ s1 = peg$c58(s3);
+ s0 = s1;
+ } else {
+ peg$currPos = s0;
+ s0 = peg$FAILED;
+ }
+ } else {
+ peg$currPos = s0;
+ s0 = peg$FAILED;
+ }
+ } else {
+ peg$currPos = s0;
+ s0 = peg$FAILED;
+ }
+ if (s0 === peg$FAILED) {
+ s0 = peg$currPos;
+ if (input.substr(peg$currPos, 7) === peg$c59) {
+ s1 = peg$c59;
+ peg$currPos += 7;
+ } else {
+ s1 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c60); }
+ }
+ if (s1 !== peg$FAILED) {
+ peg$savedPos = s0;
+ s1 = peg$c61();
+ }
+ s0 = s1;
+ if (s0 === peg$FAILED) {
+ s0 = peg$currPos;
+ if (input.substr(peg$currPos, 2) === peg$c62) {
+ s1 = peg$c62;
+ peg$currPos += 2;
+ } else {
+ s1 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c63); }
+ }
+ if (s1 !== peg$FAILED) {
+ peg$savedPos = s0;
+ s1 = peg$c64();
+ }
+ s0 = s1;
+ if (s0 === peg$FAILED) {
+ s0 = peg$currPos;
+ if (input.substr(peg$currPos, 4) === peg$c65) {
+ s1 = peg$c65;
+ peg$currPos += 4;
+ } else {
+ s1 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c66); }
+ }
+ if (s1 !== peg$FAILED) {
+ s2 = [];
+ s3 = peg$parsews();
+ if (s3 !== peg$FAILED) {
+ while (s3 !== peg$FAILED) {
+ s2.push(s3);
+ s3 = peg$parsews();
+ }
+ } else {
+ s2 = peg$FAILED;
+ }
+ if (s2 !== peg$FAILED) {
+ s3 = peg$parseStringLiteral();
+ if (s3 !== peg$FAILED) {
+ peg$savedPos = s0;
+ s1 = peg$c67(s3);
+ s0 = s1;
+ } else {
+ peg$currPos = s0;
+ s0 = peg$FAILED;
+ }
+ } else {
+ peg$currPos = s0;
+ s0 = peg$FAILED;
+ }
+ } else {
+ peg$currPos = s0;
+ s0 = peg$FAILED;
+ }
+ if (s0 === peg$FAILED) {
+ s0 = peg$currPos;
+ if (input.substr(peg$currPos, 2) === peg$c68) {
+ s1 = peg$c68;
+ peg$currPos += 2;
+ } else {
+ s1 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c69); }
+ }
+ if (s1 !== peg$FAILED) {
+ peg$savedPos = s0;
+ s1 = peg$c70();
+ }
+ s0 = s1;
+ if (s0 === peg$FAILED) {
+ s0 = peg$currPos;
+ if (input.substr(peg$currPos, 2) === peg$c71) {
+ s1 = peg$c71;
+ peg$currPos += 2;
+ } else {
+ s1 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c72); }
+ }
+ if (s1 !== peg$FAILED) {
+ s2 = [];
+ s3 = peg$parsews();
+ if (s3 !== peg$FAILED) {
+ while (s3 !== peg$FAILED) {
+ s2.push(s3);
+ s3 = peg$parsews();
+ }
+ } else {
+ s2 = peg$FAILED;
+ }
+ if (s2 !== peg$FAILED) {
+ s3 = peg$parseStringLiteral();
+ if (s3 !== peg$FAILED) {
+ peg$savedPos = s0;
+ s1 = peg$c73(s3);
+ s0 = s1;
+ } else {
+ peg$currPos = s0;
+ s0 = peg$FAILED;
+ }
+ } else {
+ peg$currPos = s0;
+ s0 = peg$FAILED;
+ }
+ } else {
+ peg$currPos = s0;
+ s0 = peg$FAILED;
+ }
+ if (s0 === peg$FAILED) {
+ s0 = peg$currPos;
+ if (input.substr(peg$currPos, 4) === peg$c74) {
+ s1 = peg$c74;
+ peg$currPos += 4;
+ } else {
+ s1 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c75); }
+ }
+ if (s1 !== peg$FAILED) {
+ peg$savedPos = s0;
+ s1 = peg$c76();
+ }
+ s0 = s1;
+ if (s0 === peg$FAILED) {
+ s0 = peg$currPos;
+ if (input.substr(peg$currPos, 3) === peg$c77) {
+ s1 = peg$c77;
+ peg$currPos += 3;
+ } else {
+ s1 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c78); }
+ }
+ if (s1 !== peg$FAILED) {
+ s2 = [];
+ s3 = peg$parsews();
+ if (s3 !== peg$FAILED) {
+ while (s3 !== peg$FAILED) {
+ s2.push(s3);
+ s3 = peg$parsews();
+ }
+ } else {
+ s2 = peg$FAILED;
+ }
+ if (s2 !== peg$FAILED) {
+ s3 = peg$parseStringLiteral();
+ if (s3 !== peg$FAILED) {
+ peg$savedPos = s0;
+ s1 = peg$c79(s3);
+ s0 = s1;
+ } else {
+ peg$currPos = s0;
+ s0 = peg$FAILED;
+ }
+ } else {
+ peg$currPos = s0;
+ s0 = peg$FAILED;
+ }
+ } else {
+ peg$currPos = s0;
+ s0 = peg$FAILED;
+ }
+ if (s0 === peg$FAILED) {
+ s0 = peg$currPos;
+ if (input.substr(peg$currPos, 3) === peg$c80) {
+ s1 = peg$c80;
+ peg$currPos += 3;
+ } else {
+ s1 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c81); }
+ }
+ if (s1 !== peg$FAILED) {
+ s2 = [];
+ s3 = peg$parsews();
+ if (s3 !== peg$FAILED) {
+ while (s3 !== peg$FAILED) {
+ s2.push(s3);
+ s3 = peg$parsews();
+ }
+ } else {
+ s2 = peg$FAILED;
+ }
+ if (s2 !== peg$FAILED) {
+ s3 = peg$parseStringLiteral();
+ if (s3 !== peg$FAILED) {
+ peg$savedPos = s0;
+ s1 = peg$c82(s3);
+ s0 = s1;
+ } else {
+ peg$currPos = s0;
+ s0 = peg$FAILED;
+ }
+ } else {
+ peg$currPos = s0;
+ s0 = peg$FAILED;
+ }
+ } else {
+ peg$currPos = s0;
+ s0 = peg$FAILED;
+ }
+ if (s0 === peg$FAILED) {
+ s0 = peg$currPos;
+ if (input.substr(peg$currPos, 2) === peg$c83) {
+ s1 = peg$c83;
+ peg$currPos += 2;
+ } else {
+ s1 = peg$FAILED;
+ if (peg$silentFails === 0) { peg$fail(peg$c84); }
+ }
+ if (s1 !== peg$FAILED) {
+ s2 = [];
+ s3 = peg$parsews();
+ if (s3 !== peg$FAILED) {
+ while (s3 !== peg$FAILED) {
+ s2.push(s3);
+ s3 = peg$parsews();
+ }
+ } else {
+ s2 = peg$FAILED;
+ }
+ if (s2 !== peg$FAILED) {
+ s3 = peg$parseStringLiteral();
+ if (s3 !== peg$FAILED) {
+ peg$savedPos = s0;
+ s1 = peg$c85(s3);
+ s0 = s1;
+ } else {
+ peg$currPos = s0;
+ s0 = peg$FAILED;
+ }
+ } else {
+ peg$currPos = s0;
+ s0 = peg$FAILED;
+ }
+ } else {
+ peg$currPos = s0;
+ s0 = peg$FAILED;
+ }
+ if (s0 === peg$FAILED) {
+ s0 = peg$currPos;
+ s1 = peg$parseStringLiteral();
+ if (s1 !== peg$FAILED) {
+ peg$savedPos = s0;
+ s1 = peg$c85(s1);
+ }
+ s0 = s1;
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ }
}
}
}
@@ -1222,53 +1282,53 @@ module.exports = (function() {
peg$silentFails++;
s0 = peg$currPos;
- if (peg$c81.test(input.charAt(peg$currPos))) {
+ if (peg$c87.test(input.charAt(peg$currPos))) {
s1 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c82); }
+ if (peg$silentFails === 0) { peg$fail(peg$c88); }
}
if (s1 === peg$FAILED) {
s1 = null;
}
if (s1 !== peg$FAILED) {
s2 = [];
- if (peg$c83.test(input.charAt(peg$currPos))) {
+ if (peg$c89.test(input.charAt(peg$currPos))) {
s3 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s3 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c84); }
+ if (peg$silentFails === 0) { peg$fail(peg$c90); }
}
if (s3 !== peg$FAILED) {
while (s3 !== peg$FAILED) {
s2.push(s3);
- if (peg$c83.test(input.charAt(peg$currPos))) {
+ if (peg$c89.test(input.charAt(peg$currPos))) {
s3 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s3 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c84); }
+ if (peg$silentFails === 0) { peg$fail(peg$c90); }
}
}
} else {
s2 = peg$FAILED;
}
if (s2 !== peg$FAILED) {
- if (peg$c81.test(input.charAt(peg$currPos))) {
+ if (peg$c87.test(input.charAt(peg$currPos))) {
s3 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s3 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c82); }
+ if (peg$silentFails === 0) { peg$fail(peg$c88); }
}
if (s3 === peg$FAILED) {
s3 = null;
}
if (s3 !== peg$FAILED) {
peg$savedPos = s0;
- s1 = peg$c85(s2);
+ s1 = peg$c91(s2);
s0 = s1;
} else {
peg$currPos = s0;
@@ -1285,7 +1345,7 @@ module.exports = (function() {
peg$silentFails--;
if (s0 === peg$FAILED) {
s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c80); }
+ if (peg$silentFails === 0) { peg$fail(peg$c86); }
}
return s0;
@@ -1297,11 +1357,11 @@ module.exports = (function() {
peg$silentFails++;
s0 = peg$currPos;
if (input.charCodeAt(peg$currPos) === 34) {
- s1 = peg$c87;
+ s1 = peg$c93;
peg$currPos++;
} else {
s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c88); }
+ if (peg$silentFails === 0) { peg$fail(peg$c94); }
}
if (s1 !== peg$FAILED) {
s2 = [];
@@ -1312,15 +1372,15 @@ module.exports = (function() {
}
if (s2 !== peg$FAILED) {
if (input.charCodeAt(peg$currPos) === 34) {
- s3 = peg$c87;
+ s3 = peg$c93;
peg$currPos++;
} else {
s3 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c88); }
+ if (peg$silentFails === 0) { peg$fail(peg$c94); }
}
if (s3 !== peg$FAILED) {
peg$savedPos = s0;
- s1 = peg$c89(s2);
+ s1 = peg$c95(s2);
s0 = s1;
} else {
peg$currPos = s0;
@@ -1337,11 +1397,11 @@ module.exports = (function() {
if (s0 === peg$FAILED) {
s0 = peg$currPos;
if (input.charCodeAt(peg$currPos) === 39) {
- s1 = peg$c90;
+ s1 = peg$c96;
peg$currPos++;
} else {
s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c91); }
+ if (peg$silentFails === 0) { peg$fail(peg$c97); }
}
if (s1 !== peg$FAILED) {
s2 = [];
@@ -1352,15 +1412,15 @@ module.exports = (function() {
}
if (s2 !== peg$FAILED) {
if (input.charCodeAt(peg$currPos) === 39) {
- s3 = peg$c90;
+ s3 = peg$c96;
peg$currPos++;
} else {
s3 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c91); }
+ if (peg$silentFails === 0) { peg$fail(peg$c97); }
}
if (s3 !== peg$FAILED) {
peg$savedPos = s0;
- s1 = peg$c89(s2);
+ s1 = peg$c95(s2);
s0 = s1;
} else {
peg$currPos = s0;
@@ -1399,7 +1459,7 @@ module.exports = (function() {
}
if (s2 !== peg$FAILED) {
peg$savedPos = s0;
- s1 = peg$c89(s2);
+ s1 = peg$c95(s2);
s0 = s1;
} else {
peg$currPos = s0;
@@ -1414,7 +1474,7 @@ module.exports = (function() {
peg$silentFails--;
if (s0 === peg$FAILED) {
s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c86); }
+ if (peg$silentFails === 0) { peg$fail(peg$c92); }
}
return s0;
@@ -1426,12 +1486,12 @@ module.exports = (function() {
s0 = peg$currPos;
s1 = peg$currPos;
peg$silentFails++;
- if (peg$c92.test(input.charAt(peg$currPos))) {
+ if (peg$c98.test(input.charAt(peg$currPos))) {
s2 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s2 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c93); }
+ if (peg$silentFails === 0) { peg$fail(peg$c99); }
}
peg$silentFails--;
if (s2 === peg$FAILED) {
@@ -1446,11 +1506,11 @@ module.exports = (function() {
peg$currPos++;
} else {
s2 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c94); }
+ if (peg$silentFails === 0) { peg$fail(peg$c100); }
}
if (s2 !== peg$FAILED) {
peg$savedPos = s0;
- s1 = peg$c95(s2);
+ s1 = peg$c101(s2);
s0 = s1;
} else {
peg$currPos = s0;
@@ -1463,17 +1523,17 @@ module.exports = (function() {
if (s0 === peg$FAILED) {
s0 = peg$currPos;
if (input.charCodeAt(peg$currPos) === 92) {
- s1 = peg$c96;
+ s1 = peg$c102;
peg$currPos++;
} else {
s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c97); }
+ if (peg$silentFails === 0) { peg$fail(peg$c103); }
}
if (s1 !== peg$FAILED) {
s2 = peg$parseEscapeSequence();
if (s2 !== peg$FAILED) {
peg$savedPos = s0;
- s1 = peg$c95(s2);
+ s1 = peg$c101(s2);
s0 = s1;
} else {
peg$currPos = s0;
@@ -1494,12 +1554,12 @@ module.exports = (function() {
s0 = peg$currPos;
s1 = peg$currPos;
peg$silentFails++;
- if (peg$c98.test(input.charAt(peg$currPos))) {
+ if (peg$c104.test(input.charAt(peg$currPos))) {
s2 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s2 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c99); }
+ if (peg$silentFails === 0) { peg$fail(peg$c105); }
}
peg$silentFails--;
if (s2 === peg$FAILED) {
@@ -1514,11 +1574,11 @@ module.exports = (function() {
peg$currPos++;
} else {
s2 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c94); }
+ if (peg$silentFails === 0) { peg$fail(peg$c100); }
}
if (s2 !== peg$FAILED) {
peg$savedPos = s0;
- s1 = peg$c95(s2);
+ s1 = peg$c101(s2);
s0 = s1;
} else {
peg$currPos = s0;
@@ -1531,17 +1591,17 @@ module.exports = (function() {
if (s0 === peg$FAILED) {
s0 = peg$currPos;
if (input.charCodeAt(peg$currPos) === 92) {
- s1 = peg$c96;
+ s1 = peg$c102;
peg$currPos++;
} else {
s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c97); }
+ if (peg$silentFails === 0) { peg$fail(peg$c103); }
}
if (s1 !== peg$FAILED) {
s2 = peg$parseEscapeSequence();
if (s2 !== peg$FAILED) {
peg$savedPos = s0;
- s1 = peg$c95(s2);
+ s1 = peg$c101(s2);
s0 = s1;
} else {
peg$currPos = s0;
@@ -1576,11 +1636,11 @@ module.exports = (function() {
peg$currPos++;
} else {
s2 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c94); }
+ if (peg$silentFails === 0) { peg$fail(peg$c100); }
}
if (s2 !== peg$FAILED) {
peg$savedPos = s0;
- s1 = peg$c95(s2);
+ s1 = peg$c101(s2);
s0 = s1;
} else {
peg$currPos = s0;
@@ -1597,53 +1657,53 @@ module.exports = (function() {
function peg$parseEscapeSequence() {
var s0, s1;
- if (peg$c100.test(input.charAt(peg$currPos))) {
+ if (peg$c106.test(input.charAt(peg$currPos))) {
s0 = input.charAt(peg$currPos);
peg$currPos++;
} else {
s0 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c101); }
+ if (peg$silentFails === 0) { peg$fail(peg$c107); }
}
if (s0 === peg$FAILED) {
s0 = peg$currPos;
if (input.charCodeAt(peg$currPos) === 110) {
- s1 = peg$c102;
+ s1 = peg$c108;
peg$currPos++;
} else {
s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c103); }
+ if (peg$silentFails === 0) { peg$fail(peg$c109); }
}
if (s1 !== peg$FAILED) {
peg$savedPos = s0;
- s1 = peg$c104();
+ s1 = peg$c110();
}
s0 = s1;
if (s0 === peg$FAILED) {
s0 = peg$currPos;
if (input.charCodeAt(peg$currPos) === 114) {
- s1 = peg$c105;
+ s1 = peg$c111;
peg$currPos++;
} else {
s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c106); }
+ if (peg$silentFails === 0) { peg$fail(peg$c112); }
}
if (s1 !== peg$FAILED) {
peg$savedPos = s0;
- s1 = peg$c107();
+ s1 = peg$c113();
}
s0 = s1;
if (s0 === peg$FAILED) {
s0 = peg$currPos;
if (input.charCodeAt(peg$currPos) === 116) {
- s1 = peg$c108;
+ s1 = peg$c114;
peg$currPos++;
} else {
s1 = peg$FAILED;
- if (peg$silentFails === 0) { peg$fail(peg$c109); }
+ if (peg$silentFails === 0) { peg$fail(peg$c115); }
}
if (s1 !== peg$FAILED) {
peg$savedPos = s0;
- s1 = peg$c110();
+ s1 = peg$c116();
}
s0 = s1;
}
@@ -1730,6 +1790,16 @@ module.exports = (function() {
domainFilter.desc = "domain matches " + regex;
return domainFilter;
}
+ function destination(regex){
+ regex = new RegExp(regex, "i");
+ function destinationFilter(flow){
+ return (!!flow.server_conn.address)
+ &&
+ regex.test(flow.server_conn.address.address[0] + ":" + flow.server_conn.address.address[1]);
+ }
+ destinationFilter.desc = "destination address matches " + regex;
+ return destinationFilter;
+ }
function errorFilter(flow){
return !!flow.error;
}
@@ -1786,7 +1856,16 @@ module.exports = (function() {
return !!flow.response;
}
responseFilter.desc = "has response";
-
+ function source(regex){
+ regex = new RegExp(regex, "i");
+ function sourceFilter(flow){
+ return (!!flow.client_conn.address)
+ &&
+ regex.test(flow.client_conn.address.address[0] + ":" + flow.client_conn.address.address[1]);
+ }
+ sourceFilter.desc = "source address matches " + regex;
+ return sourceFilter;
+ }
function contentType(regex){
regex = new RegExp(regex, "i");
function contentTypeFilter(flow){
diff --git a/web/src/js/filt/filt.peg b/web/src/js/filt/filt.peg
index f3235ccd..64780d8a 100644
--- a/web/src/js/filt/filt.peg
+++ b/web/src/js/filt/filt.peg
@@ -77,6 +77,16 @@ function domain(regex){
domainFilter.desc = "domain matches " + regex;
return domainFilter;
}
+function destination(regex){
+ regex = new RegExp(regex, "i");
+ function destinationFilter(flow){
+ return (!!flow.server_conn.address)
+ &&
+ regex.test(flow.server_conn.address.address[0] + ":" + flow.server_conn.address.address[1]);
+ }
+ destinationFilter.desc = "destination address matches " + regex;
+ return destinationFilter;
+}
function errorFilter(flow){
return !!flow.error;
}
@@ -133,7 +143,16 @@ function responseFilter(flow){
return !!flow.response;
}
responseFilter.desc = "has response";
-
+function source(regex){
+ regex = new RegExp(regex, "i");
+ function sourceFilter(flow){
+ return (!!flow.client_conn.address)
+ &&
+ regex.test(flow.client_conn.address.address[0] + ":" + flow.client_conn.address.address[1]);
+ }
+ sourceFilter.desc = "source address matches " + regex;
+ return sourceFilter;
+}
function contentType(regex){
regex = new RegExp(regex, "i");
function contentTypeFilter(flow){
@@ -205,36 +224,33 @@ BindingExpr
{ return binding(expr); }
/ Expr
-Expr
- = NullaryExpr
- / UnaryExpr
+/* All the filters except "~s" and "~src" are arranged in the ascending order as
+ given in the docs(http://docs.mitmproxy.org/en/latest/features/filters.html).
+ "~s" and "~src" are so arranged as "~s" caused problems in the evaluation of
+ "~src". */
-NullaryExpr
- = BooleanLiteral
+Expr
+ = "true" { return trueFilter; }
+ / "false" { return falseFilter; }
/ "~a" { return assetFilter; }
+ / "~c" ws+ s:IntegerLiteral { return responseCode(s); }
+ / "~d" ws+ s:StringLiteral { return domain(s); }
+ / "~dst" ws+ s:StringLiteral { return destination(s); }
/ "~e" { return errorFilter; }
+ / "~h" ws+ s:StringLiteral { return header(s); }
+ / "~hq" ws+ s:StringLiteral { return requestHeader(s); }
+ / "~hs" ws+ s:StringLiteral { return responseHeader(s); }
/ "~http" { return httpFilter; }
+ / "~m" ws+ s:StringLiteral { return method(s); }
/ "~marked" { return markedFilter; }
/ "~q" { return noResponseFilter; }
+ / "~src" ws+ s:StringLiteral { return source(s); }
/ "~s" { return responseFilter; }
+ / "~t" ws+ s:StringLiteral { return contentType(s); }
/ "~tcp" { return tcpFilter; }
-
-
-BooleanLiteral
- = "true" { return trueFilter; }
- / "false" { return falseFilter; }
-
-UnaryExpr
- = "~c" ws+ s:IntegerLiteral { return responseCode(s); }
- / "~d" ws+ s:StringLiteral { return domain(s); }
- / "~h" ws+ s:StringLiteral { return header(s); }
- / "~hq" ws+ s:StringLiteral { return requestHeader(s); }
- / "~hs" ws+ s:StringLiteral { return responseHeader(s); }
- / "~m" ws+ s:StringLiteral { return method(s); }
- / "~t" ws+ s:StringLiteral { return contentType(s); }
/ "~tq" ws+ s:StringLiteral { return requestContentType(s); }
/ "~ts" ws+ s:StringLiteral { return responseContentType(s); }
- / "~u" ws+ s:StringLiteral { return url(s); }
+ / "~u" ws+ s:StringLiteral { return url(s); }
/ s:StringLiteral { return url(s); }
IntegerLiteral "integer"