224 lines
6.4 KiB
Dart
224 lines
6.4 KiB
Dart
RegExp _email = RegExp(
|
|
r"^((([a-z]|\d|[!#\$%&'*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\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]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))$");
|
|
|
|
RegExp _phoneNumber = RegExp(r'^(84|0[3|5|7|8|9])+([0-9]{8})\b$');
|
|
|
|
RegExp _ipv4Maybe = RegExp(r'^(\d?\d?\d)\.(\d?\d?\d)\.(\d?\d?\d)\.(\d?\d?\d)$');
|
|
RegExp _ipv6 = RegExp(r'^::|^::1|^([a-fA-F0-9]{1,4}::?){1,7}([a-fA-F0-9]{1,4})$');
|
|
|
|
RegExp _creditCard = RegExp(
|
|
r'^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|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})$');
|
|
|
|
/// check if the string [str] is an email
|
|
bool isEmail(String str) {
|
|
return _email.hasMatch(str.toLowerCase());
|
|
}
|
|
|
|
bool isPhoneNumber(String str) {
|
|
return _phoneNumber.hasMatch(str.toLowerCase());
|
|
}
|
|
|
|
T? shift<T>(List<T> l) {
|
|
if (l.isNotEmpty) {
|
|
// ignore: always_specify_types
|
|
final first = l.first;
|
|
l.removeAt(0);
|
|
return first;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
/// check if the string [str] is a URL
|
|
///
|
|
/// * [protocols] sets the list of allowed protocols
|
|
/// * [requireTld] sets if TLD is required
|
|
/// * [requireProtocol] is a `bool` that sets if protocol is required for validation
|
|
/// * [allowUnderscore] sets if underscores are allowed
|
|
/// * [hostWhitelist] sets the list of allowed hosts
|
|
/// * [hostBlacklist] sets the list of disallowed hosts
|
|
bool isURL(String? str,
|
|
{List<String?> protocols = const ['http', 'https', 'ftp'],
|
|
bool requireTld = true,
|
|
bool requireProtocol = false,
|
|
bool allowUnderscore = false,
|
|
List<String> hostWhitelist = const [],
|
|
List<String> hostBlacklist = const []}) {
|
|
if (str == null || str.isEmpty || str.length > 2083 || str.startsWith('mailto:')) {
|
|
return false;
|
|
}
|
|
int port;
|
|
String? protocol, auth, user;
|
|
String host, hostname, portStr, path, query, hash;
|
|
|
|
// check protocol
|
|
var split = str.split('://');
|
|
if (split.length > 1) {
|
|
protocol = shift(split);
|
|
if (!protocols.contains(protocol)) {
|
|
return false;
|
|
}
|
|
} else if (requireProtocol == true) {
|
|
return false;
|
|
}
|
|
str = split.join('://');
|
|
|
|
// check hash
|
|
split = str.split('#');
|
|
str = shift(split);
|
|
hash = split.join('#');
|
|
if (hash.isNotEmpty && RegExp(r'\s').hasMatch(hash)) {
|
|
return false;
|
|
}
|
|
|
|
// check query params
|
|
split = str!.split('?');
|
|
str = shift(split);
|
|
query = split.join('?');
|
|
if (query.isNotEmpty && RegExp(r'\s').hasMatch(query)) {
|
|
return false;
|
|
}
|
|
|
|
// check path
|
|
split = str!.split('/');
|
|
str = shift(split);
|
|
path = split.join('/');
|
|
if (path.isNotEmpty && RegExp(r'\s').hasMatch(path)) {
|
|
return false;
|
|
}
|
|
|
|
// check auth type urls
|
|
split = str!.split('@');
|
|
if (split.length > 1) {
|
|
auth = shift(split);
|
|
if (auth?.contains(':') ?? false) {
|
|
user = shift(auth!.split(':'))!;
|
|
if (!RegExp(r'^\S+$').hasMatch(user)) {
|
|
return false;
|
|
}
|
|
if (!RegExp(r'^\S*$').hasMatch(user)) {
|
|
return false;
|
|
}
|
|
}
|
|
}
|
|
|
|
// check hostname
|
|
hostname = split.join('@');
|
|
split = hostname.split(':');
|
|
host = shift(split)!;
|
|
if (split.isNotEmpty) {
|
|
portStr = split.join(':');
|
|
try {
|
|
port = int.parse(portStr, radix: 10);
|
|
} catch (e) {
|
|
return false;
|
|
}
|
|
if (!RegExp(r'^[0-9]+$').hasMatch(portStr) || port <= 0 || port > 65535) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
if (!isIP(host, null) &&
|
|
!isFQDN(host, requireTld: requireTld, allowUnderscores: allowUnderscore) &&
|
|
host != 'localhost') {
|
|
return false;
|
|
}
|
|
|
|
if (hostWhitelist.isNotEmpty && !hostWhitelist.contains(host)) {
|
|
return false;
|
|
}
|
|
|
|
if (hostBlacklist.isNotEmpty && hostBlacklist.contains(host)) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/// check if the string [str] is IP [version] 4 or 6
|
|
///
|
|
/// * [version] is a String or an `int`.
|
|
bool isIP(String? str, int? version) {
|
|
if (version == null) {
|
|
return isIP(str, 4) || isIP(str, 6);
|
|
} else if (version == 4) {
|
|
if (!_ipv4Maybe.hasMatch(str!)) {
|
|
return false;
|
|
}
|
|
var parts = str.split('.');
|
|
parts.sort((a, b) => int.parse(a) - int.parse(b));
|
|
return int.parse(parts[3]) <= 255;
|
|
}
|
|
return version == 6 && _ipv6.hasMatch(str!);
|
|
}
|
|
|
|
/// check if the string [str] is a fully qualified domain name (e.g. domain.com).
|
|
///
|
|
/// * [requireTld] sets if TLD is required
|
|
/// * [allowUnderscore] sets if underscores are allowed
|
|
bool isFQDN(String str, {bool requireTld = true, bool allowUnderscores = false}) {
|
|
var parts = str.split('.');
|
|
if (requireTld) {
|
|
var tld = parts.removeLast();
|
|
if (parts.isEmpty || !RegExp(r'^[a-z]{2,}$').hasMatch(tld)) {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
for (var part in parts) {
|
|
if (allowUnderscores) {
|
|
if (part.contains('__')) {
|
|
return false;
|
|
}
|
|
}
|
|
if (!RegExp(r'^[a-z\\u00a1-\\uffff0-9-]+$').hasMatch(part)) {
|
|
return false;
|
|
}
|
|
if (part[0] == '-' || part[part.length - 1] == '-' || part.contains('---')) {
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/// check if the string is a credit card
|
|
bool isCreditCard(String str) {
|
|
var sanitized = str.replaceAll(RegExp(r'[^0-9]+'), '');
|
|
if (!_creditCard.hasMatch(sanitized)) {
|
|
return false;
|
|
}
|
|
|
|
// Luhn algorithm
|
|
var sum = 0;
|
|
String digit;
|
|
var shouldDouble = false;
|
|
|
|
for (var i = sanitized.length - 1; i >= 0; i--) {
|
|
digit = sanitized.substring(i, (i + 1));
|
|
var tmpNum = int.parse(digit);
|
|
|
|
if (shouldDouble == true) {
|
|
tmpNum *= 2;
|
|
if (tmpNum >= 10) {
|
|
sum += ((tmpNum % 10) + 1);
|
|
} else {
|
|
sum += tmpNum;
|
|
}
|
|
} else {
|
|
sum += tmpNum;
|
|
}
|
|
shouldDouble = !shouldDouble;
|
|
}
|
|
|
|
return (sum % 10 == 0);
|
|
}
|
|
|
|
/// check if the string is a date
|
|
bool isDate(String str) {
|
|
try {
|
|
DateTime.parse(str);
|
|
return true;
|
|
} catch (e) {
|
|
return false;
|
|
}
|
|
}
|