mirror of
https://github.com/etesync/android
synced 2025-05-09 10:28:50 +00:00
various improvements
* fixed annoying bug where all imported contacts where starred * checkbox for preemptive authentication in setup * support for (non-preemptive) Digest authentication * add UID when received entities don't contain one * version bump to 0.3.2-alpha * build.xml for ant/Fdroid
This commit is contained in:
parent
6727987051
commit
9a9d9709c9
@ -1,8 +1,8 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
package="at.bitfire.davdroid"
|
package="at.bitfire.davdroid"
|
||||||
android:versionCode="4"
|
android:versionCode="5"
|
||||||
android:versionName="0.3.1-alpha" >
|
android:versionName="0.3.2-alpha" >
|
||||||
|
|
||||||
<uses-sdk
|
<uses-sdk
|
||||||
android:minSdkVersion="14"
|
android:minSdkVersion="14"
|
||||||
|
92
build.xml
Normal file
92
build.xml
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project name="davdroid" default="help">
|
||||||
|
|
||||||
|
<!-- The local.properties file is created and updated by the 'android' tool.
|
||||||
|
It contains the path to the SDK. It should *NOT* be checked into
|
||||||
|
Version Control Systems. -->
|
||||||
|
<property file="local.properties" />
|
||||||
|
|
||||||
|
<!-- The ant.properties file can be created by you. It is only edited by the
|
||||||
|
'android' tool to add properties to it.
|
||||||
|
This is the place to change some Ant specific build properties.
|
||||||
|
Here are some properties you may want to change/update:
|
||||||
|
|
||||||
|
source.dir
|
||||||
|
The name of the source directory. Default is 'src'.
|
||||||
|
out.dir
|
||||||
|
The name of the output directory. Default is 'bin'.
|
||||||
|
|
||||||
|
For other overridable properties, look at the beginning of the rules
|
||||||
|
files in the SDK, at tools/ant/build.xml
|
||||||
|
|
||||||
|
Properties related to the SDK location or the project target should
|
||||||
|
be updated using the 'android' tool with the 'update' action.
|
||||||
|
|
||||||
|
This file is an integral part of the build system for your
|
||||||
|
application and should be checked into Version Control Systems.
|
||||||
|
|
||||||
|
-->
|
||||||
|
<property file="ant.properties" />
|
||||||
|
|
||||||
|
<!-- if sdk.dir was not set from one of the property file, then
|
||||||
|
get it from the ANDROID_HOME env var.
|
||||||
|
This must be done before we load project.properties since
|
||||||
|
the proguard config can use sdk.dir -->
|
||||||
|
<property environment="env" />
|
||||||
|
<condition property="sdk.dir" value="${env.ANDROID_HOME}">
|
||||||
|
<isset property="env.ANDROID_HOME" />
|
||||||
|
</condition>
|
||||||
|
|
||||||
|
<!-- The project.properties file is created and updated by the 'android'
|
||||||
|
tool, as well as ADT.
|
||||||
|
|
||||||
|
This contains project specific properties such as project target, and library
|
||||||
|
dependencies. Lower level build properties are stored in ant.properties
|
||||||
|
(or in .classpath for Eclipse projects).
|
||||||
|
|
||||||
|
This file is an integral part of the build system for your
|
||||||
|
application and should be checked into Version Control Systems. -->
|
||||||
|
<loadproperties srcFile="project.properties" />
|
||||||
|
|
||||||
|
<!-- quick check on sdk.dir -->
|
||||||
|
<fail
|
||||||
|
message="sdk.dir is missing. Make sure to generate local.properties using 'android update project' or to inject it through the ANDROID_HOME environment variable."
|
||||||
|
unless="sdk.dir"
|
||||||
|
/>
|
||||||
|
|
||||||
|
<!--
|
||||||
|
Import per project custom build rules if present at the root of the project.
|
||||||
|
This is the place to put custom intermediary targets such as:
|
||||||
|
-pre-build
|
||||||
|
-pre-compile
|
||||||
|
-post-compile (This is typically used for code obfuscation.
|
||||||
|
Compiled code location: ${out.classes.absolute.dir}
|
||||||
|
If this is not done in place, override ${out.dex.input.absolute.dir})
|
||||||
|
-post-package
|
||||||
|
-post-build
|
||||||
|
-pre-clean
|
||||||
|
-->
|
||||||
|
<import file="custom_rules.xml" optional="true" />
|
||||||
|
|
||||||
|
<!-- Import the actual build file.
|
||||||
|
|
||||||
|
To customize existing targets, there are two options:
|
||||||
|
- Customize only one target:
|
||||||
|
- copy/paste the target into this file, *before* the
|
||||||
|
<import> task.
|
||||||
|
- customize it to your needs.
|
||||||
|
- Customize the whole content of build.xml
|
||||||
|
- copy/paste the content of the rules files (minus the top node)
|
||||||
|
into this file, replacing the <import> task.
|
||||||
|
- customize to your needs.
|
||||||
|
|
||||||
|
***********************
|
||||||
|
****** IMPORTANT ******
|
||||||
|
***********************
|
||||||
|
In all cases you must update the value of version-tag below to read 'custom' instead of an integer,
|
||||||
|
in order to avoid having your file be overridden by tools such as "android update project"
|
||||||
|
-->
|
||||||
|
<!-- version-tag: 1 -->
|
||||||
|
<import file="${sdk.dir}/tools/ant/build.xml" />
|
||||||
|
|
||||||
|
</project>
|
@ -62,9 +62,16 @@
|
|||||||
android:layout_gravity="fill_horizontal"
|
android:layout_gravity="fill_horizontal"
|
||||||
android:inputType="textPassword"
|
android:inputType="textPassword"
|
||||||
android:text="" />
|
android:text="" />
|
||||||
|
|
||||||
|
<CheckBox
|
||||||
|
android:id="@+id/auth_preemptive"
|
||||||
|
android:layout_columnSpan="2"
|
||||||
|
android:checked="true"
|
||||||
|
android:layout_gravity="left"
|
||||||
|
android:text="@string/auth_preemptive" />
|
||||||
|
|
||||||
<Space android:layout_gravity="left|top" />
|
<Space android:layout_gravity="left|top" />
|
||||||
|
|
||||||
</GridLayout>
|
</GridLayout>
|
||||||
|
|
||||||
</ScrollView>
|
</ScrollView>
|
@ -24,5 +24,5 @@
|
|||||||
<string name="calendars">Kalender</string>
|
<string name="calendars">Kalender</string>
|
||||||
<string name="select_address_book">Ein oder kein Adressbuch auswählen (nochmal berühren, um abzuwählen):</string>
|
<string name="select_address_book">Ein oder kein Adressbuch auswählen (nochmal berühren, um abzuwählen):</string>
|
||||||
<string name="select_calendars">Kalender zur Synchronisation auswählen:</string>
|
<string name="select_calendars">Kalender zur Synchronisation auswählen:</string>
|
||||||
|
<string name="auth_preemptive">Präemptive Authentifizierung (empfohlen, aber nicht kompatibel mit Digest-Auth.)</string>
|
||||||
</resources>
|
</resources>
|
@ -30,5 +30,6 @@
|
|||||||
<string name="calendars">Calendars</string>
|
<string name="calendars">Calendars</string>
|
||||||
<string name="select_address_book">Select up to one address book (tap again to unselect):</string>
|
<string name="select_address_book">Select up to one address book (tap again to unselect):</string>
|
||||||
<string name="select_calendars">Select your calendars:</string>
|
<string name="select_calendars">Select your calendars:</string>
|
||||||
|
<string name="auth_preemptive">Preemptive authentification (recommended, but incompatible with Digest auth)</string>
|
||||||
|
|
||||||
</resources>
|
</resources>
|
||||||
|
@ -9,12 +9,14 @@ package at.bitfire.davdroid;
|
|||||||
|
|
||||||
public class Constants {
|
public class Constants {
|
||||||
public static final String
|
public static final String
|
||||||
APP_VERSION = "0.3-alpha",
|
APP_VERSION = "0.3.2-alpha",
|
||||||
|
|
||||||
ACCOUNT_TYPE = "bitfire.at.davdroid",
|
ACCOUNT_TYPE = "bitfire.at.davdroid",
|
||||||
|
|
||||||
ACCOUNT_KEY_USERNAME = "user_name",
|
ACCOUNT_KEY_USERNAME = "user_name",
|
||||||
ACCOUNT_KEY_BASE_URL = "principal_url",
|
ACCOUNT_KEY_BASE_URL = "principal_url",
|
||||||
|
ACCOUNT_KEY_AUTH_PREEMPTIVE = "auth_preemptive",
|
||||||
|
|
||||||
ACCOUNT_KEY_ADDRESSBOOK_PATH = "addressbook_path",
|
ACCOUNT_KEY_ADDRESSBOOK_PATH = "addressbook_path",
|
||||||
ACCOUNT_KEY_ADDRESSBOOK_CTAG = "addressbook_ctag",
|
ACCOUNT_KEY_ADDRESSBOOK_CTAG = "addressbook_ctag",
|
||||||
|
|
||||||
|
@ -31,7 +31,7 @@ public class CalDavCalendar extends RemoteCollection<Event> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public CalDavCalendar(String baseURL, String user, String password) throws IOException, URISyntaxException {
|
public CalDavCalendar(String baseURL, String user, String password, boolean preemptiveAuth) throws IOException, URISyntaxException {
|
||||||
super(baseURL, user, password);
|
super(baseURL, user, password, preemptiveAuth);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,7 +31,7 @@ public class CardDavAddressBook extends RemoteCollection<Contact> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public CardDavAddressBook(String baseURL, String user, String password) throws IOException, URISyntaxException {
|
public CardDavAddressBook(String baseURL, String user, String password, boolean preemptiveAuth) throws IOException, URISyntaxException {
|
||||||
super(baseURL, user, password);
|
super(baseURL, user, password, preemptiveAuth);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -18,6 +18,7 @@ import java.net.URISyntaxException;
|
|||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.UUID;
|
||||||
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
@ -117,6 +118,10 @@ public class Contact extends Resource {
|
|||||||
Uid uid = (Uid)vcard.getProperty(Id.UID);
|
Uid uid = (Uid)vcard.getProperty(Id.UID);
|
||||||
if (uid != null)
|
if (uid != null)
|
||||||
this.uid = uid.getValue();
|
this.uid = uid.getValue();
|
||||||
|
else {
|
||||||
|
Log.w(TAG, "Received VCONTACT without UID, generating new one");
|
||||||
|
this.uid = UUID.randomUUID().toString();
|
||||||
|
}
|
||||||
|
|
||||||
Starred starred = (Starred)vcard.getExtendedProperty(Starred.PROPERTY_NAME);
|
Starred starred = (Starred)vcard.getExtendedProperty(Starred.PROPERTY_NAME);
|
||||||
this.starred = starred != null && starred.getValue().equals("1");
|
this.starred = starred != null && starred.getValue().equals("1");
|
||||||
|
@ -48,6 +48,7 @@ import net.fortuna.ical4j.model.property.Status;
|
|||||||
import net.fortuna.ical4j.model.property.Summary;
|
import net.fortuna.ical4j.model.property.Summary;
|
||||||
import net.fortuna.ical4j.model.property.Uid;
|
import net.fortuna.ical4j.model.property.Uid;
|
||||||
import net.fortuna.ical4j.model.property.Version;
|
import net.fortuna.ical4j.model.property.Version;
|
||||||
|
import net.fortuna.ical4j.util.UidGenerator;
|
||||||
import android.text.format.Time;
|
import android.text.format.Time;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import at.bitfire.davdroid.Constants;
|
import at.bitfire.davdroid.Constants;
|
||||||
@ -106,6 +107,11 @@ public class Event extends Resource {
|
|||||||
|
|
||||||
if (event.getUid() != null)
|
if (event.getUid() != null)
|
||||||
uid = event.getUid().toString();
|
uid = event.getUid().toString();
|
||||||
|
else {
|
||||||
|
Log.w(TAG, "Received VEVENT without UID, generating new one");
|
||||||
|
UidGenerator uidGenerator = new UidGenerator(Integer.toString(android.os.Process.myPid()));
|
||||||
|
uid = uidGenerator.generateUid().getValue();
|
||||||
|
}
|
||||||
|
|
||||||
dtStart = event.getStartDate(); validateTimeZone(dtStart);
|
dtStart = event.getStartDate(); validateTimeZone(dtStart);
|
||||||
dtEnd = event.getEndDate(); validateTimeZone(dtEnd);
|
dtEnd = event.getEndDate(); validateTimeZone(dtEnd);
|
||||||
|
@ -12,8 +12,6 @@ import java.text.ParseException;
|
|||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.commons.lang.StringUtils;
|
|
||||||
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import net.fortuna.ical4j.model.Parameter;
|
import net.fortuna.ical4j.model.Parameter;
|
||||||
import net.fortuna.ical4j.model.ParameterList;
|
import net.fortuna.ical4j.model.ParameterList;
|
||||||
@ -28,6 +26,9 @@ import net.fortuna.ical4j.model.property.Organizer;
|
|||||||
import net.fortuna.ical4j.model.property.RDate;
|
import net.fortuna.ical4j.model.property.RDate;
|
||||||
import net.fortuna.ical4j.model.property.RRule;
|
import net.fortuna.ical4j.model.property.RRule;
|
||||||
import net.fortuna.ical4j.model.property.Status;
|
import net.fortuna.ical4j.model.property.Status;
|
||||||
|
|
||||||
|
import org.apache.commons.lang.StringUtils;
|
||||||
|
|
||||||
import android.accounts.Account;
|
import android.accounts.Account;
|
||||||
import android.annotation.SuppressLint;
|
import android.annotation.SuppressLint;
|
||||||
import android.content.ContentProviderClient;
|
import android.content.ContentProviderClient;
|
||||||
@ -73,6 +74,12 @@ public class LocalCalendar extends LocalCollection<Event> {
|
|||||||
|
|
||||||
protected String entryColumnDirty() { return Events.DIRTY; }
|
protected String entryColumnDirty() { return Events.DIRTY; }
|
||||||
protected String entryColumnDeleted() { return Events.DELETED; }
|
protected String entryColumnDeleted() { return Events.DELETED; }
|
||||||
|
|
||||||
|
@SuppressLint("InlinedApi")
|
||||||
|
protected String entryColumnUID() {
|
||||||
|
return (android.os.Build.VERSION.SDK_INT >= 17) ?
|
||||||
|
Events.UID_2445 : Events.SYNC_DATA2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* class methods, constructor */
|
/* class methods, constructor */
|
||||||
@ -158,9 +165,12 @@ public class LocalCalendar extends LocalCollection<Event> {
|
|||||||
/* 3 */ Events.DTSTART, Events.DTEND, Events.EVENT_TIMEZONE, Events.EVENT_END_TIMEZONE, Events.ALL_DAY,
|
/* 3 */ Events.DTSTART, Events.DTEND, Events.EVENT_TIMEZONE, Events.EVENT_END_TIMEZONE, Events.ALL_DAY,
|
||||||
/* 8 */ Events.STATUS, Events.ACCESS_LEVEL,
|
/* 8 */ Events.STATUS, Events.ACCESS_LEVEL,
|
||||||
/* 10 */ Events.RRULE, Events.RDATE, Events.EXRULE, Events.EXDATE,
|
/* 10 */ Events.RRULE, Events.RDATE, Events.EXRULE, Events.EXDATE,
|
||||||
/* 14 */ Events.HAS_ATTENDEE_DATA, Events.ORGANIZER, Events.SELF_ATTENDEE_STATUS
|
/* 14 */ Events.HAS_ATTENDEE_DATA, Events.ORGANIZER, Events.SELF_ATTENDEE_STATUS,
|
||||||
|
/* 17 */ entryColumnUID()
|
||||||
}, null, null, null);
|
}, null, null, null);
|
||||||
if (cursor.moveToNext()) {
|
if (cursor.moveToNext()) {
|
||||||
|
e.setUid(cursor.getString(17));
|
||||||
|
|
||||||
e.setSummary(cursor.getString(0));
|
e.setSummary(cursor.getString(0));
|
||||||
e.setLocation(cursor.getString(1));
|
e.setLocation(cursor.getString(1));
|
||||||
e.setDescription(cursor.getString(2));
|
e.setDescription(cursor.getString(2));
|
||||||
@ -357,6 +367,7 @@ public class LocalCalendar extends LocalCollection<Event> {
|
|||||||
.withValue(Events.CALENDAR_ID, id)
|
.withValue(Events.CALENDAR_ID, id)
|
||||||
.withValue(entryColumnRemoteName(), event.getName())
|
.withValue(entryColumnRemoteName(), event.getName())
|
||||||
.withValue(entryColumnETag(), event.getETag())
|
.withValue(entryColumnETag(), event.getETag())
|
||||||
|
.withValue(entryColumnUID(), event.getUid())
|
||||||
.withValue(Events.ALL_DAY, event.isAllDay() ? 1 : 0)
|
.withValue(Events.ALL_DAY, event.isAllDay() ? 1 : 0)
|
||||||
.withValue(Events.DTSTART, event.getDtStartInMillis())
|
.withValue(Events.DTSTART, event.getDtStartInMillis())
|
||||||
.withValue(Events.DTEND, event.getDtEndInMillis())
|
.withValue(Events.DTEND, event.getDtEndInMillis())
|
||||||
|
@ -9,13 +9,9 @@ package at.bitfire.davdroid.resource;
|
|||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import net.fortuna.ical4j.model.ValidationException;
|
import net.fortuna.ical4j.model.ValidationException;
|
||||||
|
|
||||||
import org.apache.commons.lang.StringUtils;
|
|
||||||
|
|
||||||
import android.accounts.Account;
|
import android.accounts.Account;
|
||||||
import android.content.ContentProviderClient;
|
import android.content.ContentProviderClient;
|
||||||
import android.content.ContentProviderOperation;
|
import android.content.ContentProviderOperation;
|
||||||
@ -23,7 +19,6 @@ import android.content.ContentProviderOperation.Builder;
|
|||||||
import android.content.ContentUris;
|
import android.content.ContentUris;
|
||||||
import android.content.OperationApplicationException;
|
import android.content.OperationApplicationException;
|
||||||
import android.database.Cursor;
|
import android.database.Cursor;
|
||||||
import android.database.DatabaseUtils;
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.RemoteException;
|
import android.os.RemoteException;
|
||||||
import android.provider.CalendarContract;
|
import android.provider.CalendarContract;
|
||||||
@ -50,6 +45,8 @@ public abstract class LocalCollection<ResourceType extends Resource> {
|
|||||||
abstract protected String entryColumnDirty();
|
abstract protected String entryColumnDirty();
|
||||||
abstract protected String entryColumnDeleted();
|
abstract protected String entryColumnDeleted();
|
||||||
|
|
||||||
|
abstract protected String entryColumnUID();
|
||||||
|
|
||||||
|
|
||||||
LocalCollection(Account account, ContentProviderClient providerClient) {
|
LocalCollection(Account account, ContentProviderClient providerClient) {
|
||||||
this.account = account;
|
this.account = account;
|
||||||
|
@ -32,8 +32,8 @@ public abstract class RemoteCollection<ResourceType extends Resource> {
|
|||||||
abstract protected MultigetType multiGetType();
|
abstract protected MultigetType multiGetType();
|
||||||
abstract protected ResourceType newResourceSkeleton(String name, String ETag);
|
abstract protected ResourceType newResourceSkeleton(String name, String ETag);
|
||||||
|
|
||||||
public RemoteCollection(String baseURL, String user, String password) throws IOException, URISyntaxException {
|
public RemoteCollection(String baseURL, String user, String password, boolean preemptiveAuth) throws IOException, URISyntaxException {
|
||||||
collection = new WebDavCollection(new URI(baseURL), user, password);
|
collection = new WebDavCollection(new URI(baseURL), user, password, preemptiveAuth);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -60,30 +60,34 @@ public abstract class RemoteCollection<ResourceType extends Resource> {
|
|||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public Resource[] multiGet(ResourceType[] resources) throws IOException, IncapableResourceException, HttpException, ParserException {
|
public Resource[] multiGet(ResourceType[] resources) throws IOException, IncapableResourceException, HttpException, ParserException {
|
||||||
if (resources.length == 1) {
|
try {
|
||||||
Resource resource = get(resources[0]);
|
if (resources.length == 1) {
|
||||||
return (resource != null) ? (ResourceType[]) new Resource[] { resource } : null;
|
Resource resource = get(resources[0]);
|
||||||
|
return (resource != null) ? (ResourceType[]) new Resource[] { resource } : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
LinkedList<String> names = new LinkedList<String>();
|
||||||
|
for (ResourceType resource : resources)
|
||||||
|
names.add(resource.getName());
|
||||||
|
|
||||||
|
collection.multiGet(names.toArray(new String[0]), multiGetType());
|
||||||
|
|
||||||
|
LinkedList<ResourceType> foundResources = new LinkedList<ResourceType>();
|
||||||
|
for (WebDavResource member : collection.getMembers()) {
|
||||||
|
ResourceType resource = newResourceSkeleton(member.getName(), member.getETag());
|
||||||
|
resource.parseEntity(member.getContent());
|
||||||
|
foundResources.add(resource);
|
||||||
|
}
|
||||||
|
return foundResources.toArray(new Resource[0]);
|
||||||
|
} catch(ValidationException ex) {
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
LinkedList<String> names = new LinkedList<String>();
|
|
||||||
for (ResourceType resource : resources)
|
|
||||||
names.add(resource.getName());
|
|
||||||
|
|
||||||
collection.multiGet(names.toArray(new String[0]), multiGetType());
|
|
||||||
|
|
||||||
LinkedList<ResourceType> foundResources = new LinkedList<ResourceType>();
|
|
||||||
for (WebDavResource member : collection.getMembers()) {
|
|
||||||
ResourceType resource = newResourceSkeleton(member.getName(), member.getETag());
|
|
||||||
resource.parseEntity(member.getContent());
|
|
||||||
foundResources.add(resource);
|
|
||||||
}
|
|
||||||
return foundResources.toArray(new Resource[0]);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* internal member operations */
|
/* internal member operations */
|
||||||
|
|
||||||
public ResourceType get(ResourceType resource) throws IOException, HttpException, ParserException {
|
public ResourceType get(ResourceType resource) throws IOException, HttpException, ParserException, ValidationException {
|
||||||
WebDavResource member = new WebDavResource(collection, resource.getName());
|
WebDavResource member = new WebDavResource(collection, resource.getName());
|
||||||
member.get();
|
member.get();
|
||||||
resource.parseEntity(member.getContent());
|
resource.parseEntity(member.getContent());
|
||||||
|
@ -35,6 +35,7 @@ import at.bitfire.davdroid.resource.CalDavCalendar;
|
|||||||
import at.bitfire.davdroid.resource.IncapableResourceException;
|
import at.bitfire.davdroid.resource.IncapableResourceException;
|
||||||
import at.bitfire.davdroid.resource.LocalCalendar;
|
import at.bitfire.davdroid.resource.LocalCalendar;
|
||||||
import at.bitfire.davdroid.resource.RemoteCollection;
|
import at.bitfire.davdroid.resource.RemoteCollection;
|
||||||
|
import at.bitfire.davdroid.webdav.WebDavResource;
|
||||||
|
|
||||||
public class CalendarsSyncAdapterService extends Service {
|
public class CalendarsSyncAdapterService extends Service {
|
||||||
private static SyncAdapter syncAdapter;
|
private static SyncAdapter syncAdapter;
|
||||||
@ -75,7 +76,8 @@ public class CalendarsSyncAdapterService extends Service {
|
|||||||
URI uri = new URI(accountManager.getUserData(account, Constants.ACCOUNT_KEY_BASE_URL)).resolve(calendar.getPath());
|
URI uri = new URI(accountManager.getUserData(account, Constants.ACCOUNT_KEY_BASE_URL)).resolve(calendar.getPath());
|
||||||
RemoteCollection dav = new CalDavCalendar(uri.toString(),
|
RemoteCollection dav = new CalDavCalendar(uri.toString(),
|
||||||
accountManager.getUserData(account, Constants.ACCOUNT_KEY_USERNAME),
|
accountManager.getUserData(account, Constants.ACCOUNT_KEY_USERNAME),
|
||||||
accountManager.getPassword(account));
|
accountManager.getPassword(account),
|
||||||
|
Boolean.parseBoolean(accountManager.getUserData(account, Constants.ACCOUNT_KEY_AUTH_PREEMPTIVE)));
|
||||||
syncManager.synchronize(calendar, dav, extras.containsKey(ContentResolver.SYNC_EXTRAS_MANUAL), syncResult);
|
syncManager.synchronize(calendar, dav, extras.containsKey(ContentResolver.SYNC_EXTRAS_MANUAL), syncResult);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -32,12 +32,10 @@ import android.os.RemoteException;
|
|||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import at.bitfire.davdroid.Constants;
|
import at.bitfire.davdroid.Constants;
|
||||||
import at.bitfire.davdroid.resource.CardDavAddressBook;
|
import at.bitfire.davdroid.resource.CardDavAddressBook;
|
||||||
import at.bitfire.davdroid.resource.Contact;
|
|
||||||
import at.bitfire.davdroid.resource.IncapableResourceException;
|
import at.bitfire.davdroid.resource.IncapableResourceException;
|
||||||
import at.bitfire.davdroid.resource.LocalAddressBook;
|
import at.bitfire.davdroid.resource.LocalAddressBook;
|
||||||
import at.bitfire.davdroid.resource.LocalCollection;
|
import at.bitfire.davdroid.resource.LocalCollection;
|
||||||
import at.bitfire.davdroid.resource.RemoteCollection;
|
import at.bitfire.davdroid.resource.RemoteCollection;
|
||||||
import at.bitfire.davdroid.resource.Resource;
|
|
||||||
|
|
||||||
public class ContactsSyncAdapterService extends Service {
|
public class ContactsSyncAdapterService extends Service {
|
||||||
private static SyncAdapter syncAdapter;
|
private static SyncAdapter syncAdapter;
|
||||||
@ -75,8 +73,9 @@ public class ContactsSyncAdapterService extends Service {
|
|||||||
|
|
||||||
RemoteCollection dav = new CardDavAddressBook(
|
RemoteCollection dav = new CardDavAddressBook(
|
||||||
uri.toString(),
|
uri.toString(),
|
||||||
accountManager.getUserData(account, Constants.ACCOUNT_KEY_USERNAME),
|
accountManager.getUserData(account, Constants.ACCOUNT_KEY_USERNAME),
|
||||||
accountManager.getPassword(account));
|
accountManager.getPassword(account),
|
||||||
|
Boolean.parseBoolean(accountManager.getUserData(account, Constants.ACCOUNT_KEY_AUTH_PREEMPTIVE)));
|
||||||
|
|
||||||
LocalCollection database = new LocalAddressBook(account, provider, accountManager);
|
LocalCollection database = new LocalAddressBook(account, provider, accountManager);
|
||||||
|
|
||||||
|
@ -22,6 +22,7 @@ import android.view.ViewGroup;
|
|||||||
import android.widget.AdapterView;
|
import android.widget.AdapterView;
|
||||||
import android.widget.AdapterView.OnItemSelectedListener;
|
import android.widget.AdapterView.OnItemSelectedListener;
|
||||||
import android.widget.Button;
|
import android.widget.Button;
|
||||||
|
import android.widget.CheckBox;
|
||||||
import android.widget.EditText;
|
import android.widget.EditText;
|
||||||
import android.widget.Spinner;
|
import android.widget.Spinner;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
@ -32,6 +33,7 @@ public class EnterCredentialsFragment extends Fragment implements TextWatcher {
|
|||||||
|
|
||||||
TextView textHttpWarning;
|
TextView textHttpWarning;
|
||||||
EditText editBaseURL, editUserName, editPassword;
|
EditText editBaseURL, editUserName, editPassword;
|
||||||
|
CheckBox checkboxPreemptive;
|
||||||
Button btnNext;
|
Button btnNext;
|
||||||
|
|
||||||
|
|
||||||
@ -72,6 +74,8 @@ public class EnterCredentialsFragment extends Fragment implements TextWatcher {
|
|||||||
editPassword = (EditText) v.findViewById(R.id.password);
|
editPassword = (EditText) v.findViewById(R.id.password);
|
||||||
editPassword.addTextChangedListener(this);
|
editPassword.addTextChangedListener(this);
|
||||||
|
|
||||||
|
checkboxPreemptive = (CheckBox) v.findViewById(R.id.auth_preemptive);
|
||||||
|
|
||||||
// hook into action bar
|
// hook into action bar
|
||||||
setHasOptionsMenu(true);
|
setHasOptionsMenu(true);
|
||||||
|
|
||||||
@ -105,6 +109,7 @@ public class EnterCredentialsFragment extends Fragment implements TextWatcher {
|
|||||||
args.putString(QueryServerDialogFragment.EXTRA_BASE_URL, protocol + host_path);
|
args.putString(QueryServerDialogFragment.EXTRA_BASE_URL, protocol + host_path);
|
||||||
args.putString(QueryServerDialogFragment.EXTRA_USER_NAME, editUserName.getText().toString());
|
args.putString(QueryServerDialogFragment.EXTRA_USER_NAME, editUserName.getText().toString());
|
||||||
args.putString(QueryServerDialogFragment.EXTRA_PASSWORD, editPassword.getText().toString());
|
args.putString(QueryServerDialogFragment.EXTRA_PASSWORD, editPassword.getText().toString());
|
||||||
|
args.putBoolean(QueryServerDialogFragment.EXTRA_AUTH_PREEMPTIVE, checkboxPreemptive.isChecked());
|
||||||
|
|
||||||
DialogFragment dialog = new QueryServerDialogFragment();
|
DialogFragment dialog = new QueryServerDialogFragment();
|
||||||
dialog.setArguments(args);
|
dialog.setArguments(args);
|
||||||
|
@ -35,9 +35,11 @@ import at.bitfire.davdroid.webdav.WebDavResource;
|
|||||||
|
|
||||||
public class QueryServerDialogFragment extends DialogFragment implements LoaderCallbacks<ServerInfo> {
|
public class QueryServerDialogFragment extends DialogFragment implements LoaderCallbacks<ServerInfo> {
|
||||||
private static final String TAG = "davdroid.QueryServerDialogFragment";
|
private static final String TAG = "davdroid.QueryServerDialogFragment";
|
||||||
public static final String EXTRA_BASE_URL = "base_uri",
|
public static final String
|
||||||
EXTRA_USER_NAME = "user_name",
|
EXTRA_BASE_URL = "base_uri",
|
||||||
EXTRA_PASSWORD = "password";
|
EXTRA_USER_NAME = "user_name",
|
||||||
|
EXTRA_PASSWORD = "password",
|
||||||
|
EXTRA_AUTH_PREEMPTIVE = "auth_preemptive";
|
||||||
|
|
||||||
ProgressBar progressBar;
|
ProgressBar progressBar;
|
||||||
|
|
||||||
@ -102,12 +104,14 @@ public class QueryServerDialogFragment extends DialogFragment implements LoaderC
|
|||||||
ServerInfo serverInfo = new ServerInfo(
|
ServerInfo serverInfo = new ServerInfo(
|
||||||
args.getString(EXTRA_BASE_URL),
|
args.getString(EXTRA_BASE_URL),
|
||||||
args.getString(EXTRA_USER_NAME),
|
args.getString(EXTRA_USER_NAME),
|
||||||
args.getString(EXTRA_PASSWORD)
|
args.getString(EXTRA_PASSWORD),
|
||||||
|
args.getBoolean(EXTRA_AUTH_PREEMPTIVE)
|
||||||
);
|
);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// (1/5) detect capabilities
|
// (1/5) detect capabilities
|
||||||
WebDavCollection base = new WebDavCollection(new URI(serverInfo.getBaseURL()), serverInfo.getUserName(), serverInfo.getPassword());
|
WebDavCollection base = new WebDavCollection(new URI(serverInfo.getBaseURL()), serverInfo.getUserName(),
|
||||||
|
serverInfo.getPassword(), serverInfo.isAuthPreemptive());
|
||||||
base.options();
|
base.options();
|
||||||
|
|
||||||
serverInfo.setCardDAV(base.supportsDAV("addressbook"));
|
serverInfo.setCardDAV(base.supportsDAV("addressbook"));
|
||||||
|
@ -139,6 +139,7 @@ public class SelectCollectionsFragment extends ListFragment {
|
|||||||
Bundle userData = new Bundle();
|
Bundle userData = new Bundle();
|
||||||
userData.putString(Constants.ACCOUNT_KEY_BASE_URL, serverInfo.getBaseURL());
|
userData.putString(Constants.ACCOUNT_KEY_BASE_URL, serverInfo.getBaseURL());
|
||||||
userData.putString(Constants.ACCOUNT_KEY_USERNAME, serverInfo.getUserName());
|
userData.putString(Constants.ACCOUNT_KEY_USERNAME, serverInfo.getUserName());
|
||||||
|
userData.putString(Constants.ACCOUNT_KEY_AUTH_PREEMPTIVE, Boolean.toString(serverInfo.isAuthPreemptive()));
|
||||||
|
|
||||||
if (!addressBooks.isEmpty()) {
|
if (!addressBooks.isEmpty()) {
|
||||||
userData.putString(Constants.ACCOUNT_KEY_ADDRESSBOOK_PATH, addressBooks.get(0).getPath());
|
userData.putString(Constants.ACCOUNT_KEY_ADDRESSBOOK_PATH, addressBooks.get(0).getPath());
|
||||||
|
@ -18,6 +18,7 @@ public class ServerInfo implements Serializable {
|
|||||||
|
|
||||||
final private String baseURL;
|
final private String baseURL;
|
||||||
final private String userName, password;
|
final private String userName, password;
|
||||||
|
final boolean authPreemptive;
|
||||||
|
|
||||||
private String errorMessage;
|
private String errorMessage;
|
||||||
|
|
||||||
|
@ -8,14 +8,11 @@
|
|||||||
package at.bitfire.davdroid.webdav;
|
package at.bitfire.davdroid.webdav;
|
||||||
|
|
||||||
|
|
||||||
import java.io.StringWriter;
|
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
|
||||||
import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
|
import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
|
||||||
import org.apache.http.entity.StringEntity;
|
import org.apache.http.entity.StringEntity;
|
||||||
import org.simpleframework.xml.Serializer;
|
|
||||||
import org.simpleframework.xml.core.Persister;
|
|
||||||
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
|
@ -13,6 +13,7 @@ import org.apache.http.HttpException;
|
|||||||
import org.apache.http.HttpHost;
|
import org.apache.http.HttpHost;
|
||||||
import org.apache.http.HttpRequest;
|
import org.apache.http.HttpRequest;
|
||||||
import org.apache.http.HttpRequestInterceptor;
|
import org.apache.http.HttpRequestInterceptor;
|
||||||
|
import org.apache.http.auth.AuthScheme;
|
||||||
import org.apache.http.auth.AuthScope;
|
import org.apache.http.auth.AuthScope;
|
||||||
import org.apache.http.auth.AuthState;
|
import org.apache.http.auth.AuthState;
|
||||||
import org.apache.http.auth.Credentials;
|
import org.apache.http.auth.Credentials;
|
||||||
@ -23,7 +24,6 @@ import org.apache.http.protocol.ExecutionContext;
|
|||||||
import org.apache.http.protocol.HttpContext;
|
import org.apache.http.protocol.HttpContext;
|
||||||
|
|
||||||
public class PreemptiveAuthInterceptor implements HttpRequestInterceptor {
|
public class PreemptiveAuthInterceptor implements HttpRequestInterceptor {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void process(HttpRequest request, HttpContext context) throws HttpException, IOException {
|
public void process(HttpRequest request, HttpContext context) throws HttpException, IOException {
|
||||||
AuthState authState = (AuthState) context.getAttribute(ClientContext.TARGET_AUTH_STATE);
|
AuthState authState = (AuthState) context.getAttribute(ClientContext.TARGET_AUTH_STATE);
|
||||||
|
@ -43,8 +43,8 @@ public class WebDavCollection extends WebDavResource {
|
|||||||
@Getter protected List<WebDavResource> members;
|
@Getter protected List<WebDavResource> members;
|
||||||
|
|
||||||
|
|
||||||
public WebDavCollection(URI baseURL, String username, String password) throws IOException {
|
public WebDavCollection(URI baseURL, String username, String password, boolean preemptiveAuth) throws IOException {
|
||||||
super(baseURL, username, password);
|
super(baseURL, username, password, preemptiveAuth);
|
||||||
}
|
}
|
||||||
|
|
||||||
public WebDavCollection(WebDavCollection parent, URI member) {
|
public WebDavCollection(WebDavCollection parent, URI member) {
|
||||||
|
@ -9,8 +9,6 @@ package at.bitfire.davdroid.webdav;
|
|||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
|
||||||
import java.io.StringWriter;
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
@ -20,8 +18,6 @@ import java.util.Set;
|
|||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
|
|
||||||
import org.apache.commons.io.IOUtils;
|
|
||||||
import org.apache.commons.io.input.TeeInputStream;
|
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang.StringUtils;
|
||||||
import org.apache.http.Header;
|
import org.apache.http.Header;
|
||||||
import org.apache.http.HttpException;
|
import org.apache.http.HttpException;
|
||||||
@ -68,13 +64,19 @@ public class WebDavResource {
|
|||||||
protected DefaultHttpClient client;
|
protected DefaultHttpClient client;
|
||||||
|
|
||||||
|
|
||||||
public WebDavResource(URI baseURL, String username, String password) throws IOException {
|
public WebDavResource(URI baseURL, String username, String password, boolean preemptive) throws IOException {
|
||||||
location = baseURL.normalize();
|
location = baseURL.normalize();
|
||||||
|
|
||||||
client = new DefaultHttpClient();
|
client = new DefaultHttpClient();
|
||||||
client.getCredentialsProvider().setCredentials(new AuthScope(location.getHost(), location.getPort()),
|
client.getCredentialsProvider().setCredentials(new AuthScope(location.getHost(), location.getPort()),
|
||||||
new UsernamePasswordCredentials(username, password));
|
new UsernamePasswordCredentials(username, password));
|
||||||
client.addRequestInterceptor(new PreemptiveAuthInterceptor(), 0);
|
|
||||||
|
// preemptive auth is available for Basic auth only
|
||||||
|
if (preemptive) {
|
||||||
|
Log.i(TAG, "Using preemptive Basic Authentication");
|
||||||
|
client.addRequestInterceptor(new PreemptiveAuthInterceptor(), 0);
|
||||||
|
}
|
||||||
|
|
||||||
client.getParams().setParameter(CoreProtocolPNames.USER_AGENT, "DAVdroid");
|
client.getParams().setParameter(CoreProtocolPNames.USER_AGENT, "DAVdroid");
|
||||||
GzipDecompressingEntity.enable(client);
|
GzipDecompressingEntity.enable(client);
|
||||||
}
|
}
|
||||||
|
@ -10,6 +10,7 @@ package at.bitfire.davdroid.test;
|
|||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
import net.fortuna.ical4j.data.ParserException;
|
||||||
import junit.framework.Assert;
|
import junit.framework.Assert;
|
||||||
import android.content.res.AssetManager;
|
import android.content.res.AssetManager;
|
||||||
import android.test.InstrumentationTestCase;
|
import android.test.InstrumentationTestCase;
|
||||||
@ -23,7 +24,7 @@ public class ContactTest extends InstrumentationTestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public void testParseVcard3() throws IOException {
|
public void testParseVcard3() throws IOException, ParserException {
|
||||||
String fname = "vcard3-sample1.vcf";
|
String fname = "vcard3-sample1.vcf";
|
||||||
InputStream in = assetMgr.open(fname, AssetManager.ACCESS_STREAMING);
|
InputStream in = assetMgr.open(fname, AssetManager.ACCESS_STREAMING);
|
||||||
|
|
||||||
@ -35,10 +36,12 @@ public class ContactTest extends InstrumentationTestCase {
|
|||||||
Assert.assertEquals("Gump", c.getFamilyName());
|
Assert.assertEquals("Gump", c.getFamilyName());
|
||||||
|
|
||||||
Assert.assertEquals(2, c.getPhoneNumbers().size());
|
Assert.assertEquals(2, c.getPhoneNumbers().size());
|
||||||
Assert.assertEquals("(111) 555-1212", c.getPhoneNumbers().get(0).getText());
|
Assert.assertEquals("(111) 555-1212", c.getPhoneNumbers().get(0).getValue());
|
||||||
|
|
||||||
Assert.assertEquals(1, c.getEmails().size());
|
Assert.assertEquals(1, c.getEmails().size());
|
||||||
Assert.assertEquals("forrestgump@example.com", c.getEmails().get(0).getValue());
|
Assert.assertEquals("forrestgump@example.com", c.getEmails().get(0).getValue());
|
||||||
|
|
||||||
|
Assert.assertFalse(c.isStarred());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user