Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Don't remove port from URI of nextcloud login intent #1242

Merged
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
package at.bitfire.davdroid.ui.setup

import android.content.Intent
import android.net.Uri
import org.junit.Assert.assertEquals
import org.junit.Test

class LoginActivityTest {

@Test
fun loginInfoFromIntent() {
val intent = Intent().apply {
data = Uri.parse("https://example.com/nextcloud")
putExtra(LoginActivity.EXTRA_USERNAME, "user")
putExtra(LoginActivity.EXTRA_PASSWORD, "password")
}
val loginInfo = LoginActivity.loginInfoFromIntent(intent)
assertEquals("https://example.com/nextcloud", loginInfo.baseUri.toString())
assertEquals("user", loginInfo.credentials!!.username)
assertEquals("password", loginInfo.credentials.password)
}

@Test
fun loginInfoFromIntent_withPort() {
val intent = Intent().apply {
data = Uri.parse("https://example.com:444/nextcloud")
putExtra(LoginActivity.EXTRA_USERNAME, "user")
putExtra(LoginActivity.EXTRA_PASSWORD, "password")
}
val loginInfo = LoginActivity.loginInfoFromIntent(intent)
assertEquals("https://example.com:444/nextcloud", loginInfo.baseUri.toString())
assertEquals("user", loginInfo.credentials!!.username)
assertEquals("password", loginInfo.credentials.password)
}

@Test
fun loginInfoFromIntent_implicit() {
val intent = Intent(Intent.ACTION_VIEW, Uri.parse("davx5://user:[email protected]/path"))
val loginInfo = LoginActivity.loginInfoFromIntent(intent)
assertEquals("https://example.com/path", loginInfo.baseUri.toString())
assertEquals("user", loginInfo.credentials!!.username)
assertEquals("password", loginInfo.credentials.password)
}

@Test
fun loginInfoFromIntent_implicit_withPort() {
val intent = Intent(Intent.ACTION_VIEW, Uri.parse("davx5://user:[email protected]:0/path"))
val loginInfo = LoginActivity.loginInfoFromIntent(intent)
assertEquals("https://example.com:0/path", loginInfo.baseUri.toString())
assertEquals("user", loginInfo.credentials!!.username)
assertEquals("password", loginInfo.credentials.password)
}
}
48 changes: 27 additions & 21 deletions app/src/main/kotlin/at/bitfire/davdroid/ui/setup/LoginActivity.kt
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,15 @@
package at.bitfire.davdroid.ui.setup

import android.content.Intent
import android.net.Uri
import android.os.Bundle
import androidx.activity.compose.setContent
import androidx.appcompat.app.AppCompatActivity
import at.bitfire.davdroid.db.Credentials
import at.bitfire.davdroid.ui.account.AccountActivity
import dagger.hilt.android.AndroidEntryPoint
import java.net.URI
import java.net.URISyntaxException
import java.util.logging.Logger
import javax.inject.Inject

/**
Expand Down Expand Up @@ -59,28 +60,33 @@ class LoginActivity @Inject constructor(): AppCompatActivity() {
var givenPassword: String? = null

// extract URI and optionally username/password from Intent data
val logger = Logger.getGlobal()
intent.data?.normalizeScheme()?.let { uri ->
// We've got initial login data from the Intent.
// We can't use uri.buildUpon() because this keeps the user info (it's readable, but not writable).
val realScheme = when (uri.scheme) {
"caldav", "carddav" -> "http"
"caldavs", "carddavs", "davx5" -> "https"
"http", "https" -> uri.scheme
else -> null
}
if (realScheme != null) {
val realUri = Uri.Builder()
.scheme(realScheme)
.authority(uri.host)
rfc2822 marked this conversation as resolved.
Show resolved Hide resolved
.path(uri.path)
.query(uri.query)
givenUri = realUri.build().toString()

// extract user info
uri.userInfo?.split(':')?.let { userInfo ->
givenUsername = userInfo.getOrNull(0)
givenPassword = userInfo.getOrNull(1)
try {
// replace caldav[s]:// and carddav[s]:// with http[s]://
val realScheme = when (uri.scheme) {
"caldav", "carddav" -> "http"
"caldavs", "carddavs", "davx5" -> "https"
"http", "https" -> uri.scheme
else -> null
}
if (realScheme != null) {
// extract user info
uri.userInfo?.split(':')?.let { userInfo ->
givenUsername = userInfo.getOrNull(0)
givenPassword = userInfo.getOrNull(1)
}

// use real scheme, drop user info and fragment
givenUri = try {
URI(realScheme, null, uri.host, uri.port, uri.path, uri.query, null).toString()
} catch (_: URISyntaxException) {
logger.warning("Couldn't construct URI from login Intent data: $uri")
null
}
}
} catch (_: URISyntaxException) {
logger.warning("Got invalid URI from login Intent: $uri")
}
}

Expand Down
Loading