diff --git a/mitmproxy/addons/view.py b/mitmproxy/addons/view.py index b3b6e4f5a..4d7d750a2 100644 --- a/mitmproxy/addons/view.py +++ b/mitmproxy/addons/view.py @@ -330,7 +330,7 @@ class View(collections.abc.Sequence): self.set_filter(filt) def set_filter(self, flt: typing.Optional[flowfilter.TFilter]): - self.filter = flt or matchall + self.filter = flt or flowfilter.match_all self._refilter() # View Updates diff --git a/mitmproxy/tools/web/app.py b/mitmproxy/tools/web/app.py index 9deba965e..8746c7e8e 100644 --- a/mitmproxy/tools/web/app.py +++ b/mitmproxy/tools/web/app.py @@ -58,6 +58,7 @@ def flow_to_json(flow: mitmproxy.flow.Flow) -> dict: "type": flow.type, "modified": flow.modified(), "marked": emoji.get(flow.marked, "🔴") if flow.marked else "", + "comment": flow.comment, } if flow.client_conn: diff --git a/test/mitmproxy/tools/web/test_app.py b/test/mitmproxy/tools/web/test_app.py index 99cbb61bd..ae4ee0414 100644 --- a/test/mitmproxy/tools/web/test_app.py +++ b/test/mitmproxy/tools/web/test_app.py @@ -48,6 +48,7 @@ def test_generate_tflow_js(tdata): ] tf_http.request.trailers = Headers(trailer="qvalue") tf_http.response.trailers = Headers(trailer="qvalue") + tf_http.comment = "I'm a comment!" tf_tcp = tflow.ttcpflow(err=True) tf_tcp.id = "2ea7012b-21b5-4f8f-98cd-d49819954001" diff --git a/web/src/js/__tests__/ducks/_tflow.ts b/web/src/js/__tests__/ducks/_tflow.ts index f2685e1cc..072d78e4a 100644 --- a/web/src/js/__tests__/ducks/_tflow.ts +++ b/web/src/js/__tests__/ducks/_tflow.ts @@ -22,6 +22,7 @@ export function THTTPFlow(): Required { "tls_established": true, "tls_version": "TLSv1.2" }, + "comment": "I'm a comment!", "error": { "msg": "error", "timestamp": 946681207.0 @@ -180,6 +181,7 @@ export function TTCPFlow(): Required { "tls_established": true, "tls_version": "TLSv1.2" }, + "comment": "", "error": { "msg": "error", "timestamp": 946681207.0 diff --git a/web/src/js/filt/filt.js b/web/src/js/filt/filt.js index 4131311bc..3b7699362 100644 --- a/web/src/js/filt/filt.js +++ b/web/src/js/filt/filt.js @@ -60,27 +60,27 @@ export default (function() { peg$c20 = ")", peg$c21 = { type: "literal", value: ")", description: "\")\"" }, peg$c22 = function(expr) { return binding(expr); }, - 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 = "~b", - peg$c33 = { type: "literal", value: "~b", description: "\"~b\"" }, - peg$c34 = function(s) { return body(s); }, - peg$c35 = "~bq", - peg$c36 = { type: "literal", value: "~bq", description: "\"~bq\"" }, - peg$c37 = function(s) { return requestBody(s); }, - peg$c38 = "~bs", - peg$c39 = { type: "literal", value: "~bs", description: "\"~bs\"" }, - peg$c40 = function(s) { return responseBody(s); }, - peg$c41 = "~c", - peg$c42 = { type: "literal", value: "~c", description: "\"~c\"" }, - peg$c43 = function(s) { return responseCode(s); }, + peg$c23 = "~all", + peg$c24 = { type: "literal", value: "~all", description: "\"~all\"" }, + peg$c25 = function() { return allFilter; }, + peg$c26 = "~a", + peg$c27 = { type: "literal", value: "~a", description: "\"~a\"" }, + peg$c28 = function() { return assetFilter; }, + peg$c29 = "~b", + peg$c30 = { type: "literal", value: "~b", description: "\"~b\"" }, + peg$c31 = function(s) { return body(s); }, + peg$c32 = "~bq", + peg$c33 = { type: "literal", value: "~bq", description: "\"~bq\"" }, + peg$c34 = function(s) { return requestBody(s); }, + peg$c35 = "~bs", + peg$c36 = { type: "literal", value: "~bs", description: "\"~bs\"" }, + peg$c37 = function(s) { return responseBody(s); }, + peg$c38 = "~c", + peg$c39 = { type: "literal", value: "~c", description: "\"~c\"" }, + peg$c40 = function(s) { return responseCode(s); }, + peg$c41 = "~comment", + peg$c42 = { type: "literal", value: "~comment", description: "\"~comment\"" }, + peg$c43 = function(s) { return comment(s); }, peg$c44 = "~d", peg$c45 = { type: "literal", value: "~d", description: "\"~d\"" }, peg$c46 = function(s) { return domain(s); }, @@ -102,70 +102,82 @@ export default (function() { peg$c62 = "~http", peg$c63 = { type: "literal", value: "~http", description: "\"~http\"" }, peg$c64 = function() { return httpFilter; }, - peg$c65 = "~m", - peg$c66 = { type: "literal", value: "~m", description: "\"~m\"" }, - peg$c67 = function(s) { return method(s); }, - peg$c68 = "~marked", - peg$c69 = { type: "literal", value: "~marked", description: "\"~marked\"" }, - peg$c70 = function() { return markedFilter; }, - peg$c71 = "~q", - peg$c72 = { type: "literal", value: "~q", description: "\"~q\"" }, - peg$c73 = function() { return noResponseFilter; }, - peg$c74 = "~src", - peg$c75 = { type: "literal", value: "~src", description: "\"~src\"" }, - peg$c76 = function(s) { return source(s); }, - peg$c77 = "~s", - peg$c78 = { type: "literal", value: "~s", description: "\"~s\"" }, - peg$c79 = function() { return responseFilter; }, - peg$c80 = "~t", - peg$c81 = { type: "literal", value: "~t", description: "\"~t\"" }, - peg$c82 = function(s) { return contentType(s); }, - peg$c83 = "~tcp", - peg$c84 = { type: "literal", value: "~tcp", description: "\"~tcp\"" }, - peg$c85 = function() { return tcpFilter; }, - peg$c86 = "~tq", - peg$c87 = { type: "literal", value: "~tq", description: "\"~tq\"" }, - peg$c88 = function(s) { return requestContentType(s); }, - peg$c89 = "~ts", - peg$c90 = { type: "literal", value: "~ts", description: "\"~ts\"" }, - peg$c91 = function(s) { return responseContentType(s); }, - peg$c92 = "~u", - peg$c93 = { type: "literal", value: "~u", description: "\"~u\"" }, - peg$c94 = function(s) { return url(s); }, - peg$c95 = "~websocket", - peg$c96 = { type: "literal", value: "~websocket", description: "\"~websocket\"" }, - peg$c97 = function() { return websocketFilter; }, - peg$c98 = { type: "other", description: "integer" }, - peg$c99 = /^['"]/, - peg$c100 = { type: "class", value: "['\"]", description: "['\"]" }, - peg$c101 = /^[0-9]/, - peg$c102 = { type: "class", value: "[0-9]", description: "[0-9]" }, - peg$c103 = function(digits) { return parseInt(digits.join(""), 10); }, - peg$c104 = { type: "other", description: "string" }, - peg$c105 = "\"", - peg$c106 = { type: "literal", value: "\"", description: "\"\\\"\"" }, - peg$c107 = function(chars) { return chars.join(""); }, - peg$c108 = "'", - peg$c109 = { type: "literal", value: "'", description: "\"'\"" }, - peg$c110 = /^["\\]/, - peg$c111 = { type: "class", value: "[\"\\\\]", description: "[\"\\\\]" }, - peg$c112 = { type: "any", description: "any character" }, - peg$c113 = function(char) { return char; }, - peg$c114 = "\\", - peg$c115 = { type: "literal", value: "\\", description: "\"\\\\\"" }, - peg$c116 = /^['\\]/, - peg$c117 = { type: "class", value: "['\\\\]", description: "['\\\\]" }, - peg$c118 = /^['"\\]/, - peg$c119 = { type: "class", value: "['\"\\\\]", description: "['\"\\\\]" }, - peg$c120 = "n", - peg$c121 = { type: "literal", value: "n", description: "\"n\"" }, - peg$c122 = function() { return "\n"; }, - peg$c123 = "r", - peg$c124 = { type: "literal", value: "r", description: "\"r\"" }, - peg$c125 = function() { return "\r"; }, - peg$c126 = "t", - peg$c127 = { type: "literal", value: "t", description: "\"t\"" }, - peg$c128 = function() { return "\t"; }, + peg$c65 = "~marked", + peg$c66 = { type: "literal", value: "~marked", description: "\"~marked\"" }, + peg$c67 = function() { return markedFilter; }, + peg$c68 = "~marker", + peg$c69 = { type: "literal", value: "~marker", description: "\"~marker\"" }, + peg$c70 = function(s) { return marker(s); }, + peg$c71 = "~m", + peg$c72 = { type: "literal", value: "~m", description: "\"~m\"" }, + peg$c73 = function(s) { return method(s); }, + peg$c74 = "~q", + peg$c75 = { type: "literal", value: "~q", description: "\"~q\"" }, + peg$c76 = function() { return noResponseFilter; }, + peg$c77 = "~replayq", + peg$c78 = { type: "literal", value: "~replayq", description: "\"~replayq\"" }, + peg$c79 = function() { return clientReplayFilter; }, + peg$c80 = "~replays", + peg$c81 = { type: "literal", value: "~replays", description: "\"~replays\"" }, + peg$c82 = function() { return serverReplayFilter; }, + peg$c83 = "~replay", + peg$c84 = { type: "literal", value: "~replay", description: "\"~replay\"" }, + peg$c85 = function() { return replayFilter; }, + peg$c86 = "~src", + peg$c87 = { type: "literal", value: "~src", description: "\"~src\"" }, + peg$c88 = function(s) { return source(s); }, + peg$c89 = "~s", + peg$c90 = { type: "literal", value: "~s", description: "\"~s\"" }, + peg$c91 = function() { return responseFilter; }, + peg$c92 = "~tcp", + peg$c93 = { type: "literal", value: "~tcp", description: "\"~tcp\"" }, + peg$c94 = function() { return tcpFilter; }, + peg$c95 = "~tq", + peg$c96 = { type: "literal", value: "~tq", description: "\"~tq\"" }, + peg$c97 = function(s) { return requestContentType(s); }, + peg$c98 = "~ts", + peg$c99 = { type: "literal", value: "~ts", description: "\"~ts\"" }, + peg$c100 = function(s) { return responseContentType(s); }, + peg$c101 = "~t", + peg$c102 = { type: "literal", value: "~t", description: "\"~t\"" }, + peg$c103 = function(s) { return contentType(s); }, + peg$c104 = "~u", + peg$c105 = { type: "literal", value: "~u", description: "\"~u\"" }, + peg$c106 = function(s) { return url(s); }, + peg$c107 = "~websocket", + peg$c108 = { type: "literal", value: "~websocket", description: "\"~websocket\"" }, + peg$c109 = function() { return websocketFilter; }, + peg$c110 = { type: "other", description: "integer" }, + peg$c111 = /^['"]/, + peg$c112 = { type: "class", value: "['\"]", description: "['\"]" }, + peg$c113 = /^[0-9]/, + peg$c114 = { type: "class", value: "[0-9]", description: "[0-9]" }, + peg$c115 = function(digits) { return parseInt(digits.join(""), 10); }, + peg$c116 = { type: "other", description: "string" }, + peg$c117 = "\"", + peg$c118 = { type: "literal", value: "\"", description: "\"\\\"\"" }, + peg$c119 = function(chars) { return chars.join(""); }, + peg$c120 = "'", + peg$c121 = { type: "literal", value: "'", description: "\"'\"" }, + peg$c122 = /^["\\]/, + peg$c123 = { type: "class", value: "[\"\\\\]", description: "[\"\\\\]" }, + peg$c124 = { type: "any", description: "any character" }, + peg$c125 = function(char) { return char; }, + peg$c126 = "\\", + peg$c127 = { type: "literal", value: "\\", description: "\"\\\\\"" }, + peg$c128 = /^['\\]/, + peg$c129 = { type: "class", value: "['\\\\]", description: "['\\\\]" }, + peg$c130 = /^['"\\]/, + peg$c131 = { type: "class", value: "['\"\\\\]", description: "['\"\\\\]" }, + peg$c132 = "n", + peg$c133 = { type: "literal", value: "n", description: "\"n\"" }, + peg$c134 = function() { return "\n"; }, + peg$c135 = "r", + peg$c136 = { type: "literal", value: "r", description: "\"r\"" }, + peg$c137 = function() { return "\r"; }, + peg$c138 = "t", + peg$c139 = { type: "literal", value: "t", description: "\"t\"" }, + peg$c140 = function() { return "\t"; }, peg$currPos = 0, peg$savedPos = 0, @@ -691,9 +703,9 @@ export default (function() { s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; - if (input.substr(peg$currPos, 5) === peg$c26) { + if (input.substr(peg$currPos, 2) === peg$c26) { s1 = peg$c26; - peg$currPos += 5; + peg$currPos += 2; } else { s1 = peg$FAILED; if (peg$silentFails === 0) { peg$fail(peg$c27); } @@ -713,15 +725,39 @@ export default (function() { if (peg$silentFails === 0) { peg$fail(peg$c30); } } if (s1 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$c31(); + 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$c31(s3); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; } - s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; - if (input.substr(peg$currPos, 2) === peg$c32) { + if (input.substr(peg$currPos, 3) === peg$c32) { s1 = peg$c32; - peg$currPos += 2; + peg$currPos += 3; } else { s1 = peg$FAILED; if (peg$silentFails === 0) { peg$fail(peg$c33); } @@ -795,9 +831,9 @@ export default (function() { } if (s0 === peg$FAILED) { s0 = peg$currPos; - if (input.substr(peg$currPos, 3) === peg$c38) { + if (input.substr(peg$currPos, 2) === peg$c38) { s1 = peg$c38; - peg$currPos += 3; + peg$currPos += 2; } else { s1 = peg$FAILED; if (peg$silentFails === 0) { peg$fail(peg$c39); } @@ -814,7 +850,7 @@ export default (function() { s2 = peg$FAILED; } if (s2 !== peg$FAILED) { - s3 = peg$parseStringLiteral(); + s3 = peg$parseIntegerLiteral(); if (s3 !== peg$FAILED) { peg$savedPos = s0; s1 = peg$c40(s3); @@ -833,9 +869,9 @@ export default (function() { } if (s0 === peg$FAILED) { s0 = peg$currPos; - if (input.substr(peg$currPos, 2) === peg$c41) { + if (input.substr(peg$currPos, 8) === peg$c41) { s1 = peg$c41; - peg$currPos += 2; + peg$currPos += 8; } else { s1 = peg$FAILED; if (peg$silentFails === 0) { peg$fail(peg$c42); } @@ -852,7 +888,7 @@ export default (function() { s2 = peg$FAILED; } if (s2 !== peg$FAILED) { - s3 = peg$parseIntegerLiteral(); + s3 = peg$parseStringLiteral(); if (s3 !== peg$FAILED) { peg$savedPos = s0; s1 = peg$c43(s3); @@ -1089,42 +1125,18 @@ export default (function() { s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; - if (input.substr(peg$currPos, 2) === peg$c65) { + if (input.substr(peg$currPos, 7) === peg$c65) { s1 = peg$c65; - peg$currPos += 2; + peg$currPos += 7; } 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; + peg$savedPos = s0; + s1 = peg$c67(); } + s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; if (input.substr(peg$currPos, 7) === peg$c68) { @@ -1135,10 +1147,34 @@ export default (function() { if (peg$silentFails === 0) { peg$fail(peg$c69); } } if (s1 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$c70(); + 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; } - s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; if (input.substr(peg$currPos, 2) === peg$c71) { @@ -1149,40 +1185,22 @@ export default (function() { if (peg$silentFails === 0) { peg$fail(peg$c72); } } if (s1 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$c73(); - } - s0 = s1; - 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) { - s2 = []; - s3 = peg$parsews(); - if (s3 !== peg$FAILED) { - while (s3 !== peg$FAILED) { - s2.push(s3); - s3 = peg$parsews(); - } - } else { - s2 = peg$FAILED; + s2 = []; + s3 = peg$parsews(); + if (s3 !== peg$FAILED) { + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$parsews(); } - if (s2 !== peg$FAILED) { - s3 = peg$parseStringLiteral(); - if (s3 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$c76(s3); - s0 = s1; - } else { - peg$currPos = s0; - s0 = peg$FAILED; - } + } 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; @@ -1191,11 +1209,29 @@ export default (function() { 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$c74) { + s1 = peg$c74; + peg$currPos += 2; + } 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, 2) === peg$c77) { + if (input.substr(peg$currPos, 8) === peg$c77) { s1 = peg$c77; - peg$currPos += 2; + peg$currPos += 8; } else { s1 = peg$FAILED; if (peg$silentFails === 0) { peg$fail(peg$c78); } @@ -1207,47 +1243,23 @@ export default (function() { s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; - if (input.substr(peg$currPos, 2) === peg$c80) { + if (input.substr(peg$currPos, 8) === peg$c80) { s1 = peg$c80; - peg$currPos += 2; + peg$currPos += 8; } 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; + peg$savedPos = s0; + s1 = peg$c82(); } + s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; - if (input.substr(peg$currPos, 4) === peg$c83) { + if (input.substr(peg$currPos, 7) === peg$c83) { s1 = peg$c83; - peg$currPos += 4; + peg$currPos += 7; } else { s1 = peg$FAILED; if (peg$silentFails === 0) { peg$fail(peg$c84); } @@ -1259,9 +1271,9 @@ export default (function() { s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; - if (input.substr(peg$currPos, 3) === peg$c86) { + if (input.substr(peg$currPos, 4) === peg$c86) { s1 = peg$c86; - peg$currPos += 3; + peg$currPos += 4; } else { s1 = peg$FAILED; if (peg$silentFails === 0) { peg$fail(peg$c87); } @@ -1297,68 +1309,62 @@ export default (function() { } if (s0 === peg$FAILED) { s0 = peg$currPos; - if (input.substr(peg$currPos, 3) === peg$c89) { + if (input.substr(peg$currPos, 2) === peg$c89) { s1 = peg$c89; - peg$currPos += 3; + peg$currPos += 2; } else { s1 = peg$FAILED; if (peg$silentFails === 0) { peg$fail(peg$c90); } } 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$c91(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$c91(); } + s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; - if (input.substr(peg$currPos, 2) === peg$c92) { + if (input.substr(peg$currPos, 4) === peg$c92) { s1 = peg$c92; - peg$currPos += 2; + peg$currPos += 4; } else { s1 = peg$FAILED; if (peg$silentFails === 0) { peg$fail(peg$c93); } } if (s1 !== peg$FAILED) { - s2 = []; - s3 = peg$parsews(); - if (s3 !== peg$FAILED) { - while (s3 !== peg$FAILED) { - s2.push(s3); - s3 = peg$parsews(); - } + peg$savedPos = s0; + s1 = peg$c94(); + } + s0 = s1; + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.substr(peg$currPos, 3) === peg$c95) { + s1 = peg$c95; + peg$currPos += 3; } else { - s2 = peg$FAILED; + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c96); } } - if (s2 !== peg$FAILED) { - s3 = peg$parseStringLiteral(); + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$parsews(); if (s3 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$c94(s3); - s0 = s1; + 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$c97(s3); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } } else { peg$currPos = s0; s0 = peg$FAILED; @@ -1367,32 +1373,146 @@ export default (function() { 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, 10) === peg$c95) { - s1 = peg$c95; - peg$currPos += 10; - } else { - s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c96); } - } - if (s1 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$c97(); - } - s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; - s1 = peg$parseStringLiteral(); - if (s1 !== peg$FAILED) { - peg$savedPos = s0; - s1 = peg$c94(s1); + if (input.substr(peg$currPos, 3) === peg$c98) { + s1 = peg$c98; + peg$currPos += 3; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c99); } + } + 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$c100(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$c101) { + s1 = peg$c101; + peg$currPos += 2; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c102); } + } + 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$c103(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$c104) { + s1 = peg$c104; + peg$currPos += 2; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c105); } + } + 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$c106(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, 10) === peg$c107) { + s1 = peg$c107; + peg$currPos += 10; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c108); } + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c109(); + } + s0 = s1; + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parseStringLiteral(); + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c106(s1); + } + s0 = s1; + } + } + } } - s0 = s1; } } } @@ -1427,53 +1547,53 @@ export default (function() { peg$silentFails++; s0 = peg$currPos; - if (peg$c99.test(input.charAt(peg$currPos))) { + if (peg$c111.test(input.charAt(peg$currPos))) { s1 = input.charAt(peg$currPos); peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c100); } + if (peg$silentFails === 0) { peg$fail(peg$c112); } } if (s1 === peg$FAILED) { s1 = null; } if (s1 !== peg$FAILED) { s2 = []; - if (peg$c101.test(input.charAt(peg$currPos))) { + if (peg$c113.test(input.charAt(peg$currPos))) { s3 = input.charAt(peg$currPos); peg$currPos++; } else { s3 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c102); } + if (peg$silentFails === 0) { peg$fail(peg$c114); } } if (s3 !== peg$FAILED) { while (s3 !== peg$FAILED) { s2.push(s3); - if (peg$c101.test(input.charAt(peg$currPos))) { + if (peg$c113.test(input.charAt(peg$currPos))) { s3 = input.charAt(peg$currPos); peg$currPos++; } else { s3 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c102); } + if (peg$silentFails === 0) { peg$fail(peg$c114); } } } } else { s2 = peg$FAILED; } if (s2 !== peg$FAILED) { - if (peg$c99.test(input.charAt(peg$currPos))) { + if (peg$c111.test(input.charAt(peg$currPos))) { s3 = input.charAt(peg$currPos); peg$currPos++; } else { s3 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c100); } + if (peg$silentFails === 0) { peg$fail(peg$c112); } } if (s3 === peg$FAILED) { s3 = null; } if (s3 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c103(s2); + s1 = peg$c115(s2); s0 = s1; } else { peg$currPos = s0; @@ -1490,7 +1610,7 @@ export default (function() { peg$silentFails--; if (s0 === peg$FAILED) { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c98); } + if (peg$silentFails === 0) { peg$fail(peg$c110); } } return s0; @@ -1502,11 +1622,11 @@ export default (function() { peg$silentFails++; s0 = peg$currPos; if (input.charCodeAt(peg$currPos) === 34) { - s1 = peg$c105; + s1 = peg$c117; peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c106); } + if (peg$silentFails === 0) { peg$fail(peg$c118); } } if (s1 !== peg$FAILED) { s2 = []; @@ -1517,15 +1637,15 @@ export default (function() { } if (s2 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 34) { - s3 = peg$c105; + s3 = peg$c117; peg$currPos++; } else { s3 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c106); } + if (peg$silentFails === 0) { peg$fail(peg$c118); } } if (s3 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c107(s2); + s1 = peg$c119(s2); s0 = s1; } else { peg$currPos = s0; @@ -1542,11 +1662,11 @@ export default (function() { if (s0 === peg$FAILED) { s0 = peg$currPos; if (input.charCodeAt(peg$currPos) === 39) { - s1 = peg$c108; + s1 = peg$c120; peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c109); } + if (peg$silentFails === 0) { peg$fail(peg$c121); } } if (s1 !== peg$FAILED) { s2 = []; @@ -1557,15 +1677,15 @@ export default (function() { } if (s2 !== peg$FAILED) { if (input.charCodeAt(peg$currPos) === 39) { - s3 = peg$c108; + s3 = peg$c120; peg$currPos++; } else { s3 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c109); } + if (peg$silentFails === 0) { peg$fail(peg$c121); } } if (s3 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c107(s2); + s1 = peg$c119(s2); s0 = s1; } else { peg$currPos = s0; @@ -1604,7 +1724,7 @@ export default (function() { } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c107(s2); + s1 = peg$c119(s2); s0 = s1; } else { peg$currPos = s0; @@ -1619,7 +1739,7 @@ export default (function() { peg$silentFails--; if (s0 === peg$FAILED) { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c104); } + if (peg$silentFails === 0) { peg$fail(peg$c116); } } return s0; @@ -1631,12 +1751,12 @@ export default (function() { s0 = peg$currPos; s1 = peg$currPos; peg$silentFails++; - if (peg$c110.test(input.charAt(peg$currPos))) { + if (peg$c122.test(input.charAt(peg$currPos))) { s2 = input.charAt(peg$currPos); peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c111); } + if (peg$silentFails === 0) { peg$fail(peg$c123); } } peg$silentFails--; if (s2 === peg$FAILED) { @@ -1651,11 +1771,11 @@ export default (function() { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c112); } + if (peg$silentFails === 0) { peg$fail(peg$c124); } } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c113(s2); + s1 = peg$c125(s2); s0 = s1; } else { peg$currPos = s0; @@ -1668,17 +1788,17 @@ export default (function() { if (s0 === peg$FAILED) { s0 = peg$currPos; if (input.charCodeAt(peg$currPos) === 92) { - s1 = peg$c114; + s1 = peg$c126; peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c115); } + if (peg$silentFails === 0) { peg$fail(peg$c127); } } if (s1 !== peg$FAILED) { s2 = peg$parseEscapeSequence(); if (s2 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c113(s2); + s1 = peg$c125(s2); s0 = s1; } else { peg$currPos = s0; @@ -1699,12 +1819,12 @@ export default (function() { s0 = peg$currPos; s1 = peg$currPos; peg$silentFails++; - if (peg$c116.test(input.charAt(peg$currPos))) { + if (peg$c128.test(input.charAt(peg$currPos))) { s2 = input.charAt(peg$currPos); peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c117); } + if (peg$silentFails === 0) { peg$fail(peg$c129); } } peg$silentFails--; if (s2 === peg$FAILED) { @@ -1719,11 +1839,11 @@ export default (function() { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c112); } + if (peg$silentFails === 0) { peg$fail(peg$c124); } } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c113(s2); + s1 = peg$c125(s2); s0 = s1; } else { peg$currPos = s0; @@ -1736,17 +1856,17 @@ export default (function() { if (s0 === peg$FAILED) { s0 = peg$currPos; if (input.charCodeAt(peg$currPos) === 92) { - s1 = peg$c114; + s1 = peg$c126; peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c115); } + if (peg$silentFails === 0) { peg$fail(peg$c127); } } if (s1 !== peg$FAILED) { s2 = peg$parseEscapeSequence(); if (s2 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c113(s2); + s1 = peg$c125(s2); s0 = s1; } else { peg$currPos = s0; @@ -1781,11 +1901,11 @@ export default (function() { peg$currPos++; } else { s2 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c112); } + if (peg$silentFails === 0) { peg$fail(peg$c124); } } if (s2 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c113(s2); + s1 = peg$c125(s2); s0 = s1; } else { peg$currPos = s0; @@ -1802,53 +1922,53 @@ export default (function() { function peg$parseEscapeSequence() { var s0, s1; - if (peg$c118.test(input.charAt(peg$currPos))) { + if (peg$c130.test(input.charAt(peg$currPos))) { s0 = input.charAt(peg$currPos); peg$currPos++; } else { s0 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c119); } + if (peg$silentFails === 0) { peg$fail(peg$c131); } } if (s0 === peg$FAILED) { s0 = peg$currPos; if (input.charCodeAt(peg$currPos) === 110) { - s1 = peg$c120; + s1 = peg$c132; peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c121); } + if (peg$silentFails === 0) { peg$fail(peg$c133); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c122(); + s1 = peg$c134(); } s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; if (input.charCodeAt(peg$currPos) === 114) { - s1 = peg$c123; + s1 = peg$c135; peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c124); } + if (peg$silentFails === 0) { peg$fail(peg$c136); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c125(); + s1 = peg$c137(); } s0 = s1; if (s0 === peg$FAILED) { s0 = peg$currPos; if (input.charCodeAt(peg$currPos) === 116) { - s1 = peg$c126; + s1 = peg$c138; peg$currPos++; } else { s1 = peg$FAILED; - if (peg$silentFails === 0) { peg$fail(peg$c127); } + if (peg$silentFails === 0) { peg$fail(peg$c139); } } if (s1 !== peg$FAILED) { peg$savedPos = s0; - s1 = peg$c128(); + s1 = peg$c140(); } s0 = s1; } @@ -1867,6 +1987,7 @@ export default (function() { orFilter.desc = first.desc + " or " + second.desc; return orFilter; } + function and(first, second) { function andFilter() { return first.apply(this, arguments) && second.apply(this, arguments); @@ -1874,6 +1995,7 @@ export default (function() { andFilter.desc = first.desc + " and " + second.desc; return andFilter; } + function not(expr) { function notFilter() { return !expr.apply(this, arguments); @@ -1881,6 +2003,7 @@ export default (function() { notFilter.desc = "not " + expr.desc; return notFilter; } + function binding(expr) { function bindingFilter() { return expr.apply(this, arguments); @@ -1888,22 +2011,20 @@ export default (function() { bindingFilter.desc = "(" + expr.desc + ")"; return bindingFilter; } - function trueFilter(flow) { + + // ~all + function allFilter(flow) { return true; } - trueFilter.desc = "true"; - function falseFilter(flow) { - return false; - } - falseFilter.desc = "false"; + allFilter.desc = "all flows"; + // ~a var ASSET_TYPES = [ new RegExp("text/javascript"), new RegExp("application/x-javascript"), new RegExp("application/javascript"), new RegExp("text/css"), - new RegExp("image/.*"), - new RegExp("application/x-shockwave-flash") + new RegExp("image/.*") ]; function assetFilter(flow) { if (flow.response) { @@ -1918,13 +2039,8 @@ export default (function() { return false; } assetFilter.desc = "is asset"; - function responseCode(code){ - function responseCodeFilter(flow){ - return flow.response && flow.response.status_code === code; - } - responseCodeFilter.desc = "resp. code is " + code; - return responseCodeFilter; - } + + // ~b function body(regex){ regex = new RegExp(regex, "i"); function bodyFilter(flow){ @@ -1933,6 +2049,8 @@ export default (function() { bodyFilter.desc = "body filters are not implemented yet, see https://github.com/mitmproxy/mitmweb/issues/10"; return bodyFilter; } + + // ~bq function requestBody(regex){ regex = new RegExp(regex, "i"); function requestBodyFilter(flow){ @@ -1941,6 +2059,8 @@ export default (function() { requestBodyFilter.desc = "body filters are not implemented yet, see https://github.com/mitmproxy/mitmweb/issues/10"; return requestBodyFilter; } + + // ~bs function responseBody(regex){ regex = new RegExp(regex, "i"); function responseBodyFilter(flow){ @@ -1949,6 +2069,27 @@ export default (function() { responseBodyFilter.desc = "body filters are not implemented yet, see https://github.com/mitmproxy/mitmweb/issues/10"; return responseBodyFilter; } + + // ~c + function responseCode(code){ + function responseCodeFilter(flow){ + return flow.response && flow.response.status_code === code; + } + responseCodeFilter.desc = "resp. code is " + code; + return responseCodeFilter; + } + + // ~comment + function comment(regex){ + regex = new RegExp(regex, "i"); + function commentFilter(flow){ + return regex.test(flow.comment) + } + commentFilter.desc = "comment matches " + regex; + return commentFilter; + } + + // ~d function domain(regex){ regex = new RegExp(regex, "i"); function domainFilter(flow){ @@ -1957,6 +2098,8 @@ export default (function() { domainFilter.desc = "domain matches " + regex; return domainFilter; } + + // ~dst function destination(regex){ regex = new RegExp(regex, "i"); function destinationFilter(flow){ @@ -1967,10 +2110,14 @@ export default (function() { destinationFilter.desc = "destination address matches " + regex; return destinationFilter; } + + // ~e function errorFilter(flow){ return !!flow.error; } errorFilter.desc = "has error"; + + // ~h function header(regex){ regex = new RegExp(regex, "i"); function headerFilter(flow){ @@ -1983,6 +2130,8 @@ export default (function() { headerFilter.desc = "header matches " + regex; return headerFilter; } + + // ~hq function requestHeader(regex){ regex = new RegExp(regex, "i"); function requestHeaderFilter(flow){ @@ -1991,6 +2140,8 @@ export default (function() { requestHeaderFilter.desc = "req. header matches " + regex; return requestHeaderFilter; } + + // ~hs function responseHeader(regex){ regex = new RegExp(regex, "i"); function responseHeaderFilter(flow){ @@ -1999,10 +2150,30 @@ export default (function() { responseHeaderFilter.desc = "resp. header matches " + regex; return responseHeaderFilter; } + + // ~http function httpFilter(flow){ return flow.type === "http"; } httpFilter.desc = "is an HTTP Flow"; + + // ~marked + function markedFilter(flow){ + return flow.marked; + } + markedFilter.desc = "is marked"; + + // ~marker + function marker(regex){ + regex = new RegExp(regex, "i"); + function markerFilter(flow){ + return regex.test(flow.marked) + } + markerFilter.desc = "marker matches " + regex; + return markerFilter; + } + + // ~m function method(regex){ regex = new RegExp(regex, "i"); function methodFilter(flow){ @@ -2011,18 +2182,32 @@ export default (function() { methodFilter.desc = "method matches " + regex; return methodFilter; } - function markedFilter(flow){ - return flow.marked; - } - markedFilter.desc = "is marked"; + + // ~q function noResponseFilter(flow){ return flow.request && !flow.response; } noResponseFilter.desc = "has no response"; - function responseFilter(flow){ - return !!flow.response; + + // ~replayq + function clientReplayFilter(flow){ + return flow.is_replay === "request"; } - responseFilter.desc = "has response"; + clientReplayFilter.desc = "request has been replayed"; + + // ~replays + function serverReplayFilter(flow){ + return flow.is_replay === "response"; + } + serverReplayFilter.desc = "response has been replayed"; + + // ~replay + function replayFilter(flow){ + return !!flow.is_replay; + } + replayFilter.desc = "flow has been replayed"; + + // ~src function source(regex){ regex = new RegExp(regex, "i"); function sourceFilter(flow){ @@ -2033,6 +2218,40 @@ export default (function() { sourceFilter.desc = "source address matches " + regex; return sourceFilter; } + + // ~s + function responseFilter(flow){ + return !!flow.response; + } + responseFilter.desc = "has response"; + + // ~tcp + function tcpFilter(flow){ + return flow.type === "tcp"; + } + tcpFilter.desc = "is a TCP Flow"; + + // ~tq + function requestContentType(regex){ + regex = new RegExp(regex, "i"); + function requestContentTypeFilter(flow){ + return flow.request && regex.test(flowutils.RequestUtils.getContentType(flow.request)); + } + requestContentTypeFilter.desc = "req. content type matches " + regex; + return requestContentTypeFilter; + } + + // ~ts + function responseContentType(regex){ + regex = new RegExp(regex, "i"); + function responseContentTypeFilter(flow){ + return flow.response && regex.test(flowutils.ResponseUtils.getContentType(flow.response)); + } + responseContentTypeFilter.desc = "resp. content type matches " + regex; + return responseContentTypeFilter; + } + + // ~t function contentType(regex){ regex = new RegExp(regex, "i"); function contentTypeFilter(flow){ @@ -2045,26 +2264,8 @@ export default (function() { contentTypeFilter.desc = "content type matches " + regex; return contentTypeFilter; } - function tcpFilter(flow){ - return flow.type === "tcp"; - } - tcpFilter.desc = "is a TCP Flow"; - function requestContentType(regex){ - regex = new RegExp(regex, "i"); - function requestContentTypeFilter(flow){ - return flow.request && regex.test(flowutils.RequestUtils.getContentType(flow.request)); - } - requestContentTypeFilter.desc = "req. content type matches " + regex; - return requestContentTypeFilter; - } - function responseContentType(regex){ - regex = new RegExp(regex, "i"); - function responseContentTypeFilter(flow){ - return flow.response && regex.test(flowutils.ResponseUtils.getContentType(flow.response)); - } - responseContentTypeFilter.desc = "resp. content type matches " + regex; - return responseContentTypeFilter; - } + + // ~u function url(regex){ regex = new RegExp(regex, "i"); function urlFilter(flow){ @@ -2073,6 +2274,8 @@ export default (function() { urlFilter.desc = "url matches " + regex; return urlFilter; } + + // ~websocket function websocketFilter(flow){ return flow.type === "websocket"; } diff --git a/web/src/js/filt/filt.peg b/web/src/js/filt/filt.peg index 987de5876..bca8bdddf 100644 --- a/web/src/js/filt/filt.peg +++ b/web/src/js/filt/filt.peg @@ -1,5 +1,4 @@ // PEG.js filter rules - see https://pegjs.org/ - { function or(first, second) { // Add explicit function names to ease debugging. @@ -9,6 +8,7 @@ function or(first, second) { orFilter.desc = first.desc + " or " + second.desc; return orFilter; } + function and(first, second) { function andFilter() { return first.apply(this, arguments) && second.apply(this, arguments); @@ -16,6 +16,7 @@ function and(first, second) { andFilter.desc = first.desc + " and " + second.desc; return andFilter; } + function not(expr) { function notFilter() { return !expr.apply(this, arguments); @@ -23,6 +24,7 @@ function not(expr) { notFilter.desc = "not " + expr.desc; return notFilter; } + function binding(expr) { function bindingFilter() { return expr.apply(this, arguments); @@ -30,22 +32,20 @@ function binding(expr) { bindingFilter.desc = "(" + expr.desc + ")"; return bindingFilter; } -function trueFilter(flow) { + +// ~all +function allFilter(flow) { return true; } -trueFilter.desc = "true"; -function falseFilter(flow) { - return false; -} -falseFilter.desc = "false"; +allFilter.desc = "all flows"; +// ~a var ASSET_TYPES = [ new RegExp("text/javascript"), new RegExp("application/x-javascript"), new RegExp("application/javascript"), new RegExp("text/css"), - new RegExp("image/.*"), - new RegExp("application/x-shockwave-flash") + new RegExp("image/.*") ]; function assetFilter(flow) { if (flow.response) { @@ -60,13 +60,8 @@ function assetFilter(flow) { return false; } assetFilter.desc = "is asset"; -function responseCode(code){ - function responseCodeFilter(flow){ - return flow.response && flow.response.status_code === code; - } - responseCodeFilter.desc = "resp. code is " + code; - return responseCodeFilter; -} + +// ~b function body(regex){ regex = new RegExp(regex, "i"); function bodyFilter(flow){ @@ -75,6 +70,8 @@ function body(regex){ bodyFilter.desc = "body filters are not implemented yet, see https://github.com/mitmproxy/mitmweb/issues/10"; return bodyFilter; } + +// ~bq function requestBody(regex){ regex = new RegExp(regex, "i"); function requestBodyFilter(flow){ @@ -83,6 +80,8 @@ function requestBody(regex){ requestBodyFilter.desc = "body filters are not implemented yet, see https://github.com/mitmproxy/mitmweb/issues/10"; return requestBodyFilter; } + +// ~bs function responseBody(regex){ regex = new RegExp(regex, "i"); function responseBodyFilter(flow){ @@ -91,6 +90,27 @@ function responseBody(regex){ responseBodyFilter.desc = "body filters are not implemented yet, see https://github.com/mitmproxy/mitmweb/issues/10"; return responseBodyFilter; } + +// ~c +function responseCode(code){ + function responseCodeFilter(flow){ + return flow.response && flow.response.status_code === code; + } + responseCodeFilter.desc = "resp. code is " + code; + return responseCodeFilter; +} + +// ~comment +function comment(regex){ + regex = new RegExp(regex, "i"); + function commentFilter(flow){ + return regex.test(flow.comment) + } + commentFilter.desc = "comment matches " + regex; + return commentFilter; +} + +// ~d function domain(regex){ regex = new RegExp(regex, "i"); function domainFilter(flow){ @@ -99,6 +119,8 @@ function domain(regex){ domainFilter.desc = "domain matches " + regex; return domainFilter; } + +// ~dst function destination(regex){ regex = new RegExp(regex, "i"); function destinationFilter(flow){ @@ -109,10 +131,14 @@ function destination(regex){ destinationFilter.desc = "destination address matches " + regex; return destinationFilter; } + +// ~e function errorFilter(flow){ return !!flow.error; } errorFilter.desc = "has error"; + +// ~h function header(regex){ regex = new RegExp(regex, "i"); function headerFilter(flow){ @@ -125,6 +151,8 @@ function header(regex){ headerFilter.desc = "header matches " + regex; return headerFilter; } + +// ~hq function requestHeader(regex){ regex = new RegExp(regex, "i"); function requestHeaderFilter(flow){ @@ -133,6 +161,8 @@ function requestHeader(regex){ requestHeaderFilter.desc = "req. header matches " + regex; return requestHeaderFilter; } + +// ~hs function responseHeader(regex){ regex = new RegExp(regex, "i"); function responseHeaderFilter(flow){ @@ -141,10 +171,30 @@ function responseHeader(regex){ responseHeaderFilter.desc = "resp. header matches " + regex; return responseHeaderFilter; } + +// ~http function httpFilter(flow){ return flow.type === "http"; } httpFilter.desc = "is an HTTP Flow"; + +// ~marked +function markedFilter(flow){ + return flow.marked; +} +markedFilter.desc = "is marked"; + +// ~marker +function marker(regex){ + regex = new RegExp(regex, "i"); + function markerFilter(flow){ + return regex.test(flow.marked) + } + markerFilter.desc = "marker matches " + regex; + return markerFilter; +} + +// ~m function method(regex){ regex = new RegExp(regex, "i"); function methodFilter(flow){ @@ -153,18 +203,32 @@ function method(regex){ methodFilter.desc = "method matches " + regex; return methodFilter; } -function markedFilter(flow){ - return flow.marked; -} -markedFilter.desc = "is marked"; + +// ~q function noResponseFilter(flow){ return flow.request && !flow.response; } noResponseFilter.desc = "has no response"; -function responseFilter(flow){ - return !!flow.response; + +// ~replayq +function clientReplayFilter(flow){ + return flow.is_replay === "request"; } -responseFilter.desc = "has response"; +clientReplayFilter.desc = "request has been replayed"; + +// ~replays +function serverReplayFilter(flow){ + return flow.is_replay === "response"; +} +serverReplayFilter.desc = "response has been replayed"; + +// ~replay +function replayFilter(flow){ + return !!flow.is_replay; +} +replayFilter.desc = "flow has been replayed"; + +// ~src function source(regex){ regex = new RegExp(regex, "i"); function sourceFilter(flow){ @@ -175,6 +239,40 @@ function source(regex){ sourceFilter.desc = "source address matches " + regex; return sourceFilter; } + +// ~s +function responseFilter(flow){ + return !!flow.response; +} +responseFilter.desc = "has response"; + +// ~tcp +function tcpFilter(flow){ + return flow.type === "tcp"; +} +tcpFilter.desc = "is a TCP Flow"; + +// ~tq +function requestContentType(regex){ + regex = new RegExp(regex, "i"); + function requestContentTypeFilter(flow){ + return flow.request && regex.test(flowutils.RequestUtils.getContentType(flow.request)); + } + requestContentTypeFilter.desc = "req. content type matches " + regex; + return requestContentTypeFilter; +} + +// ~ts +function responseContentType(regex){ + regex = new RegExp(regex, "i"); + function responseContentTypeFilter(flow){ + return flow.response && regex.test(flowutils.ResponseUtils.getContentType(flow.response)); + } + responseContentTypeFilter.desc = "resp. content type matches " + regex; + return responseContentTypeFilter; +} + +// ~t function contentType(regex){ regex = new RegExp(regex, "i"); function contentTypeFilter(flow){ @@ -187,26 +285,8 @@ function contentType(regex){ contentTypeFilter.desc = "content type matches " + regex; return contentTypeFilter; } -function tcpFilter(flow){ - return flow.type === "tcp"; -} -tcpFilter.desc = "is a TCP Flow"; -function requestContentType(regex){ - regex = new RegExp(regex, "i"); - function requestContentTypeFilter(flow){ - return flow.request && regex.test(flowutils.RequestUtils.getContentType(flow.request)); - } - requestContentTypeFilter.desc = "req. content type matches " + regex; - return requestContentTypeFilter; -} -function responseContentType(regex){ - regex = new RegExp(regex, "i"); - function responseContentTypeFilter(flow){ - return flow.response && regex.test(flowutils.ResponseUtils.getContentType(flow.response)); - } - responseContentTypeFilter.desc = "resp. content type matches " + regex; - return responseContentTypeFilter; -} + +// ~u function url(regex){ regex = new RegExp(regex, "i"); function urlFilter(flow){ @@ -215,6 +295,8 @@ function url(regex){ urlFilter.desc = "url matches " + regex; return urlFilter; } + +// ~websocket function websocketFilter(flow){ return flow.type === "websocket"; } @@ -250,19 +332,18 @@ BindingExpr { return binding(expr); } / Expr -/* All the filters except "~s" and "~src" are arranged in the ascending order as - given in the docs(https://mitmproxy.org/docs/latest/concepts-filters/). - "~s" and "~src" are so arranged as "~s" caused problems in the evaluation of - "~src". */ +/* All the filters are generally arranged in the order as they are described + on https://docs.mitmproxy.org/dev/concepts-filters/, with the exception of + single-letter filters, which are moved to the bottom so that they evaluate properly */ Expr - = "true" { return trueFilter; } - / "false" { return falseFilter; } + = "~all" { return allFilter; } / "~a" { return assetFilter; } / "~b" ws+ s:StringLiteral { return body(s); } / "~bq" ws+ s:StringLiteral { return requestBody(s); } / "~bs" ws+ s:StringLiteral { return responseBody(s); } / "~c" ws+ s:IntegerLiteral { return responseCode(s); } + / "~comment" ws+ s:StringLiteral { return comment(s); } / "~d" ws+ s:StringLiteral { return domain(s); } / "~dst" ws+ s:StringLiteral { return destination(s); } / "~e" { return errorFilter; } @@ -270,15 +351,19 @@ Expr / "~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; } + / "~marker" ws+ s:StringLiteral { return marker(s); } + / "~m" ws+ s:StringLiteral { return method(s); } / "~q" { return noResponseFilter; } + / "~replayq" { return clientReplayFilter; } + / "~replays" { return serverReplayFilter; } + / "~replay" { return replayFilter; } / "~src" ws+ s:StringLiteral { return source(s); } / "~s" { return responseFilter; } - / "~t" ws+ s:StringLiteral { return contentType(s); } / "~tcp" { return tcpFilter; } / "~tq" ws+ s:StringLiteral { return requestContentType(s); } / "~ts" ws+ s:StringLiteral { return responseContentType(s); } + / "~t" ws+ s:StringLiteral { return contentType(s); } / "~u" ws+ s:StringLiteral { return url(s); } / "~websocket" { return websocketFilter; } / s:StringLiteral { return url(s); } diff --git a/web/src/js/flow.ts b/web/src/js/flow.ts index 5f79425d0..1d46b027d 100644 --- a/web/src/js/flow.ts +++ b/web/src/js/flow.ts @@ -8,6 +8,7 @@ interface _Flow { type: string modified: boolean marked: string + comment: string client_conn: Client server_conn?: Server error?: Error