Skip to content

Commit 4c4c697

Browse files
authored
Stronger URL validation in manual server (#6231)
1 parent 7e57e88 commit 4c4c697

2 files changed

Lines changed: 22 additions & 1 deletion

File tree

app/src/main/kotlin/io/homeassistant/companion/android/onboarding/manualserver/ManualServerViewModel.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ package io.homeassistant.companion.android.onboarding.manualserver
33
import android.webkit.URLUtil
44
import androidx.lifecycle.ViewModel
55
import dagger.hilt.android.lifecycle.HiltViewModel
6+
import java.net.URL
67
import javax.inject.Inject
78
import kotlinx.coroutines.flow.MutableStateFlow
89
import kotlinx.coroutines.flow.asStateFlow
@@ -23,7 +24,7 @@ internal class ManualServerViewModel @Inject constructor() : ViewModel() {
2324

2425
private fun validateServerUrl(url: String) {
2526
isServerUrlValidMutableFlow.update {
26-
URLUtil.isValidUrl(url)
27+
URLUtil.isValidUrl(url) && runCatching { URL(url) }.isSuccess
2728
}
2829
}
2930
}

app/src/test/kotlin/io/homeassistant/companion/android/onboarding/manualserver/ManualServerViewModelTest.kt

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,26 @@ class ManualServerViewModelTest {
6363
}
6464
}
6565

66+
@Test
67+
fun `Given url with malformed port when onServerUrlChange then isServerUrlValid is false`() = runTest {
68+
val malformedUrl = "http://homeassistant.local::8123"
69+
70+
turbineScope {
71+
val serverUrlFlow = viewModel.serverUrlFlow.testIn(backgroundScope)
72+
val isServerUrlValidFlow = viewModel.isServerUrlValidFlow.testIn(backgroundScope)
73+
assertEquals("", serverUrlFlow.awaitItem())
74+
assertFalse(isServerUrlValidFlow.awaitItem())
75+
76+
// URLUtil may return true but java.net.URL parsing should fail
77+
mockUrlUtilIsValidUrl(true)
78+
79+
viewModel.onServerUrlChange(malformedUrl)
80+
81+
isServerUrlValidFlow.expectNoEvents()
82+
assertEquals(malformedUrl, serverUrlFlow.awaitItem())
83+
}
84+
}
85+
6686
private fun mockUrlUtilIsValidUrl(isValid: Boolean) {
6787
mockkStatic(URLUtil::class)
6888
every { URLUtil.isValidUrl(any()) } returns isValid

0 commit comments

Comments
 (0)