2021-03-17 23:04:36 +00:00
|
|
|
// Run this with "Basic QWxhZGRpbjpPcGVuU2VzYW1l"
|
|
|
|
|
|
|
|
import 'dart:convert';
|
|
|
|
import 'dart:io';
|
2021-05-14 06:11:50 +00:00
|
|
|
import 'package:angel3_combinator/angel3_combinator.dart';
|
2021-03-17 23:04:36 +00:00
|
|
|
import 'package:string_scanner/string_scanner.dart';
|
|
|
|
|
|
|
|
/// Parse a part of a decoded Basic auth string.
|
|
|
|
///
|
|
|
|
/// Namely, the `username` or `password` in `{username}:{password}`.
|
|
|
|
final Parser<String> string =
|
2021-05-14 06:11:50 +00:00
|
|
|
match<String>(RegExp(r'[^:$]+'), errorMessage: 'Expected a string.')
|
2021-03-18 00:00:56 +00:00
|
|
|
.value((r) => r.span!.text);
|
2021-03-17 23:04:36 +00:00
|
|
|
|
|
|
|
/// Transforms `{username}:{password}` to `{"username": username, "password": password}`.
|
|
|
|
final Parser<Map<String, String>> credentials = chain<String>([
|
|
|
|
string.opt(),
|
|
|
|
match<String>(':'),
|
|
|
|
string.opt(),
|
|
|
|
]).map<Map<String, String>>(
|
2021-05-11 09:03:52 +00:00
|
|
|
(r) => {'username': r.value![0], 'password': r.value![2]});
|
2021-03-17 23:04:36 +00:00
|
|
|
|
|
|
|
/// We can actually embed a parser within another parser.
|
|
|
|
///
|
|
|
|
/// This is used here to BASE64URL-decode a string, and then
|
|
|
|
/// parse the decoded string.
|
2021-03-18 00:00:56 +00:00
|
|
|
final Parser credentialString = match<Map<String, String>?>(
|
2021-05-14 06:11:50 +00:00
|
|
|
RegExp(r'([^\n$]+)'),
|
2021-03-17 23:04:36 +00:00
|
|
|
errorMessage: 'Expected a credential string.')
|
|
|
|
.value((r) {
|
2021-03-18 00:00:56 +00:00
|
|
|
var decoded = utf8.decode(base64Url.decode(r.span!.text));
|
2021-05-14 06:11:50 +00:00
|
|
|
var scanner = SpanScanner(decoded);
|
2021-05-02 04:12:43 +00:00
|
|
|
return credentials.parse(scanner).value;
|
2021-03-17 23:04:36 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
final Parser basic = match<Null>('Basic').space();
|
|
|
|
|
|
|
|
final Parser basicAuth = basic.then(credentialString).index(1);
|
|
|
|
|
|
|
|
void main() {
|
|
|
|
while (true) {
|
|
|
|
stdout.write('Enter a basic auth value: ');
|
2021-03-18 00:00:56 +00:00
|
|
|
var line = stdin.readLineSync()!;
|
2021-05-14 06:11:50 +00:00
|
|
|
var scanner = SpanScanner(line, sourceUrl: 'stdin');
|
2021-05-02 04:12:43 +00:00
|
|
|
var result = basicAuth.parse(scanner);
|
2021-03-17 23:04:36 +00:00
|
|
|
|
|
|
|
if (!result.successful) {
|
|
|
|
for (var error in result.errors) {
|
|
|
|
print(error.toolString);
|
2021-03-18 00:00:56 +00:00
|
|
|
print(error.span!.highlight(color: true));
|
2021-03-17 23:04:36 +00:00
|
|
|
}
|
2021-05-18 13:15:28 +00:00
|
|
|
} else {
|
2021-03-17 23:04:36 +00:00
|
|
|
print(result.value);
|
2021-05-18 13:15:28 +00:00
|
|
|
}
|
2021-03-17 23:04:36 +00:00
|
|
|
}
|
|
|
|
}
|