Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Unverified Commit acf8e4ef authored by Ricki Hirner's avatar Ricki Hirner Committed by GitHub
Browse files

Fix URL parsing to handle URLDecodeException (#149)

* Fix URL parsing to handle URLDecodeException

- Update `toUrlOrNull` method to catch all exceptions
- Add test case for invalid HTTPS URL with decoding issues

* Change catch block from `URLParserException` to `Exception` in `ResponseParser.kt` and `DavResource.kt`
parent 8f96097f
Loading
Loading
Loading
Loading
+1 −2
Original line number Diff line number Diff line
@@ -41,7 +41,6 @@ import io.ktor.http.HttpHeaders
import io.ktor.http.HttpMethod
import io.ktor.http.HttpStatusCode
import io.ktor.http.URLBuilder
import io.ktor.http.URLParserException
import io.ktor.http.Url
import io.ktor.http.contentType
import io.ktor.http.isSecure
@@ -643,7 +642,7 @@ open class DavResource(
                        URLBuilder(location)
                            .takeFrom(newLocation)
                            .build()
                    } catch (e: URLParserException) {
                    } catch (e: Exception) {
                        throw DavException("Redirected to invalid Location", cause = e)
                    }

+12 −2
Original line number Diff line number Diff line
@@ -14,7 +14,6 @@ import io.ktor.client.statement.HttpResponse
import io.ktor.http.BadContentTypeFormatException
import io.ktor.http.ContentType
import io.ktor.http.HttpStatusCode
import io.ktor.http.URLParserException
import io.ktor.http.Url

object KtorHttpUtils {
@@ -118,13 +117,24 @@ fun String?.toContentTypeOrNull(): ContentType? {
    }
}

/**
 * Converts the [String] into a Ktor [Url], if possible.
 *
 * Differs from [io.ktor.http.parseUrl]:
 *
 * - `"relative".toUrlOrNull() == Url("relative")` (without host) but
 * - `parseUrl("relative") == null` (requires host)
 *
 * @return the Ktor [Url], or `null` if the string couldn't be converted
 */
fun String?.toUrlOrNull(): Url? {
    if (this == null)
        return null

    return try {
        Url(this)
    } catch (_: URLParserException) {
    } catch (_: Exception) {
        // parseUrl doesn't catch URLDecodeException, see https://github.com/ktorio/ktor/pull/5231
        null
    }
}
 No newline at end of file
+1 −2
Original line number Diff line number Diff line
@@ -17,7 +17,6 @@ import at.bitfire.dav4jvm.property.webdav.ResourceType
import at.bitfire.dav4jvm.property.webdav.WebDAV
import io.ktor.http.HttpStatusCode
import io.ktor.http.URLBuilder
import io.ktor.http.URLParserException
import io.ktor.http.Url
import io.ktor.http.isSuccess
import io.ktor.http.takeFrom
@@ -168,7 +167,7 @@ class ResponseParser(

        val urlBuilder = try {
            URLBuilder(location).takeFrom(sHref)
        } catch (e: URLParserException) {
        } catch (e: Exception) {
            logger.log(Level.WARNING, "Unresolvable <href> in <response>: $hrefString", e)
            return null
        }
+5 −0
Original line number Diff line number Diff line
@@ -267,6 +267,11 @@ class KtorHttpUtilsTest {
        assertNull("mailto:invalid".toUrlOrNull())
    }

    @Test
    fun `toUrlOrNull with invalid HTTPS URL that can't be decoded`() {
        assertNull("https://example.com/%f".toUrlOrNull())
    }

    @Test
    fun `toUrlOrNull with valid HTTPS URL`() {
        assertEquals(