Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions GenericApp/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@ dependencies {
implementation 'com.google.firebase:firebase-messaging-ktx'
implementation 'com.google.android.material:material:1.12.0'
implementation project(':ORLib')

// Unit testing framework
testImplementation 'junit:junit:4.13.2'
}

task sourcesJar(type: Jar) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -51,12 +51,7 @@ class HostSelectionFragment : Fragment() {

private fun connectToHost(host: String) {
parentActivity.binding.progressBar.visibility = View.VISIBLE
val url = when {
URLUtil.isValidUrl(host) -> host.plus("/api/master")
UrlUtils.isIpAddress(host) -> "https://${host}/api/master"
!UrlUtils.startsWithHttp(host) && UrlUtils.endsWithTld(host) -> "https://${host}/api/master"
else -> "https://${host}.openremote.app/api/master"
}
val url = UrlUtils.hostToUrl(host).plus("/api/master")
parentActivity.apiManager = ApiManager(url)
parentActivity.apiManager.getConsoleConfig { statusCode, consoleConfig, error ->
when (statusCode) {
Expand Down
27 changes: 16 additions & 11 deletions GenericApp/app/src/main/java/io/openremote/app/util/UrlUtils.kt
Original file line number Diff line number Diff line change
@@ -1,20 +1,25 @@
package io.openremote.app.util

object UrlUtils {
fun isIpAddress(url: String): Boolean {
val ipPattern = Regex(
"^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(:\\d{1,5})?$"
fun isIpV6NoScheme(url: String): Boolean {
val ipv6Pattern = Regex(
"^(?:([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6}))$"
)
return ipPattern.matches(url)
return ipv6Pattern.matches(url)
}
fun startsWithHttp(url: String): Boolean {
return url.startsWith("http://") || url.startsWith("https://")

fun startsWithScheme(url: String): Boolean {
val schemePattern = Regex("^[a-zA-Z]+://.*$")
return schemePattern.matches(url)
}

fun endsWithTld(url: String): Boolean {
val tldPattern = Regex(
"(?:[a-zA-Z]*\\.)+([a-zA-Z]+)(?:\\/.*)?"
)
return tldPattern.matches(url)
fun hostToUrl(host: String): String {
return when {
isIpV6NoScheme(host) -> "https://[${host}]"
startsWithScheme(host) ->
if (host.contains(".") || host.contains("[")) host else "${host}.openremote.app"
(host.contains(".") || host.contains("[")) -> "https://${host}"
else -> "https://${host}.openremote.app"
}
}
}
130 changes: 130 additions & 0 deletions GenericApp/app/src/test/java/io/openremote/app/util/UrlUtilsTest.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,130 @@
import io.openremote.app.util.UrlUtils
import org.junit.Test
import org.junit.Assert.assertEquals

class UrlUtilsTest {

@Test
fun fqdnWithScheme() {
assertEquals("http://www.example.com", UrlUtils.hostToUrl("http://www.example.com"))
assertEquals("https://www.example.com", UrlUtils.hostToUrl("https://www.example.com"))
}

@Test
fun fqdnWithNonWebScheme() {
assertEquals("ftp://www.example.com", UrlUtils.hostToUrl("ftp://www.example.com"))
}

@Test
fun fqdnNoScheme() {
assertEquals("https://www.example.com", UrlUtils.hostToUrl("www.example.com"))
}

@Test
fun fqdnAndPortWithScheme() {
assertEquals("http://www.example.com:8080", UrlUtils.hostToUrl("http://www.example.com:8080"))
assertEquals("https://www.example.com:443", UrlUtils.hostToUrl("https://www.example.com:443"))
}

@Test
fun fqdnAndPortWithNonWebScheme() {
assertEquals("ftp://www.example.com:21", UrlUtils.hostToUrl("ftp://www.example.com:21"))
}

@Test
fun fqdnAndPortNoScheme() {
assertEquals("https://www.example.com:8080", UrlUtils.hostToUrl("www.example.com:8080"))
}

@Test
fun hostnameNoScheme() {
assertEquals("https://example.openremote.app", UrlUtils.hostToUrl("example"))
}

@Test
fun ipAddressWithScheme() {
assertEquals("http://192.168.1.1", UrlUtils.hostToUrl("http://192.168.1.1"))
}

@Test
fun ipAddressWithNonWebScheme() {
assertEquals("ftp://192.168.1.1", UrlUtils.hostToUrl("ftp://192.168.1.1"))
}

@Test
fun ipAddressAndPortWithScheme() {
assertEquals("http://192.168.1.1:8080", UrlUtils.hostToUrl("http://192.168.1.1:8080"))
}

@Test
fun ipAddressAndPortWithNonWebScheme() {
assertEquals("ftp://192.168.1.1:25", UrlUtils.hostToUrl("ftp://192.168.1.1:25"))
}

@Test
fun ipAddressAndInvalidPortWithScheme() {
assertEquals("http://192.168.1.1:InvalidPort", UrlUtils.hostToUrl("http://192.168.1.1:InvalidPort"))
}

@Test
fun ipAddressNoScheme() {
assertEquals("https://192.168.1.1", UrlUtils.hostToUrl("192.168.1.1"))
}

@Test
fun ipAddressAndPortNoScheme() {
assertEquals("https://192.168.1.1:8080", UrlUtils.hostToUrl("192.168.1.1:8080"))
}

@Test
fun ipv6AddressWithScheme() {
assertEquals("http://[2001:0db8:85a3:0000:0000:8a2e:0370:7334]",
UrlUtils.hostToUrl("http://[2001:0db8:85a3:0000:0000:8a2e:0370:7334]"))
}

@Test
fun ipv6AddressAndPortWithScheme() {
assertEquals("http://[2001:0db8:85a3:0000:0000:8a2e:0370:7334]:8080",
UrlUtils.hostToUrl("http://[2001:0db8:85a3:0000:0000:8a2e:0370:7334]:8080"))
}

@Test
fun ipv6AddressNoScheme() {
assertEquals("https://[2001:0db8:85a3:0000:0000:8a2e:0370:7334]",
UrlUtils.hostToUrl("2001:0db8:85a3:0000:0000:8a2e:0370:7334"))
assertEquals("https://[2001:0db8:85a3:0000:0000:8a2e:0370:7334]",
UrlUtils.hostToUrl("[2001:0db8:85a3:0000:0000:8a2e:0370:7334]"))
}

@Test
fun ipv6AddressAndPortNoScheme() {
assertEquals("https://[2001:0db8:85a3:0000:0000:8a2e:0370:7334]:8080",
UrlUtils.hostToUrl("[2001:0db8:85a3:0000:0000:8a2e:0370:7334]:8080"))
}

@Test
fun ipv6CompressedAddressWithScheme() {
assertEquals("http://[2001:db8:85a3::8a2e:370:7334]",
UrlUtils.hostToUrl("http://[2001:db8:85a3::8a2e:370:7334]"))
}

@Test
fun ipv6CompressedAddressAndPortWithScheme() {
assertEquals("http://[2001:db8:85a3::8a2e:370:7334]:8080",
UrlUtils.hostToUrl("http://[2001:db8:85a3::8a2e:370:7334]:8080"))
}

@Test
fun ipv6CompressedAddressNoScheme() {
assertEquals("https://[2001:db8:85a3::8a2e:370:7334]",
UrlUtils.hostToUrl("2001:db8:85a3::8a2e:370:7334"))
assertEquals("https://[2001:db8:85a3::8a2e:370:7334]",
UrlUtils.hostToUrl("[2001:db8:85a3::8a2e:370:7334]"))
}

@Test
fun ipv6CompressedAddressAndPortNoScheme() {
assertEquals("https://[2001:db8:85a3::8a2e:370:7334]:8080",
UrlUtils.hostToUrl("[2001:db8:85a3::8a2e:370:7334]:8080"))
}
}
Loading