...
 
Commits (3)
......@@ -9,7 +9,7 @@ buildscript {
}
dependencies {
classpath 'com.android.tools.build:gradle:3.1.1'
classpath 'com.android.tools.build:gradle:3.1.2'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
classpath "org.jetbrains.dokka:dokka-android-gradle-plugin:${dokka_version}"
}
......@@ -60,7 +60,7 @@ dependencies {
compile "com.squareup.okhttp3:okhttp:$okhttp_version"
androidTestCompile "com.squareup.okhttp3:mockwebserver:$okhttp_version"
androidTestCompile 'com.android.support.test:runner:1.0.1'
androidTestCompile 'com.android.support.test:runner:1.0.2'
testCompile "org.jetbrains.kotlin:kotlin-test-junit:$kotlin_version"
testCompile 'junit:junit:4.12'
......
......@@ -8,14 +8,14 @@
package at.bitfire.dav4android
import at.bitfire.dav4android.exception.HttpException
import at.bitfire.dav4android.property.GetETag
import at.bitfire.dav4android.property.SyncToken
import okhttp3.OkHttpClient
import okhttp3.mockwebserver.MockResponse
import okhttp3.mockwebserver.MockWebServer
import org.junit.After
import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
import org.junit.Assert.*
import org.junit.Before
import org.junit.Test
......@@ -34,9 +34,93 @@ class DavCollectionTest {
@After
fun stopServer() = mockServer.shutdown()
/**
* Test sample response for an initial sync-collection report from RFC 6578 3.8.
*/
@Test
fun testInitialSyncCollectionReport() {
val url = sampleUrl()
val collection = DavCollection(httpClient, url)
mockServer.enqueue(MockResponse()
.setResponseCode(207)
.setHeader("Content-Type", "text/xml; charset=\"utf-8\"")
.setBody("<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n" +
" <D:multistatus xmlns:D=\"DAV:\">\n" +
" <D:response>\n" +
" <D:href\n" +
" >${sampleUrl()}test.doc</D:href>\n" +
" <D:propstat>\n" +
" <D:prop>\n" +
" <D:getetag>\"00001-abcd1\"</D:getetag>\n" +
" <R:bigbox xmlns:R=\"urn:ns.example.com:boxschema\">\n" +
" <R:BoxType>Box type A</R:BoxType>\n" +
" </R:bigbox>\n" +
" </D:prop>\n" +
" <D:status>HTTP/1.1 200 OK</D:status>\n" +
" </D:propstat>\n" +
" </D:response>\n" +
" <D:response>\n" +
" <D:href\n" +
" >${sampleUrl()}vcard.vcf</D:href>\n" +
" <D:propstat>\n" +
" <D:prop>\n" +
" <D:getetag>\"00002-abcd1\"</D:getetag>\n" +
" </D:prop>\n" +
" <D:status>HTTP/1.1 200 OK</D:status>\n" +
" </D:propstat>\n" +
" <D:propstat>\n" +
" <D:prop>\n" +
" <R:bigbox xmlns:R=\"urn:ns.example.com:boxschema\"/>\n" +
" </D:prop>\n" +
" <D:status>HTTP/1.1 404 Not Found</D:status>\n" +
" </D:propstat>\n" +
" </D:response>\n" +
" <D:response>\n" +
" <D:href\n" +
" >${sampleUrl()}calendar.ics</D:href>\n" +
" <D:propstat>\n" +
" <D:prop>\n" +
" <D:getetag>\"00003-abcd1\"</D:getetag>\n" +
" </D:prop>\n" +
" <D:status>HTTP/1.1 200 OK</D:status>\n" +
" </D:propstat>\n" +
" <D:propstat>\n" +
" <D:prop>\n" +
" <R:bigbox xmlns:R=\"urn:ns.example.com:boxschema\"/>\n" +
" </D:prop>\n" +
" <D:status>HTTP/1.1 404 Not Found</D:status>\n" +
" </D:propstat>\n" +
" </D:response>\n" +
" <D:sync-token>http://example.com/ns/sync/1234</D:sync-token>\n" +
" </D:multistatus>")
)
collection.reportChanges(null, false, null, GetETag.NAME)
assertEquals(3, collection.members.size)
val members = collection.members.iterator()
val member1 = members.next()
assertEquals(sampleUrl().newBuilder().addPathSegment("test.doc").build(), member1.location)
assertEquals("00001-abcd1", member1.properties[GetETag::class.java]!!.eTag)
val member2 = members.next()
assertEquals(sampleUrl().newBuilder().addPathSegment("vcard.vcf").build(), member2.location)
assertEquals("00002-abcd1", member2.properties[GetETag::class.java]!!.eTag)
val member3 = members.next()
assertEquals(sampleUrl().newBuilder().addPathSegment("calendar.ics").build(), member3.location)
assertEquals("00003-abcd1", member3.properties[GetETag::class.java]!!.eTag)
assertEquals(0, collection.removedMembers.size)
assertFalse(collection.furtherResults)
assertEquals("http://example.com/ns/sync/1234", collection.properties[SyncToken::class.java]!!.token)
}
/**
* Test sample response for an initial sync-collection report with truncation from RFC 6578 3.10.
*/
@Test
fun testSyncCollectionReport() {
fun testInitialSyncCollectionReportWithTruncation() {
val url = sampleUrl()
val collection = DavCollection(httpClient, url)
......@@ -81,11 +165,11 @@ class DavCollectionTest {
val members = collection.members.iterator()
val member1 = members.next()
assertEquals(sampleUrl().newBuilder().addPathSegment("test.doc").build(), member1.location)
assertEquals("00001-abcd1", member1.properties.get(GetETag::class.java)!!.eTag)
assertEquals("00001-abcd1", member1.properties[GetETag::class.java]!!.eTag)
val member2 = members.next()
assertEquals(sampleUrl().newBuilder().addPathSegment("vcard.vcf").build(), member2.location)
assertEquals("00002-abcd1", member2.properties.get(GetETag::class.java)!!.eTag)
assertEquals("00002-abcd1", member2.properties[GetETag::class.java]!!.eTag)
assertEquals(1, collection.removedMembers.size)
val removedMember = collection.removedMembers.first()
......@@ -95,4 +179,31 @@ class DavCollectionTest {
assertEquals("http://example.com/ns/sync/1233", collection.properties[SyncToken::class.java]!!.token)
}
/**
* Test sample response for a sync-collection report with unsupported limit from RFC 6578 3.12.
*/
@Test
fun testSyncCollectionReportWithUnsupportedLimit() {
val url = sampleUrl()
val collection = DavCollection(httpClient, url)
mockServer.enqueue(MockResponse()
.setResponseCode(507)
.setHeader("Content-Type", "text/xml; charset=\"utf-8\"")
.setBody("<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n" +
" <D:error xmlns:D=\"DAV:\">\n" +
" <D:number-of-matches-within-limits/>\n" +
" </D:error>")
)
try {
collection.reportChanges("http://example.com/ns/sync/1232", false, 100, GetETag.NAME)
} catch (e: HttpException) {
assertEquals(507, e.status)
return
}
fail()
}
}
\ No newline at end of file
......@@ -36,8 +36,8 @@ class BasicDigestAuthHandler(
): Authenticator, Interceptor {
companion object {
private val HEADER_AUTHENTICATE = "WWW-Authenticate"
private val HEADER_AUTHORIZATION = "Authorization"
private const val HEADER_AUTHENTICATE = "WWW-Authenticate"
private const val HEADER_AUTHORIZATION = "Authorization"
// cached digest parameters
var clientNonce = h(UUID.randomUUID().toString())
......
......@@ -9,9 +9,8 @@
package at.bitfire.dav4android
import okhttp3.Response
import java.util.LinkedList
import java.util.*
import java.util.regex.Pattern
import kotlin.collections.HashMap
object HttpUtils {
......@@ -142,7 +141,7 @@ object HttpUtils {
override fun toString(): String {
val s = StringBuilder()
s.append(name + "(")
s.append("$name(")
for ((name, value) in params)
s.append("$name=[$value],")
s.append(")")
......
......@@ -42,7 +42,7 @@ class PropertyCollection {
}
}
fun getMap(): Map<Property.Name, Property?> =
private fun getMap(): Map<Property.Name, Property?> =
if (!properties.isInitialized())
mapOf()
else
......
......@@ -10,7 +10,6 @@ package at.bitfire.dav4android
import org.xmlpull.v1.XmlPullParser
import org.xmlpull.v1.XmlPullParserException
import java.io.IOException
interface PropertyFactory {
......
......@@ -22,12 +22,12 @@ object UrlUtils {
val uri1 = url1.uri()
val uri2 = url2.uri()
try {
return try {
val decoded1 = URI(uri1.scheme, uri1.schemeSpecificPart, uri1.fragment)
val decoded2 = URI (uri2.scheme, uri2.schemeSpecificPart, uri2.fragment)
return decoded1 == decoded2
decoded1 == decoded2
} catch (e: URISyntaxException) {
return false
false
}
}
......
......@@ -24,7 +24,7 @@ data class CalendarColor(
@JvmField
val NAME = Property.Name(XmlUtils.NS_APPLE_ICAL, "calendar-color")
val PATTERN = Pattern.compile("#?(\\p{XDigit}{6})(\\p{XDigit}{2})?")!!
private val PATTERN = Pattern.compile("#?(\\p{XDigit}{6})(\\p{XDigit}{2})?")!!
/**
* Converts a WebDAV color from one of these formats:
......
......@@ -37,8 +37,8 @@ data class SupportedCalendarComponentSet(
val depth = parser.depth
var eventType = parser.eventType
while (!(eventType == XmlPullParser.END_TAG && parser.getDepth() == depth)) {
if (eventType == XmlPullParser.START_TAG && parser.getDepth() == depth + 1 && parser.namespace == XmlUtils.NS_CALDAV) {
while (!(eventType == XmlPullParser.END_TAG && parser.depth == depth)) {
if (eventType == XmlPullParser.START_TAG && parser.depth == depth + 1 && parser.namespace == XmlUtils.NS_CALDAV) {
when (parser.name) {
"allcomp" -> {
components.supportsEvents = true
......
......@@ -16,9 +16,10 @@ import org.xmlpull.v1.XmlPullParser
class SupportedReportSet: Property {
companion object {
@JvmField
val NAME = Property.Name(XmlUtils.NS_WEBDAV, "supported-report-set")
val SYNC_COLLECTION = "DAV:sync-collection" // collection synchronization (RFC 6578)
const val SYNC_COLLECTION = "DAV:sync-collection" // collection synchronization (RFC 6578)
}
val reports = mutableSetOf<String>()
......