From 5ccae48b92b093d68c8df8e557624cfb29d9c2fa Mon Sep 17 00:00:00 2001 From: Maximilian Hils Date: Fri, 12 Dec 2014 19:19:00 +0100 Subject: [PATCH] web: fight against react-router --- libmproxy/web/static/css/app.css | 2 + libmproxy/web/static/js/app.js | 1750 ++++++++++++++++++++++- web/src/css/flowdetail.less | 2 + web/src/js/actions.js | 4 + web/src/js/components/flowdetail.jsx.js | 2 +- web/src/js/components/header.jsx.js | 36 +- web/src/js/components/mainview.jsx.js | 4 +- web/src/js/utils.js | 44 + 8 files changed, 1825 insertions(+), 19 deletions(-) diff --git a/libmproxy/web/static/css/app.css b/libmproxy/web/static/css/app.css index 9e0d241b8..b99cd2d71 100644 --- a/libmproxy/web/static/css/app.css +++ b/libmproxy/web/static/css/app.css @@ -206,6 +206,8 @@ header .menu { padding: 4px 8px; border-radius: 5px; word-break: break-all; + max-height: 100px; + overflow-y: auto; } .flow-detail table { font-family: Menlo, Monaco, Consolas, "Courier New", monospace; diff --git a/libmproxy/web/static/js/app.js b/libmproxy/web/static/js/app.js index d90610de9..6a886c11e 100644 --- a/libmproxy/web/static/js/app.js +++ b/libmproxy/web/static/js/app.js @@ -23,6 +23,50 @@ var StickyHeadMixin = { }; +var Navigation = _.extend({}, ReactRouter.Navigation, { + setQuery: function (k, v) { + var q = this.context.getCurrentQuery(); + q[k] = v; + this.replaceWith(this.context.getCurrentPath(), this.context.getCurrentParams(), q); + }, + replaceWith: function(routeNameOrPath, params, query) { + if(routeNameOrPath === undefined){ + routeNameOrPath = this.context.getCurrentPath(); + } + if(params === undefined){ + params = this.context.getCurrentParams(); + } + if(query === undefined){ + query = this.context.getCurrentQuery(); + } + ReactRouter.Navigation.replaceWith.call(this,routeNameOrPath, params, query); + } +}); + +var State = _.extend({}, ReactRouter.State, { + getInitialState: function () { + this._query = this.context.getCurrentQuery(); + this._queryWatches = []; + return null; + }, + onQueryChange: function (key, callback) { + this._queryWatches.push({ + key: key, + callback: callback + }); + }, + componentWillReceiveProps: function (nextProps, nextState) { + var q = this.context.getCurrentQuery(); + for (var i = 0; i < this._queryWatches.length; i++) { + var watch = this._queryWatches[i]; + if (this._query[watch.key] !== q[watch.key]) { + watch.callback(this._query[watch.key], q[watch.key], watch.key); + } + } + this._query = q; + } +}); + var Key = { UP: 38, DOWN: 40, @@ -202,6 +246,1657 @@ var EventLogActions = { }); } }; + +Query = { + FILTER: "f" +}; +Filt = (function() { + /* + * Generated by PEG.js 0.8.0. + * + * http://pegjs.majda.cz/ + */ + + function peg$subclass(child, parent) { + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor(); + } + + function SyntaxError(message, expected, found, offset, line, column) { + this.message = message; + this.expected = expected; + this.found = found; + this.offset = offset; + this.line = line; + this.column = column; + + this.name = "SyntaxError"; + } + + peg$subclass(SyntaxError, Error); + + function parse(input) { + var options = arguments.length > 1 ? arguments[1] : {}, + + peg$FAILED = {}, + + peg$startRuleFunctions = { start: peg$parsestart }, + peg$startRuleFunction = peg$parsestart, + + peg$c0 = { type: "other", description: "filter expression" }, + peg$c1 = peg$FAILED, + peg$c2 = function(orExpr) { return orExpr; }, + peg$c3 = { type: "other", description: "whitespace" }, + peg$c4 = /^[ \t\n\r]/, + peg$c5 = { type: "class", value: "[ \\t\\n\\r]", description: "[ \\t\\n\\r]" }, + peg$c6 = { type: "other", description: "control character" }, + peg$c7 = /^[|&!()~"]/, + peg$c8 = { type: "class", value: "[|&!()~\"]", description: "[|&!()~\"]" }, + peg$c9 = { type: "other", description: "optional whitespace" }, + peg$c10 = [], + peg$c11 = "|", + peg$c12 = { type: "literal", value: "|", description: "\"|\"" }, + peg$c13 = function(first, second) { return or(first, second); }, + peg$c14 = "&", + peg$c15 = { type: "literal", value: "&", description: "\"&\"" }, + peg$c16 = function(first, second) { return and(first, second); }, + peg$c17 = "!", + peg$c18 = { type: "literal", value: "!", description: "\"!\"" }, + peg$c19 = function(expr) { return not(expr); }, + peg$c20 = "(", + peg$c21 = { type: "literal", value: "(", description: "\"(\"" }, + peg$c22 = ")", + peg$c23 = { type: "literal", value: ")", description: "\")\"" }, + peg$c24 = function(expr) { return binding(orExpr); }, + peg$c25 = "~a", + peg$c26 = { type: "literal", value: "~a", description: "\"~a\"" }, + peg$c27 = function() { return assetFilter; }, + peg$c28 = "~e", + peg$c29 = { type: "literal", value: "~e", description: "\"~e\"" }, + peg$c30 = function() { return errorFilter; }, + peg$c31 = "~q", + peg$c32 = { type: "literal", value: "~q", description: "\"~q\"" }, + peg$c33 = function() { return noResponseFilter; }, + peg$c34 = "~s", + peg$c35 = { type: "literal", value: "~s", description: "\"~s\"" }, + peg$c36 = function() { return responseFilter; }, + peg$c37 = "true", + peg$c38 = { type: "literal", value: "true", description: "\"true\"" }, + peg$c39 = function() { return trueFilter; }, + peg$c40 = "false", + peg$c41 = { type: "literal", value: "false", description: "\"false\"" }, + peg$c42 = function() { return falseFilter; }, + peg$c43 = "~c", + peg$c44 = { type: "literal", value: "~c", description: "\"~c\"" }, + peg$c45 = function(s) { return responseCode(s); }, + peg$c46 = "~d", + peg$c47 = { type: "literal", value: "~d", description: "\"~d\"" }, + peg$c48 = function(s) { return domain(s); }, + peg$c49 = "~h", + peg$c50 = { type: "literal", value: "~h", description: "\"~h\"" }, + peg$c51 = function(s) { return header(s); }, + peg$c52 = "~hq", + peg$c53 = { type: "literal", value: "~hq", description: "\"~hq\"" }, + peg$c54 = function(s) { return requestHeader(s); }, + peg$c55 = "~hs", + peg$c56 = { type: "literal", value: "~hs", description: "\"~hs\"" }, + peg$c57 = function(s) { return responseHeader(s); }, + peg$c58 = "~m", + peg$c59 = { type: "literal", value: "~m", description: "\"~m\"" }, + peg$c60 = function(s) { return method(s); }, + peg$c61 = "~t", + peg$c62 = { type: "literal", value: "~t", description: "\"~t\"" }, + peg$c63 = function(s) { return contentType(s); }, + peg$c64 = "~tq", + peg$c65 = { type: "literal", value: "~tq", description: "\"~tq\"" }, + peg$c66 = function(s) { return requestContentType(s); }, + peg$c67 = "~ts", + peg$c68 = { type: "literal", value: "~ts", description: "\"~ts\"" }, + peg$c69 = function(s) { return responseContentType(s); }, + peg$c70 = "~u", + peg$c71 = { type: "literal", value: "~u", description: "\"~u\"" }, + peg$c72 = function(s) { return url(s); }, + peg$c73 = { type: "other", description: "string" }, + peg$c74 = "\"", + peg$c75 = { type: "literal", value: "\"", description: "\"\\\"\"" }, + peg$c76 = function(chars) { return chars.join(""); }, + peg$c77 = "'", + peg$c78 = { type: "literal", value: "'", description: "\"'\"" }, + peg$c79 = void 0, + peg$c80 = /^["\\]/, + peg$c81 = { type: "class", value: "[\"\\\\]", description: "[\"\\\\]" }, + peg$c82 = { type: "any", description: "any character" }, + peg$c83 = function(char) { return char; }, + peg$c84 = "\\", + peg$c85 = { type: "literal", value: "\\", description: "\"\\\\\"" }, + peg$c86 = /^['\\]/, + peg$c87 = { type: "class", value: "['\\\\]", description: "['\\\\]" }, + peg$c88 = /^['"\\]/, + peg$c89 = { type: "class", value: "['\"\\\\]", description: "['\"\\\\]" }, + peg$c90 = "n", + peg$c91 = { type: "literal", value: "n", description: "\"n\"" }, + peg$c92 = function() { return "\n"; }, + peg$c93 = "r", + peg$c94 = { type: "literal", value: "r", description: "\"r\"" }, + peg$c95 = function() { return "\r"; }, + peg$c96 = "t", + peg$c97 = { type: "literal", value: "t", description: "\"t\"" }, + peg$c98 = function() { return "\t"; }, + + peg$currPos = 0, + peg$reportedPos = 0, + peg$cachedPos = 0, + peg$cachedPosDetails = { line: 1, column: 1, seenCR: false }, + peg$maxFailPos = 0, + peg$maxFailExpected = [], + peg$silentFails = 0, + + peg$result; + + if ("startRule" in options) { + if (!(options.startRule in peg$startRuleFunctions)) { + throw new Error("Can't start parsing from rule \"" + options.startRule + "\"."); + } + + peg$startRuleFunction = peg$startRuleFunctions[options.startRule]; + } + + function text() { + return input.substring(peg$reportedPos, peg$currPos); + } + + function offset() { + return peg$reportedPos; + } + + function line() { + return peg$computePosDetails(peg$reportedPos).line; + } + + function column() { + return peg$computePosDetails(peg$reportedPos).column; + } + + function expected(description) { + throw peg$buildException( + null, + [{ type: "other", description: description }], + peg$reportedPos + ); + } + + function error(message) { + throw peg$buildException(message, null, peg$reportedPos); + } + + function peg$computePosDetails(pos) { + function advance(details, startPos, endPos) { + var p, ch; + + for (p = startPos; p < endPos; p++) { + ch = input.charAt(p); + if (ch === "\n") { + if (!details.seenCR) { details.line++; } + details.column = 1; + details.seenCR = false; + } else if (ch === "\r" || ch === "\u2028" || ch === "\u2029") { + details.line++; + details.column = 1; + details.seenCR = true; + } else { + details.column++; + details.seenCR = false; + } + } + } + + if (peg$cachedPos !== pos) { + if (peg$cachedPos > pos) { + peg$cachedPos = 0; + peg$cachedPosDetails = { line: 1, column: 1, seenCR: false }; + } + advance(peg$cachedPosDetails, peg$cachedPos, pos); + peg$cachedPos = pos; + } + + return peg$cachedPosDetails; + } + + function peg$fail(expected) { + if (peg$currPos < peg$maxFailPos) { return; } + + if (peg$currPos > peg$maxFailPos) { + peg$maxFailPos = peg$currPos; + peg$maxFailExpected = []; + } + + peg$maxFailExpected.push(expected); + } + + function peg$buildException(message, expected, pos) { + function cleanupExpected(expected) { + var i = 1; + + expected.sort(function(a, b) { + if (a.description < b.description) { + return -1; + } else if (a.description > b.description) { + return 1; + } else { + return 0; + } + }); + + while (i < expected.length) { + if (expected[i - 1] === expected[i]) { + expected.splice(i, 1); + } else { + i++; + } + } + } + + function buildMessage(expected, found) { + function stringEscape(s) { + function hex(ch) { return ch.charCodeAt(0).toString(16).toUpperCase(); } + + return s + .replace(/\\/g, '\\\\') + .replace(/"/g, '\\"') + .replace(/\x08/g, '\\b') + .replace(/\t/g, '\\t') + .replace(/\n/g, '\\n') + .replace(/\f/g, '\\f') + .replace(/\r/g, '\\r') + .replace(/[\x00-\x07\x0B\x0E\x0F]/g, function(ch) { return '\\x0' + hex(ch); }) + .replace(/[\x10-\x1F\x80-\xFF]/g, function(ch) { return '\\x' + hex(ch); }) + .replace(/[\u0180-\u0FFF]/g, function(ch) { return '\\u0' + hex(ch); }) + .replace(/[\u1080-\uFFFF]/g, function(ch) { return '\\u' + hex(ch); }); + } + + var expectedDescs = new Array(expected.length), + expectedDesc, foundDesc, i; + + for (i = 0; i < expected.length; i++) { + expectedDescs[i] = expected[i].description; + } + + expectedDesc = (expected.length > 1 + ? expectedDescs.slice(0, -1).join(", ") + + " or " + + expectedDescs[expected.length - 1] + : expectedDescs[0]); + + foundDesc = found ? "\"" + stringEscape(found) + "\"" : "end of input"; + + return "Expected " + expectedDesc + " but " + foundDesc + " found."; + } + + var posDetails = peg$computePosDetails(pos), + found = pos < input.length ? input.charAt(pos) : null; + + if (expected !== null) { + cleanupExpected(expected); + } + + return new SyntaxError( + message !== null ? message : buildMessage(expected, found), + expected, + found, + pos, + posDetails.line, + posDetails.column + ); + } + + function peg$parsestart() { + var s0, s1, s2, s3; + + peg$silentFails++; + s0 = peg$currPos; + s1 = peg$parse__(); + if (s1 !== peg$FAILED) { + s2 = peg$parseOrExpr(); + if (s2 !== peg$FAILED) { + s3 = peg$parse__(); + if (s3 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c2(s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + peg$silentFails--; + if (s0 === peg$FAILED) { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c0); } + } + + return s0; + } + + function peg$parsews() { + var s0, s1; + + peg$silentFails++; + if (peg$c4.test(input.charAt(peg$currPos))) { + s0 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c5); } + } + peg$silentFails--; + if (s0 === peg$FAILED) { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c3); } + } + + return s0; + } + + function peg$parsecc() { + var s0, s1; + + peg$silentFails++; + if (peg$c7.test(input.charAt(peg$currPos))) { + s0 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c8); } + } + peg$silentFails--; + if (s0 === peg$FAILED) { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c6); } + } + + return s0; + } + + function peg$parse__() { + var s0, s1; + + peg$silentFails++; + s0 = []; + s1 = peg$parsews(); + while (s1 !== peg$FAILED) { + s0.push(s1); + s1 = peg$parsews(); + } + peg$silentFails--; + if (s0 === peg$FAILED) { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c9); } + } + + return s0; + } + + function peg$parseOrExpr() { + var s0, s1, s2, s3, s4, s5; + + s0 = peg$currPos; + s1 = peg$parseAndExpr(); + if (s1 !== peg$FAILED) { + s2 = peg$parse__(); + if (s2 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 124) { + s3 = peg$c11; + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c12); } + } + if (s3 !== peg$FAILED) { + s4 = peg$parse__(); + if (s4 !== peg$FAILED) { + s5 = peg$parseOrExpr(); + if (s5 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c13(s1, s5); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + if (s0 === peg$FAILED) { + s0 = peg$parseAndExpr(); + } + + return s0; + } + + function peg$parseAndExpr() { + var s0, s1, s2, s3, s4, s5; + + s0 = peg$currPos; + s1 = peg$parseNotExpr(); + if (s1 !== peg$FAILED) { + s2 = peg$parse__(); + if (s2 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 38) { + s3 = peg$c14; + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c15); } + } + if (s3 !== peg$FAILED) { + s4 = peg$parse__(); + if (s4 !== peg$FAILED) { + s5 = peg$parseAndExpr(); + if (s5 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c16(s1, s5); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parseNotExpr(); + 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$c1; + } + if (s2 !== peg$FAILED) { + s3 = peg$parseAndExpr(); + if (s3 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c16(s1, s3); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + if (s0 === peg$FAILED) { + s0 = peg$parseNotExpr(); + } + } + + return s0; + } + + function peg$parseNotExpr() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 33) { + s1 = peg$c17; + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c18); } + } + if (s1 !== peg$FAILED) { + s2 = peg$parse__(); + if (s2 !== peg$FAILED) { + s3 = peg$parseNotExpr(); + if (s3 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c19(s3); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + if (s0 === peg$FAILED) { + s0 = peg$parseBindingExpr(); + } + + return s0; + } + + function peg$parseBindingExpr() { + var s0, s1, s2, s3, s4, s5; + + s0 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 40) { + s1 = peg$c20; + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c21); } + } + if (s1 !== peg$FAILED) { + s2 = peg$parse__(); + if (s2 !== peg$FAILED) { + s3 = peg$parseOrExpr(); + if (s3 !== peg$FAILED) { + s4 = peg$parse__(); + if (s4 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 41) { + s5 = peg$c22; + peg$currPos++; + } else { + s5 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c23); } + } + if (s5 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c24(s3); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + if (s0 === peg$FAILED) { + s0 = peg$parseExpr(); + } + + return s0; + } + + 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$c25) { + s1 = peg$c25; + peg$currPos += 2; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c26); } + } + if (s1 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c27(); + } + s0 = s1; + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.substr(peg$currPos, 2) === peg$c28) { + s1 = peg$c28; + peg$currPos += 2; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c29); } + } + if (s1 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c30(); + } + s0 = s1; + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.substr(peg$currPos, 2) === peg$c31) { + s1 = peg$c31; + peg$currPos += 2; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c32); } + } + if (s1 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c33(); + } + s0 = s1; + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.substr(peg$currPos, 2) === peg$c34) { + s1 = peg$c34; + peg$currPos += 2; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c35); } + } + if (s1 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c36(); + } + s0 = s1; + } + } + } + } + + return s0; + } + + function peg$parseBooleanLiteral() { + var s0, s1; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 4) === peg$c37) { + s1 = peg$c37; + peg$currPos += 4; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c38); } + } + if (s1 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c39(); + } + s0 = s1; + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.substr(peg$currPos, 5) === peg$c40) { + s1 = peg$c40; + peg$currPos += 5; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c41); } + } + if (s1 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c42(); + } + s0 = s1; + } + + return s0; + } + + function peg$parseUnaryExpr() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (input.substr(peg$currPos, 2) === peg$c43) { + s1 = peg$c43; + peg$currPos += 2; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c44); } + } + 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$c1; + } + if (s2 !== peg$FAILED) { + s3 = peg$parseStringLiteral(); + if (s3 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c45(s3); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.substr(peg$currPos, 2) === peg$c46) { + s1 = peg$c46; + peg$currPos += 2; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c47); } + } + 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$c1; + } + if (s2 !== peg$FAILED) { + s3 = peg$parseStringLiteral(); + if (s3 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c48(s3); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.substr(peg$currPos, 2) === peg$c49) { + s1 = peg$c49; + peg$currPos += 2; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c50); } + } + 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$c1; + } + if (s2 !== peg$FAILED) { + s3 = peg$parseStringLiteral(); + if (s3 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c51(s3); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.substr(peg$currPos, 3) === peg$c52) { + s1 = peg$c52; + peg$currPos += 3; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c53); } + } + 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$c1; + } + if (s2 !== peg$FAILED) { + s3 = peg$parseStringLiteral(); + if (s3 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c54(s3); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.substr(peg$currPos, 3) === peg$c55) { + s1 = peg$c55; + peg$currPos += 3; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c56); } + } + 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$c1; + } + if (s2 !== peg$FAILED) { + s3 = peg$parseStringLiteral(); + if (s3 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c57(s3); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.substr(peg$currPos, 2) === peg$c58) { + s1 = peg$c58; + peg$currPos += 2; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c59); } + } + 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$c1; + } + if (s2 !== peg$FAILED) { + s3 = peg$parseStringLiteral(); + if (s3 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c60(s3); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.substr(peg$currPos, 2) === peg$c61) { + s1 = peg$c61; + peg$currPos += 2; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c62); } + } + 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$c1; + } + if (s2 !== peg$FAILED) { + s3 = peg$parseStringLiteral(); + if (s3 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c63(s3); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.substr(peg$currPos, 3) === peg$c64) { + s1 = peg$c64; + peg$currPos += 3; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c65); } + } + 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$c1; + } + if (s2 !== peg$FAILED) { + s3 = peg$parseStringLiteral(); + if (s3 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c66(s3); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.substr(peg$currPos, 3) === peg$c67) { + s1 = peg$c67; + peg$currPos += 3; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c68); } + } + 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$c1; + } + if (s2 !== peg$FAILED) { + s3 = peg$parseStringLiteral(); + if (s3 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c69(s3); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.substr(peg$currPos, 2) === peg$c70) { + s1 = peg$c70; + peg$currPos += 2; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c71); } + } + 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$c1; + } + if (s2 !== peg$FAILED) { + s3 = peg$parseStringLiteral(); + if (s3 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c72(s3); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parseStringLiteral(); + if (s1 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c72(s1); + } + s0 = s1; + } + } + } + } + } + } + } + } + } + } + + return s0; + } + + function peg$parseStringLiteral() { + var s0, s1, s2, s3; + + peg$silentFails++; + s0 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 34) { + s1 = peg$c74; + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c75); } + } + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$parseDoubleStringChar(); + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$parseDoubleStringChar(); + } + if (s2 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 34) { + s3 = peg$c74; + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c75); } + } + if (s3 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c76(s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 39) { + s1 = peg$c77; + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c78); } + } + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$parseSingleStringChar(); + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$parseSingleStringChar(); + } + if (s2 !== peg$FAILED) { + if (input.charCodeAt(peg$currPos) === 39) { + s3 = peg$c77; + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c78); } + } + if (s3 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c76(s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$currPos; + peg$silentFails++; + s2 = peg$parsecc(); + peg$silentFails--; + if (s2 === peg$FAILED) { + s1 = peg$c79; + } else { + peg$currPos = s1; + s1 = peg$c1; + } + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$parseUnquotedStringChar(); + if (s3 !== peg$FAILED) { + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$parseUnquotedStringChar(); + } + } else { + s2 = peg$c1; + } + if (s2 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c76(s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } + } + peg$silentFails--; + if (s0 === peg$FAILED) { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c73); } + } + + return s0; + } + + function peg$parseDoubleStringChar() { + var s0, s1, s2; + + s0 = peg$currPos; + s1 = peg$currPos; + peg$silentFails++; + if (peg$c80.test(input.charAt(peg$currPos))) { + s2 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c81); } + } + peg$silentFails--; + if (s2 === peg$FAILED) { + s1 = peg$c79; + } else { + peg$currPos = s1; + s1 = peg$c1; + } + if (s1 !== peg$FAILED) { + if (input.length > peg$currPos) { + s2 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c82); } + } + if (s2 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c83(s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 92) { + s1 = peg$c84; + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c85); } + } + if (s1 !== peg$FAILED) { + s2 = peg$parseEscapeSequence(); + if (s2 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c83(s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } + + return s0; + } + + function peg$parseSingleStringChar() { + var s0, s1, s2; + + s0 = peg$currPos; + s1 = peg$currPos; + peg$silentFails++; + if (peg$c86.test(input.charAt(peg$currPos))) { + s2 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c87); } + } + peg$silentFails--; + if (s2 === peg$FAILED) { + s1 = peg$c79; + } else { + peg$currPos = s1; + s1 = peg$c1; + } + if (s1 !== peg$FAILED) { + if (input.length > peg$currPos) { + s2 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c82); } + } + if (s2 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c83(s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 92) { + s1 = peg$c84; + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c85); } + } + if (s1 !== peg$FAILED) { + s2 = peg$parseEscapeSequence(); + if (s2 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c83(s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } + + return s0; + } + + function peg$parseUnquotedStringChar() { + var s0, s1, s2; + + s0 = peg$currPos; + s1 = peg$currPos; + peg$silentFails++; + s2 = peg$parsews(); + peg$silentFails--; + if (s2 === peg$FAILED) { + s1 = peg$c79; + } else { + peg$currPos = s1; + s1 = peg$c1; + } + if (s1 !== peg$FAILED) { + if (input.length > peg$currPos) { + s2 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s2 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c82); } + } + if (s2 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c83(s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$c1; + } + } else { + peg$currPos = s0; + s0 = peg$c1; + } + + return s0; + } + + function peg$parseEscapeSequence() { + var s0, s1; + + if (peg$c88.test(input.charAt(peg$currPos))) { + s0 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c89); } + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 110) { + s1 = peg$c90; + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c91); } + } + if (s1 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c92(); + } + s0 = s1; + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 114) { + s1 = peg$c93; + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c94); } + } + if (s1 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c95(); + } + s0 = s1; + if (s0 === peg$FAILED) { + s0 = peg$currPos; + if (input.charCodeAt(peg$currPos) === 116) { + s1 = peg$c96; + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c97); } + } + if (s1 !== peg$FAILED) { + peg$reportedPos = s0; + s1 = peg$c98(); + } + s0 = s1; + } + } + } + + return s0; + } + + + function or(first, second) { + // Add explicit function names to ease debugging. + return function orFilter() { + first.apply(this, arguments) || second.apply(this, arguments); + }; + } + function and(first, second) { + return function andFilter() { + return first.apply(this, arguments) && second.apply(this, arguments); + } + } + function not(expr) { + return function notFilter() { + return !expr.apply(this, arguments); + }; + } + function binding(expr) { + return function bindingFilter() { + return expr.apply(this, arguments); + }; + } + function trueFilter(flow) { + return true; + } + function falseFilter(flow) { + return false; + } + 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") + ]; + function assetFilter(flow) { + if (flow.response) { + var ct = ResponseUtils.getContentType(flow.response); + var i = ASSET_TYPES.length; + while (i--) { + if (ASSET_TYPES[i].test(ct)) { + return true; + } + } + } + return false; + } + function responseCode(code){ + code = parseInt(code); + return function responseCodeFilter(flow){ + return flow.response && flow.response.code === code; + }; + } + function domain(regex){ + regex = new RegExp(regex, "i"); + return function domainFilter(flow){ + return flow.request && regex.test(flow.request.host); + }; + } + function errorFilter(flow){ + return !!flow.error; + } + function header(regex){ + regex = new RegExp(regex, "i"); + return function headerFilter(flow){ + return ( + (flow.request && RequestUtils.match_header(flow.request, regex)) + || + (flow.response && ResponseUtils.match_header(flow.response, regex)) + ); + }; + } + function requestHeader(regex){ + regex = new RegExp(regex, "i"); + return function requestHeaderFilter(flow){ + return (flow.request && RequestUtils.match_header(flow.request, regex)); + } + } + function responseHeader(regex){ + regex = new RegExp(regex, "i"); + return function responseHeaderFilter(flow){ + return (flow.response && ResponseUtils.match_header(flow.response, regex)); + } + } + function method(regex){ + regex = new RegExp(regex, "i"); + return function methodFilter(flow){ + return flow.request && regex.test(flow.request.method); + }; + } + function noResponseFilter(flow){ + return flow.request && !flow.response; + } + function responseFilter(flow){ + return !!flow.response; + } + + function contentType(regex){ + regex = new RegExp(regex, "i"); + return function contentTypeFilter(flow){ + return ( + (flow.request && regex.test(RequestUtils.getContentType(flow.request))) + || + (flow.response && regex.test(ResponseUtils.getContentType(flow.response))) + ); + }; + } + function requestContentType(regex){ + regex = new RegExp(regex, "i"); + return function requestContentTypeFilter(flow){ + return flow.request && regex.test(RequestUtils.getContentType(flow.request)); + }; + } + function responseContentType(regex){ + regex = new RegExp(regex, "i"); + return function responseContentTypeFilter(flow){ + return flow.response && regex.test(ResponseUtils.getContentType(flow.response)); + }; + } + function url(regex){ + regex = new RegExp(regex, "i"); + return function urlFilter(flow){ + return flow.request && regex.test(RequestUtils.pretty_url(flow.request)); + } + } + + + peg$result = peg$startRuleFunction(); + + if (peg$result !== peg$FAILED && peg$currPos === input.length) { + return peg$result; + } else { + if (peg$result !== peg$FAILED && peg$currPos < input.length) { + peg$fail({ type: "end", description: "end of input" }); + } + + throw peg$buildException(null, peg$maxFailExpected, peg$maxFailPos); + } + } + + return { + SyntaxError: SyntaxError, + parse: parse + }; +})(); var _MessageUtils = { getContentType: function (message) { return this.get_first_header(message, /^Content-Type$/i); @@ -226,6 +1921,16 @@ var _MessageUtils = { message._headerLookups[regex] = header ? header[1] : undefined; } return message._headerLookups[regex]; + }, + match_header: function(message, regex){ + var headers = message.headers; + var i = headers.length; + while(i--){ + if(regex.test(headers[i].join(" "))){ + return headers[i]; + } + } + return false; } }; @@ -742,6 +2447,15 @@ var VirtualScrollMixin = { }, }; var MainMenu = React.createClass({displayName: 'MainMenu', + mixins: [Navigation, State], + getInitialState: function(){ + this.onQueryChange(Query.FILTER, function(oldVal, nextVal){ + this.setState({filter: nextVal}); + }.bind(this)); + return { + filter: this.getQuery()[Query.FILTER] + }; + }, statics: { title: "Traffic", route: "flows" @@ -754,6 +2468,13 @@ var MainMenu = React.createClass({displayName: 'MainMenu', clearFlows: function () { $.post("/flows/clear"); }, + setFilter: function(e){ + e.preventDefault(); + this.setQuery(Query.FILTER, this.state.filter); + }, + onFilterChange: function(e){ + this.setState({filter: e.target.value}); + }, render: function () { return ( React.createElement("div", null, @@ -765,7 +2486,15 @@ var MainMenu = React.createClass({displayName: 'MainMenu', React.createElement("button", {className: "btn btn-default", onClick: this.clearFlows}, React.createElement("i", {className: "fa fa-eraser"}), " Clear Flows" - ) + ), + " ", + React.createElement("form", {className: "form-inline", onSubmit: this.setFilter, style: {display:"inline-block"}}, + React.createElement("input", {type: "text", placeholder: "filter expression", + onChange: this.onFilterChange, value: this.state.filter, + className: "form-control"} + ) + ) + ) ); } @@ -813,19 +2542,19 @@ var FileMenu = React.createClass({displayName: 'FileMenu', }); } }, - handleNewClick: function(e){ + handleNewClick: function (e) { e.preventDefault(); console.error("unimplemented: handleNewClick"); }, - handleOpenClick: function(e){ + handleOpenClick: function (e) { e.preventDefault(); console.error("unimplemented: handleOpenClick"); }, - handleSaveClick: function(e){ + handleSaveClick: function (e) { e.preventDefault(); console.error("unimplemented: handleSaveClick"); }, - handleShutdownClick: function(e){ + handleShutdownClick: function (e) { e.preventDefault(); console.error("unimplemented: handleShutdownClick"); }, @@ -872,7 +2601,7 @@ var header_entries = [MainMenu, ToolsMenu, ReportsMenu]; var Header = React.createClass({displayName: 'Header', - mixins: [ReactRouter.Navigation], + mixins: [Navigation], getInitialState: function () { return { active: header_entries[0] @@ -880,7 +2609,7 @@ var Header = React.createClass({displayName: 'Header', }, handleClick: function (active, e) { e.preventDefault(); - this.transitionTo(active.route); + this.replaceWith(active.route); this.setState({active: active}); }, render: function () { @@ -1475,7 +3204,7 @@ var allTabs = { }; var FlowDetail = React.createClass({displayName: 'FlowDetail', - mixins: [StickyHeadMixin, ReactRouter.Navigation, ReactRouter.State], + mixins: [StickyHeadMixin, Navigation, State], getTabs: function (flow) { var tabs = []; ["request", "response", "error"].forEach(function (e) { @@ -1531,7 +3260,7 @@ var FlowDetail = React.createClass({displayName: 'FlowDetail', } }); var MainView = React.createClass({displayName: 'MainView', - mixins: [ReactRouter.Navigation, ReactRouter.State], + mixins: [Navigation, State], getInitialState: function () { return { flows: [] @@ -1584,7 +3313,7 @@ var MainView = React.createClass({displayName: 'MainView', ); this.refs.flowTable.scrollIntoView(flow); } else { - this.replaceWith("flows"); + this.replaceWith("flows", {}); } }, selectFlowRelative: function (shift) { @@ -1862,6 +3591,7 @@ var ProxyAppMain = React.createClass({displayName: 'ProxyAppMain', }, componentDidMount: function () { this.state.settings.addListener("recalculate", this.onSettingsChange); + window.app = this; }, componentWillUnmount: function () { this.state.settings.removeListener("recalculate", this.onSettingsChange); diff --git a/web/src/css/flowdetail.less b/web/src/css/flowdetail.less index 3a6191d4a..7649057f2 100644 --- a/web/src/css/flowdetail.less +++ b/web/src/css/flowdetail.less @@ -24,6 +24,8 @@ padding: 4px 8px; border-radius: 5px; word-break: break-all; + max-height: 100px; + overflow-y: auto; } } diff --git a/web/src/js/actions.js b/web/src/js/actions.js index 2c4183e44..3d9b89e65 100644 --- a/web/src/js/actions.js +++ b/web/src/js/actions.js @@ -62,4 +62,8 @@ var EventLogActions = { } }); } +}; + +Query = { + FILTER: "f" }; \ No newline at end of file diff --git a/web/src/js/components/flowdetail.jsx.js b/web/src/js/components/flowdetail.jsx.js index 6d46cd2ed..5727ec753 100644 --- a/web/src/js/components/flowdetail.jsx.js +++ b/web/src/js/components/flowdetail.jsx.js @@ -294,7 +294,7 @@ var allTabs = { }; var FlowDetail = React.createClass({ - mixins: [StickyHeadMixin, ReactRouter.Navigation, ReactRouter.State], + mixins: [StickyHeadMixin, Navigation, State], getTabs: function (flow) { var tabs = []; ["request", "response", "error"].forEach(function (e) { diff --git a/web/src/js/components/header.jsx.js b/web/src/js/components/header.jsx.js index a23afa9be..b181b6707 100644 --- a/web/src/js/components/header.jsx.js +++ b/web/src/js/components/header.jsx.js @@ -1,4 +1,13 @@ var MainMenu = React.createClass({ + mixins: [Navigation, State], + getInitialState: function(){ + this.onQueryChange(Query.FILTER, function(oldVal, nextVal){ + this.setState({filter: nextVal}); + }.bind(this)); + return { + filter: this.getQuery()[Query.FILTER] + }; + }, statics: { title: "Traffic", route: "flows" @@ -11,6 +20,13 @@ var MainMenu = React.createClass({ clearFlows: function () { $.post("/flows/clear"); }, + setFilter: function(e){ + e.preventDefault(); + this.setQuery(Query.FILTER, this.state.filter); + }, + onFilterChange: function(e){ + this.setState({filter: e.target.value}); + }, render: function () { return (
@@ -23,6 +39,14 @@ var MainMenu = React.createClass({  Clear Flows +   +
+ +
+
); } @@ -70,19 +94,19 @@ var FileMenu = React.createClass({ }); } }, - handleNewClick: function(e){ + handleNewClick: function (e) { e.preventDefault(); console.error("unimplemented: handleNewClick"); }, - handleOpenClick: function(e){ + handleOpenClick: function (e) { e.preventDefault(); console.error("unimplemented: handleOpenClick"); }, - handleSaveClick: function(e){ + handleSaveClick: function (e) { e.preventDefault(); console.error("unimplemented: handleSaveClick"); }, - handleShutdownClick: function(e){ + handleShutdownClick: function (e) { e.preventDefault(); console.error("unimplemented: handleShutdownClick"); }, @@ -129,7 +153,7 @@ var header_entries = [MainMenu, ToolsMenu, ReportsMenu]; var Header = React.createClass({ - mixins: [ReactRouter.Navigation], + mixins: [Navigation], getInitialState: function () { return { active: header_entries[0] @@ -137,7 +161,7 @@ var Header = React.createClass({ }, handleClick: function (active, e) { e.preventDefault(); - this.transitionTo(active.route); + this.replaceWith(active.route); this.setState({active: active}); }, render: function () { diff --git a/web/src/js/components/mainview.jsx.js b/web/src/js/components/mainview.jsx.js index 17a024ee0..6e216b6ae 100644 --- a/web/src/js/components/mainview.jsx.js +++ b/web/src/js/components/mainview.jsx.js @@ -1,5 +1,5 @@ var MainView = React.createClass({ - mixins: [ReactRouter.Navigation, ReactRouter.State], + mixins: [Navigation, State], getInitialState: function () { return { flows: [] @@ -52,7 +52,7 @@ var MainView = React.createClass({ ); this.refs.flowTable.scrollIntoView(flow); } else { - this.replaceWith("flows"); + this.replaceWith("flows", {}); } }, selectFlowRelative: function (shift) { diff --git a/web/src/js/utils.js b/web/src/js/utils.js index 8ae7aa54d..b475980a8 100644 --- a/web/src/js/utils.js +++ b/web/src/js/utils.js @@ -23,6 +23,50 @@ var StickyHeadMixin = { }; +var Navigation = _.extend({}, ReactRouter.Navigation, { + setQuery: function (k, v) { + var q = this.context.getCurrentQuery(); + q[k] = v; + this.replaceWith(this.context.getCurrentPath(), this.context.getCurrentParams(), q); + }, + replaceWith: function(routeNameOrPath, params, query) { + if(routeNameOrPath === undefined){ + routeNameOrPath = this.context.getCurrentPath(); + } + if(params === undefined){ + params = this.context.getCurrentParams(); + } + if(query === undefined){ + query = this.context.getCurrentQuery(); + } + ReactRouter.Navigation.replaceWith.call(this, routeNameOrPath, params, query); + } +}); + +var State = _.extend({}, ReactRouter.State, { + getInitialState: function () { + this._query = this.context.getCurrentQuery(); + this._queryWatches = []; + return null; + }, + onQueryChange: function (key, callback) { + this._queryWatches.push({ + key: key, + callback: callback + }); + }, + componentWillReceiveProps: function (nextProps, nextState) { + var q = this.context.getCurrentQuery(); + for (var i = 0; i < this._queryWatches.length; i++) { + var watch = this._queryWatches[i]; + if (this._query[watch.key] !== q[watch.key]) { + watch.callback(this._query[watch.key], q[watch.key], watch.key); + } + } + this._query = q; + } +}); + var Key = { UP: 38, DOWN: 40,