You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
369 lines
11 KiB
369 lines
11 KiB
import assertString from './util/assertString'; |
|
import isInt from './isInt'; |
|
var validators = { |
|
PL: function PL(str) { |
|
assertString(str); |
|
var weightOfDigits = { |
|
1: 1, |
|
2: 3, |
|
3: 7, |
|
4: 9, |
|
5: 1, |
|
6: 3, |
|
7: 7, |
|
8: 9, |
|
9: 1, |
|
10: 3, |
|
11: 0 |
|
}; |
|
|
|
if (str != null && str.length === 11 && isInt(str, { |
|
allow_leading_zeroes: true |
|
})) { |
|
var digits = str.split('').slice(0, -1); |
|
var sum = digits.reduce(function (acc, digit, index) { |
|
return acc + Number(digit) * weightOfDigits[index + 1]; |
|
}, 0); |
|
var modulo = sum % 10; |
|
var lastDigit = Number(str.charAt(str.length - 1)); |
|
|
|
if (modulo === 0 && lastDigit === 0 || lastDigit === 10 - modulo) { |
|
return true; |
|
} |
|
} |
|
|
|
return false; |
|
}, |
|
ES: function ES(str) { |
|
assertString(str); |
|
var DNI = /^[0-9X-Z][0-9]{7}[TRWAGMYFPDXBNJZSQVHLCKE]$/; |
|
var charsValue = { |
|
X: 0, |
|
Y: 1, |
|
Z: 2 |
|
}; |
|
var controlDigits = ['T', 'R', 'W', 'A', 'G', 'M', 'Y', 'F', 'P', 'D', 'X', 'B', 'N', 'J', 'Z', 'S', 'Q', 'V', 'H', 'L', 'C', 'K', 'E']; // sanitize user input |
|
|
|
var sanitized = str.trim().toUpperCase(); // validate the data structure |
|
|
|
if (!DNI.test(sanitized)) { |
|
return false; |
|
} // validate the control digit |
|
|
|
|
|
var number = sanitized.slice(0, -1).replace(/[X,Y,Z]/g, function (_char) { |
|
return charsValue[_char]; |
|
}); |
|
return sanitized.endsWith(controlDigits[number % 23]); |
|
}, |
|
FI: function FI(str) { |
|
// https://dvv.fi/en/personal-identity-code#:~:text=control%20character%20for%20a-,personal,-identity%20code%20calculated |
|
assertString(str); |
|
|
|
if (str.length !== 11) { |
|
return false; |
|
} |
|
|
|
if (!str.match(/^\d{6}[\-A\+]\d{3}[0-9ABCDEFHJKLMNPRSTUVWXY]{1}$/)) { |
|
return false; |
|
} |
|
|
|
var checkDigits = '0123456789ABCDEFHJKLMNPRSTUVWXY'; |
|
var idAsNumber = parseInt(str.slice(0, 6), 10) * 1000 + parseInt(str.slice(7, 10), 10); |
|
var remainder = idAsNumber % 31; |
|
var checkDigit = checkDigits[remainder]; |
|
return checkDigit === str.slice(10, 11); |
|
}, |
|
IN: function IN(str) { |
|
var DNI = /^[1-9]\d{3}\s?\d{4}\s?\d{4}$/; // multiplication table |
|
|
|
var d = [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [1, 2, 3, 4, 0, 6, 7, 8, 9, 5], [2, 3, 4, 0, 1, 7, 8, 9, 5, 6], [3, 4, 0, 1, 2, 8, 9, 5, 6, 7], [4, 0, 1, 2, 3, 9, 5, 6, 7, 8], [5, 9, 8, 7, 6, 0, 4, 3, 2, 1], [6, 5, 9, 8, 7, 1, 0, 4, 3, 2], [7, 6, 5, 9, 8, 2, 1, 0, 4, 3], [8, 7, 6, 5, 9, 3, 2, 1, 0, 4], [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]]; // permutation table |
|
|
|
var p = [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [1, 5, 7, 6, 2, 8, 3, 0, 9, 4], [5, 8, 0, 3, 7, 9, 6, 1, 4, 2], [8, 9, 1, 6, 0, 4, 3, 5, 2, 7], [9, 4, 5, 3, 1, 2, 6, 8, 7, 0], [4, 2, 8, 6, 5, 7, 3, 9, 0, 1], [2, 7, 9, 3, 8, 0, 6, 4, 1, 5], [7, 0, 4, 6, 9, 1, 3, 2, 5, 8]]; // sanitize user input |
|
|
|
var sanitized = str.trim(); // validate the data structure |
|
|
|
if (!DNI.test(sanitized)) { |
|
return false; |
|
} |
|
|
|
var c = 0; |
|
var invertedArray = sanitized.replace(/\s/g, '').split('').map(Number).reverse(); |
|
invertedArray.forEach(function (val, i) { |
|
c = d[c][p[i % 8][val]]; |
|
}); |
|
return c === 0; |
|
}, |
|
IR: function IR(str) { |
|
if (!str.match(/^\d{10}$/)) return false; |
|
str = "0000".concat(str).substr(str.length - 6); |
|
if (parseInt(str.substr(3, 6), 10) === 0) return false; |
|
var lastNumber = parseInt(str.substr(9, 1), 10); |
|
var sum = 0; |
|
|
|
for (var i = 0; i < 9; i++) { |
|
sum += parseInt(str.substr(i, 1), 10) * (10 - i); |
|
} |
|
|
|
sum %= 11; |
|
return sum < 2 && lastNumber === sum || sum >= 2 && lastNumber === 11 - sum; |
|
}, |
|
IT: function IT(str) { |
|
if (str.length !== 9) return false; |
|
if (str === 'CA00000AA') return false; // https://it.wikipedia.org/wiki/Carta_d%27identit%C3%A0_elettronica_italiana |
|
|
|
return str.search(/C[A-Z][0-9]{5}[A-Z]{2}/i) > -1; |
|
}, |
|
NO: function NO(str) { |
|
var sanitized = str.trim(); |
|
if (isNaN(Number(sanitized))) return false; |
|
if (sanitized.length !== 11) return false; |
|
if (sanitized === '00000000000') return false; // https://no.wikipedia.org/wiki/F%C3%B8dselsnummer |
|
|
|
var f = sanitized.split('').map(Number); |
|
var k1 = (11 - (3 * f[0] + 7 * f[1] + 6 * f[2] + 1 * f[3] + 8 * f[4] + 9 * f[5] + 4 * f[6] + 5 * f[7] + 2 * f[8]) % 11) % 11; |
|
var k2 = (11 - (5 * f[0] + 4 * f[1] + 3 * f[2] + 2 * f[3] + 7 * f[4] + 6 * f[5] + 5 * f[6] + 4 * f[7] + 3 * f[8] + 2 * k1) % 11) % 11; |
|
if (k1 !== f[9] || k2 !== f[10]) return false; |
|
return true; |
|
}, |
|
TH: function TH(str) { |
|
if (!str.match(/^[1-8]\d{12}$/)) return false; // validate check digit |
|
|
|
var sum = 0; |
|
|
|
for (var i = 0; i < 12; i++) { |
|
sum += parseInt(str[i], 10) * (13 - i); |
|
} |
|
|
|
return str[12] === ((11 - sum % 11) % 10).toString(); |
|
}, |
|
LK: function LK(str) { |
|
var old_nic = /^[1-9]\d{8}[vx]$/i; |
|
var new_nic = /^[1-9]\d{11}$/i; |
|
if (str.length === 10 && old_nic.test(str)) return true;else if (str.length === 12 && new_nic.test(str)) return true; |
|
return false; |
|
}, |
|
'he-IL': function heIL(str) { |
|
var DNI = /^\d{9}$/; // sanitize user input |
|
|
|
var sanitized = str.trim(); // validate the data structure |
|
|
|
if (!DNI.test(sanitized)) { |
|
return false; |
|
} |
|
|
|
var id = sanitized; |
|
var sum = 0, |
|
incNum; |
|
|
|
for (var i = 0; i < id.length; i++) { |
|
incNum = Number(id[i]) * (i % 2 + 1); // Multiply number by 1 or 2 |
|
|
|
sum += incNum > 9 ? incNum - 9 : incNum; // Sum the digits up and add to total |
|
} |
|
|
|
return sum % 10 === 0; |
|
}, |
|
'ar-LY': function arLY(str) { |
|
// Libya National Identity Number NIN is 12 digits, the first digit is either 1 or 2 |
|
var NIN = /^(1|2)\d{11}$/; // sanitize user input |
|
|
|
var sanitized = str.trim(); // validate the data structure |
|
|
|
if (!NIN.test(sanitized)) { |
|
return false; |
|
} |
|
|
|
return true; |
|
}, |
|
'ar-TN': function arTN(str) { |
|
var DNI = /^\d{8}$/; // sanitize user input |
|
|
|
var sanitized = str.trim(); // validate the data structure |
|
|
|
if (!DNI.test(sanitized)) { |
|
return false; |
|
} |
|
|
|
return true; |
|
}, |
|
'zh-CN': function zhCN(str) { |
|
var provincesAndCities = ['11', // 北京 |
|
'12', // 天津 |
|
'13', // 河北 |
|
'14', // 山西 |
|
'15', // 内蒙古 |
|
'21', // 辽宁 |
|
'22', // 吉林 |
|
'23', // 黑龙江 |
|
'31', // 上海 |
|
'32', // 江苏 |
|
'33', // 浙江 |
|
'34', // 安徽 |
|
'35', // 福建 |
|
'36', // 江西 |
|
'37', // 山东 |
|
'41', // 河南 |
|
'42', // 湖北 |
|
'43', // 湖南 |
|
'44', // 广东 |
|
'45', // 广西 |
|
'46', // 海南 |
|
'50', // 重庆 |
|
'51', // 四川 |
|
'52', // 贵州 |
|
'53', // 云南 |
|
'54', // 西藏 |
|
'61', // 陕西 |
|
'62', // 甘肃 |
|
'63', // 青海 |
|
'64', // 宁夏 |
|
'65', // 新疆 |
|
'71', // 台湾 |
|
'81', // 香港 |
|
'82', // 澳门 |
|
'91' // 国外 |
|
]; |
|
var powers = ['7', '9', '10', '5', '8', '4', '2', '1', '6', '3', '7', '9', '10', '5', '8', '4', '2']; |
|
var parityBit = ['1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2']; |
|
|
|
var checkAddressCode = function checkAddressCode(addressCode) { |
|
return provincesAndCities.includes(addressCode); |
|
}; |
|
|
|
var checkBirthDayCode = function checkBirthDayCode(birDayCode) { |
|
var yyyy = parseInt(birDayCode.substring(0, 4), 10); |
|
var mm = parseInt(birDayCode.substring(4, 6), 10); |
|
var dd = parseInt(birDayCode.substring(6), 10); |
|
var xdata = new Date(yyyy, mm - 1, dd); |
|
|
|
if (xdata > new Date()) { |
|
return false; // eslint-disable-next-line max-len |
|
} else if (xdata.getFullYear() === yyyy && xdata.getMonth() === mm - 1 && xdata.getDate() === dd) { |
|
return true; |
|
} |
|
|
|
return false; |
|
}; |
|
|
|
var getParityBit = function getParityBit(idCardNo) { |
|
var id17 = idCardNo.substring(0, 17); |
|
var power = 0; |
|
|
|
for (var i = 0; i < 17; i++) { |
|
power += parseInt(id17.charAt(i), 10) * parseInt(powers[i], 10); |
|
} |
|
|
|
var mod = power % 11; |
|
return parityBit[mod]; |
|
}; |
|
|
|
var checkParityBit = function checkParityBit(idCardNo) { |
|
return getParityBit(idCardNo) === idCardNo.charAt(17).toUpperCase(); |
|
}; |
|
|
|
var check15IdCardNo = function check15IdCardNo(idCardNo) { |
|
var check = /^[1-9]\d{7}((0[1-9])|(1[0-2]))((0[1-9])|([1-2][0-9])|(3[0-1]))\d{3}$/.test(idCardNo); |
|
if (!check) return false; |
|
var addressCode = idCardNo.substring(0, 2); |
|
check = checkAddressCode(addressCode); |
|
if (!check) return false; |
|
var birDayCode = "19".concat(idCardNo.substring(6, 12)); |
|
check = checkBirthDayCode(birDayCode); |
|
if (!check) return false; |
|
return true; |
|
}; |
|
|
|
var check18IdCardNo = function check18IdCardNo(idCardNo) { |
|
var check = /^[1-9]\d{5}[1-9]\d{3}((0[1-9])|(1[0-2]))((0[1-9])|([1-2][0-9])|(3[0-1]))\d{3}(\d|x|X)$/.test(idCardNo); |
|
if (!check) return false; |
|
var addressCode = idCardNo.substring(0, 2); |
|
check = checkAddressCode(addressCode); |
|
if (!check) return false; |
|
var birDayCode = idCardNo.substring(6, 14); |
|
check = checkBirthDayCode(birDayCode); |
|
if (!check) return false; |
|
return checkParityBit(idCardNo); |
|
}; |
|
|
|
var checkIdCardNo = function checkIdCardNo(idCardNo) { |
|
var check = /^\d{15}|(\d{17}(\d|x|X))$/.test(idCardNo); |
|
if (!check) return false; |
|
|
|
if (idCardNo.length === 15) { |
|
return check15IdCardNo(idCardNo); |
|
} |
|
|
|
return check18IdCardNo(idCardNo); |
|
}; |
|
|
|
return checkIdCardNo(str); |
|
}, |
|
'zh-TW': function zhTW(str) { |
|
var ALPHABET_CODES = { |
|
A: 10, |
|
B: 11, |
|
C: 12, |
|
D: 13, |
|
E: 14, |
|
F: 15, |
|
G: 16, |
|
H: 17, |
|
I: 34, |
|
J: 18, |
|
K: 19, |
|
L: 20, |
|
M: 21, |
|
N: 22, |
|
O: 35, |
|
P: 23, |
|
Q: 24, |
|
R: 25, |
|
S: 26, |
|
T: 27, |
|
U: 28, |
|
V: 29, |
|
W: 32, |
|
X: 30, |
|
Y: 31, |
|
Z: 33 |
|
}; |
|
var sanitized = str.trim().toUpperCase(); |
|
if (!/^[A-Z][0-9]{9}$/.test(sanitized)) return false; |
|
return Array.from(sanitized).reduce(function (sum, number, index) { |
|
if (index === 0) { |
|
var code = ALPHABET_CODES[number]; |
|
return code % 10 * 9 + Math.floor(code / 10); |
|
} |
|
|
|
if (index === 9) { |
|
return (10 - sum % 10 - Number(number)) % 10 === 0; |
|
} |
|
|
|
return sum + Number(number) * (9 - index); |
|
}, 0); |
|
} |
|
}; |
|
export default function isIdentityCard(str, locale) { |
|
assertString(str); |
|
|
|
if (locale in validators) { |
|
return validators[locale](str); |
|
} else if (locale === 'any') { |
|
for (var key in validators) { |
|
// https://github.com/gotwarlost/istanbul/blob/master/ignoring-code-for-coverage.md#ignoring-code-for-coverage-purposes |
|
// istanbul ignore else |
|
if (validators.hasOwnProperty(key)) { |
|
var validator = validators[key]; |
|
|
|
if (validator(str)) { |
|
return true; |
|
} |
|
} |
|
} |
|
|
|
return false; |
|
} |
|
|
|
throw new Error("Invalid locale '".concat(locale, "'")); |
|
} |