mirror of
https://github.com/zapstore/zapstore.git
synced 2026-10-05 20:48:24 +00:00
- Introduce refresh tokens for updates and latest releases subscriptions to ensure UI updates. - Implement utility functions for relay URL handling.
97 lines
2.8 KiB
Dart
97 lines
2.8 KiB
Dart
/// Utility functions for WebSocket relay URL handling.
|
|
|
|
/// Validates and normalizes a relay URL: checks format, removes trailing
|
|
/// slashes, lowercases the host. Returns null if invalid.
|
|
///
|
|
/// Examples:
|
|
/// - ` WSS://Relay.Example.Com/ ` → `wss://relay.example.com`
|
|
/// - `wss://relay.example.com/` → `wss://relay.example.com`
|
|
/// - `wss://relay.example.com:443/path/` → `wss://relay.example.com:443/path`
|
|
/// - `invalid-url` → `null`
|
|
String? validateAndNormalizeRelayUrl(String input) {
|
|
final trimmed = input.trim();
|
|
if (trimmed.isEmpty) return null;
|
|
|
|
final uri = Uri.tryParse(trimmed);
|
|
if (uri == null) return null;
|
|
|
|
// Must have ws or wss scheme
|
|
if (uri.scheme != 'ws' && uri.scheme != 'wss') return null;
|
|
|
|
// Must have a host
|
|
if (uri.host.isEmpty) return null;
|
|
if (!_isValidRelayHost(uri.host)) return null;
|
|
|
|
// Rebuild normalized URL: scheme://host[:port][/path]
|
|
final buffer = StringBuffer()
|
|
..write(uri.scheme)
|
|
..write('://')
|
|
..write(uri.host.toLowerCase());
|
|
|
|
if (uri.hasPort && uri.port != 0) {
|
|
buffer
|
|
..write(':')
|
|
..write(uri.port);
|
|
}
|
|
|
|
// Add path if present, but remove trailing slashes
|
|
var path = uri.path;
|
|
while (path.endsWith('/')) {
|
|
path = path.substring(0, path.length - 1);
|
|
}
|
|
if (path.isNotEmpty) {
|
|
buffer.write(path);
|
|
}
|
|
|
|
return buffer.toString();
|
|
}
|
|
|
|
bool _isValidRelayHost(String host) {
|
|
if (host == 'localhost') return true;
|
|
|
|
// IPv4 validation (e.g., 192.168.0.1)
|
|
final ipv4Match = RegExp(r'^\d{1,3}(\.\d{1,3}){3}$').hasMatch(host);
|
|
if (ipv4Match) {
|
|
final parts = host.split('.');
|
|
return parts.every((p) {
|
|
final value = int.tryParse(p);
|
|
return value != null && value >= 0 && value <= 255;
|
|
});
|
|
}
|
|
|
|
// Domain validation
|
|
if (host.length > 253) return false;
|
|
final labels = host.split('.');
|
|
if (labels.length < 2) return false;
|
|
for (final label in labels) {
|
|
if (label.isEmpty || label.length > 63) return false;
|
|
if (!RegExp(r'^[a-zA-Z0-9-]+$').hasMatch(label)) return false;
|
|
if (label.startsWith('-') || label.endsWith('-')) return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
/// Checks if a relay URL already exists in the set.
|
|
/// Normalizes both URLs before comparison for robustness.
|
|
bool isDuplicateRelay(String normalizedUrl, Set<String> existingRelays) {
|
|
for (final existing in existingRelays) {
|
|
final existingNormalized = validateAndNormalizeRelayUrl(existing);
|
|
if (existingNormalized == null) continue;
|
|
|
|
if (existingNormalized == normalizedUrl) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/// Formats a relay URL for display by removing the scheme and trailing slash.
|
|
///
|
|
/// Example: `wss://relay.example.com/` → `relay.example.com`
|
|
String formatRelayUrlShort(String relayUrl) {
|
|
return relayUrl
|
|
.replaceAll('wss://', '')
|
|
.replaceAll('ws://', '')
|
|
.replaceAll(RegExp(r'/$'), '');
|
|
}
|