Files
Yuvomi-App/ios/Sources/ServerAddress.swift
T
Yuvomi Mobile Contributors 69c48169e2 fix(ios): restrict authentication capabilities and validate bootstrap types
Require iOS 18.4 for explicit upload denial in the isolated authentication window. Add origin-bound generated download policy, app-switcher privacy, typed metadata regressions and original community icon assets. Seven portable tests and Swift formatting checks pass; Apple SDK validation remains external.
2026-10-20 23:45:01 +02:00

58 lines
2.2 KiB
Swift

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."
}
}
}