-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: URL validation classes 'Url' and 'ReqUrl'
Closes #96
- Loading branch information
Showing
9 changed files
with
188 additions
and
19 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
import '../../core.dart'; | ||
import '../../type.dart'; | ||
import 'url.dart'; | ||
|
||
/// Convenience validator for required URL values. | ||
class ReqUrl { | ||
/// Non-blank and well-formed URL values. | ||
ReqUrl({String blank = 'required URL', String mal = 'malformed URL'}) | ||
: _reqUrl = Pair.str2(Req(blank: blank), Url(mal: mal)); | ||
|
||
final ValObj _reqUrl; | ||
|
||
/// Returns null if the value is a valid URL; otherwise it will return the | ||
/// error message for blank fields or the error message for malformed fields. | ||
String? call(String? value) => _reqUrl(value); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,47 @@ | ||
import 'package:formdator/formdator.dart'; | ||
|
||
/// URL Validator. | ||
/// | ||
/// Blank field - null value - is a valid input! | ||
/// | ||
/// If the URL is required, see [ReqUrl] or [Req]. | ||
/// | ||
/// Notes on possible differences from a standard/generic validation: | ||
/// | ||
/// - utf-8 char class take in consideration the full Unicode range | ||
/// - Top-level domains (TLDs) have been made mandatory so single names like | ||
/// "localhost" fails | ||
/// - protocols have been restricted to ftp, http and https | ||
/// - IP address dotted notation validation, range: 1.0.0.0 - 223.255.255.255 | ||
/// first and last IP address of each class is considered invalid (since they | ||
/// are broadcast/network addresses) | ||
/// | ||
/// - Made starting path slash optional (http://example.com?foo=bar) | ||
/// - Allow a dot (.) at the end of hostnames (http://example.com.) | ||
/// - Allow an underscore (_) character in host/domain_names | ||
/// - Check dot delimited parts length and total length | ||
/// - Made protocol optional, allowed short syntax // | ||
class Url { | ||
/// Validates URL values using a regular expression. | ||
/// | ||
/// If the URL field is mandatory, see [ReqUrl] or [Req]. | ||
const Url({this.mal = 'malformed URL'}); | ||
|
||
/// The error message in case of a malformed URL value. | ||
final String mal; | ||
|
||
/// A suitable pattern for URL values. | ||
/// | ||
/// Reference: [gist](https://gist.github.com/dperini/729294) | ||
static final RegExp urlPattern = RegExp( | ||
r'^(?:(?:(?:https?|ftp):)?\/\/)(?:\S+(?::\S*)?@)?(?:(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z0-9\u00a1-\uffff][a-z0-9\u00a1-\uffff_-]{0,62})?[a-z0-9\u00a1-\uffff]\.)+(?:[a-z\u00a1-\uffff]{2,}\.?))(?::\d{2,5})?(?:[/?#]\S*)?$', | ||
caseSensitive: false, | ||
unicode: true, | ||
); | ||
|
||
/// Returns `null` if [value] is `null` or a valid URL; returns [mal] | ||
/// otherwise. | ||
String? call(String? value) { | ||
return value == null || urlPattern.hasMatch(value) ? null : mal; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
import 'package:formdator/src/net/req_url.dart'; | ||
import 'package:test/test.dart'; | ||
|
||
void main() { | ||
group('ReqUrl', () { | ||
const blank = 'required URL value'; | ||
const mal = 'malformed URL value'; | ||
final reqUrl = ReqUrl(blank: blank, mal: mal); | ||
test('null - blank', () { | ||
expect(reqUrl(null), blank); | ||
}); | ||
test('empty - blank', () { | ||
expect(reqUrl(''), blank); | ||
}); | ||
test('valid URL', () { | ||
expect(reqUrl('http://10.0.1.1'), null); | ||
}); | ||
test('invalid URL', () { | ||
expect(reqUrl('http://10.10.10.256'), mal); | ||
}); | ||
}); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
import 'package:formdator/src/net/url.dart'; | ||
import 'package:test/test.dart'; | ||
|
||
void main() { | ||
group('URL', () { | ||
const error = 'malformed URL value'; | ||
const url = Url(mal: error); | ||
test('Valid Urls:', () { | ||
expect(url(null), null); | ||
expect(url('//shortsyntax.com'), null); | ||
expect(url('//www.shortsyntax.com'), null); | ||
expect(url('http://www.example.com'), null); | ||
expect(url('http://www.example.com.'), null); | ||
expect(url('http://www.example.com/index.html'), null); | ||
expect(url('http://example.com?foo=bar'), null); | ||
expect(url('https://www.example.com/foo/?bar=baz&inga=42&quux'), null); | ||
expect(url('http://odf.ws/123'), null); | ||
expect(url('http://userid:[email protected]:8080'), null); | ||
expect(url('http://userid:[email protected]:8080/'), null); | ||
expect(url('https://www.youtube.com/watch?v=nmhX3_m84Is'), null); | ||
expect(url('http://foo.com/blah_blah#cite-1'), null); | ||
expect(url('http://[email protected]:8080/'), null); | ||
expect(url('http://foo.com/blah_(wikipedia)#cite-1'), null); | ||
expect(url('http://foo.com/blah_(wikipedia)_blah#cite-1'), null); | ||
expect(url('http://code.google.com/events/#&product=browser'), null); | ||
expect(url('http://foo.bar/?q=Test%20URL-encoded%20stuff'), null); | ||
expect(url("http://-.~_!&'()*+,;=:%40:80%2f::::::@example.com"), null); | ||
expect(url('https://foo_bar.example.com/'), null); | ||
expect(url('http://1337.net'), null); | ||
expect(url('http://192.168.0.3'), null); | ||
expect(url('http://192.168.0.3/resource'), null); | ||
expect(url('http://223.255.255.254'), null); | ||
}); | ||
test('Valid FTP Urls:', () { | ||
expect(url('ftp://example.com'), null); | ||
expect(url('ftp://example.com:8080'), null); | ||
expect(url('ftp://example.com:8080/'), null); | ||
expect(url('ftp://example.com:8080/url-path'), null); | ||
expect(url('ftp://userid:[email protected]:8080/url-path'), null); | ||
}); | ||
test('invalid URLs', () { | ||
expect(url(''), error); | ||
expect(url('//'), error); | ||
expect(url('://'), error); | ||
expect(url('//a'), error); | ||
expect(url('http://'), error); | ||
expect(url('http:///a'), error); | ||
expect(url('foo.com'), error); | ||
expect(url('rdar://1234'), error); | ||
expect(url('http://.'), error); | ||
expect(url('http://..'), error); | ||
expect(url('http://?'), error); | ||
expect(url('http://??'), error); | ||
expect(url('http://#'), error); | ||
expect(url('http://##'), error); | ||
expect(url('1'), error); | ||
expect(url('10.10'), error); | ||
expect(url('0.0.0.0'), error); | ||
expect(url('http://10.1.1.255'), error); | ||
expect(url('http://224.1.1.1'), error); | ||
expect(url('http://3628126748'), error); | ||
// the first IP andress (network) of each class is considered invalid. | ||
expect(url('http://192.168.0.0'), error); | ||
expect(url('http://192.168.0.0/resource'), error); | ||
// the last IP andress (broadcast) of each class is considered invalid. | ||
expect(url('http://192.168.0.255/'), error); | ||
expect(url('http://192.168.0.255/resource'), error); | ||
|
||
expect(url('http://?df.ws/123'), error); | ||
expect(url('http:// shouldfail.com'), error); | ||
expect(url('http://.www.foo.bar/'), error); | ||
expect(url('http://foo.bar?q=Spaces should be encoded'), error); | ||
}); | ||
}); | ||
} |