Mercurial > stress-tester
changeset 476:a49913dd5064
benchmarks for CSRF extraction
author | Devel 1 |
---|---|
date | Tue, 08 Aug 2017 09:30:02 +0200 |
parents | 803b20d6f0cb |
children | ee228e860ea2 |
files | stress-tester-benchmark/pom.xml stress-tester-benchmark/src/main/java/com/passus/st/client/http/filter/CsrfBenchmark.java stress-tester-benchmark/src/main/java/com/passus/st/client/http/filter/HttpCsrfFormExtractor.java stress-tester-benchmark/src/main/resources/html/form_csrf.html stress-tester-benchmark/src/main/resources/html/form_csrf1.html stress-tester-benchmark/src/main/resources/html/form_csrf_mini.html |
diffstat | 6 files changed, 758 insertions(+), 2 deletions(-) [+] |
line wrap: on
line diff
--- a/stress-tester-benchmark/pom.xml Tue Aug 08 09:29:09 2017 +0200 +++ b/stress-tester-benchmark/pom.xml Tue Aug 08 09:30:02 2017 +0200 @@ -121,7 +121,7 @@ <dependency> <groupId>org.brotli</groupId> <artifactId>dec</artifactId> - <version>0.1.1</version> + <version>0.1.2</version> </dependency> <dependency> @@ -139,13 +139,19 @@ <groupId>com.passus</groupId> <artifactId>passus-data</artifactId> <version>1.0-SNAPSHOT</version> - <type>jar</type> </dependency> + <dependency> <groupId>org.bouncycastle</groupId> <artifactId>bcprov-jdk15</artifactId> <version>1.46</version> </dependency> + + <dependency> + <groupId>org.jsoup</groupId> + <artifactId>jsoup</artifactId> + <version>1.9.2</version> + </dependency> </dependencies> <build>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/stress-tester-benchmark/src/main/java/com/passus/st/client/http/filter/CsrfBenchmark.java Tue Aug 08 09:30:02 2017 +0200 @@ -0,0 +1,140 @@ +package com.passus.st.client.http.filter; + +import com.passus.commons.utils.ResourceUtils; +import com.passus.st.client.http.filter.HttpCsrfFormExtractor.FormBoundary; +import com.passus.st.client.http.filter.HttpCsrfFormExtractor.TokenEntry; +import com.passus.utils.AllocationUtils; +import java.io.File; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.List; +import java.util.concurrent.TimeUnit; +import org.openjdk.jmh.annotations.Benchmark; +import org.openjdk.jmh.annotations.BenchmarkMode; +import org.openjdk.jmh.annotations.Fork; +import org.openjdk.jmh.annotations.Measurement; +import org.openjdk.jmh.annotations.Mode; +import org.openjdk.jmh.annotations.OutputTimeUnit; +import org.openjdk.jmh.annotations.Scope; +import org.openjdk.jmh.annotations.Setup; +import org.openjdk.jmh.annotations.State; +import org.openjdk.jmh.annotations.Warmup; +import org.openjdk.jmh.runner.Runner; +import org.openjdk.jmh.runner.options.Options; +import org.openjdk.jmh.runner.options.OptionsBuilder; + +/** + * + * @author mikolaj.podbielski + */ +@State(Scope.Thread) +@BenchmarkMode(Mode.AverageTime) +@OutputTimeUnit(TimeUnit.MICROSECONDS) +@Fork(value = 1) +@Measurement(iterations = 6) +@Warmup(iterations = 6) +public class CsrfBenchmark { + + String small, medium, large; + String form; + String smallForm = "<form name=\"f1\" action=\"/svc/save\" method=\"post\"><input type=\"hidden\" id=\"t_id\" name=\"t_n\" value=\"t4val\" /></form>"; + +// @Benchmark +// public Object scanLarge() { +// return HttpCsrfFormExtractor.scan(large); +// } +// +// @Benchmark +// public Object scanMedium() { +// return HttpCsrfFormExtractor.scan(medium); +// } +// +// @Benchmark +// public Object scanSmall() { +// return HttpCsrfFormExtractor.scan(small); +// } +// @Benchmark +// public Object jsoupParse() { +// return Jsoup.parse(form); +// } +// +// @Benchmark +// public Object jsoupParseBodyFragment() { +// return Jsoup.parseBodyFragment(form); +// } + @Benchmark + public TokenEntry extract() { + return HttpCsrfFormExtractor.extract(form, "form__token", "form[_token]"); + } + + @Benchmark + public TokenEntry extract1() { + return HttpCsrfFormExtractor.extract1(form, "form__token", "form[_token]"); + } + + @Benchmark + public TokenEntry extractSmall() { + return HttpCsrfFormExtractor.extract(smallForm, "form__token", "form[_token]"); + } + +// @Benchmark +// public TokenEntry extractSelect() { +// return HttpCsrfFormExtractor.extractSelect(form); +// } +// +// @Benchmark +// public TokenEntry extractSelectById() { +// return HttpCsrfFormExtractor.extractSelectById(form, "form__token"); +// } +// +// @Benchmark +// public TokenEntry extractSelectByName() { +// return HttpCsrfFormExtractor.extractSelectByName(form, "form[_token]"); +// } + @Benchmark + public List<String> regexpOnly() { + return HttpCsrfFormExtractor.regexp(form); + } + @Benchmark + public TokenEntry regexpFull() { + return HttpCsrfFormExtractor.extractRegex(form, "form__token", "form[_token]"); + } + + @Setup + public void setup() throws IOException { + small = load("html/form_csrf1.html"); + medium = load("html/form_csrf_mini.html"); + large = load("html/form_csrf.html"); + FormBoundary bound = HttpCsrfFormExtractor.scan(small).get(0); + form = small.substring(bound.start, bound.end); + } + + private static String load(String path) throws IOException { + File file = ResourceUtils.getFile(path); + byte[] bytes = Files.readAllBytes(Paths.get(file.toURI())); + return new String(bytes); + } + + public static void main(String[] args) throws Throwable { + Options opt = new OptionsBuilder().include(CsrfBenchmark.class.getSimpleName() + ".*").build(); +// new Runner(opt).run(); + CsrfBenchmark cb = new CsrfBenchmark(); + cb.setup(); + AllocationUtils au = new AllocationUtils(); + au.checkAllocation(cb); + au.checkAllocation(cb); + + System.out.println("large=" + cb.large.length()); + System.out.println("medium=" + cb.medium.length()); + System.out.println("small=" + cb.small.length()); + System.out.println("large form=" + cb.form.length()); + System.out.println("small form=" + cb.smallForm.length()); + + cb.regexpOnly(); +// TokenEntry t1 = cb.extractSelect(); +// TokenEntry t2 = cb.extractSelectById(); +// TokenEntry t3 = cb.extractSelectByName(); + System.out.println(""); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/stress-tester-benchmark/src/main/java/com/passus/st/client/http/filter/HttpCsrfFormExtractor.java Tue Aug 08 09:30:02 2017 +0200 @@ -0,0 +1,280 @@ +package com.passus.st.client.http.filter; + +import java.util.ArrayList; +import java.util.List; +import java.util.regex.Matcher; +import java.util.regex.Pattern; +import org.jsoup.Jsoup; +import org.jsoup.nodes.Document; +import org.jsoup.nodes.Element; +import org.jsoup.nodes.FormElement; +import org.jsoup.select.Elements; + +/** + * + * @author mikolaj.podbielski + */ +public class HttpCsrfFormExtractor { + + private static final String TAG_FORM = "form"; + private static final String TAG_INPUT = "input"; + + private static final String FORM_START = "<form"; + private static final String FORM_END = "</form>"; + + private static final String ATTR_ACTION = "action"; + private static final String ATTR_METHOD = "method"; + private static final String ATTR_NAME = "name"; + private static final String ATTR_VALUE = "value"; + + // TODO: obsługiwać '< form' itp + static List<FormBoundary> scan(String document) { + document = document.toLowerCase(); + List<FormBoundary> result = new ArrayList<>(); + + int startPos = 0; + while (true) { + startPos = document.indexOf(FORM_START, startPos); + if (startPos < 0) { + break; + } + + int endPos = document.indexOf(FORM_END, startPos); + if (endPos < 0) { + break; + } + endPos += FORM_END.length(); + + result.add(new FormBoundary(startPos, endPos)); + startPos = endPos; + } + + return result; + } + private static final String PATTERN_STR = "\\<\\s*input (?>.|\\n)*?(?>\\/\\>|\\<\\/input\\>)"; + private static final Pattern PATTERN = Pattern.compile(PATTERN_STR, Pattern.MULTILINE); + + static public List<String> regexp(String formString) { + Matcher m = PATTERN.matcher(formString); + List<String> result = new ArrayList<>(); + while (m.find()) { + result.add(formString.substring(m.start(), m.end())); + } + return result; + } + + static TokenEntry extractRegex(String formString, String tokenId, String tokenName) { + List<String> inputStrings = regexp(formString); + + Element tokenInput = null; + for (String inputString : inputStrings) { + Document doc = Jsoup.parse(inputString); + Elements inputs = doc.getElementsByTag(TAG_INPUT); + Element input = inputs.get(0); + + if (!input.attr("type").equals("hidden")) { + continue; + } + if (tokenId != null) { + if (!tokenId.equals(input.id())) { + continue; + } + } + if (tokenName != null) { + if (!tokenName.equals(input.attr("name"))) { + continue; + } + } + tokenInput = input; + break; + } + + if (tokenInput != null) { + String action = "";// form.attr(ATTR_ACTION); + String method = "";//form.attr(ATTR_METHOD); + String name = "";//form.attr(ATTR_NAME); + String value = tokenInput.attr(ATTR_VALUE); + + return new TokenEntry(action, method, name, value); + } else { + return null; + } + } + + static TokenEntry extract(String formString, String tokenId, String tokenName) { + Document root = Jsoup.parse(formString); + Elements forms = root.getElementsByTag(TAG_FORM); + if (forms.size() != 1) { + throw new IllegalArgumentException("Given fragment is not a form."); + } + FormElement form = (FormElement) forms.get(0); +// Elements inputs = form.getElementsByTag(TAG_INPUT); + Elements inputs = form.elements(); + + Element tokenInput = null; + for (Element input : inputs) { + if (!input.tagName().equals("input")) { + continue; + } + if (!input.attr("type").equals("hidden")) { + continue; + } + if (tokenId != null) { + if (!tokenId.equals(input.id())) { + continue; + } + } + if (tokenName != null) { + if (!tokenName.equals(input.attr("name"))) { + continue; + } + } + tokenInput = input; + break; + } + + if (tokenInput != null) { + String action = form.attr(ATTR_ACTION); + String method = form.attr(ATTR_METHOD); + String name = form.attr(ATTR_NAME); + String value = tokenInput.attr(ATTR_VALUE); + + return new TokenEntry(action, method, name, value); + } else { + return null; + } + } + + static TokenEntry extract1(String formString, String tokenId, String tokenName) { + Document root = Jsoup.parse(formString); + Elements forms = root.getElementsByTag(TAG_FORM); + if (forms.size() != 1) { + throw new IllegalArgumentException("Given fragment is not a form."); + } + FormElement form = (FormElement) forms.get(0); + Elements inputs = form.getElementsByTag(TAG_INPUT); +// Elements inputs = form.elements(); + + Element tokenInput = null; + for (Element input : inputs) { + if (!input.attr("type").equals("hidden")) { + continue; + } + if (tokenId != null) { + if (!tokenId.equals(input.id())) { + continue; + } + } + if (tokenName != null) { + if (!tokenName.equals(input.attr("name"))) { + continue; + } + } + tokenInput = input; + break; + } + + if (tokenInput != null) { + String action = form.attr(ATTR_ACTION); + String method = form.attr(ATTR_METHOD); + String name = form.attr(ATTR_NAME); + String value = tokenInput.attr(ATTR_VALUE); + return new TokenEntry(action, method, name, value); + } else { + return null; + } + } + + static TokenEntry extractSelect(String formString) { + Document root = Jsoup.parse(formString); + Elements forms = root.getElementsByTag(TAG_FORM); + if (forms.size() != 1) { + throw new IllegalArgumentException("Given fragment is not a form."); + } + FormElement form = (FormElement) forms.get(0); + + Elements elements = form.select("input[type=hidden]"); + if (elements.size() > 0) { + Element tokenInput = elements.get(0); + String action = form.attr(ATTR_ACTION); + String method = form.attr(ATTR_METHOD); + String name = form.attr(ATTR_NAME); + String value = tokenInput.attr(ATTR_VALUE); + return new TokenEntry(action, method, name, value); + } else { + return null; + } + } + + static TokenEntry extractSelectById(String formString, String tokenId) { + Document root = Jsoup.parse(formString); + Elements forms = root.getElementsByTag(TAG_FORM); + if (forms.size() != 1) { + throw new IllegalArgumentException("Given fragment is not a form."); + } + FormElement form = (FormElement) forms.get(0); + + Elements elements = form.select("#" + tokenId); + if (elements.size() > 0) { + Element tokenInput = elements.get(0); + String action = form.attr(ATTR_ACTION); + String method = form.attr(ATTR_METHOD); + String name = form.attr(ATTR_NAME); + String value = tokenInput.attr(ATTR_VALUE); + return new TokenEntry(action, method, name, value); + + } else { + return null; + } + } + + static TokenEntry extractSelectByName(String formString, String tokenName) { + Document root = Jsoup.parse(formString); + Elements forms = root.getElementsByTag(TAG_FORM); + if (forms.size() != 1) { + throw new IllegalArgumentException("Given fragment is not a form."); + } + FormElement form = (FormElement) forms.get(0); + + Elements elements = form.select("input[name=" + tokenName + "]"); + if (elements.size() > 0) { + Element tokenInput = elements.get(0); + String action = form.attr(ATTR_ACTION); + String method = form.attr(ATTR_METHOD); + String name = form.attr(ATTR_NAME); + String value = tokenInput.attr(ATTR_VALUE); + return new TokenEntry(action, method, name, value); + } else { + return null; + + } + } + + public static class FormBoundary { + + int start; + int end; + + public FormBoundary(int start, int end) { + this.start = start; + this.end = end; + } + } + + public static class TokenEntry { + + String action; + String method; + String name; + String value; + + public TokenEntry(String action, String method, String name, String value) { + this.action = action; + this.method = method; + this.name = name; + this.value = value; + } + + } + +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/stress-tester-benchmark/src/main/resources/html/form_csrf.html Tue Aug 08 09:30:02 2017 +0200 @@ -0,0 +1,208 @@ +<!DOCTYPE html> +<html xmlns="http://www.w3.org/1999/xhtml"> + <head lang="en"> + <title>Ambience</title> + <meta charset="UTF-8" /> + + <link rel="icon" href="/bundles/passusambience/images/favicon.png" /> + <link rel="shortcut icon" href="/bundles/passusambience/images/favicon.png" /> + + <script src="/js/400f5eb_jquery.min_1.js"></script> + <script src="/js/400f5eb_kendo.all.min_2.js"></script> + <script src="/js/400f5eb_kendo.culture.custom_3.js"></script> + + <script type="text/javascript" src="/bundles/passusambience/js/codemirror.js" ></script> +<script type="text/javascript" src="/bundles/passusambience/js/passus.core.js" ></script> +<script type="text/javascript" src="/bundles/passusambience/js/passus.ui-utils.js" ></script> +<script type="text/javascript" src="/bundles/passusambience/js/passus.mvel-editor.js" ></script> +<script type="text/javascript" src="/bundles/passusambience/js/passus.mvel-popupeditor.js" ></script> +<script type="text/javascript" src="/bundles/passusambience/js/passus.event-fields-dropdownlist.js" ></script> +<script type="text/javascript" src="/bundles/passusambience/js/passus.event-fields-multiselect.js" ></script> +<script type="text/javascript" src="/bundles/passusambience/js/passus.rule-matcher.js" ></script> +<script type="text/javascript" src="/bundles/passusambience/js/passus.rule-modifier.js" ></script> +<script type="text/javascript" src="/bundles/passusambience/js/passus.dialog-window.js" ></script> +<script type="text/javascript" src="/bundles/passusambience/js/passus.rule-lookup.js" ></script> +<script type="text/javascript" src="/bundles/passusambience/js/passus.event-filter.js" ></script> + + + <link rel="stylesheet" href="/css/6aebdf5_materialdesignicons.min_1.css" /> + <link rel="stylesheet" href="/css/6aebdf5_bootstrap.min_2.css" /> + <link rel="stylesheet" href="/css/6aebdf5_kendo.common.min_3.css" /> + <link rel="stylesheet" href="/css/6aebdf5_kendo.common-material.min_4.css" /> + <link rel="stylesheet" href="/css/6aebdf5_kendo.material.min_5.css" /> + <link rel="stylesheet" href="/css/6aebdf5_style_6.css" /> + <link rel="stylesheet" href="/css/6aebdf5_style_bart_7.css" /> + + <link rel="stylesheet" href="/bundles/passusambience/css/rules.css" /> +<link rel="stylesheet" href="/bundles/passusambience/css/codemirror.css" /> + + + <script> + kendo.culture("custom"); + </script> + + </head> + <body class="main"> + <header id="header" class="black-header smaller-header"> + <div class="logo-container"> + <a href="/" title="Psssus"> + <img src="/bundles/passusambience/images/logo-passus.svg" alt="logo" /> + </a> + <p class="description"><span>Ambience</span></p> + </div> + + +<ul id="menu" style="display: none" ><li><a href="/config/profiles">Profile</a></li><li><a href="">Configuration</a><ul><li><a href="/config/lookups">Lookups</a></li><li><a href="/config/scripts">Global MVEL scripts</a></li><li><a href="/config/sensors">Sensors</a></li><li><a href="/config/ldap">LDAP</a></li><li><a href="/config/ntp">NTP</a></li><li><a href="/config/support">Support</a></li><li><a href="/config/export_import">Export / Import</a></li></ul></li><li><a href="">System</a><ul><li><a href="/system/backup">Backup</a></li><li><a href="/system/supportws">Support WS</a></li><li><a href="/system/logs">Support logs</a></li></ul></li><li><a href="">Security</a><ul><li><a href="/security/users">Users</a></li><li><a href="/security/roles">Roles</a></li><li><a href="/security/perms">Permissions</a></li><li><a href="/security/settings">Settings</a></li><li><a href="/security/audit_log">Audit Log</a></li></ul></li></ul> + <div id="profile-settings" class="profile-settings" style="display: none"> + <ul id="help" class="settings"> + <li><a href="#" title="help"><i class="mdi mdi-help" style="z-index: 100"></i></a> + <ul> + <li><a href="/about" title="About">About</a></li> + </ul> + </li> + </ul> + <ul id="user-profile" class="user-settings"> + <li> + <a href="#" title="admin"> + <span class="logo"><span>A</span></span> + </a> + <ul> + <li><a href="/security/password" title="Change password">Change password</a></li> + <li><a href="/logout" title="Logout" onClick="return confirm('Do you want to sign out?');">Log out</a></li> + </ul> + </li> + </ul> + </div> + </header> + + <div id="content" class="content" style="display: none"> + <div> + <section class="container title"> + <div class="row"> + <h2>Edit HTTP</h2> + </div> + </section> + + <section class="container"> + <div class="row" > + <div> + <form name="form" method="post" novalidate="novalidate"> + <div class="col-md-12 input-container label-left"> + <div class="row"> + + <div class="col-md-12"> + <span class="caption">General</span> + </div> + + <div class="col-md-12"> + <label for="form_name" class="control-label required">Name:</label><input type="text" id="form_name" name="form[name]" required="required" class="mp-textbox k-textbox" value="httpx" /> + </div> + + <div class="col-md-12"> + <label for="form_active" class="control-label required">Active:</label> + <input type="checkbox" id="form_active" name="form[active]" required="required" value="1" checked="checked" /> + </div> + + <div class="col-md-12"> + <label for="form_disabledEvents" class="control-label required">Disabled Events:</label><select id="form_disabledEvents" name="form[disabledEvents][]" required="required" style="width: 600px" multiple="multiple"><option value="session.http" >session.http</option><option value="session.http.request" >session.http.request</option><option value="session.http.response" >session.http.response</option></select><script type="text/javascript"> + $(function () { + $("#form_disabledEvents").kendoMultiSelect({}); + }); + </script> + </div> + + <div class="col-md-12"> + <label for="form_ports" class="control-label required">Ports:</label><textarea id="form_ports" name="form[ports]" required="required" cols="40" rows="4" class="mp-textbox k-textbox">80</textarea> + </div> + + <div class="col-md-12"> + <span class="caption">Parameters</span> + </div> + + <div class="col-md-12"> + <input type="hidden" id="form_type" name="form[type]" value="session.http" /> + </div> + <div class="col-md-12"> + + </div> + <div class="col-md-12"> + <label for="form_defaultEncoding" class="control-label required">Default Encoding:</label><input type="text" id="form_defaultEncoding" name="form[defaultEncoding]" required="required" class="mp-textbox k-textbox" value="UTF-8" /> + </div> + <div class="col-md-12"> + <label for="form_threadsNum" class="control-label required">Number of Threads:</label><input id="form_threadsNum" name="form[threadsNum]" type="text" value="1" /><script type="text/javascript"> + $(function () { + $("#form_threadsNum").kendoNumericTextBox({"format":"#","decimals":0,"min":0,"max":256,"step":1}); + }); + </script> + </div> + <div class="col-md-12"> + <label for="form_encodeMimeTypes" class="control-label required">Encode MIME Types:</label><textarea id="form_encodeMimeTypes" name="form[encodeMimeTypes]" required="required" rows="10 4" style="width: 400px" cols="40" class="mp-textbox k-textbox">text/html +text/plain +text/xml +application/json +application/x-www-form-urlencoded +multipart/form-data</textarea> + </div> + <div class="col-md-12"> + <input type="hidden" id="form__token" name="form[_token]" value="ltZxeOCIr-kgGzU8qvTl2HMwDe1RhU9WmxIcW25whoY" /> + </div> + + + <div class="col-md-12"> + <span class="caption">Post Filters</span> + </div> + + <div class="col-md-12"> + <input id="form_postFilter" name="form[postFilter]" type="hidden" value="[{"type":"match","match":{"$and":[{"session_post_match":{"$eq":"value1"}}]},"acceptOnMatch":true,"desc":"ACCEPT when $and: session_post_match $eq value1, "},{"type":"modify","modify":[{"$add":{"session_post_modify":"2"}}]}]" /><div id="filter_form_postFilter" ></div><script type="text/javascript"> + $(function () { + var filterList_form_postFilter = $("#filter_form_postFilter").kendoEventFilterList({ + }).data("kendoEventFilterList"); + var form = $('form:first'); + + var filterInput_form_postFilter = $('#form_postFilter'); + form.submit(function () { + filterInput_form_postFilter.val(JSON.stringify(filterList_form_postFilter.value(), null, "")); + return true; + }); + + var filterJson = filterInput_form_postFilter.val(); + if (filterJson) { + filterList_form_postFilter.value($.parseJSON(filterJson)); + } + }); + </script> + + </div> + + <div class="col-md-12"> + <div class="buttons-container" > + <button type="submit" id="form_save" name="form[save]" class="k-button k-primary">Save</button> + <button type="submit" id="form_cancel" name="form[cancel]" class="k-button">Cancel</button> + </div> + </div> + </div> + </div> + + </form> + </div> + + </div> + </section> + </div> + </div> + + <script> + $().ready(function () { + $('#menu').kendoMenu(); + $('#help').kendoMenu({openOnClick: false}); + $('#user-profile').kendoMenu(); + + $('#menu').show(); + $('#profile-settings').show(); + $('#content').show(); + }); </script> + + +<div id="sfwdtc554ef" class="sf-toolbar" style="display: none"></div><script>/*<![CDATA[*/ Sfjs = (function() { "use strict"; var classListIsSupported = 'classList' in document.documentElement; if (classListIsSupported) { var hasClass = function (el, cssClass) { return el.classList.contains(cssClass); }; var removeClass = function(el, cssClass) { el.classList.remove(cssClass); }; var addClass = function(el, cssClass) { el.classList.add(cssClass); }; var toggleClass = function(el, cssClass) { el.classList.toggle(cssClass); }; } else { var hasClass = function (el, cssClass) { return el.className.match(new RegExp('\\b' + cssClass + '\\b')); }; var removeClass = function(el, cssClass) { el.className = el.className.replace(new RegExp('\\b' + cssClass + '\\b'), ' '); }; var addClass = function(el, cssClass) { if (!hasClass(el, cssClass)) { el.className += " " + cssClass; } }; var toggleClass = function(el, cssClass) { hasClass(el, cssClass) ? removeClass(el, cssClass) : addClass(el, cssClass); }; } var noop = function() {}, collectionToArray = function (collection) { var length = collection.length || 0, results = new Array(length); while (length--) { results[length] = collection[length]; } return results; }, profilerStorageKey = 'sf2/profiler/', request = function(url, onSuccess, onError, payload, options) { var xhr = window.XMLHttpRequest ? new XMLHttpRequest() : new ActiveXObject('Microsoft.XMLHTTP'); options = options || {}; options.maxTries = options.maxTries || 0; xhr.open(options.method || 'GET', url, true); xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); xhr.onreadystatechange = function(state) { if (4 !== xhr.readyState) { return null; } if (xhr.status == 404 && options.maxTries > 1) { setTimeout(function(){ options.maxTries--; request(url, onSuccess, onError, payload, options); }, 500); return null; } if (200 === xhr.status) { (onSuccess || noop)(xhr); } else { (onError || noop)(xhr); } }; xhr.send(payload || ''); }, getPreference = function(name) { if (!window.localStorage) { return null; } return localStorage.getItem(profilerStorageKey + name); }, setPreference = function(name, value) { if (!window.localStorage) { return null; } localStorage.setItem(profilerStorageKey + name, value); }, requestStack = [], extractHeaders = function(xhr, stackElement) { /* Here we avoid to call xhr.getResponseHeader in order to */ /* prevent polluting the console with CORS security errors */ var allHeaders = xhr.getAllResponseHeaders(); var ret; if (ret = allHeaders.match(/^x-debug-token:\s+(.*)$/im)) { stackElement.profile = ret[1]; } if (ret = allHeaders.match(/^x-debug-token-link:\s+(.*)$/im)) { stackElement.profilerUrl = ret[1]; } }, renderAjaxRequests = function() { var requestCounter = document.querySelectorAll('.sf-toolbar-ajax-requests'); if (!requestCounter.length) { return; } var ajaxToolbarPanel = document.querySelector('.sf-toolbar-block-ajax'); var tbodies = document.querySelectorAll('.sf-toolbar-ajax-request-list'); var state = 'ok'; if (tbodies.length) { var tbody = tbodies[0]; var rows = document.createDocumentFragment(); if (requestStack.length) { for (var i = 0; i < requestStack.length; i++) { var request = requestStack[i]; var row = document.createElement('tr'); rows.insertBefore(row, rows.firstChild); var methodCell = document.createElement('td'); if (request.error) { methodCell.className = 'sf-ajax-request-error'; } methodCell.textContent = request.method; row.appendChild(methodCell); var pathCell = document.createElement('td'); pathCell.className = 'sf-ajax-request-url'; if ('GET' === request.method) { var pathLink = document.createElement('a'); pathLink.setAttribute('href', request.url); pathLink.textContent = request.url; pathCell.appendChild(pathLink); } else { pathCell.textContent = request.url; } pathCell.setAttribute('title', request.url); row.appendChild(pathCell); var durationCell = document.createElement('td'); durationCell.className = 'sf-ajax-request-duration'; if (request.duration) { durationCell.textContent = request.duration + "ms"; } else { durationCell.textContent = '-'; } row.appendChild(durationCell); row.appendChild(document.createTextNode(' ')); var profilerCell = document.createElement('td'); if (request.profilerUrl) { var profilerLink = document.createElement('a'); profilerLink.setAttribute('href', request.profilerUrl); profilerLink.textContent = request.profile; profilerCell.appendChild(profilerLink); } else { profilerCell.textContent = 'n/a'; } row.appendChild(profilerCell); var requestState = 'ok'; if (request.error) { requestState = 'error'; if (state != "loading" && i > requestStack.length - 4) { state = 'error'; } } else if (request.loading) { requestState = 'loading'; state = 'loading'; } row.className = 'sf-ajax-request sf-ajax-request-' + requestState; } var infoSpan = document.querySelectorAll(".sf-toolbar-ajax-info")[0]; var children = collectionToArray(tbody.children); for (var i = 0; i < children.length; i++) { tbody.removeChild(children[i]); } tbody.appendChild(rows); if (infoSpan) { var text = requestStack.length + ' AJAX request' + (requestStack.length > 1 ? 's' : ''); infoSpan.textContent = text; } ajaxToolbarPanel.style.display = 'block'; } else { ajaxToolbarPanel.style.display = 'none'; } } requestCounter[0].textContent = requestStack.length; var className = 'sf-toolbar-ajax-requests sf-toolbar-value'; requestCounter[0].className = className; if (state == 'ok') { Sfjs.removeClass(ajaxToolbarPanel, 'sf-ajax-request-loading'); Sfjs.removeClass(ajaxToolbarPanel, 'sf-toolbar-status-red'); } else if (state == 'error') { Sfjs.addClass(ajaxToolbarPanel, 'sf-toolbar-status-red'); Sfjs.removeClass(ajaxToolbarPanel, 'sf-ajax-request-loading'); } else { Sfjs.addClass(ajaxToolbarPanel, 'sf-ajax-request-loading'); } }; var addEventListener; var el = document.createElement('div'); if (!('addEventListener' in el)) { addEventListener = function (element, eventName, callback) { element.attachEvent('on' + eventName, callback); }; } else { addEventListener = function (element, eventName, callback) { element.addEventListener(eventName, callback, false); }; } if (window.XMLHttpRequest && XMLHttpRequest.prototype.addEventListener) { var proxied = XMLHttpRequest.prototype.open; XMLHttpRequest.prototype.open = function(method, url, async, user, pass) { var self = this; /* prevent logging AJAX calls to static and inline files, like templates */ var path = url; if (url.substr(0, 1) === '/') { if (0 === url.indexOf('')) { path = url.substr(0); } } else if (0 === url.indexOf('http\x3A\x2F\x2F172.16.60.23')) { path = url.substr(19); } if (!path.match(new RegExp("^\/(app(_[\\w]+)?\\.php\/)?_wdt"))) { var stackElement = { loading: true, error: false, url: url, method: method, start: new Date() }; requestStack.push(stackElement); this.addEventListener('readystatechange', function() { if (self.readyState == 4) { stackElement.duration = new Date() - stackElement.start; stackElement.loading = false; stackElement.error = self.status < 200 || self.status >= 400; extractHeaders(self, stackElement); Sfjs.renderAjaxRequests(); } }, false); Sfjs.renderAjaxRequests(); } proxied.apply(this, Array.prototype.slice.call(arguments)); }; } return { hasClass: hasClass, removeClass: removeClass, addClass: addClass, toggleClass: toggleClass, getPreference: getPreference, setPreference: setPreference, addEventListener: addEventListener, request: request, renderAjaxRequests: renderAjaxRequests, load: function(selector, url, onSuccess, onError, options) { var el = document.getElementById(selector); if (el && el.getAttribute('data-sfurl') !== url) { request( url, function(xhr) { el.innerHTML = xhr.responseText; el.setAttribute('data-sfurl', url); removeClass(el, 'loading'); (onSuccess || noop)(xhr, el); }, function(xhr) { (onError || noop)(xhr, el); }, '', options ); } return this; }, toggle: function(selector, elOn, elOff) { var tmp = elOn.style.display, el = document.getElementById(selector); elOn.style.display = elOff.style.display; elOff.style.display = tmp; if (el) { el.style.display = 'none' === tmp ? 'none' : 'block'; } return this; }, createTabs: function() { var tabGroups = document.querySelectorAll('.sf-tabs'); /* create the tab navigation for each group of tabs */ for (var i = 0; i < tabGroups.length; i++) { var tabs = tabGroups[i].querySelectorAll('.tab'); var tabNavigation = document.createElement('ul'); tabNavigation.className = 'tab-navigation'; for (var j = 0; j < tabs.length; j++) { var tabId = 'tab-' + i + '-' + j; var tabTitle = tabs[j].querySelector('.tab-title').innerHTML; var tabNavigationItem = document.createElement('li'); tabNavigationItem.setAttribute('data-tab-id', tabId); if (j == 0) { Sfjs.addClass(tabNavigationItem, 'active'); } if (Sfjs.hasClass(tabs[j], 'disabled')) { Sfjs.addClass(tabNavigationItem, 'disabled'); } tabNavigationItem.innerHTML = tabTitle; tabNavigation.appendChild(tabNavigationItem); var tabContent = tabs[j].querySelector('.tab-content'); tabContent.parentElement.setAttribute('id', tabId); } tabGroups[i].insertBefore(tabNavigation, tabGroups[i].firstChild); } /* display the active tab and add the 'click' event listeners */ for (i = 0; i < tabGroups.length; i++) { tabNavigation = tabGroups[i].querySelectorAll('.tab-navigation li'); for (j = 0; j < tabNavigation.length; j++) { tabId = tabNavigation[j].getAttribute('data-tab-id'); document.getElementById(tabId).querySelector('.tab-title').className = 'hidden'; if (Sfjs.hasClass(tabNavigation[j], 'active')) { document.getElementById(tabId).className = 'block'; } else { document.getElementById(tabId).className = 'hidden'; } tabNavigation[j].addEventListener('click', function(e) { var activeTab = e.target || e.srcElement; /* needed because when the tab contains HTML contents, user can click */ /* on any of those elements instead of their parent '<li>' element */ while (activeTab.tagName.toLowerCase() !== 'li') { activeTab = activeTab.parentNode; } /* get the full list of tabs through the parent of the active tab element */ var tabNavigation = activeTab.parentNode.children; for (var k = 0; k < tabNavigation.length; k++) { var tabId = tabNavigation[k].getAttribute('data-tab-id'); document.getElementById(tabId).className = 'hidden'; Sfjs.removeClass(tabNavigation[k], 'active'); } Sfjs.addClass(activeTab, 'active'); var activeTabId = activeTab.getAttribute('data-tab-id'); document.getElementById(activeTabId).className = 'block'; }); } } }, createToggles: function() { var toggles = document.querySelectorAll('.sf-toggle'); for (var i = 0; i < toggles.length; i++) { var elementSelector = toggles[i].getAttribute('data-toggle-selector'); var element = document.querySelector(elementSelector); Sfjs.addClass(element, 'sf-toggle-content'); if (toggles[i].hasAttribute('data-toggle-initial') && toggles[i].getAttribute('data-toggle-initial') == 'display') { Sfjs.addClass(element, 'sf-toggle-visible'); } else { Sfjs.addClass(element, 'sf-toggle-hidden'); } Sfjs.addEventListener(toggles[i], 'click', function(e) { e.preventDefault(); var toggle = e.target || e.srcElement; /* needed because when the toggle contains HTML contents, user can click */ /* on any of those elements instead of their parent '.sf-toggle' element */ while (!Sfjs.hasClass(toggle, 'sf-toggle')) { toggle = toggle.parentNode; } var element = document.querySelector(toggle.getAttribute('data-toggle-selector')); Sfjs.toggleClass(element, 'sf-toggle-hidden'); Sfjs.toggleClass(element, 'sf-toggle-visible'); /* the toggle doesn't change its contents when clicking on it */ if (!toggle.hasAttribute('data-toggle-alt-content')) { return; } if (!toggle.hasAttribute('data-toggle-original-content')) { toggle.setAttribute('data-toggle-original-content', toggle.innerHTML); } var currentContent = toggle.innerHTML; var originalContent = toggle.getAttribute('data-toggle-original-content'); var altContent = toggle.getAttribute('data-toggle-alt-content'); toggle.innerHTML = currentContent !== altContent ? altContent : originalContent; }); } } }; })(); Sfjs.addEventListener(window, 'load', function() { Sfjs.createTabs(); Sfjs.createToggles(); });/*]]>*/</script><script>/*<![CDATA[*/ (function () { Sfjs.load( 'sfwdtc554ef', '/_wdt/c554ef', function(xhr, el) { el.style.display = -1 !== xhr.responseText.indexOf('sf-toolbarreset') ? 'block' : 'none'; if (el.style.display == 'none') { return; } if (Sfjs.getPreference('toolbar/displayState') == 'none') { document.getElementById('sfToolbarMainContent-c554ef').style.display = 'none'; document.getElementById('sfToolbarClearer-c554ef').style.display = 'none'; document.getElementById('sfMiniToolbar-c554ef').style.display = 'block'; } else { document.getElementById('sfToolbarMainContent-c554ef').style.display = 'block'; document.getElementById('sfToolbarClearer-c554ef').style.display = 'block'; document.getElementById('sfMiniToolbar-c554ef').style.display = 'none'; } Sfjs.renderAjaxRequests(); /* Handle toolbar-info position */ var toolbarBlocks = document.querySelectorAll('.sf-toolbar-block'); for (var i = 0; i < toolbarBlocks.length; i += 1) { toolbarBlocks[i].onmouseover = function () { var toolbarInfo = this.querySelectorAll('.sf-toolbar-info')[0]; var pageWidth = document.body.clientWidth; var elementWidth = toolbarInfo.offsetWidth; var leftValue = (elementWidth + this.offsetLeft) - pageWidth; var rightValue = (elementWidth + (pageWidth - this.offsetLeft)) - pageWidth; /* Reset right and left value, useful on window resize */ toolbarInfo.style.right = ''; toolbarInfo.style.left = ''; if (elementWidth > pageWidth) { toolbarInfo.style.left = 0; } else if (leftValue > 0 && rightValue > 0) { toolbarInfo.style.right = (rightValue * -1) + 'px'; } else if (leftValue < 0) { toolbarInfo.style.left = 0; } else { toolbarInfo.style.right = '0px'; } }; } }, function(xhr) { if (xhr.status !== 0) { confirm('An error occurred while loading the web debug toolbar (' + xhr.status + ': ' + xhr.statusText + ').\n\nDo you want to open the profiler?') && (window.location = '/_profiler/c554ef'); } }, {'maxTries': 5} ); })();/*]]>*/</script> +</body> +</html> \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/stress-tester-benchmark/src/main/resources/html/form_csrf1.html Tue Aug 08 09:30:02 2017 +0200 @@ -0,0 +1,37 @@ +<!DOCTYPE html> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head lang="en"> + <title>Title</title> +</head> + +<body class="main"> + <section class="container"> + <ForM name="form1" method="post" novalidate="novalidate"> + <div class="row"> + <input type="text" id="form_name" name="form[name]" required="required" class="mp-textbox k-textbox" value="httpx" /> + <input type="checkbox" id="form_active" name="form[active]" required="required" value="1" checked="checked" /> + <input type="hidden" id="form_type" name="form[type]" value="session.http" /> + <textarea id="form_mimeTypes" name="form[mimeTypes]" required="required" rows="10 4" style="width: 400px" cols="40" class="mp-textbox k-textbox">text/html +text/plain +text/xml +application/json +application/x-www-form-urlencoded +multipart/form-data</textarea> + <input type="hidden" id="form__token" name="form[_token]" value="token-1qwerty" /> + <button type="submit" id="form_save" name="form[save]" class="k-button k-primary">Save</button> + <button type="submit" id="form_cancel" name="form[cancel]" class="k-button">Cancel</button> + </div> + </ForM> + </section> + <section class="container2"> + <form name="form2" action="" method="post"> + <input type="hidden" id="form__token" name="form[_token]" value="token-2qwerty" /> + </form><form name="form3" action="save_form" method="post"> + <input type="hidden" id="form__token" name="form[_token]" value="token-3qwerty" /> + </form> + <form name="form4" action="/service/save_form" method="post"> + <input type="hidden" id="form__token" name="form[_token]" value="token-4qwerty" /> + </form> + </section> +</body> +</html> \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/stress-tester-benchmark/src/main/resources/html/form_csrf_mini.html Tue Aug 08 09:30:02 2017 +0200 @@ -0,0 +1,85 @@ +<!DOCTYPE html> +<html xmlns="http://www.w3.org/1999/xhtml"> +<head lang="en"> + <title>Ambience</title> + <meta charset="UTF-8" /> + <link rel="icon" href="/bundles/passusambience/images/favicon.png" /> + <link rel="shortcut icon" href="/bundles/passusambience/images/favicon.png" /> + <script src="/js/400f5eb_jquery.min_1.js"></script> + <link rel="stylesheet" href="/css/6aebdf5_bootstrap.min_2.css" /> + <link rel="stylesheet" href="/css/6aebdf5_style_6.css" /> +</head> + +<body class="main"> + <section class="container"> + <div class="row" > + <form name="form" method="post" novalidate="novalidate"> + <div class="col-md-12 input-container label-left"> + <div class="row"> + <div class="col-md-12"> + <label for="form_name" class="control-label required">Name:</label> + <input type="text" id="form_name" name="form[name]" required="required" class="mp-textbox k-textbox" value="httpx" /> + </div> + <div class="col-md-12"> + <label for="form_active" class="control-label required">Active:</label> + <input type="checkbox" id="form_active" name="form[active]" required="required" value="1" checked="checked" /> + </div> + <div class="col-md-12"> + <input type="hidden" id="form_type" name="form[type]" value="session.http" /> + </div> + <div class="col-md-12"> + <label for="form_defaultEncoding" class="control-label required">Default Encoding:</label> + <input type="text" id="form_defaultEncoding" name="form[defaultEncoding]" required="required" class="mp-textbox k-textbox" value="UTF-8" /> + </div> + <div class="col-md-12"> + <label for="form_threadsNum" class="control-label required">Number of Threads:</label> + <input id="form_threadsNum" name="form[threadsNum]" type="text" value="1" /> + <script type="text/javascript"> + $(function () { + $("#form_threadsNum").kendoNumericTextBox({"format":"#","decimals":0,"min":0,"max":256,"step":1}); + }); + </script> + </div> + <div class="col-md-12"> + <label for="form_encodeMimeTypes" class="control-label required">Encode MIME Types:</label> + <textarea id="form_encodeMimeTypes" name="form[encodeMimeTypes]" required="required" rows="10 4" style="width: 400px" cols="40" class="mp-textbox k-textbox">text/html +text/plain +text/xml +application/json +application/x-www-form-urlencoded +multipart/form-data</textarea> + </div> + <div class="col-md-12"> + <input type="hidden" id="form__token" name="form[_token]" value="ltZxeOCIr-kgGzU8qvTl2HMwDe1RhU9WmxIcW25whoY" /> + </div> + <div class="col-md-12"> + <input id="form_postFilter" name="form[postFilter]" type="hidden" value="[{"type":"match","match":{"$and":[]},"acceptOnMatch":true,"desc":"ACCEPT when $and: session_post_match $eq value1, "}]" /> + <div id="filter_form_postFilter" ></div> + <script type="text/javascript"> + $(function () { + var filterList_form_postFilter = $("#filter_form_postFilter").kendoEventFilterList({ + }).data("kendoEventFilterList"); + var form = $('form:first'); + + var filterInput_form_postFilter = $('#form_postFilter'); + form.submit(function () { + filterInput_form_postFilter.val(JSON.stringify(filterList_form_postFilter.value(), null, "")); + return true; + }); + }); + </script> + </div> + + <div class="col-md-12"> + <div class="buttons-container" > + <button type="submit" id="form_save" name="form[save]" class="k-button k-primary">Save</button> + <button type="submit" id="form_cancel" name="form[cancel]" class="k-button">Cancel</button> + </div> + </div> + </div> + </div> + </form> + </div> + </section> +</body> +</html> \ No newline at end of file