From 3cba163c3badda89e62b60214d8ae7b66058323c Mon Sep 17 00:00:00 2001 From: R Hirner Date: Thu, 1 Jan 2015 18:53:03 +0100 Subject: [PATCH] Handle absolute URIs in resource detection (+ tests) --- .../syncadapter/DavResourceFinderTest.java | 20 +++++++--- .../davdroid/webdav/WebDavResourceTest.java | 40 +++++++++++++------ .../robohydra/plugins/dav/index.js | 15 ++++++- .../davdroid/resource/DavResourceFinder.java | 26 ++++++------ .../bitfire/davdroid/resource/ServerInfo.java | 6 ++- .../davdroid/webdav/WebDavResource.java | 18 +++++---- 6 files changed, 85 insertions(+), 40 deletions(-) diff --git a/app/src/androidTest/java/at/bitfire/davdroid/syncadapter/DavResourceFinderTest.java b/app/src/androidTest/java/at/bitfire/davdroid/syncadapter/DavResourceFinderTest.java index 373e586c..8e70eb7b 100644 --- a/app/src/androidTest/java/at/bitfire/davdroid/syncadapter/DavResourceFinderTest.java +++ b/app/src/androidTest/java/at/bitfire/davdroid/syncadapter/DavResourceFinderTest.java @@ -30,15 +30,23 @@ public class DavResourceFinderTest extends InstrumentationTestCase { ServerInfo info = new ServerInfo(new URI(TestConstants.ROBOHYDRA_BASE), "test", "test", true); finder.findResources(info); - // CardDAV + /*** CardDAV ***/ assertTrue(info.isCardDAV()); List collections = info.getAddressBooks(); - assertEquals(1, collections.size()); + // two address books + assertEquals(2, collections.size()); + // first one + ResourceInfo collection = collections.get(0); + assertEquals(TestConstants.roboHydra.resolve("/dav/addressbooks/test/default-v4.vcf/").toString(), collection.getURL()); + assertEquals("Default Address Book", collection.getDescription()); + assertEquals(VCardVersion.V4_0, collection.getVCardVersion()); + // second one + collection = collections.get(1); + assertEquals("https://my.server/absolute:uri/my-address-book/", collection.getURL()); + assertEquals("Absolute URI VCard3 Book", collection.getDescription()); + assertEquals(VCardVersion.V3_0, collection.getVCardVersion()); - assertEquals("Default Address Book", collections.get(0).getDescription()); - assertEquals(VCardVersion.V4_0, collections.get(0).getVCardVersion()); - - // CalDAV + /*** CalDAV ***/ assertTrue(info.isCalDAV()); collections = info.getCalendars(); assertEquals(2, collections.size()); diff --git a/app/src/androidTest/java/at/bitfire/davdroid/webdav/WebDavResourceTest.java b/app/src/androidTest/java/at/bitfire/davdroid/webdav/WebDavResourceTest.java index e2137ada..6ba7871b 100644 --- a/app/src/androidTest/java/at/bitfire/davdroid/webdav/WebDavResourceTest.java +++ b/app/src/androidTest/java/at/bitfire/davdroid/webdav/WebDavResourceTest.java @@ -14,6 +14,7 @@ import java.util.List; import javax.net.ssl.SSLPeerUnverifiedException; +import ezvcard.VCardVersion; import lombok.Cleanup; import org.apache.commons.io.IOUtils; @@ -75,7 +76,7 @@ public class WebDavResourceTest extends InstrumentationTestCase { public void testPropfindCurrentUserPrincipal() throws Exception { davCollection.propfind(HttpPropfind.Mode.CURRENT_USER_PRINCIPAL); - assertEquals("/dav/principals/users/test", davCollection.getCurrentUserPrincipal()); + assertEquals(new URI("/dav/principals/users/test"), davCollection.getCurrentUserPrincipal()); WebDavResource simpleFile = new WebDavResource(davAssets, "test.random"); try { @@ -90,21 +91,36 @@ public class WebDavResourceTest extends InstrumentationTestCase { public void testPropfindHomeSets() throws Exception { WebDavResource dav = new WebDavResource(davCollection, "principals/users/test"); dav.propfind(HttpPropfind.Mode.HOME_SETS); - assertEquals("/dav/addressbooks/test/", dav.getAddressbookHomeSet()); - assertEquals("/dav/calendars/test/", dav.getCalendarHomeSet()); + assertEquals(new URI("/dav/addressbooks/test/"), dav.getAddressbookHomeSet()); + assertEquals(new URI("/dav/calendars/test/"), dav.getCalendarHomeSet()); } public void testPropfindAddressBooks() throws Exception { WebDavResource dav = new WebDavResource(davCollection, "addressbooks/test"); dav.propfind(HttpPropfind.Mode.CARDDAV_COLLECTIONS); - assertEquals(2, dav.getMembers().size()); - for (WebDavResource member : dav.getMembers()) { - if (member.getName().equals("default-v4.vcf")) - assertTrue(member.isAddressBook()); - else - assertFalse(member.isAddressBook()); - assertFalse(member.isCalendar()); - } + + // there should be two address books + assertEquals(3, dav.getMembers().size()); + + // the first one is not an address book and not even a collection (referenced by relative URI) + WebDavResource ab = dav.getMembers().get(0); + assertEquals(TestConstants.roboHydra.resolve("/dav/addressbooks/test/useless-member"), ab.getLocation()); + assertEquals("useless-member", ab.getName()); + assertFalse(ab.isAddressBook()); + + // the second one is a VCard4-capable address book (referenced by relative URI) + ab = dav.getMembers().get(1); + assertEquals(TestConstants.roboHydra.resolve("/dav/addressbooks/test/default-v4.vcf/"), ab.getLocation()); + assertEquals("default-v4.vcf", ab.getName()); + assertTrue(ab.isAddressBook()); + assertEquals(VCardVersion.V4_0, ab.getVCardVersion()); + + // the third one is a (non-VCard4-capable) address book (referenced by an absolute URI) + ab = dav.getMembers().get(2); + assertEquals(new URI("https://my.server/absolute:uri/my-address-book/"), ab.getLocation()); + assertEquals("my-address-book", ab.getName()); + assertTrue(ab.isAddressBook()); + assertNull(ab.getVCardVersion()); } public void testPropfindCalendars() throws Exception { @@ -134,7 +150,7 @@ public class WebDavResourceTest extends InstrumentationTestCase { for (String path : requestPaths) { WebDavResource davSlash = new WebDavResource(davCollection, path); davSlash.propfind(Mode.CARDDAV_COLLECTIONS); - assertEquals(principalOK, davSlash.getCurrentUserPrincipal()); + assertEquals(new URI(principalOK), davSlash.getCurrentUserPrincipal()); } } diff --git a/app/src/androidTest/robohydra/plugins/dav/index.js b/app/src/androidTest/robohydra/plugins/dav/index.js index 3cc518e8..596c48e4 100644 --- a/app/src/androidTest/robohydra/plugins/dav/index.js +++ b/app/src/androidTest/robohydra/plugins/dav/index.js @@ -110,7 +110,7 @@ exports.getBodyParts = function(conf) { \ \ \ - /dav/addressbooks/test/default-v4.vcf/\ + /dav/addressbooks/test/default-v4.vcf\ \ \ \ @@ -126,6 +126,19 @@ exports.getBodyParts = function(conf) { HTTP/1.1 200 OK\ \ \ + \ + https://my.server/absolute:uri/my-address-book\ + \ + \ + \ + \ + \ + \ + Absolute URI VCard3 Book\ + \ + HTTP/1.1 200 OK\ + \ + \ \ '); } diff --git a/app/src/main/java/at/bitfire/davdroid/resource/DavResourceFinder.java b/app/src/main/java/at/bitfire/davdroid/resource/DavResourceFinder.java index 6d16e6f3..5d34133e 100644 --- a/app/src/main/java/at/bitfire/davdroid/resource/DavResourceFinder.java +++ b/app/src/main/java/at/bitfire/davdroid/resource/DavResourceFinder.java @@ -63,15 +63,15 @@ public class DavResourceFinder implements Closeable { serverInfo.setCardDAV(true); principal.propfind(Mode.HOME_SETS); - String pathAddressBooks = principal.getAddressbookHomeSet(); - if (pathAddressBooks != null) { - Log.i(TAG, "Found address book home set: " + pathAddressBooks); + URI uriAddressBookHomeSet = principal.getAddressbookHomeSet(); + if (uriAddressBookHomeSet != null) { + Log.i(TAG, "Found address book home set: " + uriAddressBookHomeSet); - WebDavResource homeSetAddressBooks = new WebDavResource(principal, pathAddressBooks); + WebDavResource homeSetAddressBooks = new WebDavResource(principal, uriAddressBookHomeSet); if (checkHomesetCapabilities(homeSetAddressBooks, "addressbook")) { homeSetAddressBooks.propfind(Mode.CARDDAV_COLLECTIONS); - List addressBooks = new LinkedList(); + List addressBooks = new LinkedList<>(); if (homeSetAddressBooks.getMembers() != null) for (WebDavResource resource : homeSetAddressBooks.getMembers()) if (resource.isAddressBook()) { @@ -103,15 +103,15 @@ public class DavResourceFinder implements Closeable { serverInfo.setCalDAV(true); principal.propfind(Mode.HOME_SETS); - String pathCalendars = principal.getCalendarHomeSet(); - if (pathCalendars != null) { - Log.i(TAG, "Found calendar home set: " + pathCalendars); + URI uriCalendarHomeSet = principal.getCalendarHomeSet(); + if (uriCalendarHomeSet != null) { + Log.i(TAG, "Found calendar home set: " + uriCalendarHomeSet); - WebDavResource homeSetCalendars = new WebDavResource(principal, pathCalendars); + WebDavResource homeSetCalendars = new WebDavResource(principal, uriCalendarHomeSet); if (checkHomesetCapabilities(homeSetCalendars, "calendar-access")) { homeSetCalendars.propfind(Mode.CALDAV_COLLECTIONS); - List calendars = new LinkedList(); + List calendars = new LinkedList<>(); if (homeSetCalendars.getMembers() != null) for (WebDavResource resource : homeSetCalendars.getMembers()) if (resource.isCalendar()) { @@ -159,7 +159,7 @@ public class DavResourceFinder implements Closeable { */ public URI getInitialContextURL(ServerInfo serverInfo, String serviceName) throws URISyntaxException, MalformedURLException { String scheme = null, - domain = null; + domain; int port = -1; String path = "/"; @@ -227,9 +227,9 @@ public class DavResourceFinder implements Closeable { * Detects the current-user-principal for a given WebDavResource. At first, /.well-known/ is tried. Only * if no current-user-principal can be detected for the .well-known location, the given location of the resource * is tried. - * @param resource Location that will be queried + * @param serverInfo Location that will be queried * @param serviceName Well-known service name ("carddav", "caldav") - * @return WebDavResource of current-user-principal for the given service, or null if it can't be found + * @return WebDavResource of current-user-principal for the given service, or null if it can't be found * * TODO: If a TXT record is given, always use it instead of trying .well-known first */ diff --git a/app/src/main/java/at/bitfire/davdroid/resource/ServerInfo.java b/app/src/main/java/at/bitfire/davdroid/resource/ServerInfo.java index 14f5b6f7..62da45a1 100644 --- a/app/src/main/java/at/bitfire/davdroid/resource/ServerInfo.java +++ b/app/src/main/java/at/bitfire/davdroid/resource/ServerInfo.java @@ -59,7 +59,11 @@ public class ServerInfo implements Serializable { final Type type; final boolean readOnly; - final String URL, title, description, color; + + final String URL, // absolute URL of resource + title, + description, + color; VCardVersion vCardVersion; diff --git a/app/src/main/java/at/bitfire/davdroid/webdav/WebDavResource.java b/app/src/main/java/at/bitfire/davdroid/webdav/WebDavResource.java index f2c31457..84d0a875 100644 --- a/app/src/main/java/at/bitfire/davdroid/webdav/WebDavResource.java +++ b/app/src/main/java/at/bitfire/davdroid/webdav/WebDavResource.java @@ -25,6 +25,7 @@ import org.apache.http.client.methods.HttpGetHC4; import org.apache.http.client.methods.HttpOptionsHC4; import org.apache.http.client.methods.HttpPutHC4; import org.apache.http.client.protocol.HttpClientContext; +import org.apache.http.client.utils.URIUtilsHC4; import org.apache.http.entity.ByteArrayEntityHC4; import org.apache.http.impl.auth.BasicSchemeHC4; import org.apache.http.impl.client.BasicAuthCache; @@ -129,7 +130,7 @@ public class WebDavResource { location = parent.location; } - protected WebDavResource(WebDavResource parent, URI url) { + public WebDavResource(WebDavResource parent, URI url) { this(parent); location = parent.location.resolve(url); } @@ -191,16 +192,19 @@ public class WebDavResource { /* property methods */ - public String getCurrentUserPrincipal() { - return properties.get(Property.CURRENT_USER_PRINCIPAL); + public URI getCurrentUserPrincipal() throws URISyntaxException { + String principal = properties.get(Property.CURRENT_USER_PRINCIPAL); + return principal != null ? URIUtils.parseURI(principal, false) : null; } - public String getAddressbookHomeSet() { - return properties.get(Property.ADDRESSBOOK_HOMESET); + public URI getAddressbookHomeSet() throws URISyntaxException { + String homeset = properties.get(Property.ADDRESSBOOK_HOMESET); + return homeset != null ? URIUtils.parseURI(homeset, false) : null; } - public String getCalendarHomeSet() { - return properties.get(Property.CALENDAR_HOMESET); + public URI getCalendarHomeSet() throws URISyntaxException { + String homeset = properties.get(Property.CALENDAR_HOMESET); + return homeset != null ? URIUtils.parseURI(homeset, false) : null; } public String getContentType() {