import Foundation struct ServerAddress: Equatable { let url: URL init(_ input: String) throws { let value = input.trimmingCharacters(in: .whitespacesAndNewlines) guard !value.contains("\\"), !value.contains(where: { $0.isWhitespace }), var parts = URLComponents(string: value), parts.scheme?.lowercased() == "https", let host = parts.host, !host.isEmpty, parts.user == nil, parts.password == nil, parts.query == nil, parts.fragment == nil, parts.percentEncodedPath.isEmpty || parts.percentEncodedPath == "/", parts.port == nil || (1...65535).contains(parts.port!) else { throw ConnectionError.invalidAddress } parts.scheme = "https" parts.host = host.lowercased() parts.path = "" if parts.port == 443 { parts.port = nil } guard let url = parts.url else { throw ConnectionError.invalidAddress } self.url = url } func owns(_ candidate: URL) -> Bool { guard let parts = URLComponents(url: candidate, resolvingAgainstBaseURL: false), let own = URLComponents(url: url, resolvingAgainstBaseURL: false) else { return false } return parts.scheme?.lowercased() == "https" && parts.user == nil && parts.password == nil && parts.host?.lowercased() == own.host?.lowercased() && (parts.port ?? 443) == (own.port ?? 443) } func ownsDownload(_ candidate: URL) -> Bool { if owns(candidate) { return true } guard candidate.scheme == "blob", let inner = URL(string: String(candidate.absoluteString.dropFirst(5))) else { return false } return owns(inner) } } enum ConnectionError: LocalizedError { case invalidAddress, incompatible, unavailable var errorDescription: String? { switch self { case .invalidAddress: return "Use a root HTTPS URL with a valid host and port. Remove credentials, subpaths, query and fragment." case .incompatible: return "This server does not expose compatible Yuvomi metadata." case .unavailable: return "Cannot verify the server. Check its certificate, VPN, network and reverse proxy." } } }