Loading CHANGELOG.md 0 → 100644 +7 −0 Original line number Diff line number Diff line # Version 1.x ## Version 1.0.1 - `UrlUtils.equals()`: ignore #fragment URL parts - updated dependencies build.gradle.kts +2 −2 Original line number Diff line number Diff line Loading @@ -5,7 +5,7 @@ object Libs { // We'll use 3.12 for now, but this branch won't receive feature updates anymore. Security // updates are limited to Dec 2020, so we'll have to update to 3.13 until then. On Android, // using 3.13 will raise the required SDK level to Android 5. const val okhttpVersion = "3.12.6" const val okhttpVersion = "3.12.8" // XmlPullParser library const val xpp3Version = "1.1.6" Loading @@ -18,7 +18,7 @@ repositories { } plugins { kotlin("jvm") version "1.3.50" kotlin("jvm") version "1.3.61" id("com.github.kukuhyoniatmoko.buildconfigkotlin") version "1.0.5" id("org.jetbrains.dokka") version "0.10.0" Loading src/main/kotlin/at/bitfire/dav4jvm/UrlUtils.kt +48 −7 Original line number Diff line number Diff line Loading @@ -12,14 +12,33 @@ import java.net.URISyntaxException object UrlUtils { /** * Compares two URLs in WebDAV context. If two URLs are considered *equal*, both * represent the same WebDAV resource (e.g. `http://host:80/folder1` and `http://HOST/folder1#somefragment`). * * It decodes %xx entities in the path, so `/my@dav` and `/my%40dav` are considered the same. * This is important to process multi-status responses: some servers serve a multi-status * response with href `/my@dav` when you request `/my%40dav` and vice versa. * * This method does not deal with trailing slashes, so if you want to compare collection URLs, * make sure they both (don't) have a trailing slash before calling this method, for instance * with [omitTrailingSlash] or [withTrailingSlash]. * * @param url1 the first URL to be compared * @param url2 the second URL to be compared * * @return whether [url1] and [url2] (usually) represent the same WebDAV resource */ fun equals(url1: HttpUrl, url2: HttpUrl): Boolean { // if okhttp thinks the two URLs are equal, they're in any case // (and it's a simple String comparison) if (url1 == url2) return true val uri1 = url1.uri() val uri2 = url2.uri() // drop #fragment parts and convert to URI val uri1 = url1.newBuilder().fragment(null).build().uri() val uri2 = url2.newBuilder().fragment(null).build().uri() return try { val decoded1 = URI(uri1.scheme, uri1.schemeSpecificPart, uri1.fragment) val decoded2 = URI(uri2.scheme, uri2.schemeSpecificPart, uri2.fragment) Loading @@ -29,22 +48,37 @@ object UrlUtils { } } /** * Gets the first-level domain name (without subdomains) from a host name. * Also removes trailing dots. * * @param host name (e.g. `www.example.com.`) * * @return domain name (e.g. `example.com`) */ fun hostToDomain(host: String?): String? { if (host == null) return null // remove optional dot at end @Suppress("NAME_SHADOWING") val host = host.removeSuffix(".") val withoutTrailingDot = host.removeSuffix(".") // split into labels val labels = host.split('.') val labels = withoutTrailingDot.split('.') return if (labels.size >= 2) { labels[labels.size - 2] + "." + labels[labels.size - 1] } else host withoutTrailingDot } /** * Ensures that a given URL doesn't have a trailing slash after member names. * If the path is the root path (`/`), the slash is preserved. * * @param url URL to process (e.g. 'http://host/test1/') * * @return URL without trailing slash (except when the path is the root path), e.g. `http://host/test1` */ fun omitTrailingSlash(url: HttpUrl): HttpUrl { val idxLast = url.pathSize () - 1 val hasTrailingSlash = url.pathSegments()[idxLast] == "" Loading @@ -55,6 +89,13 @@ object UrlUtils { url } /** * Ensures that a given URL has a trailing slash after member names. * * @param url URL to process (e.g. 'http://host/test1') * * @return URL with trailing slash, e.g. `http://host/test1/` */ fun withTrailingSlash(url: HttpUrl): HttpUrl { val idxLast = url.pathSize() - 1 val hasTrailingSlash = url.pathSegments()[idxLast] == "" Loading src/test/kotlin/at/bitfire/dav4jvm/UrlUtilsTest.kt +1 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ class UrlUtilsTest { assertTrue(UrlUtils.equals(HttpUrl.parse("http://host:80/resource")!!, HttpUrl.parse("http://host/resource")!!)) assertTrue(UrlUtils.equals(HttpUrl.parse("https://HOST:443/resource")!!, HttpUrl.parse("https://host/resource")!!)) assertTrue(UrlUtils.equals(HttpUrl.parse("https://host:443/my@dav/")!!, HttpUrl.parse("https://host/my%40dav/")!!)) assertTrue(UrlUtils.equals(HttpUrl.parse("http://host/resource")!!, HttpUrl.parse("http://host/resource#frag1")!!)) assertFalse(UrlUtils.equals(HttpUrl.parse("http://host/resource")!!, HttpUrl.parse("http://host/resource/")!!)) assertFalse(UrlUtils.equals(HttpUrl.parse("http://host/resource")!!, HttpUrl.parse("http://host:81/resource")!!)) Loading Loading
CHANGELOG.md 0 → 100644 +7 −0 Original line number Diff line number Diff line # Version 1.x ## Version 1.0.1 - `UrlUtils.equals()`: ignore #fragment URL parts - updated dependencies
build.gradle.kts +2 −2 Original line number Diff line number Diff line Loading @@ -5,7 +5,7 @@ object Libs { // We'll use 3.12 for now, but this branch won't receive feature updates anymore. Security // updates are limited to Dec 2020, so we'll have to update to 3.13 until then. On Android, // using 3.13 will raise the required SDK level to Android 5. const val okhttpVersion = "3.12.6" const val okhttpVersion = "3.12.8" // XmlPullParser library const val xpp3Version = "1.1.6" Loading @@ -18,7 +18,7 @@ repositories { } plugins { kotlin("jvm") version "1.3.50" kotlin("jvm") version "1.3.61" id("com.github.kukuhyoniatmoko.buildconfigkotlin") version "1.0.5" id("org.jetbrains.dokka") version "0.10.0" Loading
src/main/kotlin/at/bitfire/dav4jvm/UrlUtils.kt +48 −7 Original line number Diff line number Diff line Loading @@ -12,14 +12,33 @@ import java.net.URISyntaxException object UrlUtils { /** * Compares two URLs in WebDAV context. If two URLs are considered *equal*, both * represent the same WebDAV resource (e.g. `http://host:80/folder1` and `http://HOST/folder1#somefragment`). * * It decodes %xx entities in the path, so `/my@dav` and `/my%40dav` are considered the same. * This is important to process multi-status responses: some servers serve a multi-status * response with href `/my@dav` when you request `/my%40dav` and vice versa. * * This method does not deal with trailing slashes, so if you want to compare collection URLs, * make sure they both (don't) have a trailing slash before calling this method, for instance * with [omitTrailingSlash] or [withTrailingSlash]. * * @param url1 the first URL to be compared * @param url2 the second URL to be compared * * @return whether [url1] and [url2] (usually) represent the same WebDAV resource */ fun equals(url1: HttpUrl, url2: HttpUrl): Boolean { // if okhttp thinks the two URLs are equal, they're in any case // (and it's a simple String comparison) if (url1 == url2) return true val uri1 = url1.uri() val uri2 = url2.uri() // drop #fragment parts and convert to URI val uri1 = url1.newBuilder().fragment(null).build().uri() val uri2 = url2.newBuilder().fragment(null).build().uri() return try { val decoded1 = URI(uri1.scheme, uri1.schemeSpecificPart, uri1.fragment) val decoded2 = URI(uri2.scheme, uri2.schemeSpecificPart, uri2.fragment) Loading @@ -29,22 +48,37 @@ object UrlUtils { } } /** * Gets the first-level domain name (without subdomains) from a host name. * Also removes trailing dots. * * @param host name (e.g. `www.example.com.`) * * @return domain name (e.g. `example.com`) */ fun hostToDomain(host: String?): String? { if (host == null) return null // remove optional dot at end @Suppress("NAME_SHADOWING") val host = host.removeSuffix(".") val withoutTrailingDot = host.removeSuffix(".") // split into labels val labels = host.split('.') val labels = withoutTrailingDot.split('.') return if (labels.size >= 2) { labels[labels.size - 2] + "." + labels[labels.size - 1] } else host withoutTrailingDot } /** * Ensures that a given URL doesn't have a trailing slash after member names. * If the path is the root path (`/`), the slash is preserved. * * @param url URL to process (e.g. 'http://host/test1/') * * @return URL without trailing slash (except when the path is the root path), e.g. `http://host/test1` */ fun omitTrailingSlash(url: HttpUrl): HttpUrl { val idxLast = url.pathSize () - 1 val hasTrailingSlash = url.pathSegments()[idxLast] == "" Loading @@ -55,6 +89,13 @@ object UrlUtils { url } /** * Ensures that a given URL has a trailing slash after member names. * * @param url URL to process (e.g. 'http://host/test1') * * @return URL with trailing slash, e.g. `http://host/test1/` */ fun withTrailingSlash(url: HttpUrl): HttpUrl { val idxLast = url.pathSize() - 1 val hasTrailingSlash = url.pathSegments()[idxLast] == "" Loading
src/test/kotlin/at/bitfire/dav4jvm/UrlUtilsTest.kt +1 −0 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ class UrlUtilsTest { assertTrue(UrlUtils.equals(HttpUrl.parse("http://host:80/resource")!!, HttpUrl.parse("http://host/resource")!!)) assertTrue(UrlUtils.equals(HttpUrl.parse("https://HOST:443/resource")!!, HttpUrl.parse("https://host/resource")!!)) assertTrue(UrlUtils.equals(HttpUrl.parse("https://host:443/my@dav/")!!, HttpUrl.parse("https://host/my%40dav/")!!)) assertTrue(UrlUtils.equals(HttpUrl.parse("http://host/resource")!!, HttpUrl.parse("http://host/resource#frag1")!!)) assertFalse(UrlUtils.equals(HttpUrl.parse("http://host/resource")!!, HttpUrl.parse("http://host/resource/")!!)) assertFalse(UrlUtils.equals(HttpUrl.parse("http://host/resource")!!, HttpUrl.parse("http://host:81/resource")!!)) Loading