aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMaximilian Hils <git@maximilianhils.com>2014-12-12 19:19:00 +0100
committerMaximilian Hils <git@maximilianhils.com>2014-12-12 19:19:00 +0100
commit5ccae48b92b093d68c8df8e557624cfb29d9c2fa (patch)
tree246b31da064957d97148b95a8254b50b96a33de2
parentcb45296377972bafc3d283a8dcf00c7ebb976551 (diff)
downloadmitmproxy-5ccae48b92b093d68c8df8e557624cfb29d9c2fa.tar.gz
mitmproxy-5ccae48b92b093d68c8df8e557624cfb29d9c2fa.tar.bz2
mitmproxy-5ccae48b92b093d68c8df8e557624cfb29d9c2fa.zip
web: fight against react-router
-rw-r--r--libmproxy/web/static/css/app.css2
-rw-r--r--libmproxy/web/static/js/app.js1750
-rw-r--r--web/src/css/flowdetail.less2
-rw-r--r--web/src/js/actions.js4
-rw-r--r--web/src/js/components/flowdetail.jsx.js2
-rw-r--r--web/src/js/components/header.jsx.js36
-rw-r--r--web/src/js/components/mainview.jsx.js4
-rw-r--r--web/src/js/utils.js44
8 files changed, 1825 insertions, 19 deletions
diff --git a/libmproxy/web/static/css/app.css b/libmproxy/web/static/css/app.css
index 9e0d241b..b99cd2d7 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 d90610de..6a886c11 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 3a6191d4..7649057f 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 2c4183e4..3d9b89e6 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 6d46cd2e..5727ec75 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 a23afa9b..b181b670 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 (
<div>
@@ -23,6 +39,14 @@ var MainMenu = React.createClass({
<i className="fa fa-eraser"></i>
&nbsp;Clear Flows
</button>
+ &nbsp;
+ <form className="form-inline" onSubmit={this.setFilter} style={{display:"inline-block"}}>
+ <input type="text" placeholder="filter expression"
+ onChange={this.onFilterChange} value={this.state.filter}
+ className="form-control"
+ />
+ </form>
+
</div>
);
}
@@ -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 17a024ee..6e216b6a 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 8ae7aa54..b475980a 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,