diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index b22c4e28..88fa3895 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -1,7 +1,7 @@ addressBooks = new LinkedList<>(); - if (homeSetAddressBooks.getMembers() != null) - for (WebDavResource resource : homeSetAddressBooks.getMembers()) - if (resource.isAddressBook()) { - Log.i(TAG, "Found address book: " + resource.getLocation().getPath()); - ServerInfo.ResourceInfo info = new ServerInfo.ResourceInfo( - ServerInfo.ResourceInfo.Type.ADDRESS_BOOK, - resource.isReadOnly(), - resource.getLocation().toString(), - resource.getDisplayName(), - resource.getDescription(), resource.getColor() - ); - - VCardVersion version = resource.getVCardVersion(); - if (version == null) - version = VCardVersion.V3_0; // VCard 3.0 MUST be supported - info.setVCardVersion(version); - - addressBooks.add(info); - } - serverInfo.setAddressBooks(addressBooks); - } else - Log.w(TAG, "Found address-book home set, but it doesn't advertise CardDAV support"); - } + uriAddressBookHomeSet = principal.getAddressbookHomeSet(); + } catch (Exception e) { + Log.i(TAG, "Couldn't find address-book home set", e); } - + if (uriAddressBookHomeSet != null) { + serverInfo.setCardDAV(true); + Log.i(TAG, "Found address-book home set: " + uriAddressBookHomeSet); + + WebDavResource homeSetAddressBooks = new WebDavResource(principal, uriAddressBookHomeSet); + if (checkHomesetCapabilities(homeSetAddressBooks, "addressbook")) { + homeSetAddressBooks.propfind(Mode.CARDDAV_COLLECTIONS); + + List addressBooks = new LinkedList<>(); + if (homeSetAddressBooks.getMembers() != null) + for (WebDavResource resource : homeSetAddressBooks.getMembers()) + if (resource.isAddressBook()) { + Log.i(TAG, "Found address book: " + resource.getLocation().getPath()); + ServerInfo.ResourceInfo info = new ServerInfo.ResourceInfo( + ServerInfo.ResourceInfo.Type.ADDRESS_BOOK, + resource.isReadOnly(), + resource.getLocation().toString(), + resource.getDisplayName(), + resource.getDescription(), resource.getColor() + ); + + VCardVersion version = resource.getVCardVersion(); + if (version == null) + version = VCardVersion.V3_0; // VCard 3.0 MUST be supported + info.setVCardVersion(version); + + addressBooks.add(info); + } + serverInfo.setAddressBooks(addressBooks); + } else + Log.w(TAG, "Found address-book home set, but it doesn't advertise CardDAV support"); + } + // CalDAV principal = getCurrentUserPrincipal(serverInfo, "caldav"); - if (principal != null) { - serverInfo.setCalDAV(true); - + URI uriCalendarHomeSet = null; + try { principal.propfind(Mode.HOME_SETS); - URI uriCalendarHomeSet = principal.getCalendarHomeSet(); - if (uriCalendarHomeSet != null) { - Log.i(TAG, "Found calendar home set: " + uriCalendarHomeSet); - - WebDavResource homeSetCalendars = new WebDavResource(principal, uriCalendarHomeSet); - if (checkHomesetCapabilities(homeSetCalendars, "calendar-access")) { - homeSetCalendars.propfind(Mode.CALDAV_COLLECTIONS); - - List calendars = new LinkedList<>(); - if (homeSetCalendars.getMembers() != null) - for (WebDavResource resource : homeSetCalendars.getMembers()) - if (resource.isCalendar()) { - Log.i(TAG, "Found calendar: " + resource.getLocation().getPath()); - if (resource.getSupportedComponents() != null) { - // CALDAV:supported-calendar-component-set available - boolean supportsEvents = false; - for (String supportedComponent : resource.getSupportedComponents()) - if (supportedComponent.equalsIgnoreCase("VEVENT")) - supportsEvents = true; - if (!supportsEvents) { // ignore collections without VEVENT support - Log.i(TAG, "Ignoring this calendar because of missing VEVENT support"); - continue; - } - } - ServerInfo.ResourceInfo info = new ServerInfo.ResourceInfo( - ServerInfo.ResourceInfo.Type.CALENDAR, - resource.isReadOnly(), - resource.getLocation().toString(), - resource.getDisplayName(), - resource.getDescription(), resource.getColor() - ); - info.setTimezone(resource.getTimezone()); - calendars.add(info); - } - serverInfo.setCalendars(calendars); - } else - Log.w(TAG, "Found calendar home set, but it doesn't advertise CalDAV support"); - } + uriCalendarHomeSet = principal.getCalendarHomeSet(); + } catch(Exception e) { + Log.i(TAG, "Couldn't find calendar home set", e); } - + if (uriCalendarHomeSet != null) { + serverInfo.setCalDAV(true); + Log.i(TAG, "Found calendar home set: " + uriCalendarHomeSet); + + WebDavResource homeSetCalendars = new WebDavResource(principal, uriCalendarHomeSet); + if (checkHomesetCapabilities(homeSetCalendars, "calendar-access")) { + homeSetCalendars.propfind(Mode.CALDAV_COLLECTIONS); + + List calendars = new LinkedList<>(); + if (homeSetCalendars.getMembers() != null) + for (WebDavResource resource : homeSetCalendars.getMembers()) + if (resource.isCalendar()) { + Log.i(TAG, "Found calendar: " + resource.getLocation().getPath()); + if (resource.getSupportedComponents() != null) { + // CALDAV:supported-calendar-component-set available + boolean supportsEvents = false; + for (String supportedComponent : resource.getSupportedComponents()) + if (supportedComponent.equalsIgnoreCase("VEVENT")) + supportsEvents = true; + if (!supportsEvents) { // ignore collections without VEVENT support + Log.i(TAG, "Ignoring this calendar because of missing VEVENT support"); + continue; + } + } + ServerInfo.ResourceInfo info = new ServerInfo.ResourceInfo( + ServerInfo.ResourceInfo.Type.CALENDAR, + resource.isReadOnly(), + resource.getLocation().toString(), + resource.getDisplayName(), + resource.getDescription(), resource.getColor() + ); + info.setTimezone(resource.getTimezone()); + calendars.add(info); + } + serverInfo.setCalendars(calendars); + } else + Log.w(TAG, "Found calendar home set, but it doesn't advertise CalDAV support"); + } + if (!serverInfo.isCalDAV() && !serverInfo.isCardDAV()) throw new DavIncapableException(context.getString(R.string.setup_neither_caldav_nor_carddav)); @@ -251,11 +255,13 @@ public class DavResourceFinder implements Closeable { Log.w(TAG, "Not authorized for well-known " + serviceName + " service detection", e); throw e; } catch (URISyntaxException e) { - Log.w(TAG, "Well-known" + serviceName + " service detection failed because of invalid URIs", e); + Log.e(TAG, "Well-known" + serviceName + " service detection failed because of invalid URIs", e); } catch (HttpException e) { Log.d(TAG, "Well-known " + serviceName + " service detection failed with HTTP error", e); } catch (DavException e) { Log.w(TAG, "Well-known " + serviceName + " service detection failed with unexpected DAV response", e); + } catch (IOException e) { + Log.e(TAG, "Well-known " + serviceName + " service detection failed with I/O error", e); } // fall back to user-given initial context path @@ -271,7 +277,9 @@ public class DavResourceFinder implements Closeable { } catch (DavException e) { Log.e(TAG, "DAV error when querying principal", e); } - Log.i(TAG, "Couldn't find current-user-principal for service " + serviceName); + + Log.i(TAG, "Couldn't find current-user-principal for service " + serviceName + ", assuming user-given path is principal path"); + return base; } return null; } diff --git a/app/src/main/java/at/bitfire/davdroid/resource/LocalCalendar.java b/app/src/main/java/at/bitfire/davdroid/resource/LocalCalendar.java index 5fc72794..48729ad6 100644 --- a/app/src/main/java/at/bitfire/davdroid/resource/LocalCalendar.java +++ b/app/src/main/java/at/bitfire/davdroid/resource/LocalCalendar.java @@ -51,8 +51,10 @@ import net.fortuna.ical4j.model.property.Status; import org.apache.commons.lang.StringUtils; +import java.net.MalformedURLException; import java.net.URI; import java.net.URISyntaxException; +import java.net.URL; import java.text.ParseException; import java.util.LinkedList; import java.util.List; @@ -119,7 +121,7 @@ public class LocalCalendar extends LocalCollection { color = (color_alpha << 24) | color_rgb; } } - + ContentValues values = new ContentValues(); values.put(Calendars.ACCOUNT_NAME, account.name); values.put(Calendars.ACCOUNT_TYPE, account.type); 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 62da45a1..10e966c2 100644 --- a/app/src/main/java/at/bitfire/davdroid/resource/ServerInfo.java +++ b/app/src/main/java/at/bitfire/davdroid/resource/ServerInfo.java @@ -8,6 +8,7 @@ package at.bitfire.davdroid.resource; import java.io.Serializable; +import java.net.MalformedURLException; import java.net.URI; import java.util.LinkedList; import java.util.List; @@ -68,5 +69,18 @@ public class ServerInfo implements Serializable { VCardVersion vCardVersion; String timezone; + + + public String getTitle() { + if (title == null) { + try { + java.net.URL url = new java.net.URL(URL); + return url.getPath(); + } catch (MalformedURLException e) { + return URL; + } + } else + return title; + } } } diff --git a/app/src/main/java/at/bitfire/davdroid/syncadapter/QueryServerDialogFragment.java b/app/src/main/java/at/bitfire/davdroid/syncadapter/QueryServerDialogFragment.java index 756850ef..83eb19b7 100644 --- a/app/src/main/java/at/bitfire/davdroid/syncadapter/QueryServerDialogFragment.java +++ b/app/src/main/java/at/bitfire/davdroid/syncadapter/QueryServerDialogFragment.java @@ -125,8 +125,6 @@ public class QueryServerDialogFragment extends DialogFragment implements LoaderC // overwrite by more specific message, if possible if (ExceptionUtils.indexOfType(e, CertPathValidatorException.class) != -1) serverInfo.setErrorMessage(getContext().getString(R.string.exception_cert_path_validation, e.getMessage())); - else if (ExceptionUtils.indexOfType(e, SSLPeerUnverifiedException.class) != -1) - serverInfo.setErrorMessage(getContext().getString(R.string.exception_peer_unverified, e.getMessage())); } catch (HttpException e) { Log.e(TAG, "HTTP error while querying server info", e); serverInfo.setErrorMessage(getContext().getString(R.string.exception_http, e.getLocalizedMessage())); diff --git a/app/src/main/java/at/bitfire/davdroid/syncadapter/SelectCollectionsAdapter.java b/app/src/main/java/at/bitfire/davdroid/syncadapter/SelectCollectionsAdapter.java index 8e105757..ae750bb1 100644 --- a/app/src/main/java/at/bitfire/davdroid/syncadapter/SelectCollectionsAdapter.java +++ b/app/src/main/java/at/bitfire/davdroid/syncadapter/SelectCollectionsAdapter.java @@ -30,7 +30,7 @@ public class SelectCollectionsAdapter extends BaseAdapter implements ListAdapter protected Context context; protected ServerInfo serverInfo; - @Getter protected int nAddressBooks, nCalendars; + @Getter protected int nAddressBooks, nAddressbookHeadings, nCalendars, nCalendarHeadings; public SelectCollectionsAdapter(Context context, ServerInfo serverInfo) { @@ -38,7 +38,9 @@ public class SelectCollectionsAdapter extends BaseAdapter implements ListAdapter this.serverInfo = serverInfo; nAddressBooks = (serverInfo.getAddressBooks() == null) ? 0 : serverInfo.getAddressBooks().size(); + nAddressbookHeadings = (nAddressBooks == 0) ? 0 : 1; nCalendars = (serverInfo.getCalendars() == null) ? 0 : serverInfo.getCalendars().size(); + nCalendarHeadings = (nCalendars == 0) ? 0 : 1; } @@ -46,15 +48,17 @@ public class SelectCollectionsAdapter extends BaseAdapter implements ListAdapter @Override public int getCount() { - return nAddressBooks + nCalendars + 2; + return nAddressbookHeadings + nAddressBooks + nCalendarHeadings + nCalendars; } @Override public Object getItem(int position) { - if (position > 0 && position <= nAddressBooks) - return serverInfo.getAddressBooks().get(position - 1); - else if (position > nAddressBooks + 1) - return serverInfo.getCalendars().get(position - nAddressBooks - 2); + if (position >= nAddressbookHeadings && + position < (nAddressbookHeadings + nAddressBooks)) + return serverInfo.getAddressBooks().get(position - nAddressbookHeadings); + else if (position >= (nAddressbookHeadings + nAddressBooks + nCalendarHeadings) && + (position < (nAddressbookHeadings + nAddressBooks + nCalendarHeadings + nCalendars))) + return serverInfo.getCalendars().get(position - (nAddressbookHeadings + nAddressBooks + nCalendarHeadings)); return null; } @@ -78,13 +82,13 @@ public class SelectCollectionsAdapter extends BaseAdapter implements ListAdapter @Override public int getItemViewType(int position) { - if (position == 0) + if ((nAddressbookHeadings != 0) && (position == 0)) return TYPE_ADDRESS_BOOKS_HEADING; - else if (position <= nAddressBooks) + else if ((nAddressbookHeadings != 0) && (position > 0) && (position < nAddressbookHeadings + nAddressBooks)) return TYPE_ADDRESS_BOOKS_ROW; - else if (position == nAddressBooks + 1) + else if ((nCalendars != 0) && (position == nAddressbookHeadings + nAddressBooks)) return TYPE_CALENDARS_HEADING; - else if (position <= nAddressBooks + nCalendars + 1) + else if ((nCalendars != 0) && (position > nAddressbookHeadings + nAddressBooks) && (position < nAddressbookHeadings + nAddressBooks + nCalendarHeadings + nCalendars)) return TYPE_CALENDARS_ROW; else return IGNORE_ITEM_VIEW_TYPE; @@ -133,11 +137,7 @@ public class SelectCollectionsAdapter extends BaseAdapter implements ListAdapter view.setCompoundDrawablePadding(10); // set text - String title = info.getTitle(); - if (title == null) // unnamed collection - title = context.getString((info.getType() == Type.ADDRESS_BOOK) ? - R.string.setup_address_book : R.string.setup_calendar); - title = "" + title + ""; + String title = "" + info.getTitle() + ""; if (info.isReadOnly()) title = title + " (" + context.getString(R.string.setup_read_only) + ")"; diff --git a/app/src/main/java/at/bitfire/davdroid/webdav/HttpReport.java b/app/src/main/java/at/bitfire/davdroid/webdav/HttpReport.java index 65d30839..c9e902d3 100644 --- a/app/src/main/java/at/bitfire/davdroid/webdav/HttpReport.java +++ b/app/src/main/java/at/bitfire/davdroid/webdav/HttpReport.java @@ -30,7 +30,7 @@ public class HttpReport extends HttpEntityEnclosingRequestBaseHC4 { setHeader("Content-Type", "text/xml; charset=UTF-8"); setHeader("Accept", "text/xml"); - setHeader("Depth", "0"); + setHeader("Depth", "1"); try { setEntity(new StringEntity(entity, "UTF-8")); diff --git a/app/src/main/res/values-ca/strings.xml b/app/src/main/res/values-ca/strings.xml index 89157c1d..2c0d7091 100644 --- a/app/src/main/res/values-ca/strings.xml +++ b/app/src/main/res/values-ca/strings.xml @@ -114,9 +114,7 @@ Contactant servidor. Espereu sisuplau. Quines col·leccions s\'han de sincronitzar? Llibretes de contactes - Llibreta de contactes Calendaris - Calendari Seleccioneu com a molt una llibreta de contactes (Polseu de nou per deseleccionar): Seleccioneu els vostres calendaris: diff --git a/app/src/main/res/values-cs/strings.xml b/app/src/main/res/values-cs/strings.xml index 28c00674..52d79bc2 100644 --- a/app/src/main/res/values-cs/strings.xml +++ b/app/src/main/res/values-cs/strings.xml @@ -113,9 +113,7 @@ Probíhá komunikace se serverem. Chvilku strpení… Které sbírky mají být synchronizovány? Adresáře - Adresář Kalendáře - Kalendář Vybrat alespoň jeden adresář (opakovaně tapnout pro odebrání): Vybrat své kalendáře: diff --git a/app/src/main/res/values-de/strings.xml b/app/src/main/res/values-de/strings.xml index c1d1c403..409aac8e 100644 --- a/app/src/main/res/values-de/strings.xml +++ b/app/src/main/res/values-de/strings.xml @@ -10,7 +10,6 @@ HTTP-Fehler: %s Fehlende Server-Unterstützung: %s E/A-Fehler: %s - Zertifikat ist nicht für \"%s\" ausgestellt URI ungültig: %s @@ -110,9 +109,7 @@ Daten werden vom Server abgefragt. Bitte warten… Welche Ordner sollen synchronisiert werden? Adressbücher - Adressbuch Kalender - Kalender Ein oder kein Adressbuch auswählen (nochmal berühren, um abzuwählen): Kalender zur Synchronisation auswählen: diff --git a/app/src/main/res/values-hu/strings.xml b/app/src/main/res/values-hu/strings.xml index f08b9afe..2b1e1a6b 100644 --- a/app/src/main/res/values-hu/strings.xml +++ b/app/src/main/res/values-hu/strings.xml @@ -117,9 +117,7 @@ Kapcsolódás a szerverhez. Egy pillanat… Melyik gyűjtemények legyenek szinkronizálva? Címjegyzékek - Címjegyzék Naptárak - Naptár Egy címjegyzék választható (a kijelölés visszavonása újbóli érintéssel vagy másik tétel kiválasztásával): Naptárak kiválasztása: diff --git a/app/src/main/res/values-sr/strings.xml b/app/src/main/res/values-sr/strings.xml index dfe1b168..1110c9e0 100644 --- a/app/src/main/res/values-sr/strings.xml +++ b/app/src/main/res/values-sr/strings.xml @@ -108,9 +108,7 @@ Шаљем упит серверу. Сачекајте… Које збирке да синхронизујем? Адресари - Адресар Календари - Календар Изаберите један адресар (додирните поново да поништите избор): Изаберите ваше календаре: diff --git a/app/src/main/res/values-zh-rcn/strings.xml b/app/src/main/res/values-zh-rcn/strings.xml index 66d1d568..6f577395 100644 --- a/app/src/main/res/values-zh-rcn/strings.xml +++ b/app/src/main/res/values-zh-rcn/strings.xml @@ -98,9 +98,7 @@ 正在请求,请稍等… 需要同步哪些集合? 通讯录 - 通讯录 日历 - 日历 最多选择一个通讯录:(再次点按可取消选择) 选择日历: diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index de00c57a..7fdc21bf 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -12,7 +12,6 @@ HTTP error: %s Missing capabilities: %s I/O error: %s - Certificate not issued for \"%s\" Invalid URI: %s @@ -114,9 +113,7 @@ Querying server. Please wait… Which collections shall be synchronized? Address books - Address book Calendars - Calendar Select up to one address book (tap again to unselect): Select your calendars: