Skip to content

Commit 97fd3b2

Browse files
committed
Sanitize URL entry path, not just token, to prevent WebSocket crash
1 parent c1c998a commit 97fd3b2

3 files changed

Lines changed: 15 additions & 7 deletions

File tree

LoopFollow/Controllers/Nightscout/NightscoutSocketManager.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,10 +40,10 @@ class NightscoutSocketManager {
4040
return
4141
}
4242

43-
let url = Storage.shared.url.value
44-
// Sanitize defensively: tokens saved before this fix may still hold a stray
43+
// Sanitize defensively: values saved before this fix may still hold a stray
4544
// whitespace/control char that crashes Socket.IO's URL builder on iOS 26.
46-
let token = NightscoutUtils.sanitizeToken(Storage.shared.token.value)
45+
let url = NightscoutUtils.sanitizeConnectionInput(Storage.shared.url.value)
46+
let token = NightscoutUtils.sanitizeConnectionInput(Storage.shared.token.value)
4747

4848
guard !url.isEmpty else {
4949
disconnect()

LoopFollow/Helpers/NightscoutUtils.swift

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -163,9 +163,11 @@ class NightscoutUtils {
163163
}
164164

165165
// Strip whitespace/newlines/control characters that can sneak in via paste.
166-
// A raw one breaks WebSocket connect (invalid percent-encoded query traps on iOS 26).
167-
static func sanitizeToken(_ token: String) -> String {
168-
token.unicodeScalars
166+
// Neither a URL nor a token may legally contain them, and a stray one breaks
167+
// WebSocket connect (invalid percent-encoded query traps on iOS 26) or makes
168+
// URL parsing fall back to a lossy cleanup that mangles the address.
169+
static func sanitizeConnectionInput(_ input: String) -> String {
170+
input.unicodeScalars
169171
.filter { !CharacterSet.whitespacesAndNewlines.contains($0) && !CharacterSet.controlCharacters.contains($0) }
170172
.map(String.init)
171173
.joined()

LoopFollow/Nightscout/NightscoutSettingsViewModel.swift

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ class NightscoutSettingsViewModel: ObservableObject {
2727
@Published var nightscoutToken: String = Storage.shared.token.value {
2828
willSet {
2929
if newValue != nightscoutToken {
30-
Storage.shared.token.value = NightscoutUtils.sanitizeToken(newValue)
30+
Storage.shared.token.value = NightscoutUtils.sanitizeConnectionInput(newValue)
3131
triggerCheckStatus()
3232
}
3333
}
@@ -93,6 +93,12 @@ class NightscoutSettingsViewModel: ObservableObject {
9393
}
9494

9595
func processURL(_ value: String) {
96+
// Strip whitespace/newlines/control chars first. A URL can't legally contain
97+
// them, and a stray one (e.g. a trailing newline from a paste) otherwise makes
98+
// URLComponents parsing fail and falls through to the lossy fallback below,
99+
// mangling a URL-with-embedded-token into an invalid address.
100+
let value = NightscoutUtils.sanitizeConnectionInput(value)
101+
96102
var useTokenUrl = false
97103

98104
if let urlComponents = URLComponents(string: value), let queryItems = urlComponents.queryItems {

0 commit comments

Comments
 (0)