123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566 |
- <!DOCTYPE HTML>
- <html>
- <!--
- https://bugzilla.mozilla.org/show_bug.cgi?id=549475
- -->
- <head>
- <title>Test for Bug 549475</title>
- <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
- <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
- </head>
- <body>
- <a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=549475">Mozilla Bug 549475</a>
- <p id="display"></p>
- <pre id="test">
- <div id='content'>
- <form>
- </form>
- </div>
- <script type="application/javascript">
- SimpleTest.requestLongerTimeout(2);
- /**
- * This files tests the 'value sanitization algorithm' for the various input
- * types. Note that an input's value is affected by more than just its type's
- * value sanitization algorithm; e.g. some type=range has actions that the user
- * agent must perform to change the element's value to avoid underflow/overflow
- * and step mismatch (when possible). We specifically avoid triggering these
- * other actions here so that this test only tests the value sanitization
- * algorithm for the various input types.
- *
- * XXXjwatt splitting out testing of the value sanitization algorithm and
- * "other things" that affect .value makes it harder to know what we're testing
- * and what we've missed, because what's included in the value sanitization
- * algorithm and what's not is different from input type to input type. It
- * seems to me it would be better to have a test (maybe one per type) focused
- * on testing .value for permutations of all other inputs that can affect it.
- * The value sanitization algorithm is just an internal spec concept after all.
- */
- // We buffer up the results of sets of sub-tests, and avoid outputting log
- // entries for them all if they all pass. Otherwise, we have an enormous amount
- // of test output.
- var delayedTests = [];
- var anyFailedDelayedTests = false;
- function delayed_is(actual, expected, description)
- {
- var result = actual == expected;
- delayedTests.push({ actual: actual, expected: expected, description: description });
- if (!result) {
- anyFailedDelayedTests = true;
- }
- }
- function flushDelayedTests(description)
- {
- if (anyFailedDelayedTests) {
- info("Outputting individual results for \"" + description + "\" due to failures in subtests");
- for (var test of delayedTests) {
- is(test.actual, test.expected, test.description);
- }
- } else {
- ok(true, description + " (" + delayedTests.length + " subtests)");
- }
- delayedTests = [];
- anyFailedDelayedTests = false;
- }
- // We are excluding "file" because it's too different from the other types.
- // And it has no sanitizing algorithm.
- var inputTypes =
- [
- "text", "password", "search", "tel", "hidden", "checkbox", "radio",
- "submit", "image", "reset", "button", "email", "url", "number", "date",
- "time", "range", "color", "month", "week", "datetime-local"
- ];
- var valueModeValue =
- [
- "text", "search", "url", "tel", "email", "password", "date", "datetime",
- "month", "week", "time", "datetime-local", "number", "range", "color",
- ];
- function sanitizeDate(aValue)
- {
- // http://www.whatwg.org/specs/web-apps/current-work/multipage/common-microsyntaxes.html#valid-date-string
- function getNumbersOfDaysInMonth(aMonth, aYear) {
- if (aMonth === 2) {
- return (aYear % 400 === 0 || (aYear % 100 != 0 && aYear % 4 === 0)) ? 29 : 28;
- }
- return (aMonth === 1 || aMonth === 3 || aMonth === 5 || aMonth === 7 ||
- aMonth === 8 || aMonth === 10 || aMonth === 12) ? 31 : 30;
- }
- var match = /^([0-9]{4,})-([0-9]{2})-([0-9]{2})$/.exec(aValue);
- if (!match) {
- return "";
- }
- var year = Number(match[1]);
- if (year === 0) {
- return "";
- }
- var month = Number(match[2]);
- if (month > 12 || month < 1) {
- return "";
- }
- var day = Number(match[3]);
- return 1 <= day && day <= getNumbersOfDaysInMonth(month, year) ? aValue : "";
- }
- function sanitizeTime(aValue)
- {
- // http://www.whatwg.org/specs/web-apps/current-work/multipage/common-microsyntaxes.html#valid-time-string
- var match = /^([0-9]{2}):([0-9]{2})(.*)$/.exec(aValue);
- if (!match) {
- return "";
- }
- var hours = match[1];
- if (hours < 0 || hours > 23) {
- return "";
- }
- var minutes = match[2];
- if (minutes < 0 || minutes > 59) {
- return "";
- }
- var other = match[3];
- if (other == "") {
- return aValue;
- }
- match = /^:([0-9]{2})(.*)$/.exec(other);
- if (!match) {
- return "";
- }
- var seconds = match[1];
- if (seconds < 0 || seconds > 59) {
- return "";
- }
- var other = match[2];
- if (other == "") {
- return aValue;
- }
- match = /^.([0-9]{1,3})$/.exec(other);
- if (!match) {
- return "";
- }
- return aValue;
- }
- function sanitizeDateTimeLocal(aValue)
- {
- // https://html.spec.whatwg.org/multipage/infrastructure.html#valid-local-date-and-time-string
- if (aValue.length < 16) {
- return "";
- }
- var separator = aValue[10];
- if (separator != "T" && separator != " ") {
- return "";
- }
- var [date, time] = aValue.split(separator);
- if (!sanitizeDate(date)) {
- return "";
- }
- if (!sanitizeTime(time)) {
- return "";
- }
- // Normalize datetime-local string.
- // https://html.spec.whatwg.org/multipage/infrastructure.html#valid-normalised-local-date-and-time-string
- if (separator == " ") {
- aValue = date + "T" + time;
- }
- if (aValue.length == 16) {
- return aValue;
- }
- if (aValue.length > 19) {
- var milliseconds = aValue.substring(20);
- if (Number(milliseconds) != 0) {
- return aValue;
- }
- aValue = aValue.slice(0, 19);
- }
- var seconds = aValue.substring(17);
- if (Number(seconds) != 0) {
- return aValue;
- }
- aValue = aValue.slice(0, 16);
- return aValue;
- }
- function sanitizeValue(aType, aValue)
- {
- // http://www.whatwg.org/html/#value-sanitization-algorithm
- switch (aType) {
- case "text":
- case "password":
- case "search":
- case "tel":
- return aValue.replace(/[\n\r]/g, "");
- case "url":
- case "email":
- return aValue.replace(/[\n\r]/g, "").replace(/^[\u0020\u0009\t\u000a\u000c\u000d]+|[\u0020\u0009\t\u000a\u000c\u000d]+$/g, "");
- case "number":
- return isNaN(Number(aValue)) ? "" : aValue;
- case "range":
- var defaultMinimum = 0;
- var defaultMaximum = 100;
- var value = Number(aValue);
- if (isNaN(value)) {
- return ((defaultMaximum - defaultMinimum)/2).toString(); // "50"
- }
- if (value < defaultMinimum) {
- return defaultMinimum.toString();
- }
- if (value > defaultMaximum) {
- return defaultMaximum.toString();
- }
- return aValue;
- case "date":
- return sanitizeDate(aValue);
- case "time":
- return sanitizeTime(aValue);
- case "month":
- // https://html.spec.whatwg.org/multipage/infrastructure.html#valid-month-string
- var match = /^([0-9]{4,})-([0-9]{2})$/.exec(aValue);
- if (!match) {
- return "";
- }
- var year = Number(match[1]);
- if (year === 0) {
- return "";
- }
- var month = Number(match[2]);
- if (month > 12 || month < 1) {
- return "";
- }
- return aValue;
- case "week":
- // https://html.spec.whatwg.org/multipage/infrastructure.html#valid-week-string
- function isLeapYear(aYear) {
- return ((aYear % 4 == 0) && (aYear % 100 != 0)) || (aYear % 400 == 0);
- }
- function getDayofWeek(aYear, aMonth, aDay) { /* 0 = Sunday */
- // Tomohiko Sakamoto algorithm.
- var monthTable = [0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4];
- aYear -= Number(aMonth < 3);
- return (aYear + parseInt(aYear / 4) - parseInt(aYear / 100) +
- parseInt(aYear / 400) + monthTable[aMonth - 1] + aDay) % 7;
- }
- function getMaximumWeekInYear(aYear) {
- var day = getDayofWeek(aYear, 1, 1);
- return day == 4 || (day == 3 && isLeapYear(aYear)) ? 53 : 52;
- }
- var match = /^([0-9]{4,})-W([0-9]{2})$/.exec(aValue);
- if (!match) {
- return "";
- }
- var year = Number(match[1]);
- if (year === 0) {
- return "";
- }
- var week = Number(match[2]);
- if (week > 53 || month < 1) {
- return "";
- }
- return 1 <= week && week <= getMaximumWeekInYear(year) ? aValue : "";
- case "datetime-local":
- return sanitizeDateTimeLocal(aValue);
- case "color":
- return /^#[0-9A-Fa-f]{6}$/.exec(aValue) ? aValue.toLowerCase() : "#000000";
- default:
- return aValue;
- }
- }
- function checkSanitizing(element, inputTypeDescription)
- {
- var testData =
- [
- // For text, password, search, tel, email:
- "\n\rfoo\n\r",
- "foo\n\rbar",
- " foo ",
- " foo\n\r bar ",
- // For url:
- "\r\n foobar \n\r",
- "\u000B foo \u000B",
- "\u000A foo \u000A",
- "\u000C foo \u000C",
- "\u000d foo \u000d",
- "\u0020 foo \u0020",
- " \u0009 foo \u0009 ",
- // For number and range:
- "42",
- "13.37",
- "1.234567898765432",
- "12foo",
- "1e2",
- "3E42",
- // For date:
- "1970-01-01",
- "1234-12-12",
- "1234567890-01-02",
- "2012-12-31",
- "2012-02-29",
- "2000-02-29",
- "1234",
- "1234-",
- "12345",
- "1234-01",
- "1234-012",
- "1234-01-",
- "12-12",
- "999-01-01",
- "1234-56-78-91",
- "1234-567-78",
- "1234--7-78",
- "abcd-12-12",
- "thisinotadate",
- "2012-13-01",
- "1234-12-42",
- " 2012-13-01",
- " 123-01-01",
- "2012- 3-01",
- "12- 10- 01",
- " 12-0-1",
- "2012-3-001",
- "2012-12-00",
- "2012-12-1r",
- "2012-11-31",
- "2011-02-29",
- "2100-02-29",
- "a2000-01-01",
- "2000a-01-0'",
- "20aa00-01-01",
- "2000a2000-01-01",
- "2000-1-1",
- "2000-1-01",
- "2000-01-1",
- "2000-01-01 ",
- "2000- 01-01",
- "-1970-01-01",
- "0000-00-00",
- "0001-00-00",
- "0000-01-01",
- "1234-12 12",
- "1234 12-12",
- "1234 12 12",
- // For time:
- "1",
- "10",
- "10:",
- "10:1",
- "21:21",
- ":21:21",
- "-21:21",
- " 21:21",
- "21-21",
- "21:21:",
- "21:211",
- "121:211",
- "21:21 ",
- "00:00",
- "-1:00",
- "24:00",
- "00:60",
- "01:01",
- "23:59",
- "99:99",
- "8:30",
- "19:2",
- "19:a2",
- "4c:19",
- "10:.1",
- "1.:10",
- "13:37:42",
- "13:37.42",
- "13:37:42 ",
- "13:37:42.",
- "13:37:61.",
- "13:37:00",
- "13:37:99",
- "13:37:b5",
- "13:37:-1",
- "13:37:.1",
- "13:37:1.",
- "13:37:42.001",
- "13:37:42.001",
- "13:37:42.abc",
- "13:37:42.00c",
- "13:37:42.a23",
- "13:37:42.12e",
- "13:37:42.1e1",
- "13:37:42.e11",
- "13:37:42.1",
- "13:37:42.99",
- "13:37:42.0",
- "13:37:42.00",
- "13:37:42.000",
- "13:37:42.-1",
- "13:37:42.1.1",
- "13:37:42.1,1",
- "13:37:42.",
- "foo12:12",
- "13:37:42.100000000000",
- // For color
- "#00ff00",
- "#000000",
- "red",
- "#0f0",
- "#FFFFAA",
- "FFAABB",
- "fFAaBb",
- "FFAAZZ",
- "ABCDEF",
- "#7654321",
- // For month
- "1970-01",
- "1234-12",
- "123456789-01",
- "2013-13",
- "0000-00",
- "2015-00",
- "0001-01",
- "1-1",
- "888-05",
- "2013-3",
- "2013-may",
- "2000-1a",
- "2013-03-13",
- "december",
- "abcdef",
- "12",
- " 2013-03",
- "2013 - 03",
- "2013 03",
- "2013/03",
- // For week
- "1970-W01",
- "1970-W53",
- "1964-W53",
- "1900-W10",
- "2004-W53",
- "2065-W53",
- "2099-W53",
- "2010-W53",
- "2016-W30",
- "1900-W3",
- "2016-w30",
- "2016-30",
- "16-W30",
- "2016-Week30",
- "2000-100",
- "0000-W01",
- "00-W01",
- "123456-W05",
- "1985-W100",
- "week",
- // For datetime-local
- "1970-01-01T00:00",
- "1970-01-01Z12:00",
- "1970-01-01 00:00:00",
- "1970-01-01T00:00:00.0",
- "1970-01-01T00:00:00.00",
- "1970-01-01T00:00:00.000",
- "1970-01-01 00:00:00.20",
- "1234567-01-01T12:00",
- "2016-13-01T12:00",
- "2016-12-32T12:00",
- "2016-11-08 15:40:30.0",
- "2016-11-08T15:40:30.00",
- "2016-11-07T17:30:10",
- "2016-12-1T12:45",
- "2016-12-01T12:45:30.123456",
- "2016-12-01T24:00",
- "2016-12-01T12:88:30",
- "2016-12-01T12:30:99",
- "2016-12-01T12:30:100",
- "2016-12-01",
- "2016-12-01T",
- "2016-Dec-01T00:00",
- "12-05-2016T00:00",
- "datetime-local"
- ];
- for (value of testData) {
- element.setAttribute('value', value);
- delayed_is(element.value, sanitizeValue(type, value),
- "The value has not been correctly sanitized for type=" + type);
- delayed_is(element.getAttribute('value'), value,
- "The content value should not have been sanitized");
- if (type in valueModeValue) {
- element.setAttribute('value', 'tulip');
- element.value = value;
- delayed_is(element.value, sanitizeValue(type, value),
- "The value has not been correctly sanitized for type=" + type);
- delayed_is(element.getAttribute('value'), 'tulip',
- "The content value should not have been sanitized");
- }
- element.setAttribute('value', '');
- form.reset();
- element.type = 'checkbox'; // We know this type has no sanitizing algorithm.
- element.setAttribute('value', value);
- delayed_is(element.value, value, "The value should not have been sanitized");
- element.type = type;
- delayed_is(element.value, sanitizeValue(type, value),
- "The value has not been correctly sanitized for type=" + type);
- delayed_is(element.getAttribute('value'), value,
- "The content value should not have been sanitized");
- element.setAttribute('value', '');
- form.reset();
- element.setAttribute('value', value);
- form.reset();
- delayed_is(element.value, sanitizeValue(type, value),
- "The value has not been correctly sanitized for type=" + type);
- delayed_is(element.getAttribute('value'), value,
- "The content value should not have been sanitized");
- // Cleaning-up.
- element.setAttribute('value', '');
- form.reset();
- }
- flushDelayedTests(inputTypeDescription);
- }
- for (type of inputTypes) {
- var form = document.forms[0];
- var element = document.createElement("input");
- element.style.display = "none";
- element.type = type;
- form.appendChild(element);
- checkSanitizing(element, "type=" + type + ", no frame, no editor");
- element.style.display = "";
- checkSanitizing(element, "type=" + type + ", frame, no editor");
- element.focus();
- element.blur();
- checkSanitizing(element, "type=" + type + ", frame, editor");
- element.style.display = "none";
- checkSanitizing(element, "type=" + type + ", no frame, editor");
- form.removeChild(element);
- }
- </script>
- </pre>
- </body>
- </html>
|