diff --git a/app/src/main/java/org/tasks/Tasks.kt b/app/src/main/java/org/tasks/Tasks.kt index 21fe1e02c..917af0cf2 100644 --- a/app/src/main/java/org/tasks/Tasks.kt +++ b/app/src/main/java/org/tasks/Tasks.kt @@ -19,6 +19,7 @@ import kotlinx.coroutines.launch import org.tasks.billing.BillingClient import org.tasks.billing.Inventory import org.tasks.caldav.property.Invite +import org.tasks.caldav.property.OCInvite import org.tasks.caldav.property.OCOwnerPrincipal import org.tasks.caldav.property.PropertyUtils.register import org.tasks.caldav.property.ShareAccess @@ -99,6 +100,7 @@ class Tasks : Application(), Configuration.Provider { ShareAccess.Factory(), Invite.Factory(), OCOwnerPrincipal.Factory(), + OCInvite.Factory(), ) } diff --git a/app/src/main/java/org/tasks/caldav/CaldavClient.kt b/app/src/main/java/org/tasks/caldav/CaldavClient.kt index 75dc00ee4..48bc87a1e 100644 --- a/app/src/main/java/org/tasks/caldav/CaldavClient.kt +++ b/app/src/main/java/org/tasks/caldav/CaldavClient.kt @@ -20,6 +20,7 @@ import okhttp3.OkHttpClient import org.tasks.R import org.tasks.Strings.isNullOrEmpty import org.tasks.caldav.property.Invite +import org.tasks.caldav.property.OCInvite import org.tasks.caldav.property.OCOwnerPrincipal import org.tasks.caldav.property.ShareAccess import org.tasks.data.CaldavAccount @@ -222,6 +223,7 @@ open class CaldavClient( ShareAccess.NAME, Invite.NAME, OCOwnerPrincipal.NAME, + OCInvite.NAME, ) private suspend fun DavResource.propfind( diff --git a/app/src/main/java/org/tasks/caldav/property/OCAccess.kt b/app/src/main/java/org/tasks/caldav/property/OCAccess.kt new file mode 100644 index 000000000..9a4c8fa2e --- /dev/null +++ b/app/src/main/java/org/tasks/caldav/property/OCAccess.kt @@ -0,0 +1,41 @@ +package org.tasks.caldav.property + +import at.bitfire.dav4jvm.Property +import at.bitfire.dav4jvm.XmlUtils.propertyName +import org.tasks.BuildConfig +import org.tasks.caldav.property.PropertyUtils.NS_OWNCLOUD +import org.xmlpull.v1.XmlPullParser + +class OCAccess(parser: XmlPullParser) : Property { + + lateinit var access: Property.Name + private set + + init { + val depth = parser.depth + var eventType = parser.eventType + while (!(eventType == XmlPullParser.END_TAG && parser.depth == depth)) { + if (eventType == XmlPullParser.START_TAG && parser.depth == depth + 1) { + when (val name = parser.propertyName()) { + SHARED_OWNER, READ_WRITE, NOT_SHARED, READ -> access = name + } + } + eventType = parser.next() + } + if (BuildConfig.DEBUG && parser.depth != depth) { + error("Assertion failed") + } + } + + override fun toString(): String { + return "OCAccess(access=$access)" + } + + companion object { + val ACCESS = Property.Name(NS_OWNCLOUD, "access") + val SHARED_OWNER = Property.Name(NS_OWNCLOUD, "shared-owner") + val READ_WRITE = Property.Name(NS_OWNCLOUD, "read-write") + val NOT_SHARED = Property.Name(NS_OWNCLOUD, "not-shared") + val READ = Property.Name(NS_OWNCLOUD, "read") + } +} diff --git a/app/src/main/java/org/tasks/caldav/property/OCInvite.kt b/app/src/main/java/org/tasks/caldav/property/OCInvite.kt new file mode 100644 index 000000000..ff5fa9463 --- /dev/null +++ b/app/src/main/java/org/tasks/caldav/property/OCInvite.kt @@ -0,0 +1,39 @@ +package org.tasks.caldav.property + +import at.bitfire.dav4jvm.Property +import at.bitfire.dav4jvm.PropertyFactory +import at.bitfire.dav4jvm.XmlUtils.propertyName +import org.tasks.BuildConfig +import org.tasks.caldav.property.PropertyUtils.NS_OWNCLOUD +import org.xmlpull.v1.XmlPullParser + +data class OCInvite(val users: List): Property { + + companion object { + @JvmField + val NAME = Property.Name(NS_OWNCLOUD, "invite") + + val USER = Property.Name(NS_OWNCLOUD, "user") + } + + class Factory : PropertyFactory { + + override fun getName() = NAME + + override fun create(parser: XmlPullParser): OCInvite { + val depth = parser.depth + var eventType = parser.eventType + val users = ArrayList() + while (!(eventType == XmlPullParser.END_TAG && parser.depth == depth)) { + if (eventType == XmlPullParser.START_TAG && parser.depth == depth + 1) { + if (parser.propertyName() == USER) { + users.add(OCUser(parser)) + } + } + eventType = parser.next() + } + if (BuildConfig.DEBUG && parser.depth != depth) { error("Assertion failed") } + return OCInvite(users) + } + } +} diff --git a/app/src/main/java/org/tasks/caldav/property/OCUser.kt b/app/src/main/java/org/tasks/caldav/property/OCUser.kt new file mode 100644 index 000000000..98fdf3cbd --- /dev/null +++ b/app/src/main/java/org/tasks/caldav/property/OCUser.kt @@ -0,0 +1,49 @@ +package org.tasks.caldav.property + +import at.bitfire.dav4jvm.DavResource +import at.bitfire.dav4jvm.Property +import at.bitfire.dav4jvm.XmlUtils +import at.bitfire.dav4jvm.XmlUtils.propertyName +import org.tasks.BuildConfig +import org.tasks.caldav.property.PropertyUtils.NS_OWNCLOUD +import org.xmlpull.v1.XmlPullParser + +class OCUser(parser: XmlPullParser) { + lateinit var href: String + private set + lateinit var commonName: String + private set + lateinit var access: OCAccess + private set + lateinit var response: Property.Name + private set + + init { + val depth = parser.depth + var eventType = parser.eventType + while (!(eventType == XmlPullParser.END_TAG && parser.depth == depth)) { + if (eventType == XmlPullParser.START_TAG && parser.depth == depth + 1) { + when (val name = parser.propertyName()) { + DavResource.HREF -> + XmlUtils.readText(parser)?.let { href = it } + COMMON_NAME -> + XmlUtils.readText(parser)?.let { commonName = it } + OCAccess.ACCESS -> + access = OCAccess(parser) + INVITE_ACCEPTED, INVITE_DECLINED, INVITE_NORESPONSE, INVITE_INVALID -> + response = name + } + } + eventType = parser.next() + } + if (BuildConfig.DEBUG && parser.depth != depth) { error("Assertion failed") } + } + + companion object { + val COMMON_NAME = Property.Name(NS_OWNCLOUD, "common-name") + val INVITE_ACCEPTED = Property.Name(NS_OWNCLOUD, "invite-accepted") + val INVITE_DECLINED = Property.Name(NS_OWNCLOUD, "invite-declined") + val INVITE_NORESPONSE = Property.Name(NS_OWNCLOUD, "invite-noresponse") + val INVITE_INVALID = Property.Name(NS_OWNCLOUD, "invite-invalid") + } +} \ No newline at end of file diff --git a/app/src/test/java/org/tasks/caldav/property/OCInviteTest.kt b/app/src/test/java/org/tasks/caldav/property/OCInviteTest.kt new file mode 100644 index 000000000..4dec67e0f --- /dev/null +++ b/app/src/test/java/org/tasks/caldav/property/OCInviteTest.kt @@ -0,0 +1,51 @@ +package org.tasks.caldav.property + +import at.bitfire.dav4jvm.PropertyRegistry +import org.junit.Assert.assertEquals +import org.junit.Assert.assertTrue +import org.junit.Before +import org.junit.Test +import org.tasks.caldav.property.PropertyUtils.NS_OWNCLOUD +import org.tasks.caldav.property.TestPropertyUtils.toProperty + +class OCInviteTest { + @Before + fun setUp() { + PropertyRegistry.register(OCInvite.Factory()) + } + + @Test + fun emptyInvite() = + assertTrue("".toProperty("oc" to NS_OWNCLOUD).users.isEmpty()) + + @Test + fun userHref() = + assertEquals("principal:principals/users/testuser", user(SHARED_USER).href) + + @Test + fun commonName() = assertEquals("testuser", user(SHARED_USER).commonName) + + @Test + fun access() = assertEquals(OCAccess.READ_WRITE, user(SHARED_USER).access.access) + + @Test + fun response() = assertEquals(OCUser.INVITE_ACCEPTED, user(SHARED_USER).response) + + private fun user(xml: String) = + xml.toProperty("oc" to NS_OWNCLOUD).users.first() + + companion object { + private val SHARED_USER = """ + + + principal:principals/users/testuser + testuser + + + + + + + """.trimIndent() + } +} \ No newline at end of file diff --git a/app/src/test/java/org/tasks/caldav/property/OCOwnerPrincipalTest.kt b/app/src/test/java/org/tasks/caldav/property/OCOwnerPrincipalTest.kt index e0b3d90a5..6cef69510 100644 --- a/app/src/test/java/org/tasks/caldav/property/OCOwnerPrincipalTest.kt +++ b/app/src/test/java/org/tasks/caldav/property/OCOwnerPrincipalTest.kt @@ -4,6 +4,7 @@ import at.bitfire.dav4jvm.PropertyRegistry import org.junit.Assert.assertEquals import org.junit.Before import org.junit.Test +import org.tasks.caldav.property.PropertyUtils.NS_OWNCLOUD import org.tasks.caldav.property.TestPropertyUtils.toProperty class OCOwnerPrincipalTest { @@ -15,7 +16,7 @@ class OCOwnerPrincipalTest { @Test fun ownerPrincipal() { val owner = "principals/users/test" - .toProperty("oc='${PropertyUtils.NS_OWNCLOUD}'") + .toProperty("oc" to NS_OWNCLOUD) assertEquals("principals/users/test", owner.owner) } diff --git a/app/src/test/java/org/tasks/caldav/property/TestPropertyUtils.kt b/app/src/test/java/org/tasks/caldav/property/TestPropertyUtils.kt index ce8375d4e..54cfe1d89 100644 --- a/app/src/test/java/org/tasks/caldav/property/TestPropertyUtils.kt +++ b/app/src/test/java/org/tasks/caldav/property/TestPropertyUtils.kt @@ -5,8 +5,10 @@ import at.bitfire.dav4jvm.XmlUtils import java.io.StringReader object TestPropertyUtils { - fun String.toProperty(ns: String = """d="DAV:""""): T = - toProperties(ns) + private val DAV = "d" to XmlUtils.NS_WEBDAV + + fun String.toProperty(vararg ns: Pair): T = + toProperties(*ns) .apply { if (this.size != 1) throw IllegalStateException("${this.size} items") } .first() .let { @@ -14,12 +16,15 @@ object TestPropertyUtils { it as T } - fun String.toProperties(ns: String = """d="DAV:""""): List = + fun String.toProperties(vararg ns: Pair): List = XmlUtils.newPullParser() .apply { + val namespaces = ns.toList().plus(DAV).joinToString(" ") { + """xmlns:${it.first}="${it.second}"""" + } setInput( StringReader(""" - + ${this@toProperties} """.trimIndent()