refactor: parseIdentifierIntoParts

This commit is contained in:
Lukas Lihotzki 2021-09-23 13:15:24 +02:00 committed by Krille Fear
parent 7fce5b6040
commit fb0ea2efc3
1 changed files with 39 additions and 49 deletions

View File

@ -58,18 +58,14 @@ extension MatrixIdExtension on String {
bool equals(String other) => toLowerCase() == other?.toLowerCase(); bool equals(String other) => toLowerCase() == other?.toLowerCase();
/// Separate a matrix identifier string into a primary indentifier, a secondary identifier, /// Parse a matrix identifier string into a Uri. Primary and secondary identifiers
/// a query string and already parsed `via` parameters. A matrix identifier string /// are stored in pathSegments. The query string is stored as such.
/// can be an mxid, a matrix.to-url or a matrix-uri. Uri _parseIdentifierIntoUri() {
MatrixIdentifierStringExtensionResults parseIdentifierIntoParts() {
const matrixUriPrefix = 'matrix:'; const matrixUriPrefix = 'matrix:';
const matrixToPrefix = 'https://matrix.to/#/';
// check if we have a "matrix:" uri
if (toLowerCase().startsWith(matrixUriPrefix)) { if (toLowerCase().startsWith(matrixUriPrefix)) {
final uri = Uri.tryParse(this); final uri = Uri.tryParse(this);
if (uri == null) { if (uri == null) return null;
return null;
}
final pathSegments = uri.pathSegments; final pathSegments = uri.pathSegments;
final identifiers = <String>[]; final identifiers = <String>[];
for (var i = 0; i < pathSegments.length - 1; i += 2) { for (var i = 0; i < pathSegments.length - 1; i += 2) {
@ -82,50 +78,44 @@ extension MatrixIdExtension on String {
if (thisSigil == null) { if (thisSigil == null) {
break; break;
} }
final identifier = thisSigil + pathSegments[i + 1]; identifiers.add(thisSigil + pathSegments[i + 1]);
if (!identifier.isValidMatrixId) {
return null;
}
identifiers.add(identifier);
} }
if (identifiers.isEmpty) { return uri.replace(pathSegments: identifiers);
return null; } else if (toLowerCase().startsWith(matrixToPrefix)) {
} return Uri.tryParse('//' +
return MatrixIdentifierStringExtensionResults( substring(matrixToPrefix.length - 1)
primaryIdentifier: identifiers.first, .replaceAllMapped(
secondaryIdentifier: identifiers.length > 1 ? identifiers[1] : null, RegExp(r'(?<=/)[#!@+][^:]*:|(\?.*$)'),
queryString: uri.query.isNotEmpty ? uri.query : null, (m) => m.group(0).replaceAllMapped(
via: (uri.queryParametersAll['via'] ?? []).toSet(), RegExp(m.group(1) != null ? '' : '[/?]'),
action: uri.queryParameters['action'], (m) => Uri.encodeComponent(m.group(0))))
); .replaceAll('#', '%23'));
} else {
final match =
RegExp(r'^([#!@+][^:]*:[^\/?]*)(?:\/(\$[^?]*))?(?:\?(.*))?$')
.firstMatch(this);
if (match == null) return null;
return Uri(
pathSegments:
[match.group(1), match.group(2)].where((x) => x != null),
query: match.group(3));
} }
}
/// Separate a matrix identifier string into a primary indentifier, a secondary identifier,
/// a query string and already parsed `via` parameters. A matrix identifier string
/// can be an mxid, a matrix.to-url or a matrix-uri.
MatrixIdentifierStringExtensionResults parseIdentifierIntoParts() {
final uri = _parseIdentifierIntoUri();
if (uri == null) return null;
final primary = uri.pathSegments.isNotEmpty ? uri.pathSegments[0] : null;
if (primary == null || !primary.isValidMatrixId) return null;
final secondary = uri.pathSegments.length > 1 ? uri.pathSegments[1] : null;
if (secondary != null && !secondary.isValidMatrixId) return null;
const matrixToPrefix = 'https://matrix.to/#/';
// matrix identifiers and matrix.to URLs are parsed similarly, so we do them here
var s = this;
if (toLowerCase().startsWith(matrixToPrefix)) {
// as we decode a component we may only call it on the url part *before* the "query" part
final parts = substring(matrixToPrefix.length).split('?');
var ident = parts.removeAt(0);
try {
ident = Uri.decodeComponent(ident);
} catch (_) {
// do nothing: the identifier wasn't url-encoded, and we already have the
// plaintext version in the `ident` variable
}
s = ident + '?' + parts.join('?');
}
final match = RegExp(r'^([#!@+][^:]*:[^\/?]*)(?:\/(\$[^?]*))?(?:\?(.*))?$')
.firstMatch(s);
if (match == null ||
!match.group(1).isValidMatrixId ||
!(match.group(2)?.isValidMatrixId ?? true)) {
return null;
}
final uri = Uri(query: match.group(3));
return MatrixIdentifierStringExtensionResults( return MatrixIdentifierStringExtensionResults(
primaryIdentifier: match.group(1), primaryIdentifier: primary,
secondaryIdentifier: match.group(2), secondaryIdentifier: secondary,
queryString: uri.query.isNotEmpty ? uri.query : null, queryString: uri.query.isNotEmpty ? uri.query : null,
via: (uri.queryParametersAll['via'] ?? []).toSet(), via: (uri.queryParametersAll['via'] ?? []).toSet(),
action: uri.queryParameters['action'], action: uri.queryParameters['action'],