diff --git a/README.md b/README.md index 53bc33529..9bf2e47b5 100644 --- a/README.md +++ b/README.md @@ -100,6 +100,7 @@ Validator | Description **isHash(str, algorithm)** | check if the string is a hash of type algorithm.

Algorithm is one of `['md4', 'md5', 'sha1', 'sha256', 'sha384', 'sha512', 'ripemd128', 'ripemd160', 'tiger128', 'tiger160', 'tiger192', 'crc32', 'crc32b']` **isHexColor(str)** | check if the string is a hexadecimal color. **isHexadecimal(str)** | check if the string is a hexadecimal number. +**isIBAN(str, locale)** | check if the string is a valid IBAN number,

(locale is one of `[ 'AD', 'AT', 'AU', 'BE', 'BG', 'CA', 'CH', 'CZ', 'DE', 'DK', 'DZ', 'EE', 'ES', 'FI', 'FR', 'GB', 'GR', 'HR', 'HU', 'ID', 'IL', 'IN', 'IS', 'IT', 'JP', 'KE', 'LI', 'LT', 'LU', 'LV', 'MX', 'NL', 'NO', 'PL', 'PT', 'RO', 'RU', 'SA', 'SE', 'SI', 'TN', 'TW', 'UA', 'US', 'ZA', 'ZM' ]` OR 'any'. If 'any' is used, function will check if any of the locals match with the first twi caracters of the IBAN number (wich corresponds to the ISO 3166-1 alpha-2 country code). Locale list is `validator.isIBANLocales`). **isIdentityCard(str [, locale])** | check if the string is a valid identity card code.

`locale` is one of `['ES', 'zh-TW', 'he-IL']` OR `'any'`. If 'any' is used, function will check if any of the locals match.

Defaults to 'any'. **isIP(str [, version])** | check if the string is an IP (version 4 or 6). **isIPRange(str)** | check if the string is an IP Range(version 4 only). diff --git a/index.js b/index.js index 0af96d5e6..0d3eda308 100644 --- a/index.js +++ b/index.js @@ -95,6 +95,8 @@ var _isBefore = _interopRequireDefault(require("./lib/isBefore")); var _isIn = _interopRequireDefault(require("./lib/isIn")); +var _isIBAN = _interopRequireWildcard(require("./lib/isIBAN")); + var _isCreditCard = _interopRequireDefault(require("./lib/isCreditCard")); var _isIdentityCard = _interopRequireDefault(require("./lib/isIdentityCard")); @@ -206,6 +208,8 @@ var validator = { isAfter: _isAfter.default, isBefore: _isBefore.default, isIn: _isIn.default, + isIBAN: _isIBAN.default, + isIBANLocales: _isIBAN.locales, isCreditCard: _isCreditCard.default, isIdentityCard: _isIdentityCard.default, isISIN: _isISIN.default, diff --git a/lib/isIBAN.js b/lib/isIBAN.js new file mode 100644 index 000000000..29bd60593 --- /dev/null +++ b/lib/isIBAN.js @@ -0,0 +1,128 @@ +"use strict"; + +Object.defineProperty(exports, "__esModule", { + value: true +}); +exports.default = isIBAN; +exports.locales = void 0; + +var _assertString = _interopRequireDefault(require("./util/assertString")); + +function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } + +/* eslint-disable max-len */ +var iban = { + AD: /^(AD[0-9]{2})\d{8}[0-9A-Z]{12}$/, + AL: /^(AL[0-9]{2})\d{8}[A-Z0-9]{16}$/, + AT: /^(AT[0-9]{2})\d{16}$/, + BA: /^(BA[0-9]{2})\d{16}$/, + BE: /^(BE[0-9]{2})\d{12}$/, + BG: /^(BG[0-9]{2})[A-Z]{4}\d{4}[A-Z0-9]{10}$/, + BH: /^(BH[0-9]{2})[A-Z]{4}[A-Z0-9]{14}$/, + BR: /^(BR[0-9]{2})\d{23}[A-Z][A-Z0-9]$/, + CH: /^(CH[0-9]{2})\d{17}$/, + CY: /^(CY[0-9]{2})\d{8}[A-Z0-9]{16}$/, + CZ: /^(CZ[0-9]{2})\d{20}$/, + DE: /^(DE[0-9]{2})\d{18}$/, + DK: /^(DK[0-9]{2})\d{14}$/, + EE: /^(EE[0-9]{2})\d{16}$/, + ES: /^(ES[0-9]{2})\d{20}$/, + FO: /^(FO[0-9]{2})\d{14}$/, + FI: /^(FI[0-9]{2})\d{14}$/, + FR: /^(FR[0-9]{2})\d{10}[A-Z0-9]{11}\d{2}$/, + GB: /^(GB[0-9]{2})[A-Z]{4}\d{14}$/, + GE: /^(GE[0-9]{2})[A-Z]{2}\d{16}$/, + GI: /^(GI[0-9]{2})[A-Z]{4}[A-Z0-9]{15}$/, + GL: /^(GL[0-9]{2})\d{14}$/, + GR: /^(GR[0-9]{2})\d{7}[A-Z0-9]{16}$/, + HR: /^(HR[0-9]{2})\d{17}$/, + HU: /^(HU[0-9]{2})\d{24}$/, + IE: /^(IE[0-9]{2})[A-Z]{4}\d{14}$/, + IS: /^(IS[0-9]{2})\d{22}$/, + IT: /^(IT[0-9]{2})[A-Z]\d{10}[A-Z0-9]{12}$/, + JO: /^(JO[0-9]{2})[A-Z]{4}\d{4}[A-Z0-9]{18}$/, + KW: /^(KW[0-9]{2})[A-Z]{4}[A-Z0-9]{22}$/, + KZ: /^(KZ[0-9]{2})\d{3}[A-Z0-9]{13}$/, + LB: /^(LB[0-9]{2})\d{4}[A-Z0-9]{20}$/, + LI: /^(LI[0-9]{2})\d{5}[A-Z0-9]{12}$/, + LT: /^(LT[0-9]{2})\d{16}$/, + LU: /^(LU[0-9]{2})\d{3}[A-Z0-9]{13}$/, + LV: /^(LV[0-9]{2})[A-Z]{4}[A-Z0-9]{13}$/, + MC: /^(MC[0-9]{2})\d{10}[A-Z0-9]{11}\d{2}$/, + MD: /^(MD[0-9]{2})[A-Z]{2}[A-Z0-9]{18}$/, + ME: /^(ME[0-9]{2})\d{18}$/, + MK: /^(MK[0-9]{2})\d{3}[A-Z0-9]{12}$/, + MT: /^(MT[0-9]{2})[A-Z]{4}\d{5}[A-Z0-9]{18}$/, + NL: /^(NL[0-9]{2})[A-Z]{4}\d{10}$/, + NO: /^(NO[0-9]{2})\d{11}$/, + PL: /^(PL[0-9]{2})\d{24}$/, + PS: /^(PS[0-9]{2})[A-Z]{4}[A-Z0-9]{21}$/, + PT: /^(PT[0-9]{2})\d{21}$/, + QA: /^(QA[0-9]{2})[A-Z]{4}[A-Z0-9]{21}$/, + RO: /^(RO[0-9]{2})[A-Z]{4}[A-Z0-9]{16}$/, + SA: /^(SA[0-9]{2})\d{2}[A-Z0-9]{18}$/, + SE: /^(SE[0-9]{2})\d{20}$/, + SI: /^(SI[0-9]{2})\d{15}$/, + SK: /^(SK[0-9]{2})\d{20}$/, + SM: /^(SM[0-9]{2})[A-Z]{1}\d{10}[A-Z0-9]{12}$/, + RS: /^(RS[0-9]{2})\d{18}$/, + TN: /^(TN[0-9]{2})\d{20}$/, + TR: /^(TR[0-9]{2})\d{5}[A-Z0-9]{17}$/, + UA: /^(UA[0-9]{2})\d{6}[A-Z0-9]{19}$/, + XK: /^(XK[0-9]{2})\d{16}$/ +}; +/* eslint-enable max-len */ + +/** + * @function IbanCalcul - calculate if the IBAN corresponds to the reglementation: converting + * it into an integer and performing a basic mod-97 operation. If the IBAN is valid, the remainder + * equals 1. + * 1- Check that the total IBAN length is correct as per the country. If not, the IBAN is invalid + * 2- Move the four initial characters to the end of the string + * 3- Replace each letter in the string with two digits, thereby expanding the string, + * where A = 10..., Z = 35 + * 4- Interpret the string as a decimal integer and compute the remainder of that number on + * division by 97 + * @param {e} - recieves the IBAN tested + * @warns IBAN's length differs from country to another, the maximum length is 34 characters so + * calculating its modulus 97 is not possible for all machines.To solve this, the function calculate + * the modulus of the first 9 digit by 97 and add the result to the beginning of the remain IBAN + * number. The process is repeated untill the result's length is less than 10 + */ + +var IbanCalcul = function IbanCalcul(e) { + var countryCode = e.slice(0, 4); + var result = e.slice(4, e.length) + countryCode; + + for (var counter = 1; counter <= Math.ceil(e.length / 10) + 1; counter++) { + var remainder = result.slice(0, 10).replace(/[A-Z]/g, function (element) { + return element.charCodeAt() - 55; + }) % 97; + result = remainder + result.slice(10); + } + + if (result === '1') return true; + return false; +}; + +function isIBAN(str, locale) { + (0, _assertString.default)(str); + str = str.toUpperCase(); + + if (locale in iban) { + return iban[locale].test(str) && IbanCalcul(str); + } else if (!locale || locale === 'any') { + locale = str.slice(0, 2); + + if (locale in iban) { + return iban[locale].test(str) && IbanCalcul(str); + } + + return false; + } + + throw new Error("Invalid locale '".concat(locale, "'")); +} + +var locales = Object.keys(iban); +exports.locales = locales; \ No newline at end of file diff --git a/src/index.js b/src/index.js index 1d21203d9..259e417f5 100644 --- a/src/index.js +++ b/src/index.js @@ -57,6 +57,8 @@ import isBefore from './lib/isBefore'; import isIn from './lib/isIn'; +import isIBAN, { locales as isIBANLocales } from './lib/isIBAN'; + import isCreditCard from './lib/isCreditCard'; import isIdentityCard from './lib/isIdentityCard'; @@ -147,6 +149,8 @@ const validator = { isAfter, isBefore, isIn, + isIBAN, + isIBANLocales, isCreditCard, isIdentityCard, isISIN, diff --git a/src/lib/isIBAN.js b/src/lib/isIBAN.js new file mode 100644 index 000000000..c8a30f341 --- /dev/null +++ b/src/lib/isIBAN.js @@ -0,0 +1,109 @@ +import assertString from './util/assertString'; + +/* eslint-disable max-len */ +const iban = { + AD: /^(AD[0-9]{2})\d{8}[0-9A-Z]{12}$/, + AL: /^(AL[0-9]{2})\d{8}[A-Z0-9]{16}$/, + AT: /^(AT[0-9]{2})\d{16}$/, + BA: /^(BA[0-9]{2})\d{16}$/, + BE: /^(BE[0-9]{2})\d{12}$/, + BG: /^(BG[0-9]{2})[A-Z]{4}\d{4}[A-Z0-9]{10}$/, + BH: /^(BH[0-9]{2})[A-Z]{4}[A-Z0-9]{14}$/, + BR: /^(BR[0-9]{2})\d{23}[A-Z][A-Z0-9]$/, + CH: /^(CH[0-9]{2})\d{17}$/, + CY: /^(CY[0-9]{2})\d{8}[A-Z0-9]{16}$/, + CZ: /^(CZ[0-9]{2})\d{20}$/, + DE: /^(DE[0-9]{2})\d{18}$/, + DK: /^(DK[0-9]{2})\d{14}$/, + EE: /^(EE[0-9]{2})\d{16}$/, + ES: /^(ES[0-9]{2})\d{20}$/, + FO: /^(FO[0-9]{2})\d{14}$/, + FI: /^(FI[0-9]{2})\d{14}$/, + FR: /^(FR[0-9]{2})\d{10}[A-Z0-9]{11}\d{2}$/, + GB: /^(GB[0-9]{2})[A-Z]{4}\d{14}$/, + GE: /^(GE[0-9]{2})[A-Z]{2}\d{16}$/, + GI: /^(GI[0-9]{2})[A-Z]{4}[A-Z0-9]{15}$/, + GL: /^(GL[0-9]{2})\d{14}$/, + GR: /^(GR[0-9]{2})\d{7}[A-Z0-9]{16}$/, + HR: /^(HR[0-9]{2})\d{17}$/, + HU: /^(HU[0-9]{2})\d{24}$/, + IE: /^(IE[0-9]{2})[A-Z]{4}\d{14}$/, + IS: /^(IS[0-9]{2})\d{22}$/, + IT: /^(IT[0-9]{2})[A-Z]\d{10}[A-Z0-9]{12}$/, + JO: /^(JO[0-9]{2})[A-Z]{4}\d{4}[A-Z0-9]{18}$/, + KW: /^(KW[0-9]{2})[A-Z]{4}[A-Z0-9]{22}$/, + KZ: /^(KZ[0-9]{2})\d{3}[A-Z0-9]{13}$/, + LB: /^(LB[0-9]{2})\d{4}[A-Z0-9]{20}$/, + LI: /^(LI[0-9]{2})\d{5}[A-Z0-9]{12}$/, + LT: /^(LT[0-9]{2})\d{16}$/, + LU: /^(LU[0-9]{2})\d{3}[A-Z0-9]{13}$/, + LV: /^(LV[0-9]{2})[A-Z]{4}[A-Z0-9]{13}$/, + MC: /^(MC[0-9]{2})\d{10}[A-Z0-9]{11}\d{2}$/, + MD: /^(MD[0-9]{2})[A-Z]{2}[A-Z0-9]{18}$/, + ME: /^(ME[0-9]{2})\d{18}$/, + MK: /^(MK[0-9]{2})\d{3}[A-Z0-9]{12}$/, + MT: /^(MT[0-9]{2})[A-Z]{4}\d{5}[A-Z0-9]{18}$/, + NL: /^(NL[0-9]{2})[A-Z]{4}\d{10}$/, + NO: /^(NO[0-9]{2})\d{11}$/, + PL: /^(PL[0-9]{2})\d{24}$/, + PS: /^(PS[0-9]{2})[A-Z]{4}[A-Z0-9]{21}$/, + PT: /^(PT[0-9]{2})\d{21}$/, + QA: /^(QA[0-9]{2})[A-Z]{4}[A-Z0-9]{21}$/, + RO: /^(RO[0-9]{2})[A-Z]{4}[A-Z0-9]{16}$/, + SA: /^(SA[0-9]{2})\d{2}[A-Z0-9]{18}$/, + SE: /^(SE[0-9]{2})\d{20}$/, + SI: /^(SI[0-9]{2})\d{15}$/, + SK: /^(SK[0-9]{2})\d{20}$/, + SM: /^(SM[0-9]{2})[A-Z]{1}\d{10}[A-Z0-9]{12}$/, + RS: /^(RS[0-9]{2})\d{18}$/, + TN: /^(TN[0-9]{2})\d{20}$/, + TR: /^(TR[0-9]{2})\d{5}[A-Z0-9]{17}$/, + UA: /^(UA[0-9]{2})\d{6}[A-Z0-9]{19}$/, + XK: /^(XK[0-9]{2})\d{16}$/, +}; +/* eslint-enable max-len */ + +/** + * @function IbanCalcul - calculate if the IBAN corresponds to the reglementation: converting + * it into an integer and performing a basic mod-97 operation. If the IBAN is valid, the remainder + * equals 1. + * 1- Check that the total IBAN length is correct as per the country. If not, the IBAN is invalid + * 2- Move the four initial characters to the end of the string + * 3- Replace each letter in the string with two digits, thereby expanding the string, + * where A = 10..., Z = 35 + * 4- Interpret the string as a decimal integer and compute the remainder of that number on + * division by 97 + * @param {e} - recieves the IBAN tested + * @warns IBAN's length differs from country to another, the maximum length is 34 characters so + * calculating its modulus 97 is not possible for all machines.To solve this, the function calculate + * the modulus of the first 9 digit by 97 and add the result to the beginning of the remain IBAN + * number. The process is repeated untill the result's length is less than 10 + */ +const IbanCalcul = (e) => { + const countryCode = e.slice(0, 4); + let result = e.slice(4, e.length) + countryCode; + for (let counter = 1; counter <= Math.ceil(e.length / 10) + 1; counter++) { + let remainder = + result.slice(0, 10).replace(/[A-Z]/g, element => element.charCodeAt() - 55) % 97; + result = remainder + result.slice(10); + } + if (result === '1') return true; + return false; +}; + +export default function isIBAN(str, locale) { + assertString(str); + str = str.toUpperCase(); + if (locale in iban) { + return iban[locale].test(str) && IbanCalcul(str); + } else if (!locale || locale === 'any') { + locale = str.slice(0, 2); + if (locale in iban) { + return iban[locale].test(str) && IbanCalcul(str); + } + return false; + } + throw new Error(`Invalid locale '${locale}'`); +} + +export const locales = Object.keys(iban); diff --git a/test/validators.js b/test/validators.js index acb5ac226..e7081309a 100644 --- a/test/validators.js +++ b/test/validators.js @@ -5266,6 +5266,496 @@ describe('Validators', () => { }); }); + it('should validate IBAN number', () => { + let fixtures = [ + { + locale: 'AD', + valid: ['AD1200012030200359100100'], + invalid: ['AD1200012030200359100109', 'AB1200012030200359100109'], + }, + { + locale: 'AL', + valid: ['AL47212110090000000235698741'], + invalid: [ + 'AL47212110090000000235698749', + 'AL472A2110090000000235698741', + 'AL472121100900000002356987419', + ], + }, + { + locale: 'AT', + valid: ['AT611904300234573201'], + invalid: ['AT611904300234573209', 'AT6119043002345732019', 'AT61190430023457320X'], + }, + { + locale: 'BH', + valid: ['BH67BMAG00001299123456'], + invalid: ['BH67BMAG00001299123451', 'BH67BM2G00001299123456', 'BH67BMAG000012991234569'], + }, + { + locale: 'BE', + valid: ['BE68539007547034'], + invalid: ['BE68539007547031', 'BE6853900754703X', 'BE685390075470349'], + }, + { + locale: 'BA', + valid: ['BA391290079401028494'], + invalid: ['BA391290079401028499', 'BA39129007940102849X', 'BA3912900794010284949'], + }, + { + locale: 'BG', + valid: ['BG80BNBG96611020345678'], + invalid: [ + 'BG80BNBG96611020345679', + 'BG80B9BG96611020345678', + 'BG80BNBG9A611020345678', + 'BG80BNBG966110203456789', + ], + }, + { + locale: 'BR', + valid: ['BR9700360305000010009795493P1'], + invalid: [ + 'BR9700360305000010009795499P1', + 'BR970036030500001000979549391', + 'BR970036030500001000979549AP1', + 'BR9700360305000010009795493P19', + ], + }, + { + locale: 'CH', + valid: ['CH9300762011623852957'], + invalid: ['CH9300762011623852959', 'CH930076201162385295A', 'CH93007620116238529579'], + }, + { + locale: 'CY', + valid: ['CY17002001280000001200527600'], + invalid: [ + 'CY17002001280000001200527609', + 'CY17A02001280000001200527600', + 'CY170020012800000012005276009', + ], + }, + { + locale: 'CZ', + valid: ['CZ6508000000192000145399'], + invalid: [ + 'CZ6508000000192000145391', + 'CZ650800000019200014539A', + 'CZ65080000001920001453999', + ], + }, + { + locale: 'DE', + valid: ['DE89370400440532013000'], + invalid: ['DE89370400440532013009', 'DE8937040044053201300A', 'DE893704004405320130009'], + }, + { + locale: 'DK', + valid: ['DK5000400440116243'], + invalid: ['DK5000400440116249', 'DK500040044011624A', 'DK50004004401162439'], + }, + { + locale: 'EE', + valid: ['EE382200221020145685'], + invalid: ['EE382200221020145689', 'EE38220022102014568A', 'EE3822002210201456859'], + }, + { + locale: 'ES', + valid: ['ES9121000418450200051332'], + invalid: [ + 'ES9121000418450200051339', + 'ES912100041845020005133A', + 'ES91210004184502000513329', + ], + }, + { + locale: 'FO', + valid: ['FO6264600001631634'], + invalid: ['FO6264600001631639', 'FO626460000163163A', 'FO62646000016316349'], + }, + { + locale: 'FI', + valid: ['FI2112345600000785'], + invalid: ['FI2112345600000789', 'FI211234560000078A', 'FI21123456000007859'], + }, + { + locale: 'FR', + valid: ['FR1420041010050500013M02606'], + invalid: [ + 'FR1420041010050500013M02609', + 'FR1420041010050500013M0260A', + 'FR1420041010050500013M026A6', + 'FR14A0041010050500013M02606', + 'FR1420041010050500013M026069', + ], + }, + { + locale: 'GB', + valid: ['GB29NWBK60161331926819'], + invalid: [ + 'GB29NWBK60161331926811', + 'GB29NWBK6016133192681A', + 'GB29N9BK60161331926819', + 'GB29NWBK601613319268199', + ], + }, + { + locale: 'GE', + valid: ['GE29NB0000000101904917'], + invalid: [ + 'GE29NB0000000101904919', + 'GE29NB000000010190491A', + 'GE29N90000000101904917', + 'GE29NB00000001019049179', + ], + }, + { + locale: 'GI', + valid: ['GI75NWBK000000007099453'], + invalid: ['GI75NWBK000000007099459', 'GI75N9BK000000007099453', 'GI75NWBK0000000070994539'], + }, + { + locale: 'GL', + valid: ['GL8964710001000206'], + invalid: ['GL8964710001000209', 'GL896471000100020A', 'GL89647100010002069'], + }, + { + locale: 'GR', + valid: ['GR1601101250000000012300695'], + invalid: [ + 'GR1601101250000000012300699', + 'GR16A1101250000000012300695', + 'GR16011012500000000123006959', + ], + }, + { + locale: 'HU', + valid: ['HU42117730161111101800000000'], + invalid: [ + 'HU42117730161111101800000009', + 'HU4211773016111110180000000A', + 'HU421177301611111018000000009', + ], + }, + { + locale: 'HR', + valid: ['HR1210010051863000160'], + invalid: ['HR1210010051863000169', 'HR121001005186300016A', 'HR12100100518630001609'], + }, + { + locale: 'IE', + valid: ['IE29AIBK93115212345678'], + invalid: [ + 'IE29AIBK93115212345679', + 'IE29AEBK9311521234567A', + 'IE29A9BK93115212345678', + 'IE29AIBK931152123456789', + ], + }, + { + locale: 'IS', + valid: ['IS140159260076545510730339'], + invalid: [ + 'IS140159260076545510730331', + 'IS14015926007654551073033A', + 'IS1401592600765455107303399', + ], + }, + { + locale: 'IT', + valid: ['IT60X0542811101000000123456'], + invalid: [ + 'IT60X0542811101000000123459', + 'IT6090542811101000000123456', + 'IT60XA542811101000000123456', + 'IT60X05428111010000001234569', + ], + }, + { + locale: 'JO', + valid: ['JO94CBJO0010000000000131000302'], + invalid: [ + 'JO94CBJO0010000000000131000309', + 'JO94C9JO0010000000000131000302', + 'JO94CBJOA010000000000131000302', + 'JO94CBJO00100000000001310003029', + ], + }, + { + locale: 'KW', + valid: ['KW81CBKU0000000000001234560101'], + invalid: [ + 'KW81CBKU0000000000001234560109', + 'KW81CB9U0000000000001234560101', + 'KW81CBKU00000000000012345601019', + ], + }, + { + locale: 'KZ', + valid: ['KZ86125KZT5004100100'], + invalid: ['KZ86125KZT5004100109', 'KZ86125K9T5004100100', 'KZ86125KZT50041001009'], + }, + { + locale: 'LB', + valid: ['LB62099900000001001901229114'], + invalid: [ + 'LB62099900000001001901229119', + 'LB6209A900000001001901229114', + 'LB620999000000010019012291149', + ], + }, + { + locale: 'LI', + valid: ['LI21088100002324013AA'], + invalid: ['LI21088100002324013A9', 'LI21A88100002324013AA', 'LI21088100002324013AA9'], + }, + { + locale: 'LT', + valid: ['LT121000011101001000'], + invalid: ['LT121000011101001009', 'LT12100001110100100A', 'LT1210000111010010009'], + }, + { + locale: 'LV', + valid: ['LV80BANK0000435195001'], + invalid: ['LV80BANK0000435195009', 'LV80B9NK0000435195001', 'LV80BANK00004351950019'], + }, + { + locale: 'MC', + valid: ['MC5811222000010123456789030'], + invalid: [ + 'MC5811222000010123456789039', + 'MC581122200001012345678903A', + 'MC58A1222000010123456789030', + 'MC58112220000101234567890309', + ], + }, + { + locale: 'MD', + valid: ['MD24AG000225100013104168'], + invalid: [ + 'MD24AG000225100013104169', + 'MD24A9000225100013104168', + 'MD24AG0002251000131041689', + ], + }, + { + locale: 'ME', + valid: ['ME25505000012345678951'], + invalid: ['ME25505000012345678959', 'ME2550500001234567895A', 'ME255050000123456789519'], + }, + { + locale: 'MK', + valid: ['MK07250120000058984'], + invalid: ['MK07250120000058989', 'MK07A50120000058984', 'MK072501200000589849'], + }, + { + locale: 'MT', + valid: ['MT84MALT011000012345MTLCAST001S'], + invalid: [ + 'MT84MALT011000012345MTLCAST0019', + 'MT84M9LT011000012345MTLCAST001S', + 'MT84MALT0A1000012345MTLCAST001S', + 'MT84MALT011000012345MTLCAST001S9', + ], + }, + { + locale: 'NL', + valid: ['NL91ABNA0417164300'], + invalid: [ + 'NL91ABNA0417164309', + 'NL91AB9A0417164300', + 'NL91ABNA041716430A', + 'NL91ABNA04171643009', + ], + }, + { + locale: 'NO', + valid: ['NO9386011117947'], + invalid: ['NO9386011117949', 'NO938601111794A', 'NO93860111179479'], + }, + { + locale: 'PL', + valid: ['PL61109010140000071219812874'], + invalid: [ + 'PL61109010140000071219812879', + 'PL6110901014000007121981287A', + 'PL611090101400000712198128749', + ], + }, + { + locale: 'PS', + valid: ['PS92PALS000000000400123456702'], + invalid: [ + 'PS92PALS000000000400123456709', + 'PS92P9LS000000000400123456702', + 'PS92PALS0000000004001234567029', + ], + }, + { + locale: 'PT', + valid: ['PT50000201231234567890154'], + invalid: [ + 'PT50000201231234567890159', + 'PT5000020123123456789015A', + 'PT500002012312345678901549', + ], + }, + { + locale: 'QA', + valid: ['QA73BBME000000000004056677001'], + invalid: [ + 'QA73BBME000000000004056677009', + 'QA73B9ME000000000004056677001', + 'QA73BBME0000000000040566770019', + ], + }, + { + locale: 'RO', + valid: ['RO49AAAA1B31007593840000'], + invalid: [ + 'RO49AAAA1B31007593840009', + 'RO49A9AA1B31007593840000', + 'RO49AAAA1B310075938400009', + ], + }, + { + locale: 'SA', + valid: ['SA0380000000608010167519'], + invalid: [ + 'SA0380000000608010167511', + 'SA03A0000000608010167519', + 'SA03800000006080101675199', + ], + }, + { + locale: 'SE', + valid: ['SE4550000000058398257466'], + invalid: [ + 'SE4550000000058398257469', + 'SE455000000005839825746A', + 'SE45500000000583982574669', + ], + }, + { + locale: 'SI', + valid: ['SI56263300012039086'], + invalid: ['SI56263300012039089', 'SI5626330001203908A', 'SI562633000120390869'], + }, + { + locale: 'SK', + valid: ['SK3112000000198742637541'], + invalid: [ + 'SK3112000000198742637549', + 'SK311200000019874263754A', + 'SK31120000001987426375419', + ], + }, + { + locale: 'SM', + valid: ['SM86U0322509800000000270100'], + invalid: [ + 'SM86U0322509800000000270109', + 'SM8690322509800000000270100', + 'SM86UA322509800000000270100', + 'SM86U03225098000000002701009', + ], + }, + { + locale: 'RS', + valid: ['RS35260005601001611379'], + invalid: ['RS35260005601001611371', 'RS3526000560100161137A', 'RS352600056010016113799'], + }, + { + locale: 'TN', + valid: ['TN5910006035183598478831'], + invalid: [ + 'TN5910006035183598478839', + 'TN591000603518359847883A', + 'TN59100060351835984788319', + ], + }, + { + locale: 'TR', + valid: ['TR330006100519786457841326'], + invalid: [ + 'TR330006100519786457841329', + 'TR33A006100519786457841326', + 'TR3300061005197864578413269', + ], + }, + { + locale: 'UA', + valid: ['UA213996220000026007233566001'], + invalid: [ + 'UA213996220000026007233566009', + 'UA21A996220000026007233566001', + 'UA2139962200000260072335660019', + ], + }, + { + locale: 'XK', + valid: ['XK051212012345678906'], + invalid: ['XK051212012345678909', 'XK05121201234567890A', 'XK0512120123456789069'], + }, + ]; + + let allValid = []; + + fixtures.forEach((fixture) => { + // to be used later on for validating 'any' locale + if (fixture.valid) allValid = allValid.concat(fixture.valid); + + test({ + validator: 'isIBAN', + valid: fixture.valid, + invalid: fixture.invalid, + args: [fixture.locale], + }); + }); + + test({ + validator: 'isIBAN', + valid: allValid, + invalid: [ + '', + 'asdf', + '1', + 'ASDFGJKLmZXJtZtesting123', + 'Vml2YW11cyBmZXJtZtesting123', + ], + args: ['any'], + }); + + // falsey locale defaults to 'any' + test({ + validator: 'isIBAN', + valid: allValid, + invalid: [ + '', + 'asdf', + '1', + 'ASDFGJKLmZXJtZtesting123', + 'Vml2YW11cyBmZXJtZtesting123', + ], + args: [], + }); + }); + + it('should error on invalid locale isIBAN', () => { + test({ + validator: 'isIBAN', + args: ['is-NOT'], + error: [ + '', + 'asdf', + '1', + 'ASDFGJKLmZXJtZtesting123', + 'Vml2YW11cyBmZXJtZtesting123', + ], + }); + }); + it('should validate currency', () => { // -$##,###.## (en-US, en-CA, en-AU, en-NZ, en-HK) test({ diff --git a/validator.js b/validator.js index f9fe7b4da..f821e3f38 100644 --- a/validator.js +++ b/validator.js @@ -1077,6 +1077,122 @@ function isIn(str, options) { /* eslint-disable max-len */ +var iban = { + AD: /^(AD[0-9]{2})\d{8}[0-9A-Z]{12}$/, + AL: /^(AL[0-9]{2})\d{8}[A-Z0-9]{16}$/, + AT: /^(AT[0-9]{2})\d{16}$/, + BA: /^(BA[0-9]{2})\d{16}$/, + BE: /^(BE[0-9]{2})\d{12}$/, + BG: /^(BG[0-9]{2})[A-Z]{4}\d{4}[A-Z0-9]{10}$/, + BH: /^(BH[0-9]{2})[A-Z]{4}[A-Z0-9]{14}$/, + BR: /^(BR[0-9]{2})\d{23}[A-Z][A-Z0-9]$/, + CH: /^(CH[0-9]{2})\d{17}$/, + CY: /^(CY[0-9]{2})\d{8}[A-Z0-9]{16}$/, + CZ: /^(CZ[0-9]{2})\d{20}$/, + DE: /^(DE[0-9]{2})\d{18}$/, + DK: /^(DK[0-9]{2})\d{14}$/, + EE: /^(EE[0-9]{2})\d{16}$/, + ES: /^(ES[0-9]{2})\d{20}$/, + FO: /^(FO[0-9]{2})\d{14}$/, + FI: /^(FI[0-9]{2})\d{14}$/, + FR: /^(FR[0-9]{2})\d{10}[A-Z0-9]{11}\d{2}$/, + GB: /^(GB[0-9]{2})[A-Z]{4}\d{14}$/, + GE: /^(GE[0-9]{2})[A-Z]{2}\d{16}$/, + GI: /^(GI[0-9]{2})[A-Z]{4}[A-Z0-9]{15}$/, + GL: /^(GL[0-9]{2})\d{14}$/, + GR: /^(GR[0-9]{2})\d{7}[A-Z0-9]{16}$/, + HR: /^(HR[0-9]{2})\d{17}$/, + HU: /^(HU[0-9]{2})\d{24}$/, + IE: /^(IE[0-9]{2})[A-Z]{4}\d{14}$/, + IS: /^(IS[0-9]{2})\d{22}$/, + IT: /^(IT[0-9]{2})[A-Z]\d{10}[A-Z0-9]{12}$/, + JO: /^(JO[0-9]{2})[A-Z]{4}\d{4}[A-Z0-9]{18}$/, + KW: /^(KW[0-9]{2})[A-Z]{4}[A-Z0-9]{22}$/, + KZ: /^(KZ[0-9]{2})\d{3}[A-Z0-9]{13}$/, + LB: /^(LB[0-9]{2})\d{4}[A-Z0-9]{20}$/, + LI: /^(LI[0-9]{2})\d{5}[A-Z0-9]{12}$/, + LT: /^(LT[0-9]{2})\d{16}$/, + LU: /^(LU[0-9]{2})\d{3}[A-Z0-9]{13}$/, + LV: /^(LV[0-9]{2})[A-Z]{4}[A-Z0-9]{13}$/, + MC: /^(MC[0-9]{2})\d{10}[A-Z0-9]{11}\d{2}$/, + MD: /^(MD[0-9]{2})[A-Z]{2}[A-Z0-9]{18}$/, + ME: /^(ME[0-9]{2})\d{18}$/, + MK: /^(MK[0-9]{2})\d{3}[A-Z0-9]{12}$/, + MT: /^(MT[0-9]{2})[A-Z]{4}\d{5}[A-Z0-9]{18}$/, + NL: /^(NL[0-9]{2})[A-Z]{4}\d{10}$/, + NO: /^(NO[0-9]{2})\d{11}$/, + PL: /^(PL[0-9]{2})\d{24}$/, + PS: /^(PS[0-9]{2})[A-Z]{4}[A-Z0-9]{21}$/, + PT: /^(PT[0-9]{2})\d{21}$/, + QA: /^(QA[0-9]{2})[A-Z]{4}[A-Z0-9]{21}$/, + RO: /^(RO[0-9]{2})[A-Z]{4}[A-Z0-9]{16}$/, + SA: /^(SA[0-9]{2})\d{2}[A-Z0-9]{18}$/, + SE: /^(SE[0-9]{2})\d{20}$/, + SI: /^(SI[0-9]{2})\d{15}$/, + SK: /^(SK[0-9]{2})\d{20}$/, + SM: /^(SM[0-9]{2})[A-Z]{1}\d{10}[A-Z0-9]{12}$/, + RS: /^(RS[0-9]{2})\d{18}$/, + TN: /^(TN[0-9]{2})\d{20}$/, + TR: /^(TR[0-9]{2})\d{5}[A-Z0-9]{17}$/, + UA: /^(UA[0-9]{2})\d{6}[A-Z0-9]{19}$/, + XK: /^(XK[0-9]{2})\d{16}$/ +}; +/* eslint-enable max-len */ + +/** + * @function IbanCalcul - calculate if the IBAN corresponds to the reglementation: converting + * it into an integer and performing a basic mod-97 operation. If the IBAN is valid, the remainder + * equals 1. + * 1- Check that the total IBAN length is correct as per the country. If not, the IBAN is invalid + * 2- Move the four initial characters to the end of the string + * 3- Replace each letter in the string with two digits, thereby expanding the string, + * where A = 10..., Z = 35 + * 4- Interpret the string as a decimal integer and compute the remainder of that number on + * division by 97 + * @param {e} - recieves the IBAN tested + * @warns IBAN's length differs from country to another, the maximum length is 34 characters so + * calculating its modulus 97 is not possible for all machines.To solve this, the function calculate + * the modulus of the first 9 digit by 97 and add the result to the beginning of the remain IBAN + * number. The process is repeated untill the result's length is less than 10 + */ + +var IbanCalcul = function IbanCalcul(e) { + var countryCode = e.slice(0, 4); + var result = e.slice(4, e.length) + countryCode; + + for (var counter = 1; counter <= Math.ceil(e.length / 10) + 1; counter++) { + var remainder = result.slice(0, 10).replace(/[A-Z]/g, function (element) { + return element.charCodeAt() - 55; + }) % 97; + result = remainder + result.slice(10); + } + + if (result === '1') return true; + return false; +}; + +function isIBAN(str, locale) { + assertString(str); + str = str.toUpperCase(); + + if (locale in iban) { + return iban[locale].test(str) && IbanCalcul(str); + } else if (!locale || locale === 'any') { + locale = str.slice(0, 2); + + if (locale in iban) { + return iban[locale].test(str) && IbanCalcul(str); + } + + return false; + } + + throw new Error("Invalid locale '".concat(locale, "'")); +} +var locales$3 = Object.keys(iban); + +/* eslint-disable max-len */ + var creditCard = /^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|(222[1-9]|22[3-9][0-9]|2[3-6][0-9]{2}|27[01][0-9]|2720)[0-9]{12}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\d{3})\d{11}|6[27][0-9]{14})$/; /* eslint-enable max-len */ @@ -1471,7 +1587,7 @@ function isMobilePhone(str, locale, options) { throw new Error("Invalid locale '".concat(locale, "'")); } -var locales$3 = Object.keys(phones); +var locales$4 = Object.keys(phones); function currencyRegex(options) { var decimal_digits = "\\d{".concat(options.digits_after_decimal[0], "}"); @@ -1800,7 +1916,7 @@ var patterns = { ZA: fourDigit, ZM: fiveDigit }; -var locales$4 = Object.keys(patterns); +var locales$5 = Object.keys(patterns); var isPostalCode = function (str, locale) { assertString(str); @@ -2070,15 +2186,17 @@ var validator = { isAfter: isAfter, isBefore: isBefore, isIn: isIn, + isIBAN: isIBAN, + isIBANLocales: locales$3, isCreditCard: isCreditCard, isIdentityCard: isIdentityCard, isISIN: isISIN, isISBN: isISBN, isISSN: isISSN, isMobilePhone: isMobilePhone, - isMobilePhoneLocales: locales$3, + isMobilePhoneLocales: locales$4, isPostalCode: isPostalCode, - isPostalCodeLocales: locales$4, + isPostalCodeLocales: locales$5, isCurrency: isCurrency, isISO8601: isISO8601, isRFC3339: isRFC3339, diff --git a/validator.min.js b/validator.min.js index 46acfae86..12d36649b 100644 --- a/validator.min.js +++ b/validator.min.js @@ -20,4 +20,4 @@ * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */ -!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):t.validator=e()}(this,function(){"use strict";function a(t){return(a="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(t){return typeof t}:function(t){return t&&"function"==typeof Symbol&&t.constructor===Symbol&&t!==Symbol.prototype?"symbol":typeof t})(t)}function g(t,e){return function(t){if(Array.isArray(t))return t}(t)||function(t,e){var r=[],n=!0,o=!1,i=void 0;try{for(var a,l=t[Symbol.iterator]();!(n=(a=l.next()).done)&&(r.push(a.value),!e||r.length!==e);n=!0);}catch(t){o=!0,i=t}finally{try{n||null==l.return||l.return()}finally{if(o)throw i}}return r}(t,e)||function(){throw new TypeError("Invalid attempt to destructure non-iterable instance")}()}function $(t){var e;if(!("string"==typeof t||t instanceof String))throw e=null===t?"null":"object"===(e=a(t))&&t.constructor&&t.constructor.hasOwnProperty("name")?t.constructor.name:"a ".concat(e),new TypeError("Expected string but received ".concat(e,"."))}function o(t){return $(t),t=Date.parse(t),isNaN(t)?null:new Date(t)}function r(t){return $(t),parseFloat(t)}function i(t){return"object"===a(t)&&null!==t?t="function"==typeof t.toString?t.toString():"[object Object]":(null==t||isNaN(t)&&!t.length)&&(t=""),String(t)}function m(t,e){var r=0i)return!1;if("::"===t)return!0;"::"===t.substr(0,2)?(r.shift(),r.shift(),n=!0):"::"===t.substr(t.length-2)&&(r.pop(),r.pop(),n=!0);for(var a=0;a$/i,E=/^[a-z\d!#\$%&'\*\+\-\/=\?\^_`{\|}~]+$/i,x=/^[a-z\d]+$/,M=/^([\s\x01-\x08\x0b\x0c\x0e-\x1f\x7f\x21\x23-\x5b\x5d-\x7e]|(\\[\x01-\x09\x0b\x0c\x0d-\x7f]))*$/i,N=/^[a-z\d!#\$%&'\*\+\-\/=\?\^_`{\|}~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+$/i,C=/^([\s\x01-\x08\x0b\x0c\x0e-\x1f\x7f\x21\x23-\x5b\x5d-\x7e\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]|(\\[\x01-\x09\x0b\x0c\x0d-\x7f\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))*$/i;var d={protocols:["http","https","ftp"],require_tld:!0,require_protocol:!1,require_host:!0,require_valid_protocol:!0,allow_underscores:!1,allow_trailing_dot:!1,allow_protocol_relative_urls:!1},f=/^\[([^\]]+)\](?::([0-9]+))?$/;function p(t,e){for(var r=0;r=e.min,o=!e.hasOwnProperty("max")||t<=e.max,i=!e.hasOwnProperty("lt")||te.gt;return r.test(t)&&n&&o&&i&&a}var V=/^[\x00-\x7F]+$/;var j=/[^\u0020-\u007E\uFF61-\uFF9F\uFFA0-\uFFDC\uFFE8-\uFFEE0-9a-zA-Z]/;var J=/[\u0020-\u007E\uFF61-\uFF9F\uFFA0-\uFFDC\uFFE8-\uFFEE0-9a-zA-Z]/;var q=/[^\x00-\x7F]/;var Q=/[\uD800-\uDBFF][\uDC00-\uDFFF]/;function X(t,e){return t.some(function(t){return e===t})}var tt=Object.keys(T);var et={force_decimal:!1,decimal_digits:"1,",locale:"en-US"},rt=["","-","+"];var nt=/^[0-9A-F]+$/i;function ot(t){return $(t),nt.test(t)}var it=/^#?([0-9A-F]{3}|[0-9A-F]{6})$/i;var at=/^[A-Z]{2}[0-9A-Z]{3}\d{2}\d{5}$/;var lt=/^[a-f0-9]{32}$/;var st={md5:32,md4:32,sha1:40,sha256:64,sha384:96,sha512:128,ripemd128:32,ripemd160:40,tiger128:32,tiger160:40,tiger192:48,crc32:8,crc32b:8};var ut=/^([A-Za-z0-9\-_~+\/]+[=]{0,2})\.([A-Za-z0-9\-_~+\/]+[=]{0,2})(?:\.([A-Za-z0-9\-_~+\/]+[=]{0,2}))?$/;var ct={ignore_whitespace:!1};var dt={3:/^[0-9A-F]{8}-[0-9A-F]{4}-3[0-9A-F]{3}-[0-9A-F]{4}-[0-9A-F]{12}$/i,4:/^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i,5:/^[0-9A-F]{8}-[0-9A-F]{4}-5[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i,all:/^[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$/i};var ft=/^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|(222[1-9]|22[3-9][0-9]|2[3-6][0-9]{2}|27[01][0-9]|2720)[0-9]{12}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\d{3})\d{11}|6[27][0-9]{14})$/;var pt={ES:function(t){$(t);var e={X:0,Y:1,Z:2},r=t.trim().toUpperCase();if(!/^[0-9X-Z][0-9]{7}[TRWAGMYFPDXBNJZSQVHLCKE]$/.test(r))return!1;var n=r.slice(0,-1).replace(/[X,Y,Z]/g,function(t){return e[t]});return r.endsWith(["T","R","W","A","G","M","Y","F","P","D","X","B","N","J","Z","S","Q","V","H","L","C","K","E"][n%23])},"he-IL":function(t){var e=t.trim();if(!/^\d{9}$/.test(e))return!1;for(var r,n=e,o=0,i=0;i]/.test(r)){if(!e)return!1;if(!(r.split('"').length===r.split('\\"').length))return!1}return!0}(n))return!1}else if(e.require_display_name)return!1}if(!e.ignore_max_length&&254]/.test(t))return!1;if(0===t.indexOf("mailto:"))return!1;var r,n,o,i,a,l,s,u;if(e=m(e,d),1<(s=(t=(s=(t=(s=t.split("#")).shift()).split("?")).shift()).split("://")).length){if(r=s.shift().toLowerCase(),e.require_valid_protocol&&-1===e.protocols.indexOf(r))return!1}else{if(e.require_protocol)return!1;if("//"===t.substr(0,2)){if(!e.allow_protocol_relative_urls)return!1;s[0]=t.substr(2)}}if(""===(t=s.join("://")))return!1;if(""===(t=(s=t.split("/")).shift())&&!e.require_host)return!0;if(1<(s=t.split("@")).length){if(e.disallow_auth)return!1;if(0<=(n=s.shift()).indexOf(":")&&2=e.min)&&(!e.hasOwnProperty("max")||n<=e.max)&&(!e.hasOwnProperty("lt")||ne.gt)},isFloatLocales:tt,isDecimal:function(t,e){if($(t),(e=m(e,et)).locale in T)return!X(rt,t.replace(/ /g,""))&&function(t){return new RegExp("^[-+]?([0-9]+)?(\\".concat(T[t.locale],"[0-9]{").concat(t.decimal_digits,"})").concat(t.force_decimal?"":"?","$"))}(e).test(t);throw new Error("Invalid locale '".concat(e.locale,"'"))},isHexadecimal:ot,isDivisibleBy:function(t,e){return $(t),r(t)%parseInt(e,10)==0},isHexColor:function(t){return $(t),it.test(t)},isISRC:function(t){return $(t),at.test(t)},isMD5:function(t){return $(t),lt.test(t)},isHash:function(t,e){return $(t),new RegExp("^[a-fA-F0-9]{".concat(st[e],"}$")).test(t)},isJWT:function(t){return $(t),ut.test(t)},isJSON:function(t){$(t);try{var e=JSON.parse(t);return!!e&&"object"===a(e)}catch(t){}return!1},isEmpty:function(t,e){return $(t),0===((e=m(e,ct)).ignore_whitespace?t.trim().length:t.length)},isLength:function(t,e){var r,n;$(t),n="object"===a(e)?(r=e.min||0,e.max):(r=e||0,arguments[2]);var o=t.match(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g)||[],i=t.length-o.length;return r<=i&&(void 0===n||i<=n)},isByteLength:v,isUUID:function(t){var e=1/g,">").replace(/\//g,"/").replace(/\\/g,"\").replace(/`/g,"`")},unescape:function(t){return $(t),t.replace(/&/g,"&").replace(/"/g,'"').replace(/'/g,"'").replace(/</g,"<").replace(/>/g,">").replace(///g,"/").replace(/\/g,"\\").replace(/`/g,"`")},stripLow:function(t,e){return $(t),Jt(t,e?"\\x00-\\x09\\x0B\\x0C\\x0E-\\x1F\\x7F":"\\x00-\\x1F\\x7F")},whitelist:function(t,e){return $(t),t.replace(new RegExp("[^".concat(e,"]+"),"g"),"")},blacklist:Jt,isWhitelisted:function(t,e){$(t);for(var r=t.length-1;0<=r;r--)if(-1===e.indexOf(t[r]))return!1;return!0},normalizeEmail:function(t,e){e=m(e,qt);var r=t.split("@"),n=r.pop(),o=[r.join("@"),n];if(o[1]=o[1].toLowerCase(),"gmail.com"===o[1]||"googlemail.com"===o[1]){if(e.gmail_remove_subaddress&&(o[0]=o[0].split("+")[0]),e.gmail_remove_dots&&(o[0]=o[0].replace(/\.+/g,re)),!o[0].length)return!1;(e.all_lowercase||e.gmail_lowercase)&&(o[0]=o[0].toLowerCase()),o[1]=e.gmail_convert_googlemaildotcom?"gmail.com":o[1]}else if(0<=Qt.indexOf(o[1])){if(e.icloud_remove_subaddress&&(o[0]=o[0].split("+")[0]),!o[0].length)return!1;(e.all_lowercase||e.icloud_lowercase)&&(o[0]=o[0].toLowerCase())}else if(0<=Xt.indexOf(o[1])){if(e.outlookdotcom_remove_subaddress&&(o[0]=o[0].split("+")[0]),!o[0].length)return!1;(e.all_lowercase||e.outlookdotcom_lowercase)&&(o[0]=o[0].toLowerCase())}else if(0<=te.indexOf(o[1])){if(e.yahoo_remove_subaddress){var i=o[0].split("-");o[0]=1i)return!1;if("::"===t)return!0;"::"===t.substr(0,2)?(r.shift(),r.shift(),n=!0):"::"===t.substr(t.length-2)&&(r.pop(),r.pop(),n=!0);for(var a=0;a$/i,E=/^[a-z\d!#\$%&'\*\+\-\/=\?\^_`{\|}~]+$/i,R=/^[a-z\d]+$/,L=/^([\s\x01-\x08\x0b\x0c\x0e-\x1f\x7f\x21\x23-\x5b\x5d-\x7e]|(\\[\x01-\x09\x0b\x0c\x0d-\x7f]))*$/i,M=/^[a-z\d!#\$%&'\*\+\-\/=\?\^_`{\|}~\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]+$/i,I=/^([\s\x01-\x08\x0b\x0c\x0e-\x1f\x7f\x21\x23-\x5b\x5d-\x7e\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]|(\\[\x01-\x09\x0b\x0c\x0d-\x7f\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))*$/i;var d={protocols:["http","https","ftp"],require_tld:!0,require_protocol:!1,require_host:!0,require_valid_protocol:!0,allow_underscores:!1,allow_trailing_dot:!1,allow_protocol_relative_urls:!1},f=/^\[([^\]]+)\](?::([0-9]+))?$/;function A(t,e){for(var r=0;r=e.min,o=!e.hasOwnProperty("max")||t<=e.max,i=!e.hasOwnProperty("lt")||te.gt;return r.test(t)&&n&&o&&i&&a}var V=/^[\x00-\x7F]+$/;var j=/[^\u0020-\u007E\uFF61-\uFF9F\uFFA0-\uFFDC\uFFE8-\uFFEE0-9a-zA-Z]/;var J=/[\u0020-\u007E\uFF61-\uFF9F\uFFA0-\uFFDC\uFFE8-\uFFEE0-9a-zA-Z]/;var q=/[^\x00-\x7F]/;var Q=/[\uD800-\uDBFF][\uDC00-\uDFFF]/;function X(t,e){return t.some(function(t){return e===t})}var tt=Object.keys(x);var et={force_decimal:!1,decimal_digits:"1,",locale:"en-US"},rt=["","-","+"];var nt=/^[0-9A-F]+$/i;function ot(t){return g(t),nt.test(t)}var it=/^#?([0-9A-F]{3}|[0-9A-F]{6})$/i;var at=/^[A-Z]{2}[0-9A-Z]{3}\d{2}\d{5}$/;var lt=/^[a-f0-9]{32}$/;var st={md5:32,md4:32,sha1:40,sha256:64,sha384:96,sha512:128,ripemd128:32,ripemd160:40,tiger128:32,tiger160:40,tiger192:48,crc32:8,crc32b:8};var ut=/^([A-Za-z0-9\-_~+\/]+[=]{0,2})\.([A-Za-z0-9\-_~+\/]+[=]{0,2})(?:\.([A-Za-z0-9\-_~+\/]+[=]{0,2}))?$/;var ct={ignore_whitespace:!1};var dt={3:/^[0-9A-F]{8}-[0-9A-F]{4}-3[0-9A-F]{3}-[0-9A-F]{4}-[0-9A-F]{12}$/i,4:/^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i,5:/^[0-9A-F]{8}-[0-9A-F]{4}-5[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i,all:/^[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$/i};function ft(t){for(var e=t.slice(0,4),r=t.slice(4,t.length)+e,n=1;n<=Math.ceil(t.length/10)+1;n++){r=r.slice(0,10).replace(/[A-Z]/g,function(t){return t.charCodeAt()-55})%97+r.slice(10)}return"1"===r}var At={AD:/^(AD[0-9]{2})\d{8}[0-9A-Z]{12}$/,AL:/^(AL[0-9]{2})\d{8}[A-Z0-9]{16}$/,AT:/^(AT[0-9]{2})\d{16}$/,BA:/^(BA[0-9]{2})\d{16}$/,BE:/^(BE[0-9]{2})\d{12}$/,BG:/^(BG[0-9]{2})[A-Z]{4}\d{4}[A-Z0-9]{10}$/,BH:/^(BH[0-9]{2})[A-Z]{4}[A-Z0-9]{14}$/,BR:/^(BR[0-9]{2})\d{23}[A-Z][A-Z0-9]$/,CH:/^(CH[0-9]{2})\d{17}$/,CY:/^(CY[0-9]{2})\d{8}[A-Z0-9]{16}$/,CZ:/^(CZ[0-9]{2})\d{20}$/,DE:/^(DE[0-9]{2})\d{18}$/,DK:/^(DK[0-9]{2})\d{14}$/,EE:/^(EE[0-9]{2})\d{16}$/,ES:/^(ES[0-9]{2})\d{20}$/,FO:/^(FO[0-9]{2})\d{14}$/,FI:/^(FI[0-9]{2})\d{14}$/,FR:/^(FR[0-9]{2})\d{10}[A-Z0-9]{11}\d{2}$/,GB:/^(GB[0-9]{2})[A-Z]{4}\d{14}$/,GE:/^(GE[0-9]{2})[A-Z]{2}\d{16}$/,GI:/^(GI[0-9]{2})[A-Z]{4}[A-Z0-9]{15}$/,GL:/^(GL[0-9]{2})\d{14}$/,GR:/^(GR[0-9]{2})\d{7}[A-Z0-9]{16}$/,HR:/^(HR[0-9]{2})\d{17}$/,HU:/^(HU[0-9]{2})\d{24}$/,IE:/^(IE[0-9]{2})[A-Z]{4}\d{14}$/,IS:/^(IS[0-9]{2})\d{22}$/,IT:/^(IT[0-9]{2})[A-Z]\d{10}[A-Z0-9]{12}$/,JO:/^(JO[0-9]{2})[A-Z]{4}\d{4}[A-Z0-9]{18}$/,KW:/^(KW[0-9]{2})[A-Z]{4}[A-Z0-9]{22}$/,KZ:/^(KZ[0-9]{2})\d{3}[A-Z0-9]{13}$/,LB:/^(LB[0-9]{2})\d{4}[A-Z0-9]{20}$/,LI:/^(LI[0-9]{2})\d{5}[A-Z0-9]{12}$/,LT:/^(LT[0-9]{2})\d{16}$/,LU:/^(LU[0-9]{2})\d{3}[A-Z0-9]{13}$/,LV:/^(LV[0-9]{2})[A-Z]{4}[A-Z0-9]{13}$/,MC:/^(MC[0-9]{2})\d{10}[A-Z0-9]{11}\d{2}$/,MD:/^(MD[0-9]{2})[A-Z]{2}[A-Z0-9]{18}$/,ME:/^(ME[0-9]{2})\d{18}$/,MK:/^(MK[0-9]{2})\d{3}[A-Z0-9]{12}$/,MT:/^(MT[0-9]{2})[A-Z]{4}\d{5}[A-Z0-9]{18}$/,NL:/^(NL[0-9]{2})[A-Z]{4}\d{10}$/,NO:/^(NO[0-9]{2})\d{11}$/,PL:/^(PL[0-9]{2})\d{24}$/,PS:/^(PS[0-9]{2})[A-Z]{4}[A-Z0-9]{21}$/,PT:/^(PT[0-9]{2})\d{21}$/,QA:/^(QA[0-9]{2})[A-Z]{4}[A-Z0-9]{21}$/,RO:/^(RO[0-9]{2})[A-Z]{4}[A-Z0-9]{16}$/,SA:/^(SA[0-9]{2})\d{2}[A-Z0-9]{18}$/,SE:/^(SE[0-9]{2})\d{20}$/,SI:/^(SI[0-9]{2})\d{15}$/,SK:/^(SK[0-9]{2})\d{20}$/,SM:/^(SM[0-9]{2})[A-Z]{1}\d{10}[A-Z0-9]{12}$/,RS:/^(RS[0-9]{2})\d{18}$/,TN:/^(TN[0-9]{2})\d{20}$/,TR:/^(TR[0-9]{2})\d{5}[A-Z0-9]{17}$/,UA:/^(UA[0-9]{2})\d{6}[A-Z0-9]{19}$/,XK:/^(XK[0-9]{2})\d{16}$/};var $t=Object.keys(At),ht=/^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|(222[1-9]|22[3-9][0-9]|2[3-6][0-9]{2}|27[01][0-9]|2720)[0-9]{12}|6(?:011|5[0-9][0-9])[0-9]{12}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|(?:2131|1800|35\d{3})\d{11}|6[27][0-9]{14})$/;var pt={ES:function(t){g(t);var e={X:0,Y:1,Z:2},r=t.trim().toUpperCase();if(!/^[0-9X-Z][0-9]{7}[TRWAGMYFPDXBNJZSQVHLCKE]$/.test(r))return!1;var n=r.slice(0,-1).replace(/[X,Y,Z]/g,function(t){return e[t]});return r.endsWith(["T","R","W","A","G","M","Y","F","P","D","X","B","N","J","Z","S","Q","V","H","L","C","K","E"][n%23])},"he-IL":function(t){var e=t.trim();if(!/^\d{9}$/.test(e))return!1;for(var r,n=e,o=0,i=0;i]/.test(r)){if(!e)return!1;if(!(r.split('"').length===r.split('\\"').length))return!1}return!0}(n))return!1}else if(e.require_display_name)return!1}if(!e.ignore_max_length&&254]/.test(t))return!1;if(0===t.indexOf("mailto:"))return!1;var r,n,o,i,a,l,s,u;if(e=m(e,d),1<(s=(t=(s=(t=(s=t.split("#")).shift()).split("?")).shift()).split("://")).length){if(r=s.shift().toLowerCase(),e.require_valid_protocol&&-1===e.protocols.indexOf(r))return!1}else{if(e.require_protocol)return!1;if("//"===t.substr(0,2)){if(!e.allow_protocol_relative_urls)return!1;s[0]=t.substr(2)}}if(""===(t=s.join("://")))return!1;if(""===(t=(s=t.split("/")).shift())&&!e.require_host)return!0;if(1<(s=t.split("@")).length){if(e.disallow_auth)return!1;if(0<=(n=s.shift()).indexOf(":")&&2=e.min)&&(!e.hasOwnProperty("max")||n<=e.max)&&(!e.hasOwnProperty("lt")||ne.gt)},isFloatLocales:tt,isDecimal:function(t,e){if(g(t),(e=m(e,et)).locale in x)return!X(rt,t.replace(/ /g,""))&&function(t){return new RegExp("^[-+]?([0-9]+)?(\\".concat(x[t.locale],"[0-9]{").concat(t.decimal_digits,"})").concat(t.force_decimal?"":"?","$"))}(e).test(t);throw new Error("Invalid locale '".concat(e.locale,"'"))},isHexadecimal:ot,isDivisibleBy:function(t,e){return g(t),r(t)%parseInt(e,10)==0},isHexColor:function(t){return g(t),it.test(t)},isISRC:function(t){return g(t),at.test(t)},isMD5:function(t){return g(t),lt.test(t)},isHash:function(t,e){return g(t),new RegExp("^[a-fA-F0-9]{".concat(st[e],"}$")).test(t)},isJWT:function(t){return g(t),ut.test(t)},isJSON:function(t){g(t);try{var e=JSON.parse(t);return!!e&&"object"===a(e)}catch(t){}return!1},isEmpty:function(t,e){return g(t),0===((e=m(e,ct)).ignore_whitespace?t.trim().length:t.length)},isLength:function(t,e){var r,n;g(t),n="object"===a(e)?(r=e.min||0,e.max):(r=e||0,arguments[2]);var o=t.match(/[\uD800-\uDBFF][\uDC00-\uDFFF]/g)||[],i=t.length-o.length;return r<=i&&(void 0===n||i<=n)},isByteLength:v,isUUID:function(t){var e=1/g,">").replace(/\//g,"/").replace(/\\/g,"\").replace(/`/g,"`")},unescape:function(t){return g(t),t.replace(/&/g,"&").replace(/"/g,'"').replace(/'/g,"'").replace(/</g,"<").replace(/>/g,">").replace(///g,"/").replace(/\/g,"\\").replace(/`/g,"`")},stripLow:function(t,e){return g(t),Xt(t,e?"\\x00-\\x09\\x0B\\x0C\\x0E-\\x1F\\x7F":"\\x00-\\x1F\\x7F")},whitelist:function(t,e){return g(t),t.replace(new RegExp("[^".concat(e,"]+"),"g"),"")},blacklist:Xt,isWhitelisted:function(t,e){g(t);for(var r=t.length-1;0<=r;r--)if(-1===e.indexOf(t[r]))return!1;return!0},normalizeEmail:function(t,e){e=m(e,te);var r=t.split("@"),n=r.pop(),o=[r.join("@"),n];if(o[1]=o[1].toLowerCase(),"gmail.com"===o[1]||"googlemail.com"===o[1]){if(e.gmail_remove_subaddress&&(o[0]=o[0].split("+")[0]),e.gmail_remove_dots&&(o[0]=o[0].replace(/\.+/g,ie)),!o[0].length)return!1;(e.all_lowercase||e.gmail_lowercase)&&(o[0]=o[0].toLowerCase()),o[1]=e.gmail_convert_googlemaildotcom?"gmail.com":o[1]}else if(0<=ee.indexOf(o[1])){if(e.icloud_remove_subaddress&&(o[0]=o[0].split("+")[0]),!o[0].length)return!1;(e.all_lowercase||e.icloud_lowercase)&&(o[0]=o[0].toLowerCase())}else if(0<=re.indexOf(o[1])){if(e.outlookdotcom_remove_subaddress&&(o[0]=o[0].split("+")[0]),!o[0].length)return!1;(e.all_lowercase||e.outlookdotcom_lowercase)&&(o[0]=o[0].toLowerCase())}else if(0<=ne.indexOf(o[1])){if(e.yahoo_remove_subaddress){var i=o[0].split("-");o[0]=1