'use strict';

var util = require('./util');

var DATE = /^(dddd)-(dd)-(dd)$/; var DAYS = [0,31,28,31,30,31,30,31,31,30,31,30,31]; var TIME = /^(dd):(dd):(dd)(.d+)?(z|[+-]dd:dd)?$/i; var HOSTNAME = /^[a-z0-9](?:[a-z0-9-]{0,61})?(?:.[a-z0-9](?:[-0-9a-z]{0,61})?)*$/i; var URI = /^(?:[a-z]*:)(?:/?/(?:(?:[%\^`{|}]|%[0-9a-f]{2})|{[+#./;?&=,!@|]?(?:[a-z0-9_]|%[0-9a-f]{2})+(?::[1-9][0-9]{0,3}|*)?(?:,(?:[a-z0-9_]|%[0-9a-f]{2})+(?::[1-9][0-9]{0,3}|*)?)*})*$/i; // For the source: https://gist.github.com/dperini/729294 // For test cases: https://mathiasbynens.be/demo/url-regex // @todo Delete current URL in favour of the commented out URL rule when this issue is fixed https://github.com/eslint/eslint/issues/7983. // var URL = /^(?:(?:https?|ftp)://)(?:S+(?::S*)?@)?(?:(?!10(?:.d{1,3}){3})(?!127(?:.d{1,3}){3})(?!169.254(?:.d{1,3}){2})(?!192.168(?:.d{1,3}){2})(?!172.(?:1[6-9]|2d|3[0-1])(?:.d{1,3}){2})(?:[1-9]d?|1dd|2[01]d|22[0-3])(?:.(?:1?d{1,2}|2[0-4]d|25[0-5])){2}(?:.(?:[1-9]d?|1dd|2[0-4]d|25[0-4]))|(?:(?:[a-zu{00a1}-u{ffff}0-9]+-?)*[a-zu{00a1}-u{ffff}0-9]+)(?:.(?:[a-zu{00a1}-u{ffff}0-9]+-?)*[a-zu{00a1}-u{ffff}0-9]+)*(?:.(?:[a-zu{00a1}-u{ffff}]{2,})))(?::d{2,5})?(?:/[^s]*)?$/iu; var URL = /^(?:(?:http[su017F]?|ftp)://)(?:(?:[0-x08x0E-x1F!-x9FxA1-u167Fu1681-u1FFFu200B-u2027u202A-u202Eu2030-u205Eu2060-u2FFFu3001-uD7FFuE000-uFEFEuFF00-uFFFF]|[uD800-uDBFF][uDC00-uDFFF]|[uD800-uDBFF](?![uDC00-uDFFF])|(?:[^uD800-uDBFF]|^)[uDC00-uDFFF])+(?::(?:[0-x08x0E-x1F!-x9FxA1-u167Fu1681-u1FFFu200B-u2027u202A-u202Eu2030-u205Eu2060-u2FFFu3001-uD7FFuE000-uFEFEuFF00-uFFFF]|[uD800-uDBFF][uDC00-uDFFF]|[uD800-uDBFF](?![uDC00-uDFFF])|(?:[^uD800-uDBFF]|^)[uDC00-uDFFF])*)?@)?(?:(?!10(?:.[0-9]{1,3}){3})(?!127(?:.[0-9]{1,3}){3})(?!169.254(?:.[0-9]{1,3}){2})(?!192.168(?:.[0-9]{1,3}){2})(?!172.(?:1[6-9]|2[0-9]|3[01])(?:.[0-9]{1,3}){2})(?:[1-9][0-9]?|1[0-9][0-9]|2[01][0-9]|22[0-3])(?:.(?:1?[0-9]{1,2}|2[0-4][0-9]|25[0-5])){2}(?:.(?:[1-9][0-9]?|1[0-9][0-9]|2[0-4][0-9]|25[0-4]))|(?:(?:(?:[0-9KSa-zxA1-uD7FFuE000-uFFFF]|[uD800-uDBFF](?![uDC00-uDFFF])|(?:[^uD800-uDBFF]|^)[uDC00-uDFFF])+-?)*(?:[0-9KSa-zxA1-uD7FFuE000-uFFFF]|[uD800-uDBFF](?![uDC00-uDFFF])|(?:[^uD800-uDBFF]|^)[uDC00-uDFFF])+)(?:.(?:(?:[0-9KSa-zxA1-uD7FFuE000-uFFFF]|[uD800-uDBFF](?![uDC00-uDFFF])|(?:[^uD800-uDBFF]|^)[uDC00-uDFFF])+-?)*(?:[0-9KSa-zxA1-uD7FFuE000-uFFFF]|[uD800-uDBFF](?![uDC00-uDFFF])|(?:[^uD800-uDBFF]|^)[uDC00-uDFFF])+)*(?:.(?:(?:[KSa-zxA1-uD7FFuE000-uFFFF]|[uD800-uDBFF](?![uDC00-uDFFF])|(?:[^uD800-uDBFF]|^)[uDC00-uDFFF]){2,})))(?::[0-9]{2,5})?(?:/(?:[0-x08x0E-x1F!-x9FxA1-u167Fu1681-u1FFFu200B-u2027u202A-u202Eu2030-u205Eu2060-u2FFFu3001-uD7FFuE000-uFEFEuFF00-uFFFF]|[uD800-uDBFF][uDC00-uDFFF]|[uD800-uDBFF](?![uDC00-uDFFF])|(?:[^uD800-uDBFF]|^)[uDC00-uDFFF])*)?$/i; var UUID = /^(?:urn:uuid:)?[0-9a-f]{8}-(?:[0-9a-f]{4}-){3}[0-9a-f“>a-z0-9-._~!$&‘()*+,;=:]|%[0-9a-f]{2})*@)?(?:[(?:(?:(?:(?:[0-9a-f]{1,4}:){6}|::(?:[0-9a-f]{1,4}:){5}|(?:[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){4}|(?:(?:[0-9a-f]{1,4}:){0,1}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){3}|(?:(?:[0-9a-f]{1,4}:){0,2}[0-9a-f]{1,4})?::(?:[0-9a-f]{1,4}:){2}|(?:(?:[0-9a-f]{1,4}:){0,3}[0-9a-f]{1,4})?::[0-9a-f]{1,4}:|(?:(?:[0-9a-f]{1,4}:){0,4}[0-9a-f]{1,4})?::)(?:[0-9a-f]{1,4}:[0-9a-f]{1,4}|(?:(?:25[0-5]|2[0-4]d|[01]?dd?).){3}(?:25[0-5]|2[0-4]d|[01]?dd?))|(?:(?:[0-9a-f]{1,4}:){0,5}[0-9a-f]{1,4})?::[0-9a-f]{1,4}|(?:(?:[0-9a-f]{1,4}:){0,6}[0-9a-f]{1,4})?::)|[Vv][0-9a-f]+.[a-z0-9-._~!$&’()*+,;=:]+)]|(?:(?:25[0-5]|2[0-4]d|[01]?dd?).){3}(?:25[0-5]|2[0-4]d|[01]?dd?)|(?:[a-z0-9-._~!$&‘()*+,;=]|%[0-9a-f]{2})*)(?::d*)?(?:/(?:[a-z0-9-._~!$&’()*+,;=:@]|%[0-9a-f]{2})*)*|/(?:(?:[a-z0-9-._~!$&‘()*+,;=:@]|%[0-9a-f]{2})+(?:/(?:[a-z0-9-._~!$&’()*+,;=:@]|%[0-9a-f]{2})*)*)?|(?:[a-z0-9-._~!$&‘()*+,;=:@]|%[0-9a-f]{2})+(?:/(?:[a-z0-9-._~!$&’()*+,;=:@]|%[0-9a-f]{2})*)*)(?:?(?:[a-z0-9-._~!$&‘()*+,;=:@/?]|%[0-9a-f]{2})*)?(?:#(?:[a-z0-9-._~!$&’()*+,;=:@/?]|%{12}$/i; var JSON_POINTER = /^(?:/(?:[^~/]|~0|~1)*)*$/; var JSON_POINTER_URI_FRAGMENT = /^#(?:/(?:[a-z0-9_-.!$&‘()*+,;:=@]|%{2}|~0|~1)*)*$/i; var RELATIVE_JSON_POINTER = /^(?:0|[0-9]*)(?:#|(?:/(?:|~0|~1)*)*)$/;

module.exports = formats;

function formats(mode) {

mode = mode == 'full' ? 'full' : 'fast';
return util.copy(formats[mode]);

}

formats.fast = {

// date: http://tools.ietf.org/html/rfc3339#section-5.6
date: /^\d\d\d\d-[0-1]\d-[0-3]\d$/,
// date-time: http://tools.ietf.org/html/rfc3339#section-5.6
time: /^(?:[0-2]\d:[0-5]\d:[0-5]\d|23:59:60)(?:\.\d+)?(?:z|[+-]\d\d:\d\d)?$/i,
'date-time': /^\d\d\d\d-[0-1]\d-[0-3]\d[t\s](?:[0-2]\d:[0-5]\d:[0-5]\d|23:59:60)(?:\.\d+)?(?:z|[+-]\d\d:\d\d)$/i,
// uri: https://github.com/mafintosh/is-my-json-valid/blob/master/formats.js
uri: /^(?:[a-z][a-z0-9+-.]*:)(?:\/?\/)?[^\s]*$/i,
'uri-reference': /^(?:(?:[a-z][a-z0-9+-.]*:)?\/?\/)?(?:[^\\\s#][^\s#]*)?(?:#[^\\\s]*)?$/i,
'uri-template': URITEMPLATE,
url: URL,
// email (sources from jsen validator):
// http://stackoverflow.com/questions/201323/using-a-regular-expression-to-validate-an-email-address#answer-8829363
// http://www.w3.org/TR/html5/forms.html#valid-e-mail-address (search for 'willful violation')
email: /^[a-z0-9.!#$%&'*+/=?^_`{|}~-]+@[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?(?:\.[a-z0-9](?:[a-z0-9-]{0,61}[a-z0-9])?)*$/i,
hostname: HOSTNAME,
// optimized https://www.safaribooksonline.com/library/view/regular-expressions-cookbook/9780596802837/ch07s16.html
ipv4: /^(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)$/,
// optimized http://stackoverflow.com/questions/53497/regular-expression-that-matches-valid-ipv6-addresses
ipv6: /^\s*(?:(?:(?:[0-9a-f]{1,4}:){7}(?:[0-9a-f]{1,4}|:))|(?:(?:[0-9a-f]{1,4}:){6}(?::[0-9a-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(?:(?:[0-9a-f]{1,4}:){5}(?:(?:(?::[0-9a-f]{1,4}){1,2})|:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(?:(?:[0-9a-f]{1,4}:){4}(?:(?:(?::[0-9a-f]{1,4}){1,3})|(?:(?::[0-9a-f]{1,4})?:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){3}(?:(?:(?::[0-9a-f]{1,4}){1,4})|(?:(?::[0-9a-f]{1,4}){0,2}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){2}(?:(?:(?::[0-9a-f]{1,4}){1,5})|(?:(?::[0-9a-f]{1,4}){0,3}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){1}(?:(?:(?::[0-9a-f]{1,4}){1,6})|(?:(?::[0-9a-f]{1,4}){0,4}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?::(?:(?:(?::[0-9a-f]{1,4}){1,7})|(?:(?::[0-9a-f]{1,4}){0,5}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(?:%.+)?\s*$/i,
regex: regex,
// uuid: http://tools.ietf.org/html/rfc4122
uuid: UUID,
// JSON-pointer: https://tools.ietf.org/html/rfc6901
// uri fragment: https://tools.ietf.org/html/rfc3986#appendix-A
'json-pointer': JSON_POINTER,
'json-pointer-uri-fragment': JSON_POINTER_URI_FRAGMENT,
// relative JSON-pointer: http://tools.ietf.org/html/draft-luff-relative-json-pointer-00
'relative-json-pointer': RELATIVE_JSON_POINTER

};

formats.full = {

date: date,
time: time,
'date-time': date_time,
uri: uri,
'uri-reference': URIREF,
'uri-template': URITEMPLATE,
url: URL,
email: /^[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/i,
hostname: hostname,
ipv4: /^(?:(?:25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(?:25[0-5]|2[0-4]\d|[01]?\d\d?)$/,
ipv6: /^\s*(?:(?:(?:[0-9a-f]{1,4}:){7}(?:[0-9a-f]{1,4}|:))|(?:(?:[0-9a-f]{1,4}:){6}(?::[0-9a-f]{1,4}|(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(?:(?:[0-9a-f]{1,4}:){5}(?:(?:(?::[0-9a-f]{1,4}){1,2})|:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(?:(?:[0-9a-f]{1,4}:){4}(?:(?:(?::[0-9a-f]{1,4}){1,3})|(?:(?::[0-9a-f]{1,4})?:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){3}(?:(?:(?::[0-9a-f]{1,4}){1,4})|(?:(?::[0-9a-f]{1,4}){0,2}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){2}(?:(?:(?::[0-9a-f]{1,4}){1,5})|(?:(?::[0-9a-f]{1,4}){0,3}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?:(?:[0-9a-f]{1,4}:){1}(?:(?:(?::[0-9a-f]{1,4}){1,6})|(?:(?::[0-9a-f]{1,4}){0,4}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(?::(?:(?:(?::[0-9a-f]{1,4}){1,7})|(?:(?::[0-9a-f]{1,4}){0,5}:(?:(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(?:\.(?:25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(?:%.+)?\s*$/i,
regex: regex,
uuid: UUID,
'json-pointer': JSON_POINTER,
'json-pointer-uri-fragment': JSON_POINTER_URI_FRAGMENT,
'relative-json-pointer': RELATIVE_JSON_POINTER

};

function isLeapYear(year) {

// https://tools.ietf.org/html/rfc3339#appendix-C
return year % 4 === 0 && (year % 100 !== 0 || year % 400 === 0);

}

function date(str) {

// full-date from http://tools.ietf.org/html/rfc3339#section-5.6
var matches = str.match(DATE);
if (!matches) return false;

var year = +matches[1];
var month = +matches[2];
var day = +matches[3];

return month >= 1 && month <= 12 && day >= 1 &&
        day <= (month == 2 && isLeapYear(year) ? 29 : DAYS[month]);

}

function time(str, full) {

var matches = str.match(TIME);
if (!matches) return false;

var hour = matches[1];
var minute = matches[2];
var second = matches[3];
var timeZone = matches[5];
return ((hour <= 23 && minute <= 59 && second <= 59) ||
        (hour == 23 && minute == 59 && second == 60)) &&
       (!full || timeZone);

}

var DATE_TIME_SEPARATOR = /t|s/i; function date_time(str) {

// http://tools.ietf.org/html/rfc3339#section-5.6
var dateTime = str.split(DATE_TIME_SEPARATOR);
return dateTime.length == 2 && date(dateTime[0]) && time(dateTime[1], true);

}

function hostname(str) {

// https://tools.ietf.org/html/rfc1034#section-3.5
// https://tools.ietf.org/html/rfc1123#section-2
return str.length <= 255 && HOSTNAME.test(str);

}

var NOT_URI_FRAGMENT = //|:/; function uri(str) {

// http://jmrware.com/articles/2009/uri_regexp/URI_regex.html + optional protocol + required "."
return NOT_URI_FRAGMENT.test(str) && URI.test(str);

}

var Z_ANCHOR = /[^\]\Z/; function regex(str) {

if (Z_ANCHOR.test(str)) return false;
try {
  new RegExp(str);
  return true;
} catch(e) {
  return false;
}

}