Skip to content

Commit 4ec51a9

Browse files
committed
Remove validators dependency
1 parent d99f78a commit 4ec51a9

File tree

4 files changed

+238
-11
lines changed

4 files changed

+238
-11
lines changed

lib/src/form_builder_validators.dart

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import 'package:flutter/material.dart';
22
import 'package:flutter_form_builder/flutter_form_builder.dart';
3-
import 'package:validators/validators.dart';
3+
4+
import 'utils/validators.dart';
45

56
/// For creation of [FormFieldValidator]s.
67
class FormBuilderValidators {
@@ -221,7 +222,7 @@ class FormBuilderValidators {
221222
/// * [version] is a `String` or an `int`.
222223
static FormFieldValidator<String> ip(
223224
BuildContext context, {
224-
dynamic version,
225+
int? version,
225226
String? errorText,
226227
}) =>
227228
(valueCandidate) =>

lib/src/utils/helpers.dart

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// Helper functions for validator and sanitizer.
2+
3+
T? shift<T>(List<T> l) {
4+
if (l.isNotEmpty) {
5+
var first = l.first;
6+
l.removeAt(0);
7+
return first;
8+
}
9+
return null;
10+
}
11+
12+
Map merge(Map? obj, Map? defaults) {
13+
obj ??= <dynamic, dynamic>{};
14+
defaults?.forEach((dynamic key, dynamic val) => obj!.putIfAbsent(key, () => val));
15+
return obj;
16+
}

lib/src/utils/validators.dart

Lines changed: 217 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,217 @@
1+
import 'helpers.dart';
2+
3+
RegExp _email = RegExp(
4+
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])))$");
5+
6+
RegExp _ipv4Maybe = RegExp(r'^(\d?\d?\d)\.(\d?\d?\d)\.(\d?\d?\d)\.(\d?\d?\d)$');
7+
RegExp _ipv6 =
8+
RegExp(r'^::|^::1|^([a-fA-F0-9]{1,4}::?){1,7}([a-fA-F0-9]{1,4})$');
9+
10+
RegExp _creditCard = RegExp(
11+
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})$');
12+
13+
/// check if the string [str] is an email
14+
bool isEmail(String str) {
15+
return _email.hasMatch(str.toLowerCase());
16+
}
17+
18+
/// check if the string [str] is a URL
19+
///
20+
/// * [protocols] sets the list of allowed protocols
21+
/// * [requireTld] sets if TLD is required
22+
/// * [requireProtocol] is a `bool` that sets if protocol is required for validation
23+
/// * [allowUnderscore] sets if underscores are allowed
24+
/// * [hostWhitelist] sets the list of allowed hosts
25+
/// * [hostBlacklist] sets the list of disallowed hosts
26+
bool isURL(String? str,
27+
{List<String?> protocols = const ['http', 'https', 'ftp'],
28+
bool requireTld = true,
29+
bool requireProtocol = false,
30+
bool allowUnderscore = false,
31+
List<String> hostWhitelist = const [],
32+
List<String> hostBlacklist = const []}) {
33+
if (str == null ||
34+
str.isEmpty ||
35+
str.length > 2083 ||
36+
str.startsWith('mailto:')) {
37+
return false;
38+
}
39+
int port;
40+
String? protocol, auth, user;
41+
String host, hostname, port_str, path, query, hash;
42+
43+
// check protocol
44+
var split = str.split('://');
45+
if (split.length > 1) {
46+
protocol = shift(split);
47+
if (!protocols.contains(protocol)) {
48+
return false;
49+
}
50+
} else if (requireProtocol == true) {
51+
return false;
52+
}
53+
str = split.join('://');
54+
55+
// check hash
56+
split = str.split('#');
57+
str = shift(split);
58+
hash = split.join('#');
59+
if (hash.isNotEmpty && RegExp(r'\s').hasMatch(hash)) {
60+
return false;
61+
}
62+
63+
// check query params
64+
split = str!.split('?');
65+
str = shift(split);
66+
query = split.join('?');
67+
if (query.isNotEmpty && RegExp(r'\s').hasMatch(query)) {
68+
return false;
69+
}
70+
71+
// check path
72+
split = str!.split('/');
73+
str = shift(split);
74+
path = split.join('/');
75+
if (path.isNotEmpty && RegExp(r'\s').hasMatch(path)) {
76+
return false;
77+
}
78+
79+
// check auth type urls
80+
split = str!.split('@');
81+
if (split.length > 1) {
82+
auth = shift(split);
83+
if (auth?.contains(':') ?? false) {
84+
user = shift(auth!.split(':'))!;
85+
if (!RegExp(r'^\S+$').hasMatch(user)) {
86+
return false;
87+
}
88+
if (!RegExp(r'^\S*$').hasMatch(user)) {
89+
return false;
90+
}
91+
}
92+
}
93+
94+
// check hostname
95+
hostname = split.join('@');
96+
split = hostname.split(':');
97+
host = shift(split)!;
98+
if (split.isNotEmpty) {
99+
port_str = split.join(':');
100+
try {
101+
port = int.parse(port_str, radix: 10);
102+
} catch (e) {
103+
return false;
104+
}
105+
if (!RegExp(r'^[0-9]+$').hasMatch(port_str) || port <= 0 || port > 65535) {
106+
return false;
107+
}
108+
}
109+
110+
if (!isIP(host, null) &&
111+
!isFQDN(host,
112+
requireTld: requireTld, allowUnderscores: allowUnderscore) &&
113+
host != 'localhost') {
114+
return false;
115+
}
116+
117+
if (hostWhitelist.isNotEmpty && !hostWhitelist.contains(host)) {
118+
return false;
119+
}
120+
121+
if (hostBlacklist.isNotEmpty && hostBlacklist.contains(host)) {
122+
return false;
123+
}
124+
125+
return true;
126+
}
127+
128+
/// check if the string [str] is IP [version] 4 or 6
129+
///
130+
/// * [version] is a String or an `int`.
131+
bool isIP(String? str, int? version) {
132+
if (version == null) {
133+
return isIP(str, 4) || isIP(str, 6);
134+
} else if (version == 4) {
135+
if (!_ipv4Maybe.hasMatch(str!)) {
136+
return false;
137+
}
138+
var parts = str.split('.');
139+
parts.sort((a, b) => int.parse(a) - int.parse(b));
140+
return int.parse(parts[3]) <= 255;
141+
}
142+
return version == 6 && _ipv6.hasMatch(str!);
143+
}
144+
145+
/// check if the string [str] is a fully qualified domain name (e.g. domain.com).
146+
///
147+
/// * [requireTld] sets if TLD is required
148+
/// * [allowUnderscore] sets if underscores are allowed
149+
bool isFQDN(String str,
150+
{bool requireTld = true, bool allowUnderscores = false}) {
151+
var parts = str.split('.');
152+
if (requireTld) {
153+
var tld = parts.removeLast();
154+
if (parts.isEmpty || !RegExp(r'^[a-z]{2,}$').hasMatch(tld)) {
155+
return false;
156+
}
157+
}
158+
159+
for (var part in parts) {
160+
if (allowUnderscores) {
161+
if (part.contains('__')) {
162+
return false;
163+
}
164+
}
165+
if (!RegExp(r'^[a-z\\u00a1-\\uffff0-9-]+$').hasMatch(part)) {
166+
return false;
167+
}
168+
if (part[0] == '-' ||
169+
part[part.length - 1] == '-' ||
170+
part.contains('---')) {
171+
return false;
172+
}
173+
}
174+
return true;
175+
}
176+
177+
/// check if the string is a credit card
178+
bool isCreditCard(String str) {
179+
var sanitized = str.replaceAll(RegExp(r'[^0-9]+'), '');
180+
if (!_creditCard.hasMatch(sanitized)) {
181+
return false;
182+
}
183+
184+
// Luhn algorithm
185+
var sum = 0;
186+
String digit;
187+
var shouldDouble = false;
188+
189+
for (var i = sanitized.length - 1; i >= 0; i--) {
190+
digit = sanitized.substring(i, (i + 1));
191+
var tmpNum = int.parse(digit);
192+
193+
if (shouldDouble == true) {
194+
tmpNum *= 2;
195+
if (tmpNum >= 10) {
196+
sum += ((tmpNum % 10) + 1);
197+
} else {
198+
sum += tmpNum;
199+
}
200+
} else {
201+
sum += tmpNum;
202+
}
203+
shouldDouble = !shouldDouble;
204+
}
205+
206+
return (sum % 10 == 0);
207+
}
208+
209+
/// check if the string is a date
210+
bool isDate(String str) {
211+
try {
212+
DateTime.parse(str);
213+
return true;
214+
} catch (e) {
215+
return false;
216+
}
217+
}

pubspec.yaml

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,8 @@ dependencies:
1313
sdk: flutter
1414

1515
intl: ^0.17.0
16-
validators: # ^2.0.1
17-
git: https://github.com/beerstorm-net/validators.git
18-
collection: ^1.15.0-nullsafety.4
19-
#dependency_overrides:
20-
# intl: ^0.17.0
21-
# json_annotation: ^4.0.0
22-
# basic_utils: 3.0.0-nullsafety.0
23-
# validators: # ^2.0.1
24-
# git: https://github.com/beerstorm-net/validators.git
16+
collection: ^1.15.0
17+
2518
dev_dependencies:
2619
flutter_test:
2720
sdk: flutter

0 commit comments

Comments
 (0)