commit b014df85438a2d7c5537e35c871d68d77dac6e24 Author: Timothy J. Warren Date: Fri Jul 19 16:21:17 2013 -0400 Initial Commit diff --git a/LazyFormFuzz-live.js b/LazyFormFuzz-live.js new file mode 100644 index 0000000..3290e0e --- /dev/null +++ b/LazyFormFuzz-live.js @@ -0,0 +1 @@ +javascript:(function(b){var a=document.createElement("script");a.src="//github.timshomepage.net/LazyFormFuzz/LazyFormFuzz.js";a.async=!1;document.getElementsByTagName("head")[0].appendChild(a)})(); \ No newline at end of file diff --git a/LazyFormFuzz.js b/LazyFormFuzz.js new file mode 100644 index 0000000..f2c83c5 --- /dev/null +++ b/LazyFormFuzz.js @@ -0,0 +1,28 @@ +javascript:(function(w){var b=function(e,h){var c=b.resolve(e,h||"/"),f=b.modules[c];if(!f)throw Error("Failed to resolve module "+e+", tried "+c);return f._cached?f._cached:f()};b.paths=[];b.modules={};b.extensions=[".js",".coffee"];b._core={assert:!0,events:!0,fs:!0,path:!0,vm:!0};b.resolve=function(){return function(e,h){function c(a){if(b.modules[a])return a;for(var g=0;g=a?-32:65<=a&&90>=a?32:0)},g=function(a,b,c,d){return a<=c&&c<=b?{from:c,to:Math.min(b,d)}:a<=d&&d<=b?{from:Math.max(a,c),to:d}:!1},n=function(a,b,c){for(var e,f,h=[],m=!1,l=0,p=a.length;l'; + + return $output; +} + +$js_lib = file_get_contents("src/randexp.min.js"); +$js = file_get_contents("src/LazyFormFuzz-src.js"); +$lff = google_min($js); + +$new_file = "javascript:{$js_lib};{$lff}"; + +file_put_contents("LazyFormFuzz.js", $new_file); + +echo "Bookmarklet created\n"; + diff --git a/src/LazyFormFuzz-src.js b/src/LazyFormFuzz-src.js new file mode 100644 index 0000000..04c6689 --- /dev/null +++ b/src/LazyFormFuzz-src.js @@ -0,0 +1,243 @@ +/** + * Lazy Form Fuzz + * + * A tool to take some drudgery out of form testing + * + * @author Timothy J Warren + * @license MIT + */ +(function(RandExp, undefined) { + + "use strict"; + + // Some 'constants' + var MONTH = "-(1[0-2]|0[1-9])", + YEAR = "(20|1[0-9])[0-9]{2}", // Year 1000 - 2099 + TIME = "(2[0-3]|[0-1][0-9]):[0-5][0-9]", + DATE = YEAR+MONTH+"-(2[0-8]|1[0-9]|0[1-9])"; + + // A map of some common regex patterns + var patterns = { + email: /[a-z0-9._+\-]{1,20}@[a-z0-9]{3,15}\.[a-z]{2,4}/i, + url: /^(https?:\/\/)([a-z\.\-]+)\.([a-z\.]{2,6})\/?$/, + sql: /[a-z0-9"'`\-]{5,17}/, + text: /[\x20-\x7E]{10,15}/, // Visible ASCII character range + color: /^\#[0-9a-f]{6}$/i, + tel: /[0-9+\-]{7,15}/, + alphanumeric: /[A-Z][0-9]+/i, + week: new RegExp(YEAR+"-W(5[1-2]|[1-4][0-9]|0[1-9])"), + month: new RegExp(YEAR+MONTH), + datetime: new RegExp(DATE+"T"+TIME+"Z"), + "datetime-local": new RegExp(DATE+"T"+TIME), + date: new RegExp(DATE), + time: new RegExp(TIME) + }; + + if ( ! Array.prototype.forEach ) { + Array.prototype.forEach = function(fn, scope) { + for(var i = 0, len = this.length; i < len; ++i) { + if (i in this) { + fn.call(scope, this[i], i, this); + } + } + }; + } + + var array_diff = function(arr1) + { + // http://kevin.vanzonneveld.net + // original by: Kevin van Zonneveld (http://kevin.vanzonneveld.net) + // improved by: Sanjoy Roy + // revised by: Brett Zamir (http://brett-zamir.me) + // example 1: array_diff(['Kevin', 'van', 'Zonneveld'], ['van', 'Zonneveld']); + // returns 1: {0:'Kevin'} + var retArr = [], + argl = arguments.length, + k1 = '', + i = 1, + k = '', + arr = {}; + + arr1keys: for (k1 in arr1) { + for (i = 1; i < argl; i++) { + arr = arguments[i]; + for (k in arr) { + if (arr[k] === arr1[k1]) { + // If it reaches here, it was found in at least one array, so try next value + continue arr1keys; + } + } + retArr.push(arr1[k1]); + } + } + + return retArr; + }; + + + /** + * Returns a randomly picked number from a maximum, interval, and minimum + * + * @param int max + * @param int step + * @param int min + * @return int + */ + var pickRand = function(max, step, min) + { + max = max || 1000; + step = step || 1; + min = min || 0; + + var len = Math.round(max / step); + return Math.ceil(Math.random() * len) * step - min; + }; + + var run = function(xdoc, options) + { + // Get all the form elements + var x, + attr, + itype, + self; + var elems = xdoc.querySelectorAll("input, select, textarea"); + var len = elems.length; + + // Remove selections from any option fields + var opts = xdoc.querySelectorAll("option"); + [].forEach.call(opts, function(el) { + el.selected = false; + }); + + // Remove checks from radio or checkboxes + var chkd = xdoc.querySelectorAll("[checked]"); + [].forEach.call(chkd, function(el) { + el.checked = false; + }); + + for(x=0; x < len; x++) + { + self = elems[x]; + + // Check for attributes to skip + if (self.hasAttribute('readonly') || self.hasAttribute('disabled')) {continue;} + + // Uncheck any elements that fall through + if (self.hasAttribute('checked')) { self.checked = false; } + + // Check for pattern attribute + if (self.hasAttribute('pattern')) + { + attr = self.getAttribute('pattern'); + self.value = new RandExp(attr).gen(); + continue; + } + + // ! Non-input form elements + if (self.hasAttribute("type") === false && self.nodeName !== "INPUT") + { + switch(self.nodeName) + { + case "TEXTAREA": + var txt = new RandExp(patterns.text).gen(); + self.value = txt; + continue; + //break; + + case "SELECT": + var sel_opts = self.querySelectorAll("option"); + sel_opts[Math.floor(Math.random() * sel_opts.length)].selected = true; + continue; + //break; + + default: + continue; + //break; + } + } + + // Default pattern for special input types + itype = self.getAttribute('type'); + + var patt, + boxen, + boxen_names = {}; + + switch(itype) + { + case "radio": + if (boxen_names[self.name] == null) + { + boxen = array_diff( + xdoc.querySelectorAll('input[type=radio][name='+self.name+']'), + xdoc.querySelectorAll('[name='+self.name+'][disabled]') + ); + + boxen[Math.floor(Math.random() * boxen.length)].checked = true; + boxen_names[self.name] = true; + } + continue; + //break; + + case "number": + case "range": + self.value = pickRand(self.getAttribute('max'), self.getAttribute('step'), self.getAttribute('min')); + continue; + //break; + + case "checkbox": + var chk = Math.round(Math.random()); + self.checked = chk; + continue; + //break; + + case "search": + case "text": + patt = patterns.text; + break; + + case "hidden": + case "button": + case "image": + case "file": + case "password": + case "reset": + case "submit": + continue; + //break; + + default: + if (patterns[itype] != null) + { + patt = patterns[itype]; + } + break; + } + + if (patt !== null && patt !== undefined) + { + var val = new RandExp(patt).gen(); + self.value = val; + if (String(self.value).toLowerCase() != String(val).toLowerCase()) + { + console.log(itype+" : "+val); + console.log(self.value); + } + continue; + } + } + }; + + // Run on the main document + run(document); + + // Run on frames if they exist + var frms = document.querySelectorAll("frame, iframe"); + var frlen = frms.length; + if (frlen > 0) + { + [].forEach.call(frms, function(frm) { + run(frm.contentWindow.document); + }); + } +}(RandExp)); \ No newline at end of file diff --git a/src/randexp.min.js b/src/randexp.min.js new file mode 100644 index 0000000..11abf9c --- /dev/null +++ b/src/randexp.min.js @@ -0,0 +1,23 @@ +(function(w){var b=function(e,h){var c=b.resolve(e,h||"/"),f=b.modules[c];if(!f)throw Error("Failed to resolve module "+e+", tried "+c);return f._cached?f._cached:f()};b.paths=[];b.modules={};b.extensions=[".js",".coffee"];b._core={assert:!0,events:!0,fs:!0,path:!0,vm:!0};b.resolve=function(){return function(e,h){function c(a){if(b.modules[a])return a;for(var g=0;g=a?-32:65<=a&&90>=a?32:0)},g=function(a,b,c,d){return a<=c&&c<=b?{from:c,to:Math.min(b,d)}:a<=d&&d<=b?{from:Math.max(a,c),to:d}:!1},n=function(a,b,c){for(var e,f,h=[],m=!1,l=0,p=a.length;l + + + Test + + + +

Form Filler/Fuzzer Test

+ +
+
+ HTML5 Miscellaneous Input Types +
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+
+ HTML5 Date/Time Input Types +
+
+
+ +
+
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+
+ Traditional Form Elements +
+
+
+ +
+ +
+
+ +
+ +
+
+ +
+ +
+
+ +
+
+
+
+ Traditional Input Types +
+
+
+ + + +
+ + + +
+ + + +
+ +
+
+ +
+
+ +
Radio
+
+ + +
+ + +
+ + +
+ + +
+ + +
+ + + +
+ +
+
+ +
+
+ +
+
+ +
+
+
+
+
+ + + \ No newline at end of file diff --git a/test/inner_form.html b/test/inner_form.html new file mode 100644 index 0000000..4377d08 --- /dev/null +++ b/test/inner_form.html @@ -0,0 +1,98 @@ + + + + Test + + + +

Form Filler/Fuzzer Frame Test

+
+
+ HTML5 Miscellaneous Input Types +
+
+
+
+
+
+ +
+
+ HTML5 Date/Time Input Types +
+
+
+
+
+ +
+
+ Traditional Form Elements +
+
+
+ +
+
+ Traditional Input Types +
+ + + +
+ + + +
+ + + +
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + \ No newline at end of file