mirror of
https://github.com/etesync/android
synced 2024-11-22 16:08:13 +00:00
Library updates
* use ical4j/2.0.x instead of 1.0.x (thanks @benfortuna) * use Apache Commons 3.x instead of 2.x * code optimizations
This commit is contained in:
parent
c8cfbd6b07
commit
a796a1e9b3
@ -32,6 +32,7 @@ android {
|
|||||||
}
|
}
|
||||||
|
|
||||||
packagingOptions {
|
packagingOptions {
|
||||||
|
exclude 'LICENSE'
|
||||||
exclude 'META-INF/LICENSE.txt'
|
exclude 'META-INF/LICENSE.txt'
|
||||||
exclude 'META-INF/NOTICE.txt'
|
exclude 'META-INF/NOTICE.txt'
|
||||||
}
|
}
|
||||||
@ -43,12 +44,15 @@ configurations.all {
|
|||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
// Apache Commons
|
// Apache Commons
|
||||||
compile 'commons-lang:commons-lang:2.6'
|
compile 'org.apache.commons:commons-lang3:3.4'
|
||||||
compile 'commons-io:commons-io:2.4'
|
compile 'commons-io:commons-io:2.4'
|
||||||
// Lombok for useful @helpers
|
// Lombok for useful @helpers
|
||||||
provided 'org.projectlombok:lombok:1.16.4'
|
provided 'org.projectlombok:lombok:1.16.4'
|
||||||
// ical4j for parsing/generating iCalendars
|
// ical4j for parsing/generating iCalendars
|
||||||
compile 'org.mnode.ical4j:ical4j:1.0.6'
|
compile('org.mnode.ical4j:ical4j:2.0-alpha1') {
|
||||||
|
// we don't need content builders, see https://github.com/ical4j/ical4j/wiki/Groovy
|
||||||
|
exclude group: 'org.codehaus.groovy', module: 'groovy-all'
|
||||||
|
}
|
||||||
// ez-vcard for parsing/generating VCards
|
// ez-vcard for parsing/generating VCards
|
||||||
compile('com.googlecode.ez-vcard:ez-vcard:0.9.6') {
|
compile('com.googlecode.ez-vcard:ez-vcard:0.9.6') {
|
||||||
// hCard functionality not needed
|
// hCard functionality not needed
|
||||||
|
@ -15,7 +15,7 @@ import java.net.URISyntaxException;
|
|||||||
|
|
||||||
public class TestConstants {
|
public class TestConstants {
|
||||||
public static final String ROBOHYDRA_BASE = "http://192.168.0.11:3000/";
|
public static final String ROBOHYDRA_BASE = "http://192.168.0.11:3000/";
|
||||||
|
|
||||||
public static URI roboHydra;
|
public static URI roboHydra;
|
||||||
static {
|
static {
|
||||||
try {
|
try {
|
||||||
|
@ -73,22 +73,22 @@ public class ContactTest extends InstrumentationTestCase {
|
|||||||
assertTrue(Arrays.equals(c.getPhoto(), expectedPhoto));
|
assertTrue(Arrays.equals(c.getPhoto(), expectedPhoto));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testParseInvalidUnknownProperties() throws IOException, InvalidResourceException {
|
public void testParseInvalidUnknownProperties() throws IOException {
|
||||||
Contact c = parseVCF("invalid-unknown-properties.vcf");
|
Contact c = parseVCF("invalid-unknown-properties.vcf");
|
||||||
assertEquals("VCard with invalid unknown properties", c.getDisplayName());
|
assertEquals("VCard with invalid unknown properties", c.getDisplayName());
|
||||||
assertNull(c.getUnknownProperties());
|
assertNull(c.getUnknownProperties());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
protected Contact parseVCF(String fname) throws IOException, InvalidResourceException {
|
protected Contact parseVCF(String fname) throws IOException {
|
||||||
@Cleanup InputStream in = assetMgr.open(fname, AssetManager.ACCESS_STREAMING);
|
@Cleanup InputStream in = assetMgr.open(fname, AssetManager.ACCESS_STREAMING);
|
||||||
Contact c = new Contact(fname, null);
|
Contact c = new Contact(fname, null);
|
||||||
c.parseEntity(in, new Resource.AssetDownloader() {
|
c.parseEntity(in, new Resource.AssetDownloader() {
|
||||||
@Override
|
@Override
|
||||||
public byte[] download(URI uri) throws URISyntaxException, IOException, HttpException, DavException {
|
public byte[] download(URI uri) throws URISyntaxException, IOException, HttpException, DavException {
|
||||||
return IOUtils.toByteArray(uri);
|
return IOUtils.toByteArray(uri);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -53,7 +53,7 @@ public class LocalCalendarTest extends InstrumentationTestCase {
|
|||||||
Context targetContext;
|
Context targetContext;
|
||||||
|
|
||||||
ContentProviderClient providerClient;
|
ContentProviderClient providerClient;
|
||||||
Account testAccount = new Account(calendarName, accountType);
|
final Account testAccount = new Account(calendarName, accountType);
|
||||||
|
|
||||||
Uri calendarURI;
|
Uri calendarURI;
|
||||||
LocalCalendar testCalendar;
|
LocalCalendar testCalendar;
|
||||||
@ -69,7 +69,7 @@ public class LocalCalendarTest extends InstrumentationTestCase {
|
|||||||
build();
|
build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private long insertNewEvent() throws LocalStorageException, RemoteException {
|
private long insertNewEvent() throws RemoteException {
|
||||||
ContentValues values = new ContentValues();
|
ContentValues values = new ContentValues();
|
||||||
values.put(Events.CALENDAR_ID, testCalendar.getId());
|
values.put(Events.CALENDAR_ID, testCalendar.getId());
|
||||||
values.put(Events.TITLE, "Test Event");
|
values.put(Events.TITLE, "Test Event");
|
||||||
|
@ -13,14 +13,12 @@ import android.test.InstrumentationTestCase;
|
|||||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||||
import org.apache.http.client.methods.HttpGetHC4;
|
import org.apache.http.client.methods.HttpGetHC4;
|
||||||
import org.apache.http.client.methods.HttpPostHC4;
|
import org.apache.http.client.methods.HttpPostHC4;
|
||||||
import org.apache.http.client.methods.HttpRequestBaseHC4;
|
|
||||||
import org.apache.http.impl.client.CloseableHttpClient;
|
import org.apache.http.impl.client.CloseableHttpClient;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
|
||||||
import at.bitfire.davdroid.TestConstants;
|
import at.bitfire.davdroid.TestConstants;
|
||||||
import lombok.Cleanup;
|
|
||||||
|
|
||||||
public class DavHttpClientTest extends InstrumentationTestCase {
|
public class DavHttpClientTest extends InstrumentationTestCase {
|
||||||
final static URI testCookieURI = TestConstants.roboHydra.resolve("/dav/testCookieStore");
|
final static URI testCookieURI = TestConstants.roboHydra.resolve("/dav/testCookieStore");
|
||||||
|
@ -25,7 +25,7 @@ import at.bitfire.davdroid.TestConstants;
|
|||||||
public class DavRedirectStrategyTest extends TestCase {
|
public class DavRedirectStrategyTest extends TestCase {
|
||||||
|
|
||||||
CloseableHttpClient httpClient;
|
CloseableHttpClient httpClient;
|
||||||
DavRedirectStrategy strategy = DavRedirectStrategy.INSTANCE;
|
final DavRedirectStrategy strategy = DavRedirectStrategy.INSTANCE;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected void setUp() {
|
protected void setUp() {
|
||||||
|
@ -12,8 +12,8 @@ import android.util.Log;
|
|||||||
|
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
import org.apache.commons.lang.ArrayUtils;
|
import org.apache.commons.lang3.ArrayUtils;
|
||||||
import org.apache.commons.lang.exception.ExceptionUtils;
|
import org.apache.commons.lang3.exception.ExceptionUtils;
|
||||||
import org.apache.http.HttpHost;
|
import org.apache.http.HttpHost;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -29,7 +29,7 @@ import lombok.Cleanup;
|
|||||||
public class TlsSniSocketFactoryTest extends TestCase {
|
public class TlsSniSocketFactoryTest extends TestCase {
|
||||||
private static final String TAG = "davdroid.TlsSniSocketFactoryTest";
|
private static final String TAG = "davdroid.TlsSniSocketFactoryTest";
|
||||||
|
|
||||||
TlsSniSocketFactory factory = TlsSniSocketFactory.getSocketFactory();
|
final TlsSniSocketFactory factory = TlsSniSocketFactory.getSocketFactory();
|
||||||
|
|
||||||
private InetSocketAddress sampleTlsEndpoint;
|
private InetSocketAddress sampleTlsEndpoint;
|
||||||
|
|
||||||
@ -75,7 +75,7 @@ public class TlsSniSocketFactoryTest extends TestCase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void testProtocolVersions() throws IOException {
|
public void testProtocolVersions() throws IOException {
|
||||||
String enabledProtocols[] = factory.protocols;
|
String enabledProtocols[] = TlsSniSocketFactory.protocols;
|
||||||
// SSL (all versions) should be disabled
|
// SSL (all versions) should be disabled
|
||||||
for (String protocol : enabledProtocols)
|
for (String protocol : enabledProtocols)
|
||||||
assertFalse(protocol.contains("SSL"));
|
assertFalse(protocol.contains("SSL"));
|
||||||
|
@ -28,9 +28,7 @@ import lombok.Cleanup;
|
|||||||
// tests require running robohydra!
|
// tests require running robohydra!
|
||||||
|
|
||||||
public class WebDavResourceTest extends InstrumentationTestCase {
|
public class WebDavResourceTest extends InstrumentationTestCase {
|
||||||
static byte[] SAMPLE_CONTENT = new byte[] { 1, 2, 3, 4, 5 };
|
final static byte[] SAMPLE_CONTENT = new byte[] { 1, 2, 3, 4, 5 };
|
||||||
|
|
||||||
final static String PATH_SIMPLE_FILE = "collection/new.file";
|
|
||||||
|
|
||||||
AssetManager assetMgr;
|
AssetManager assetMgr;
|
||||||
CloseableHttpClient httpClient;
|
CloseableHttpClient httpClient;
|
||||||
|
@ -7,6 +7,7 @@
|
|||||||
*/
|
*/
|
||||||
package at.bitfire.davdroid;
|
package at.bitfire.davdroid;
|
||||||
|
|
||||||
|
import net.fortuna.ical4j.model.Calendar;
|
||||||
import net.fortuna.ical4j.model.property.ProdId;
|
import net.fortuna.ical4j.model.property.ProdId;
|
||||||
|
|
||||||
public class Constants {
|
public class Constants {
|
||||||
@ -16,5 +17,5 @@ public class Constants {
|
|||||||
WEB_URL_HELP = "https://davdroid.bitfire.at/configuration?pk_campaign=davdroid-app",
|
WEB_URL_HELP = "https://davdroid.bitfire.at/configuration?pk_campaign=davdroid-app",
|
||||||
WEB_URL_VIEW_LOGS = "https://github.com/bitfireAT/davdroid/wiki/How-to-view-the-logs";
|
WEB_URL_VIEW_LOGS = "https://github.com/bitfireAT/davdroid/wiki/How-to-view-the-logs";
|
||||||
|
|
||||||
public static final ProdId ICAL_PRODID = new ProdId("-//bitfire web engineering//DAVdroid " + Constants.APP_VERSION + " (ical4j 1.0.x)//EN");
|
public static final ProdId ICAL_PRODID = new ProdId("-//bitfire web engineering//DAVdroid " + Constants.APP_VERSION + " (ical4j 2.0-alpha1)//EN");
|
||||||
}
|
}
|
||||||
|
@ -15,7 +15,7 @@ import net.fortuna.ical4j.model.DefaultTimeZoneRegistryFactory;
|
|||||||
import net.fortuna.ical4j.model.TimeZone;
|
import net.fortuna.ical4j.model.TimeZone;
|
||||||
import net.fortuna.ical4j.model.TimeZoneRegistry;
|
import net.fortuna.ical4j.model.TimeZoneRegistry;
|
||||||
|
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import java.util.SimpleTimeZone;
|
import java.util.SimpleTimeZone;
|
||||||
|
|
||||||
|
@ -9,11 +9,6 @@ package at.bitfire.davdroid;
|
|||||||
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import org.apache.commons.codec.EncoderException;
|
|
||||||
import org.apache.commons.codec.net.URLCodec;
|
|
||||||
import org.apache.commons.lang.StringEscapeUtils;
|
|
||||||
import org.apache.commons.lang.StringUtils;
|
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
|
|
||||||
|
@ -7,7 +7,6 @@
|
|||||||
*/
|
*/
|
||||||
package at.bitfire.davdroid.resource;
|
package at.bitfire.davdroid.resource;
|
||||||
|
|
||||||
import android.accounts.Account;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import org.apache.http.impl.client.CloseableHttpClient;
|
import org.apache.http.impl.client.CloseableHttpClient;
|
||||||
@ -17,7 +16,6 @@ import org.simpleframework.xml.core.Persister;
|
|||||||
import java.io.StringWriter;
|
import java.io.StringWriter;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
|
|
||||||
import at.bitfire.davdroid.syncadapter.AccountSettings;
|
|
||||||
import at.bitfire.davdroid.webdav.DavCalendarQuery;
|
import at.bitfire.davdroid.webdav.DavCalendarQuery;
|
||||||
import at.bitfire.davdroid.webdav.DavCompFilter;
|
import at.bitfire.davdroid.webdav.DavCompFilter;
|
||||||
import at.bitfire.davdroid.webdav.DavFilter;
|
import at.bitfire.davdroid.webdav.DavFilter;
|
||||||
|
@ -7,8 +7,6 @@
|
|||||||
*/
|
*/
|
||||||
package at.bitfire.davdroid.resource;
|
package at.bitfire.davdroid.resource;
|
||||||
|
|
||||||
import android.accounts.Account;
|
|
||||||
|
|
||||||
import org.apache.http.impl.client.CloseableHttpClient;
|
import org.apache.http.impl.client.CloseableHttpClient;
|
||||||
|
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
|
@ -9,20 +9,14 @@ package at.bitfire.davdroid.resource;
|
|||||||
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import net.fortuna.ical4j.model.property.ProdId;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import org.apache.commons.lang.StringUtils;
|
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URL;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import at.bitfire.davdroid.Constants;
|
import at.bitfire.davdroid.Constants;
|
||||||
@ -30,7 +24,6 @@ import ezvcard.Ezvcard;
|
|||||||
import ezvcard.VCard;
|
import ezvcard.VCard;
|
||||||
import ezvcard.VCardVersion;
|
import ezvcard.VCardVersion;
|
||||||
import ezvcard.ValidationWarnings;
|
import ezvcard.ValidationWarnings;
|
||||||
import ezvcard.Warning;
|
|
||||||
import ezvcard.parameter.EmailType;
|
import ezvcard.parameter.EmailType;
|
||||||
import ezvcard.parameter.ImageType;
|
import ezvcard.parameter.ImageType;
|
||||||
import ezvcard.parameter.RelatedType;
|
import ezvcard.parameter.RelatedType;
|
||||||
@ -59,8 +52,6 @@ import ezvcard.property.Telephone;
|
|||||||
import ezvcard.property.Title;
|
import ezvcard.property.Title;
|
||||||
import ezvcard.property.Uid;
|
import ezvcard.property.Uid;
|
||||||
import ezvcard.property.Url;
|
import ezvcard.property.Url;
|
||||||
import ezvcard.property.VCardProperty;
|
|
||||||
import ezvcard.util.ListMultimap;
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
@ -265,7 +256,7 @@ public class Contact extends Resource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// NOTE
|
// NOTE
|
||||||
List<String> notes = new LinkedList<String>();
|
List<String> notes = new LinkedList<>();
|
||||||
for (Note note : vcard.getNotes())
|
for (Note note : vcard.getNotes())
|
||||||
notes.add(note.getValue());
|
notes.add(note.getValue());
|
||||||
if (!notes.isEmpty())
|
if (!notes.isEmpty())
|
||||||
@ -420,7 +411,7 @@ public class Contact extends Resource {
|
|||||||
|
|
||||||
// CATEGORY
|
// CATEGORY
|
||||||
if (!categories.isEmpty())
|
if (!categories.isEmpty())
|
||||||
vcard.setCategories(categories.toArray(new String[0]));
|
vcard.setCategories(categories.toArray(new String[categories.size()]));
|
||||||
|
|
||||||
// URL
|
// URL
|
||||||
for (String url : URLs)
|
for (String url : URLs)
|
||||||
|
@ -9,7 +9,6 @@ package at.bitfire.davdroid.resource;
|
|||||||
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
import android.widget.Toast;
|
|
||||||
|
|
||||||
import org.apache.http.HttpException;
|
import org.apache.http.HttpException;
|
||||||
import org.apache.http.impl.client.CloseableHttpClient;
|
import org.apache.http.impl.client.CloseableHttpClient;
|
||||||
@ -22,7 +21,6 @@ import org.xbill.DNS.Type;
|
|||||||
|
|
||||||
import java.io.Closeable;
|
import java.io.Closeable;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.MalformedURLException;
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
@ -40,8 +38,8 @@ import ezvcard.VCardVersion;
|
|||||||
public class DavResourceFinder implements Closeable {
|
public class DavResourceFinder implements Closeable {
|
||||||
private final static String TAG = "davdroid.ResourceFinder";
|
private final static String TAG = "davdroid.ResourceFinder";
|
||||||
|
|
||||||
protected Context context;
|
final protected Context context;
|
||||||
protected CloseableHttpClient httpClient;
|
final protected CloseableHttpClient httpClient;
|
||||||
|
|
||||||
|
|
||||||
public DavResourceFinder(Context context) {
|
public DavResourceFinder(Context context) {
|
||||||
@ -187,10 +185,9 @@ public class DavResourceFinder implements Closeable {
|
|||||||
* @param serviceName Service name ("carddav" or "caldav")
|
* @param serviceName Service name ("carddav" or "caldav")
|
||||||
* @return Initial service URL (HTTP/HTTPS), without user credentials
|
* @return Initial service URL (HTTP/HTTPS), without user credentials
|
||||||
* @throws URISyntaxException when the user-given URI is invalid
|
* @throws URISyntaxException when the user-given URI is invalid
|
||||||
* @throws MalformedURLException when the user-given URI is invalid
|
|
||||||
*/
|
*/
|
||||||
public URI getInitialContextURL(ServerInfo serverInfo, String serviceName) throws URISyntaxException, MalformedURLException {
|
public URI getInitialContextURL(ServerInfo serverInfo, String serviceName) throws URISyntaxException {
|
||||||
String scheme = null,
|
String scheme,
|
||||||
domain;
|
domain;
|
||||||
int port = -1;
|
int port = -1;
|
||||||
String path = "/";
|
String path = "/";
|
||||||
|
@ -38,7 +38,6 @@ import net.fortuna.ical4j.model.property.ExRule;
|
|||||||
import net.fortuna.ical4j.model.property.LastModified;
|
import net.fortuna.ical4j.model.property.LastModified;
|
||||||
import net.fortuna.ical4j.model.property.Location;
|
import net.fortuna.ical4j.model.property.Location;
|
||||||
import net.fortuna.ical4j.model.property.Organizer;
|
import net.fortuna.ical4j.model.property.Organizer;
|
||||||
import net.fortuna.ical4j.model.property.ProdId;
|
|
||||||
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.RecurrenceId;
|
import net.fortuna.ical4j.model.property.RecurrenceId;
|
||||||
@ -51,19 +50,15 @@ import net.fortuna.ical4j.util.CompatibilityHints;
|
|||||||
import net.fortuna.ical4j.util.SimpleHostInfo;
|
import net.fortuna.ical4j.util.SimpleHostInfo;
|
||||||
import net.fortuna.ical4j.util.UidGenerator;
|
import net.fortuna.ical4j.util.UidGenerator;
|
||||||
|
|
||||||
import org.apache.commons.lang.StringUtils;
|
|
||||||
|
|
||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.StringReader;
|
import java.io.StringReader;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Iterator;
|
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.SimpleTimeZone;
|
|
||||||
import java.util.TimeZone;
|
import java.util.TimeZone;
|
||||||
|
|
||||||
import at.bitfire.davdroid.Constants;
|
import at.bitfire.davdroid.Constants;
|
||||||
@ -98,9 +93,9 @@ public class Event extends Resource {
|
|||||||
@Getter @Setter protected boolean opaque;
|
@Getter @Setter protected boolean opaque;
|
||||||
|
|
||||||
@Getter @Setter protected Organizer organizer;
|
@Getter @Setter protected Organizer organizer;
|
||||||
@Getter protected List<Attendee> attendees = new LinkedList<Attendee>();
|
@Getter protected List<Attendee> attendees = new LinkedList<>();
|
||||||
|
|
||||||
@Getter protected List<VAlarm> alarms = new LinkedList<VAlarm>();
|
@Getter protected List<VAlarm> alarms = new LinkedList<>();
|
||||||
|
|
||||||
static {
|
static {
|
||||||
CompatibilityHints.setHintEnabled(CompatibilityHints.KEY_RELAXED_UNFOLDING, true);
|
CompatibilityHints.setHintEnabled(CompatibilityHints.KEY_RELAXED_UNFOLDING, true);
|
||||||
@ -201,10 +196,10 @@ public class Event extends Resource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
rrule = (RRule)event.getProperty(Property.RRULE);
|
rrule = (RRule)event.getProperty(Property.RRULE);
|
||||||
for (RDate rdate : (Iterable<RDate>)event.getProperties(Property.RDATE))
|
for (RDate rdate : (List<RDate>)(List<?>)event.getProperties(Property.RDATE))
|
||||||
rdates.add(rdate);
|
rdates.add(rdate);
|
||||||
exrule = (ExRule)event.getProperty(Property.EXRULE);
|
exrule = (ExRule)event.getProperty(Property.EXRULE);
|
||||||
for (ExDate exdate : (Iterable<ExDate>)event.getProperties(Property.EXDATE))
|
for (ExDate exdate : (List<ExDate>)(List<?>)event.getProperties(Property.EXDATE))
|
||||||
exdates.add(exdate);
|
exdates.add(exdate);
|
||||||
|
|
||||||
if (event.getSummary() != null)
|
if (event.getSummary() != null)
|
||||||
@ -218,7 +213,7 @@ public class Event extends Resource {
|
|||||||
opaque = event.getTransparency() != Transp.TRANSPARENT;
|
opaque = event.getTransparency() != Transp.TRANSPARENT;
|
||||||
|
|
||||||
organizer = event.getOrganizer();
|
organizer = event.getOrganizer();
|
||||||
for (Attendee attendee : (Iterable<Attendee>)event.getProperties(Property.ATTENDEE))
|
for (Attendee attendee : (List<Attendee>)(List<?>)event.getProperties(Property.ATTENDEE))
|
||||||
attendees.add(attendee);
|
attendees.add(attendee);
|
||||||
|
|
||||||
Clazz classification = event.getClassification();
|
Clazz classification = event.getClassification();
|
||||||
|
@ -41,21 +41,17 @@ import android.provider.ContactsContract.RawContacts;
|
|||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.commons.lang.WordUtils;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import at.bitfire.davdroid.syncadapter.AccountSettings;
|
import at.bitfire.davdroid.syncadapter.AccountSettings;
|
||||||
@ -64,7 +60,6 @@ import ezvcard.parameter.EmailType;
|
|||||||
import ezvcard.parameter.ImppType;
|
import ezvcard.parameter.ImppType;
|
||||||
import ezvcard.parameter.RelatedType;
|
import ezvcard.parameter.RelatedType;
|
||||||
import ezvcard.parameter.TelephoneType;
|
import ezvcard.parameter.TelephoneType;
|
||||||
import ezvcard.parameter.VCardParameter;
|
|
||||||
import ezvcard.property.Address;
|
import ezvcard.property.Address;
|
||||||
import ezvcard.property.Anniversary;
|
import ezvcard.property.Anniversary;
|
||||||
import ezvcard.property.Birthday;
|
import ezvcard.property.Birthday;
|
||||||
@ -81,7 +76,7 @@ public class LocalAddressBook extends LocalCollection<Contact> {
|
|||||||
protected final static String COLUMN_UNKNOWN_PROPERTIES = RawContacts.SYNC3;
|
protected final static String COLUMN_UNKNOWN_PROPERTIES = RawContacts.SYNC3;
|
||||||
|
|
||||||
|
|
||||||
protected AccountSettings accountSettings;
|
final protected AccountSettings accountSettings;
|
||||||
|
|
||||||
|
|
||||||
/* database fields */
|
/* database fields */
|
||||||
@ -138,7 +133,7 @@ public class LocalAddressBook extends LocalCollection<Contact> {
|
|||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void deleteAllExceptRemoteNames(Resource[] remoteResources) {
|
public int deleteAllExceptRemoteNames(Resource[] remoteResources) throws LocalStorageException {
|
||||||
String where;
|
String where;
|
||||||
|
|
||||||
if (remoteResources.length != 0) {
|
if (remoteResources.length != 0) {
|
||||||
@ -148,16 +143,17 @@ public class LocalAddressBook extends LocalCollection<Contact> {
|
|||||||
where = entryColumnRemoteName() + " NOT IN (" + StringUtils.join(sqlFileNames, ",") + ")";
|
where = entryColumnRemoteName() + " NOT IN (" + StringUtils.join(sqlFileNames, ",") + ")";
|
||||||
} else
|
} else
|
||||||
where = entryColumnRemoteName() + " IS NOT NULL";
|
where = entryColumnRemoteName() + " IS NOT NULL";
|
||||||
|
|
||||||
Builder builder = ContentProviderOperation.newDelete(entriesURI()).withSelection(where, null);
|
try {
|
||||||
pendingOperations.add(builder
|
return providerClient.delete(entriesURI(), where, null);
|
||||||
.withYieldAllowed(true)
|
} catch (RemoteException e) {
|
||||||
.build());
|
throw new LocalStorageException("Couldn't delete contacts locally", e);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void commit() throws LocalStorageException {
|
public int commit() throws LocalStorageException {
|
||||||
super.commit();
|
int affected = super.commit();
|
||||||
|
|
||||||
// update group details for groups we have just created
|
// update group details for groups we have just created
|
||||||
Uri groupsUri = syncAdapterURI(Groups.CONTENT_URI);
|
Uri groupsUri = syncAdapterURI(Groups.CONTENT_URI);
|
||||||
@ -175,11 +171,13 @@ public class LocalAddressBook extends LocalCollection<Contact> {
|
|||||||
.withValue(Groups.TITLE, sourceID)
|
.withValue(Groups.TITLE, sourceID)
|
||||||
.withValue(Groups.GROUP_VISIBLE, 1)
|
.withValue(Groups.GROUP_VISIBLE, 1)
|
||||||
.build());
|
.build());
|
||||||
super.commit();
|
affected += super.commit();
|
||||||
}
|
}
|
||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
throw new LocalStorageException("Couldn't update group names", e);
|
throw new LocalStorageException("Couldn't update group names", e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return affected;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -542,11 +540,11 @@ public class LocalAddressBook extends LocalCollection<Contact> {
|
|||||||
Log.d(TAG, "Group not found (maybe deleted)");
|
Log.d(TAG, "Group not found (maybe deleted)");
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void populateURL(Contact c, ContentValues row) throws RemoteException {
|
protected void populateURL(Contact c, ContentValues row) {
|
||||||
c.getURLs().add(row.getAsString(Website.URL));
|
c.getURLs().add(row.getAsString(Website.URL));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void populateEvent(Contact c, ContentValues row) throws RemoteException {
|
protected void populateEvent(Contact c, ContentValues row) {
|
||||||
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd", Locale.US);
|
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd", Locale.US);
|
||||||
try {
|
try {
|
||||||
Date date = formatter.parse(row.getAsString(CommonDataKinds.Event.START_DATE));
|
Date date = formatter.parse(row.getAsString(CommonDataKinds.Event.START_DATE));
|
||||||
@ -563,7 +561,7 @@ public class LocalAddressBook extends LocalCollection<Contact> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void populateRelation(Contact c, ContentValues row) throws RemoteException {
|
protected void populateRelation(Contact c, ContentValues row) {
|
||||||
String name = row.getAsString(Relation.NAME);
|
String name = row.getAsString(Relation.NAME);
|
||||||
|
|
||||||
// don't process empty relations
|
// don't process empty relations
|
||||||
@ -634,7 +632,7 @@ public class LocalAddressBook extends LocalCollection<Contact> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void populateSipAddress(Contact c, ContentValues row) throws RemoteException {
|
protected void populateSipAddress(Contact c, ContentValues row) {
|
||||||
try {
|
try {
|
||||||
Impp impp = new Impp("sip:" + row.getAsString(SipAddress.SIP_ADDRESS));
|
Impp impp = new Impp("sip:" + row.getAsString(SipAddress.SIP_ADDRESS));
|
||||||
switch (row.getAsInteger(SipAddress.TYPE)) {
|
switch (row.getAsInteger(SipAddress.TYPE)) {
|
||||||
@ -971,11 +969,11 @@ public class LocalAddressBook extends LocalCollection<Contact> {
|
|||||||
lineLocality = StringUtils.join(new String[] { address.getPostalCode(), address.getLocality() }, " ");
|
lineLocality = StringUtils.join(new String[] { address.getPostalCode(), address.getLocality() }, " ");
|
||||||
|
|
||||||
List<String> lines = new LinkedList<>();
|
List<String> lines = new LinkedList<>();
|
||||||
if (lineStreet != null)
|
if (StringUtils.isNotBlank(lineStreet))
|
||||||
lines.add(lineStreet);
|
lines.add(lineStreet);
|
||||||
if (address.getRegion() != null && !address.getRegion().isEmpty())
|
if (address.getRegion() != null && !address.getRegion().isEmpty())
|
||||||
lines.add(address.getRegion());
|
lines.add(address.getRegion());
|
||||||
if (lineLocality != null)
|
if (StringUtils.isNotBlank(lineLocality))
|
||||||
lines.add(lineLocality);
|
lines.add(lineLocality);
|
||||||
|
|
||||||
formattedAddress = StringUtils.join(lines, "\n");
|
formattedAddress = StringUtils.join(lines, "\n");
|
||||||
@ -1088,7 +1086,7 @@ public class LocalAddressBook extends LocalCollection<Contact> {
|
|||||||
String lowerCase = StringUtils.lowerCase(xname, Locale.US),
|
String lowerCase = StringUtils.lowerCase(xname, Locale.US),
|
||||||
withoutPrefix = StringUtils.removeStart(lowerCase, "x-"),
|
withoutPrefix = StringUtils.removeStart(lowerCase, "x-"),
|
||||||
withSpaces = StringUtils.replace(withoutPrefix, "_", " ");
|
withSpaces = StringUtils.replace(withoutPrefix, "_", " ");
|
||||||
return WordUtils.capitalize(withSpaces);
|
return StringUtils.capitalize(withSpaces);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -28,21 +28,14 @@ import android.provider.CalendarContract.Attendees;
|
|||||||
import android.provider.CalendarContract.Calendars;
|
import android.provider.CalendarContract.Calendars;
|
||||||
import android.provider.CalendarContract.Events;
|
import android.provider.CalendarContract.Events;
|
||||||
import android.provider.CalendarContract.Reminders;
|
import android.provider.CalendarContract.Reminders;
|
||||||
import android.provider.ContactsContract;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import net.fortuna.ical4j.model.Date;
|
import net.fortuna.ical4j.model.Date;
|
||||||
import net.fortuna.ical4j.model.DateList;
|
|
||||||
import net.fortuna.ical4j.model.DateTime;
|
import net.fortuna.ical4j.model.DateTime;
|
||||||
import net.fortuna.ical4j.model.Dur;
|
import net.fortuna.ical4j.model.Dur;
|
||||||
import net.fortuna.ical4j.model.Parameter;
|
import net.fortuna.ical4j.model.Parameter;
|
||||||
import net.fortuna.ical4j.model.ParameterList;
|
import net.fortuna.ical4j.model.ParameterList;
|
||||||
import net.fortuna.ical4j.model.Period;
|
|
||||||
import net.fortuna.ical4j.model.PeriodList;
|
|
||||||
import net.fortuna.ical4j.model.PropertyList;
|
import net.fortuna.ical4j.model.PropertyList;
|
||||||
import net.fortuna.ical4j.model.TimeZone;
|
|
||||||
import net.fortuna.ical4j.model.TimeZoneRegistry;
|
|
||||||
import net.fortuna.ical4j.model.TimeZoneRegistryFactory;
|
|
||||||
import net.fortuna.ical4j.model.component.VAlarm;
|
import net.fortuna.ical4j.model.component.VAlarm;
|
||||||
import net.fortuna.ical4j.model.parameter.Cn;
|
import net.fortuna.ical4j.model.parameter.Cn;
|
||||||
import net.fortuna.ical4j.model.parameter.CuType;
|
import net.fortuna.ical4j.model.parameter.CuType;
|
||||||
@ -51,7 +44,6 @@ import net.fortuna.ical4j.model.parameter.Role;
|
|||||||
import net.fortuna.ical4j.model.property.Action;
|
import net.fortuna.ical4j.model.property.Action;
|
||||||
import net.fortuna.ical4j.model.property.Attendee;
|
import net.fortuna.ical4j.model.property.Attendee;
|
||||||
import net.fortuna.ical4j.model.property.DateListProperty;
|
import net.fortuna.ical4j.model.property.DateListProperty;
|
||||||
import net.fortuna.ical4j.model.property.DateProperty;
|
|
||||||
import net.fortuna.ical4j.model.property.Description;
|
import net.fortuna.ical4j.model.property.Description;
|
||||||
import net.fortuna.ical4j.model.property.Duration;
|
import net.fortuna.ical4j.model.property.Duration;
|
||||||
import net.fortuna.ical4j.model.property.ExDate;
|
import net.fortuna.ical4j.model.property.ExDate;
|
||||||
@ -61,19 +53,14 @@ 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.RecurrenceId;
|
import net.fortuna.ical4j.model.property.RecurrenceId;
|
||||||
import net.fortuna.ical4j.model.property.Status;
|
import net.fortuna.ical4j.model.property.Status;
|
||||||
import net.fortuna.ical4j.util.TimeZones;
|
|
||||||
|
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import java.net.MalformedURLException;
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
import java.net.URL;
|
|
||||||
import java.text.ParseException;
|
import java.text.ParseException;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.regex.Matcher;
|
|
||||||
import java.util.regex.Pattern;
|
|
||||||
|
|
||||||
import at.bitfire.davdroid.DAVUtils;
|
import at.bitfire.davdroid.DAVUtils;
|
||||||
import at.bitfire.davdroid.DateUtils;
|
import at.bitfire.davdroid.DateUtils;
|
||||||
@ -91,7 +78,7 @@ public class LocalCalendar extends LocalCollection<Event> {
|
|||||||
@Getter protected String url;
|
@Getter protected String url;
|
||||||
@Getter protected long id;
|
@Getter protected long id;
|
||||||
|
|
||||||
protected static String COLLECTION_COLUMN_CTAG = Calendars.CAL_SYNC1;
|
protected static final String COLLECTION_COLUMN_CTAG = Calendars.CAL_SYNC1;
|
||||||
|
|
||||||
|
|
||||||
/* database fields */
|
/* database fields */
|
||||||
@ -118,7 +105,7 @@ public class LocalCalendar extends LocalCollection<Event> {
|
|||||||
|
|
||||||
@SuppressLint("InlinedApi")
|
@SuppressLint("InlinedApi")
|
||||||
public static Uri create(Account account, ContentResolver resolver, ServerInfo.ResourceInfo info) throws LocalStorageException {
|
public static Uri create(Account account, ContentResolver resolver, ServerInfo.ResourceInfo info) throws LocalStorageException {
|
||||||
final ContentProviderClient client = resolver.acquireContentProviderClient(CalendarContract.AUTHORITY);
|
@Cleanup("release") final ContentProviderClient client = resolver.acquireContentProviderClient(CalendarContract.AUTHORITY);
|
||||||
if (client == null)
|
if (client == null)
|
||||||
throw new LocalStorageException("No Calendar Provider found (Calendar app disabled?)");
|
throw new LocalStorageException("No Calendar Provider found (Calendar app disabled?)");
|
||||||
|
|
||||||
@ -168,7 +155,7 @@ public class LocalCalendar extends LocalCollection<Event> {
|
|||||||
return calendars.toArray(new LocalCalendar[calendars.size()]);
|
return calendars.toArray(new LocalCalendar[calendars.size()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public LocalCalendar(Account account, ContentProviderClient providerClient, long id, String url) throws RemoteException {
|
public LocalCalendar(Account account, ContentProviderClient providerClient, long id, String url) {
|
||||||
super(account, providerClient);
|
super(account, providerClient);
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.url = url;
|
this.url = url;
|
||||||
@ -229,7 +216,7 @@ public class LocalCalendar extends LocalCollection<Event> {
|
|||||||
return new Event(localID, resourceName, eTag);
|
return new Event(localID, resourceName, eTag);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void deleteAllExceptRemoteNames(Resource[] remoteResources) {
|
public int deleteAllExceptRemoteNames(Resource[] remoteResources) throws LocalStorageException {
|
||||||
List<String> sqlFileNames = new LinkedList<>();
|
List<String> sqlFileNames = new LinkedList<>();
|
||||||
for (Resource res : remoteResources)
|
for (Resource res : remoteResources)
|
||||||
sqlFileNames.add(DatabaseUtils.sqlEscapeString(res.getName()));
|
sqlFileNames.add(DatabaseUtils.sqlEscapeString(res.getName()));
|
||||||
@ -256,6 +243,7 @@ public class LocalCalendar extends LocalCollection<Event> {
|
|||||||
.withYieldAllowed(true)
|
.withYieldAllowed(true)
|
||||||
.build()
|
.build()
|
||||||
);
|
);
|
||||||
|
return commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -454,7 +442,7 @@ public class LocalCalendar extends LocalCollection<Event> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void populateAttendee(Event event, ContentValues values) throws RemoteException {
|
void populateAttendee(Event event, ContentValues values) {
|
||||||
try {
|
try {
|
||||||
Attendee attendee = new Attendee(new URI("mailto", values.getAsString(Attendees.ATTENDEE_EMAIL), null));
|
Attendee attendee = new Attendee(new URI("mailto", values.getAsString(Attendees.ATTENDEE_EMAIL), null));
|
||||||
ParameterList params = attendee.getParameters();
|
ParameterList params = attendee.getParameters();
|
||||||
@ -504,7 +492,7 @@ public class LocalCalendar extends LocalCollection<Event> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void populateReminder(Event event, ContentValues row) throws RemoteException {
|
void populateReminder(Event event, ContentValues row) {
|
||||||
VAlarm alarm = new VAlarm(new Dur(0, 0, -row.getAsInteger(Reminders.MINUTES), 0));
|
VAlarm alarm = new VAlarm(new Dur(0, 0, -row.getAsInteger(Reminders.MINUTES), 0));
|
||||||
|
|
||||||
PropertyList props = alarm.getProperties();
|
PropertyList props = alarm.getProperties();
|
||||||
|
@ -11,6 +11,7 @@ import android.accounts.Account;
|
|||||||
import android.content.ContentProviderClient;
|
import android.content.ContentProviderClient;
|
||||||
import android.content.ContentProviderOperation;
|
import android.content.ContentProviderOperation;
|
||||||
import android.content.ContentProviderOperation.Builder;
|
import android.content.ContentProviderOperation.Builder;
|
||||||
|
import android.content.ContentProviderResult;
|
||||||
import android.content.ContentUris;
|
import android.content.ContentUris;
|
||||||
import android.content.ContentValues;
|
import android.content.ContentValues;
|
||||||
import android.content.OperationApplicationException;
|
import android.content.OperationApplicationException;
|
||||||
@ -21,14 +22,13 @@ import android.os.RemoteException;
|
|||||||
import android.provider.CalendarContract;
|
import android.provider.CalendarContract;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import lombok.Cleanup;
|
import lombok.Cleanup;
|
||||||
import lombok.Getter;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a locally-stored synchronizable collection (for instance, the
|
* Represents a locally-stored synchronizable collection (for instance, the
|
||||||
@ -40,9 +40,9 @@ import lombok.Getter;
|
|||||||
public abstract class LocalCollection<T extends Resource> {
|
public abstract class LocalCollection<T extends Resource> {
|
||||||
private static final String TAG = "davdroid.Collection";
|
private static final String TAG = "davdroid.Collection";
|
||||||
|
|
||||||
protected Account account;
|
final protected Account account;
|
||||||
protected ContentProviderClient providerClient;
|
final protected ContentProviderClient providerClient;
|
||||||
protected ArrayList<ContentProviderOperation> pendingOperations = new ArrayList<ContentProviderOperation>();
|
final protected ArrayList<ContentProviderOperation> pendingOperations = new ArrayList<>();
|
||||||
|
|
||||||
|
|
||||||
// database fields
|
// database fields
|
||||||
@ -269,8 +269,8 @@ public abstract class LocalCollection<T extends Resource> {
|
|||||||
* @return the new resource object */
|
* @return the new resource object */
|
||||||
abstract public T newResource(long localID, String resourceName, String eTag);
|
abstract public T newResource(long localID, String resourceName, String eTag);
|
||||||
|
|
||||||
/** Enqueues adding the resource (including all data) to the local collection. Requires commit(). */
|
/** Enqueues adding the resource (including all data) to the local collection. */
|
||||||
public void add(Resource resource) {
|
public void add(Resource resource) throws LocalStorageException {
|
||||||
int idx = pendingOperations.size();
|
int idx = pendingOperations.size();
|
||||||
pendingOperations.add(
|
pendingOperations.add(
|
||||||
buildEntry(ContentProviderOperation.newInsert(entriesURI()), resource, false)
|
buildEntry(ContentProviderOperation.newInsert(entriesURI()), resource, false)
|
||||||
@ -278,6 +278,7 @@ public abstract class LocalCollection<T extends Resource> {
|
|||||||
.build());
|
.build());
|
||||||
|
|
||||||
addDataRows(resource, -1, idx);
|
addDataRows(resource, -1, idx);
|
||||||
|
commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Enqueues updating an existing resource in the local collection. The resource will be found by
|
/** Enqueues updating an existing resource in the local collection. The resource will be found by
|
||||||
@ -292,6 +293,7 @@ public abstract class LocalCollection<T extends Resource> {
|
|||||||
|
|
||||||
removeDataRows(localResource);
|
removeDataRows(localResource);
|
||||||
addDataRows(remoteResource, localResource.getLocalID(), -1);
|
addDataRows(remoteResource, localResource.getLocalID(), -1);
|
||||||
|
commit();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Enqueues deleting a resource from the local collection. Requires commit(). */
|
/** Enqueues deleting a resource from the local collection. Requires commit(). */
|
||||||
@ -303,10 +305,11 @@ public abstract class LocalCollection<T extends Resource> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Enqueues deleting all resources except the give ones from the local collection. Requires commit().
|
* Deletes all resources except the give ones from the local collection.
|
||||||
* @param remoteResources resources with these remote file names will be kept
|
* @param remoteResources resources with these remote file names will be kept
|
||||||
|
* @return number of deleted resources
|
||||||
*/
|
*/
|
||||||
public void deleteAllExceptRemoteNames(Resource[] remoteResources) {
|
public int deleteAllExceptRemoteNames(Resource[] remoteResources) throws LocalStorageException {
|
||||||
final String where;
|
final String where;
|
||||||
|
|
||||||
if (remoteResources.length != 0) {
|
if (remoteResources.length != 0) {
|
||||||
@ -319,13 +322,17 @@ public abstract class LocalCollection<T extends Resource> {
|
|||||||
// delete all entries
|
// delete all entries
|
||||||
where = entryColumnRemoteName() + " IS NOT NULL";
|
where = entryColumnRemoteName() + " IS NOT NULL";
|
||||||
|
|
||||||
ContentProviderOperation.Builder builder = ContentProviderOperation.newDelete(entriesURI())
|
try {
|
||||||
.withSelection( // restrict deletion to parent collection
|
return providerClient.delete(
|
||||||
entryColumnParentID() + "=? AND (" + where + ')',
|
entriesURI(),
|
||||||
new String[] { String.valueOf(getId()) }
|
// restrict deletion to parent collection
|
||||||
);
|
entryColumnParentID() + "=? AND (" + where + ')',
|
||||||
pendingOperations.add(builder.withYieldAllowed(true).build());
|
new String[] { String.valueOf(getId()) }
|
||||||
}
|
);
|
||||||
|
} catch (RemoteException e) {
|
||||||
|
throw new LocalStorageException("Couldn't delete local resources", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Updates the locally-known ETag of a resource. */
|
/** Updates the locally-known ETag of a resource. */
|
||||||
@ -350,17 +357,21 @@ public abstract class LocalCollection<T extends Resource> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/** Commits enqueued operations to the content provider (for batch operations). */
|
/** Commits enqueued operations to the content provider (for batch operations). */
|
||||||
public void commit() throws LocalStorageException {
|
public int commit() throws LocalStorageException {
|
||||||
|
int affected = 0;
|
||||||
if (!pendingOperations.isEmpty())
|
if (!pendingOperations.isEmpty())
|
||||||
try {
|
try {
|
||||||
Log.d(TAG, "Committing " + pendingOperations.size() + " operations");
|
Log.d(TAG, "Committing " + pendingOperations.size() + " operations ...");
|
||||||
providerClient.applyBatch(pendingOperations);
|
ContentProviderResult[] results = providerClient.applyBatch(pendingOperations);
|
||||||
|
for (ContentProviderResult result : results)
|
||||||
|
if (result != null && result.count != null)
|
||||||
|
affected += result.count;
|
||||||
|
Log.d(TAG, "... " + affected + " row(s) affected");
|
||||||
pendingOperations.clear();
|
pendingOperations.clear();
|
||||||
} catch (RemoteException ex) {
|
} catch(OperationApplicationException | RemoteException ex) {
|
||||||
throw new LocalStorageException(ex);
|
|
||||||
} catch(OperationApplicationException ex) {
|
|
||||||
throw new LocalStorageException(ex);
|
throw new LocalStorageException(ex);
|
||||||
}
|
}
|
||||||
|
return affected;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -24,17 +24,15 @@ import net.fortuna.ical4j.model.Date;
|
|||||||
import net.fortuna.ical4j.model.DateTime;
|
import net.fortuna.ical4j.model.DateTime;
|
||||||
import net.fortuna.ical4j.model.Dur;
|
import net.fortuna.ical4j.model.Dur;
|
||||||
import net.fortuna.ical4j.model.TimeZone;
|
import net.fortuna.ical4j.model.TimeZone;
|
||||||
import net.fortuna.ical4j.model.TimeZoneRegistry;
|
|
||||||
import net.fortuna.ical4j.model.property.Clazz;
|
import net.fortuna.ical4j.model.property.Clazz;
|
||||||
import net.fortuna.ical4j.model.property.Completed;
|
import net.fortuna.ical4j.model.property.Completed;
|
||||||
import net.fortuna.ical4j.model.property.Created;
|
|
||||||
import net.fortuna.ical4j.model.property.DtStart;
|
import net.fortuna.ical4j.model.property.DtStart;
|
||||||
import net.fortuna.ical4j.model.property.Due;
|
import net.fortuna.ical4j.model.property.Due;
|
||||||
import net.fortuna.ical4j.model.property.Duration;
|
import net.fortuna.ical4j.model.property.Duration;
|
||||||
import net.fortuna.ical4j.model.property.Status;
|
import net.fortuna.ical4j.model.property.Status;
|
||||||
import net.fortuna.ical4j.util.TimeZones;
|
import net.fortuna.ical4j.util.TimeZones;
|
||||||
|
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.dmfs.provider.tasks.TaskContract;
|
import org.dmfs.provider.tasks.TaskContract;
|
||||||
|
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
@ -52,7 +50,7 @@ public class LocalTaskList extends LocalCollection<Task> {
|
|||||||
|
|
||||||
public static final String TASKS_AUTHORITY = "org.dmfs.tasks";
|
public static final String TASKS_AUTHORITY = "org.dmfs.tasks";
|
||||||
|
|
||||||
protected static String COLLECTION_COLUMN_CTAG = TaskContract.TaskLists.SYNC1;
|
protected static final String COLLECTION_COLUMN_CTAG = TaskContract.TaskLists.SYNC1;
|
||||||
|
|
||||||
@Override protected Uri entriesURI() { return syncAdapterURI(TaskContract.Tasks.getContentUri(TASKS_AUTHORITY)); }
|
@Override protected Uri entriesURI() { return syncAdapterURI(TaskContract.Tasks.getContentUri(TASKS_AUTHORITY)); }
|
||||||
@Override protected String entryColumnAccountType() { return TaskContract.Tasks.ACCOUNT_TYPE; }
|
@Override protected String entryColumnAccountType() { return TaskContract.Tasks.ACCOUNT_TYPE; }
|
||||||
@ -67,7 +65,7 @@ public class LocalTaskList extends LocalCollection<Task> {
|
|||||||
|
|
||||||
|
|
||||||
public static Uri create(Account account, ContentResolver resolver, ServerInfo.ResourceInfo info) throws LocalStorageException {
|
public static Uri create(Account account, ContentResolver resolver, ServerInfo.ResourceInfo info) throws LocalStorageException {
|
||||||
final ContentProviderClient client = resolver.acquireContentProviderClient(TASKS_AUTHORITY);
|
@Cleanup("release") final ContentProviderClient client = resolver.acquireContentProviderClient(TASKS_AUTHORITY);
|
||||||
if (client == null)
|
if (client == null)
|
||||||
throw new LocalStorageException("No tasks provider found");
|
throw new LocalStorageException("No tasks provider found");
|
||||||
|
|
||||||
@ -101,7 +99,7 @@ public class LocalTaskList extends LocalCollection<Task> {
|
|||||||
return taskList.toArray(new LocalTaskList[taskList.size()]);
|
return taskList.toArray(new LocalTaskList[taskList.size()]);
|
||||||
}
|
}
|
||||||
|
|
||||||
public LocalTaskList(Account account, ContentProviderClient providerClient, long id, String url) throws RemoteException {
|
public LocalTaskList(Account account, ContentProviderClient providerClient, long id, String url) {
|
||||||
super(account, providerClient);
|
super(account, providerClient);
|
||||||
this.id = id;
|
this.id = id;
|
||||||
this.url = url;
|
this.url = url;
|
||||||
|
@ -16,11 +16,7 @@ public class RecordNotFoundException extends LocalStorageException {
|
|||||||
|
|
||||||
private static final String detailMessage = "Record not found in local content provider";
|
private static final String detailMessage = "Record not found in local content provider";
|
||||||
|
|
||||||
|
|
||||||
RecordNotFoundException(Throwable ex) {
|
|
||||||
super(detailMessage, ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
RecordNotFoundException() {
|
RecordNotFoundException() {
|
||||||
super(detailMessage);
|
super(detailMessage);
|
||||||
}
|
}
|
||||||
|
@ -7,11 +7,8 @@
|
|||||||
*/
|
*/
|
||||||
package at.bitfire.davdroid.resource;
|
package at.bitfire.davdroid.resource;
|
||||||
|
|
||||||
import android.accounts.Account;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import net.fortuna.ical4j.model.ValidationException;
|
|
||||||
|
|
||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.apache.http.impl.client.CloseableHttpClient;
|
import org.apache.http.impl.client.CloseableHttpClient;
|
||||||
|
|
||||||
@ -25,10 +22,7 @@ import java.util.LinkedList;
|
|||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import at.bitfire.davdroid.URIUtils;
|
import at.bitfire.davdroid.URIUtils;
|
||||||
import at.bitfire.davdroid.syncadapter.AccountSettings;
|
|
||||||
import at.bitfire.davdroid.webdav.DavCalendarQuery;
|
|
||||||
import at.bitfire.davdroid.webdav.DavException;
|
import at.bitfire.davdroid.webdav.DavException;
|
||||||
import at.bitfire.davdroid.webdav.DavFilter;
|
|
||||||
import at.bitfire.davdroid.webdav.DavMultiget;
|
import at.bitfire.davdroid.webdav.DavMultiget;
|
||||||
import at.bitfire.davdroid.webdav.DavNoContentException;
|
import at.bitfire.davdroid.webdav.DavNoContentException;
|
||||||
import at.bitfire.davdroid.webdav.HttpException;
|
import at.bitfire.davdroid.webdav.HttpException;
|
||||||
@ -38,7 +32,6 @@ import at.bitfire.davdroid.webdav.WebDavResource.PutMode;
|
|||||||
import ezvcard.io.text.VCardParseException;
|
import ezvcard.io.text.VCardParseException;
|
||||||
import lombok.Cleanup;
|
import lombok.Cleanup;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Represents a remotely stored synchronizable collection (collection as in
|
* Represents a remotely stored synchronizable collection (collection as in
|
||||||
@ -49,7 +42,6 @@ import lombok.Setter;
|
|||||||
public abstract class RemoteCollection<T extends Resource> {
|
public abstract class RemoteCollection<T extends Resource> {
|
||||||
private static final String TAG = "davdroid.resource";
|
private static final String TAG = "davdroid.resource";
|
||||||
|
|
||||||
CloseableHttpClient httpClient;
|
|
||||||
URI baseURI;
|
URI baseURI;
|
||||||
@Getter WebDavResource collection;
|
@Getter WebDavResource collection;
|
||||||
|
|
||||||
@ -59,8 +51,6 @@ public abstract class RemoteCollection<T extends Resource> {
|
|||||||
abstract protected T newResourceSkeleton(String name, String ETag);
|
abstract protected T newResourceSkeleton(String name, String ETag);
|
||||||
|
|
||||||
public RemoteCollection(CloseableHttpClient httpClient, String baseURL, String user, String password, boolean preemptiveAuth) throws URISyntaxException {
|
public RemoteCollection(CloseableHttpClient httpClient, String baseURL, String user, String password, boolean preemptiveAuth) throws URISyntaxException {
|
||||||
this.httpClient = httpClient;
|
|
||||||
|
|
||||||
baseURI = URIUtils.parseURI(baseURL, false);
|
baseURI = URIUtils.parseURI(baseURL, false);
|
||||||
collection = new WebDavResource(httpClient, baseURI, user, password, preemptiveAuth);
|
collection = new WebDavResource(httpClient, baseURI, user, password, preemptiveAuth);
|
||||||
}
|
}
|
||||||
@ -101,12 +91,12 @@ public abstract class RemoteCollection<T extends Resource> {
|
|||||||
else
|
else
|
||||||
collection.propfind(HttpPropfind.Mode.MEMBERS_ETAG);
|
collection.propfind(HttpPropfind.Mode.MEMBERS_ETAG);
|
||||||
|
|
||||||
List<T> resources = new LinkedList<T>();
|
List<T> resources = new LinkedList<>();
|
||||||
if (collection.getMembers() != null)
|
if (collection.getMembers() != null)
|
||||||
for (WebDavResource member : collection.getMembers())
|
for (WebDavResource member : collection.getMembers())
|
||||||
resources.add(newResourceSkeleton(member.getName(), member.getETag()));
|
resources.add(newResourceSkeleton(member.getName(), member.getETag()));
|
||||||
|
|
||||||
return resources.toArray(new Resource[0]);
|
return resources.toArray(new Resource[resources.size()]);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -115,16 +105,16 @@ public abstract class RemoteCollection<T extends Resource> {
|
|||||||
public Resource[] multiGet(Resource[] resources) throws URISyntaxException, IOException, DavException, HttpException {
|
public Resource[] multiGet(Resource[] resources) throws URISyntaxException, IOException, DavException, HttpException {
|
||||||
try {
|
try {
|
||||||
if (resources.length == 1)
|
if (resources.length == 1)
|
||||||
return (T[]) new Resource[] { get(resources[0]) };
|
return new Resource[] { get(resources[0]) };
|
||||||
|
|
||||||
Log.i(TAG, "Multi-getting " + resources.length + " remote resource(s)");
|
Log.i(TAG, "Multi-getting " + resources.length + " remote resource(s)");
|
||||||
|
|
||||||
LinkedList<String> names = new LinkedList<String>();
|
LinkedList<String> names = new LinkedList<>();
|
||||||
for (Resource resource : resources)
|
for (Resource resource : resources)
|
||||||
names.add(resource.getName());
|
names.add(resource.getName());
|
||||||
|
|
||||||
LinkedList<T> foundResources = new LinkedList<T>();
|
LinkedList<T> foundResources = new LinkedList<>();
|
||||||
collection.multiGet(multiGetType(), names.toArray(new String[0]));
|
collection.multiGet(multiGetType(), names.toArray(new String[names.size()]));
|
||||||
if (collection.getMembers() == null)
|
if (collection.getMembers() == null)
|
||||||
throw new DavNoContentException();
|
throw new DavNoContentException();
|
||||||
|
|
||||||
@ -142,7 +132,7 @@ public abstract class RemoteCollection<T extends Resource> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return foundResources.toArray(new Resource[0]);
|
return foundResources.toArray(new Resource[foundResources.size()]);
|
||||||
} catch (InvalidResourceException e) {
|
} catch (InvalidResourceException e) {
|
||||||
Log.e(TAG, "Couldn't parse entity from GET", e);
|
Log.e(TAG, "Couldn't parse entity from GET", e);
|
||||||
}
|
}
|
||||||
@ -172,7 +162,7 @@ public abstract class RemoteCollection<T extends Resource> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// returns ETag of the created resource, if returned by server
|
// returns ETag of the created resource, if returned by server
|
||||||
public String add(Resource res) throws URISyntaxException, IOException, HttpException, ValidationException {
|
public String add(Resource res) throws URISyntaxException, IOException, HttpException {
|
||||||
WebDavResource member = new WebDavResource(collection, res.getName(), res.getETag());
|
WebDavResource member = new WebDavResource(collection, res.getName(), res.getETag());
|
||||||
member.setContentType(res.getMimeType());
|
member.setContentType(res.getMimeType());
|
||||||
|
|
||||||
@ -193,7 +183,7 @@ public abstract class RemoteCollection<T extends Resource> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// returns ETag of the updated resource, if returned by server
|
// returns ETag of the updated resource, if returned by server
|
||||||
public String update(Resource res) throws URISyntaxException, IOException, HttpException, ValidationException {
|
public String update(Resource res) throws URISyntaxException, IOException, HttpException {
|
||||||
WebDavResource member = new WebDavResource(collection, res.getName(), res.getETag());
|
WebDavResource member = new WebDavResource(collection, res.getName(), res.getETag());
|
||||||
member.setContentType(res.getMimeType());
|
member.setContentType(res.getMimeType());
|
||||||
|
|
||||||
@ -211,22 +201,22 @@ public abstract class RemoteCollection<T extends Resource> {
|
|||||||
|
|
||||||
Resource.AssetDownloader getDownloader() {
|
Resource.AssetDownloader getDownloader() {
|
||||||
return new Resource.AssetDownloader() {
|
return new Resource.AssetDownloader() {
|
||||||
@Override
|
@Override
|
||||||
public byte[] download(URI uri) throws URISyntaxException, IOException, HttpException, DavException {
|
public byte[] download(URI uri) throws URISyntaxException, IOException, HttpException, DavException {
|
||||||
if (!uri.isAbsolute())
|
if (!uri.isAbsolute())
|
||||||
throw new URISyntaxException(uri.toString(), "URI referenced from entity must be absolute");
|
throw new URISyntaxException(uri.toString(), "URI referenced from entity must be absolute");
|
||||||
|
|
||||||
if (uri.getScheme().equalsIgnoreCase(baseURI.getScheme()) &&
|
if (uri.getScheme().equalsIgnoreCase(baseURI.getScheme()) &&
|
||||||
uri.getAuthority().equalsIgnoreCase(baseURI.getAuthority())) {
|
uri.getAuthority().equalsIgnoreCase(baseURI.getAuthority())) {
|
||||||
// resource is on same server, send Authorization
|
// resource is on same server, send Authorization
|
||||||
WebDavResource file = new WebDavResource(collection, uri);
|
WebDavResource file = new WebDavResource(collection, uri);
|
||||||
file.get("image/*");
|
file.get("image/*");
|
||||||
return file.getContent();
|
return file.getContent();
|
||||||
} else {
|
} else {
|
||||||
// resource is on an external server, don't send Authorization
|
// resource is on an external server, don't send Authorization
|
||||||
return IOUtils.toByteArray(uri);
|
return IOUtils.toByteArray(uri);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,7 +12,6 @@ import java.io.IOException;
|
|||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
import java.net.URL;
|
|
||||||
|
|
||||||
import at.bitfire.davdroid.webdav.DavException;
|
import at.bitfire.davdroid.webdav.DavException;
|
||||||
import at.bitfire.davdroid.webdav.HttpException;
|
import at.bitfire.davdroid.webdav.HttpException;
|
||||||
@ -58,6 +57,6 @@ public abstract class Resource {
|
|||||||
|
|
||||||
|
|
||||||
public interface AssetDownloader {
|
public interface AssetDownloader {
|
||||||
public byte[] download(URI url) throws URISyntaxException, IOException, HttpException, DavException;
|
byte[] download(URI url) throws URISyntaxException, IOException, HttpException, DavException;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,6 @@
|
|||||||
*/
|
*/
|
||||||
package at.bitfire.davdroid.resource;
|
package at.bitfire.davdroid.resource;
|
||||||
|
|
||||||
import java.io.Serializable;
|
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
@ -20,10 +19,6 @@ import lombok.RequiredArgsConstructor;
|
|||||||
@RequiredArgsConstructor(suppressConstructorProperties=true)
|
@RequiredArgsConstructor(suppressConstructorProperties=true)
|
||||||
@Data
|
@Data
|
||||||
public class ServerInfo {
|
public class ServerInfo {
|
||||||
enum Scheme {
|
|
||||||
HTTP, HTTPS, MAILTO
|
|
||||||
}
|
|
||||||
|
|
||||||
final private URI baseURI;
|
final private URI baseURI;
|
||||||
final private String userName, password;
|
final private String userName, password;
|
||||||
final boolean authPreemptive;
|
final boolean authPreemptive;
|
||||||
|
@ -38,7 +38,7 @@ public class AccountAuthenticatorService extends Service {
|
|||||||
|
|
||||||
|
|
||||||
private static class AccountAuthenticator extends AbstractAccountAuthenticator {
|
private static class AccountAuthenticator extends AbstractAccountAuthenticator {
|
||||||
Context context;
|
final Context context;
|
||||||
|
|
||||||
public AccountAuthenticator(Context context) {
|
public AccountAuthenticator(Context context) {
|
||||||
super(context);
|
super(context);
|
||||||
|
@ -19,7 +19,6 @@ import android.net.Uri;
|
|||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.provider.CalendarContract;
|
import android.provider.CalendarContract;
|
||||||
import android.provider.CalendarContract.Calendars;
|
import android.provider.CalendarContract.Calendars;
|
||||||
import android.provider.ContactsContract;
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
@ -46,9 +45,9 @@ public class AccountSettings {
|
|||||||
|
|
||||||
public final static long SYNC_INTERVAL_MANUALLY = -1;
|
public final static long SYNC_INTERVAL_MANUALLY = -1;
|
||||||
|
|
||||||
Context context;
|
final Context context;
|
||||||
AccountManager accountManager;
|
final AccountManager accountManager;
|
||||||
Account account;
|
final Account account;
|
||||||
|
|
||||||
|
|
||||||
public AccountSettings(Context context, Account account) {
|
public AccountSettings(Context context, Account account) {
|
||||||
@ -78,7 +77,7 @@ public class AccountSettings {
|
|||||||
if (addressBook.isEnabled()) {
|
if (addressBook.isEnabled()) {
|
||||||
bundle.putString(KEY_ADDRESSBOOK_URL, addressBook.getURL());
|
bundle.putString(KEY_ADDRESSBOOK_URL, addressBook.getURL());
|
||||||
bundle.putString(KEY_ADDRESSBOOK_VCARD_VERSION, addressBook.getVCardVersion().getVersion());
|
bundle.putString(KEY_ADDRESSBOOK_VCARD_VERSION, addressBook.getVCardVersion().getVersion());
|
||||||
continue;
|
break;
|
||||||
}
|
}
|
||||||
return bundle;
|
return bundle;
|
||||||
}
|
}
|
||||||
|
@ -61,7 +61,7 @@ public class CalendarsSyncAdapterService extends Service {
|
|||||||
boolean preemptive = settings.getPreemptiveAuth();
|
boolean preemptive = settings.getPreemptiveAuth();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Map<LocalCollection<?>, RemoteCollection<?>> map = new HashMap<LocalCollection<?>, RemoteCollection<?>>();
|
Map<LocalCollection<?>, RemoteCollection<?>> map = new HashMap<>();
|
||||||
|
|
||||||
for (LocalCalendar calendar : LocalCalendar.findAll(account, provider)) {
|
for (LocalCalendar calendar : LocalCalendar.findAll(account, provider)) {
|
||||||
RemoteCollection<?> dav = new CalDavCalendar(httpClient, calendar.getUrl(), userName, password, preemptive);
|
RemoteCollection<?> dav = new CalDavCalendar(httpClient, calendar.getUrl(), userName, password, preemptive);
|
||||||
|
@ -67,7 +67,7 @@ public class ContactsSyncAdapterService extends Service {
|
|||||||
LocalCollection<?> database = new LocalAddressBook(account, provider, settings);
|
LocalCollection<?> database = new LocalAddressBook(account, provider, settings);
|
||||||
RemoteCollection<?> dav = new CardDavAddressBook(settings, httpClient, addressBookURL, userName, password, preemptive);
|
RemoteCollection<?> dav = new CardDavAddressBook(settings, httpClient, addressBookURL, userName, password, preemptive);
|
||||||
|
|
||||||
Map<LocalCollection<?>, RemoteCollection<?>> map = new HashMap<LocalCollection<?>, RemoteCollection<?>>();
|
Map<LocalCollection<?>, RemoteCollection<?>> map = new HashMap<>();
|
||||||
map.put(database, dav);
|
map.put(database, dav);
|
||||||
|
|
||||||
return map;
|
return map;
|
||||||
|
@ -8,8 +8,6 @@
|
|||||||
package at.bitfire.davdroid.syncadapter;
|
package at.bitfire.davdroid.syncadapter;
|
||||||
|
|
||||||
import android.accounts.Account;
|
import android.accounts.Account;
|
||||||
import android.accounts.AccountManager;
|
|
||||||
import android.annotation.SuppressLint;
|
|
||||||
import android.annotation.TargetApi;
|
import android.annotation.TargetApi;
|
||||||
import android.app.Notification;
|
import android.app.Notification;
|
||||||
import android.app.NotificationManager;
|
import android.app.NotificationManager;
|
||||||
@ -19,17 +17,15 @@ import android.content.ContentProviderClient;
|
|||||||
import android.content.ContentResolver;
|
import android.content.ContentResolver;
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.SharedPreferences;
|
|
||||||
import android.content.SyncResult;
|
import android.content.SyncResult;
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.os.AsyncTask;
|
import android.os.AsyncTask;
|
||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.preference.PreferenceManager;
|
|
||||||
import android.provider.Settings;
|
import android.provider.Settings;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import org.apache.commons.lang.exception.ExceptionUtils;
|
import org.apache.commons.lang3.exception.ExceptionUtils;
|
||||||
import org.apache.http.HttpStatus;
|
import org.apache.http.HttpStatus;
|
||||||
import org.apache.http.impl.client.CloseableHttpClient;
|
import org.apache.http.impl.client.CloseableHttpClient;
|
||||||
|
|
||||||
@ -57,7 +53,7 @@ public abstract class DavSyncAdapter extends AbstractThreadedSyncAdapter impleme
|
|||||||
|
|
||||||
@Getter private static String androidID;
|
@Getter private static String androidID;
|
||||||
|
|
||||||
protected Context context;
|
final protected Context context;
|
||||||
|
|
||||||
/* We use one static httpClient for
|
/* We use one static httpClient for
|
||||||
* - all sync adapters (CalendarsSyncAdapter, ContactsSyncAdapter)
|
* - all sync adapters (CalendarsSyncAdapter, ContactsSyncAdapter)
|
||||||
@ -120,7 +116,6 @@ public abstract class DavSyncAdapter extends AbstractThreadedSyncAdapter impleme
|
|||||||
httpClientLock.writeLock().lock();
|
httpClientLock.writeLock().lock();
|
||||||
if (httpClient == null) {
|
if (httpClient == null) {
|
||||||
Log.d(TAG, "Creating new DavHttpClient");
|
Log.d(TAG, "Creating new DavHttpClient");
|
||||||
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(getContext());
|
|
||||||
httpClient = DavHttpClient.create();
|
httpClient = DavHttpClient.create();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -129,10 +124,6 @@ public abstract class DavSyncAdapter extends AbstractThreadedSyncAdapter impleme
|
|||||||
httpClientLock.readLock().lock();
|
httpClientLock.readLock().lock();
|
||||||
httpClientLock.writeLock().unlock();
|
httpClientLock.writeLock().unlock();
|
||||||
|
|
||||||
// TODO use VCard 4.0 if possible
|
|
||||||
AccountSettings accountSettings = new AccountSettings(getContext(), account);
|
|
||||||
Log.d(TAG, "Server supports VCard version " + accountSettings.getAddressBookVCardVersion());
|
|
||||||
|
|
||||||
Exception exceptionToShow = null; // exception to show notification for
|
Exception exceptionToShow = null; // exception to show notification for
|
||||||
Intent exceptionIntent = null; // what shall happen when clicking on the exception notification
|
Intent exceptionIntent = null; // what shall happen when clicking on the exception notification
|
||||||
try {
|
try {
|
||||||
@ -199,7 +190,7 @@ public abstract class DavSyncAdapter extends AbstractThreadedSyncAdapter impleme
|
|||||||
.setContentTitle(context.getString(R.string.sync_error_title))
|
.setContentTitle(context.getString(R.string.sync_error_title))
|
||||||
.setContentText(exceptionToShow.getLocalizedMessage())
|
.setContentText(exceptionToShow.getLocalizedMessage())
|
||||||
.setContentInfo(account.name)
|
.setContentInfo(account.name)
|
||||||
.setStyle(new Notification.BigTextStyle().bigText(account.name + ":\n" + ExceptionUtils.getFullStackTrace(exceptionToShow)))
|
.setStyle(new Notification.BigTextStyle().bigText(account.name + ":\n" + ExceptionUtils.getStackTrace(exceptionToShow)))
|
||||||
.setContentIntent(contentIntent);
|
.setContentIntent(contentIntent);
|
||||||
|
|
||||||
NotificationManager notificationManager = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
|
NotificationManager notificationManager = (NotificationManager)context.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||||
|
@ -10,8 +10,6 @@ package at.bitfire.davdroid.syncadapter;
|
|||||||
import android.content.SyncResult;
|
import android.content.SyncResult;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import net.fortuna.ical4j.model.ValidationException;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
@ -33,8 +31,8 @@ public class SyncManager {
|
|||||||
|
|
||||||
private static final int MAX_MULTIGET_RESOURCES = 35;
|
private static final int MAX_MULTIGET_RESOURCES = 35;
|
||||||
|
|
||||||
protected LocalCollection<? extends Resource> local;
|
final protected LocalCollection<? extends Resource> local;
|
||||||
protected RemoteCollection<? extends Resource> remote;
|
final protected RemoteCollection<? extends Resource> remote;
|
||||||
|
|
||||||
|
|
||||||
public SyncManager(LocalCollection<? extends Resource> local, RemoteCollection<? extends Resource> remote) {
|
public SyncManager(LocalCollection<? extends Resource> local, RemoteCollection<? extends Resource> remote) {
|
||||||
@ -49,10 +47,8 @@ public class SyncManager {
|
|||||||
addedRemotely = pushNew(),
|
addedRemotely = pushNew(),
|
||||||
updatedRemotely = pushDirty();
|
updatedRemotely = pushDirty();
|
||||||
|
|
||||||
syncResult.stats.numEntries = deletedRemotely + addedRemotely + updatedRemotely;
|
|
||||||
|
|
||||||
// PHASE 2A: check if there's a reason to do a sync with remote (= forced sync or remote CTag changed)
|
// PHASE 2A: check if there's a reason to do a sync with remote (= forced sync or remote CTag changed)
|
||||||
boolean fetchCollection = syncResult.stats.numEntries > 0;
|
boolean fetchCollection = (deletedRemotely + addedRemotely + updatedRemotely) > 0;
|
||||||
if (manualSync) {
|
if (manualSync) {
|
||||||
Log.i(TAG, "Synchronization forced");
|
Log.i(TAG, "Synchronization forced");
|
||||||
fetchCollection = true;
|
fetchCollection = true;
|
||||||
@ -72,8 +68,8 @@ public class SyncManager {
|
|||||||
|
|
||||||
// PHASE 2B: detect details of remote changes
|
// PHASE 2B: detect details of remote changes
|
||||||
Log.i(TAG, "Fetching remote resource list");
|
Log.i(TAG, "Fetching remote resource list");
|
||||||
Set<Resource> remotelyAdded = new HashSet<Resource>(),
|
Set<Resource> remotelyAdded = new HashSet<>(),
|
||||||
remotelyUpdated = new HashSet<Resource>();
|
remotelyUpdated = new HashSet<>();
|
||||||
|
|
||||||
Resource[] remoteResources = remote.getMemberETags();
|
Resource[] remoteResources = remote.getMemberETags();
|
||||||
for (Resource remoteResource : remoteResources) {
|
for (Resource remoteResource : remoteResources) {
|
||||||
@ -87,13 +83,13 @@ public class SyncManager {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// PHASE 3: pull remote changes from server
|
// PHASE 3: pull remote changes from server
|
||||||
syncResult.stats.numInserts = pullNew(remotelyAdded.toArray(new Resource[0]));
|
syncResult.stats.numInserts = pullNew(remotelyAdded.toArray(new Resource[remotelyAdded.size()]));
|
||||||
syncResult.stats.numUpdates = pullChanged(remotelyUpdated.toArray(new Resource[0]));
|
syncResult.stats.numUpdates = pullChanged(remotelyUpdated.toArray(new Resource[remotelyUpdated.size()]));
|
||||||
syncResult.stats.numEntries += syncResult.stats.numInserts + syncResult.stats.numUpdates;
|
|
||||||
|
|
||||||
Log.i(TAG, "Removing non-dirty resources that are not present remotely anymore");
|
Log.i(TAG, "Removing non-dirty resources that are not present remotely anymore");
|
||||||
local.deleteAllExceptRemoteNames(remoteResources);
|
syncResult.stats.numDeletes = local.deleteAllExceptRemoteNames(remoteResources);
|
||||||
local.commit();
|
|
||||||
|
syncResult.stats.numEntries = syncResult.stats.numInserts + syncResult.stats.numUpdates + syncResult.stats.numDeletes;
|
||||||
|
|
||||||
// update collection CTag
|
// update collection CTag
|
||||||
Log.i(TAG, "Sync complete, fetching new CTag");
|
Log.i(TAG, "Sync complete, fetching new CTag");
|
||||||
@ -145,10 +141,8 @@ public class SyncManager {
|
|||||||
local.updateETag(res, eTag);
|
local.updateETag(res, eTag);
|
||||||
local.clearDirty(res);
|
local.clearDirty(res);
|
||||||
count++;
|
count++;
|
||||||
} catch(PreconditionFailedException e) {
|
} catch (PreconditionFailedException e) {
|
||||||
Log.i(TAG, "Didn't overwrite existing resource with other content");
|
Log.i(TAG, "Didn't overwrite existing resource with other content");
|
||||||
} catch (ValidationException e) {
|
|
||||||
Log.e(TAG, "Couldn't create entity for adding: " + e.toString());
|
|
||||||
} catch (RecordNotFoundException e) {
|
} catch (RecordNotFoundException e) {
|
||||||
Log.wtf(TAG, "Couldn't read new record", e);
|
Log.wtf(TAG, "Couldn't read new record", e);
|
||||||
}
|
}
|
||||||
@ -171,10 +165,8 @@ public class SyncManager {
|
|||||||
local.updateETag(res, eTag);
|
local.updateETag(res, eTag);
|
||||||
local.clearDirty(res);
|
local.clearDirty(res);
|
||||||
count++;
|
count++;
|
||||||
} catch(PreconditionFailedException e) {
|
} catch (PreconditionFailedException e) {
|
||||||
Log.i(TAG, "Locally changed resource has been changed on the server in the meanwhile");
|
Log.i(TAG, "Locally changed resource has been changed on the server in the meanwhile");
|
||||||
} catch (ValidationException e) {
|
|
||||||
Log.e(TAG, "Couldn't create entity for updating: " + e.toString());
|
|
||||||
} catch (RecordNotFoundException e) {
|
} catch (RecordNotFoundException e) {
|
||||||
Log.e(TAG, "Couldn't read dirty record", e);
|
Log.e(TAG, "Couldn't read dirty record", e);
|
||||||
}
|
}
|
||||||
@ -193,7 +185,6 @@ public class SyncManager {
|
|||||||
for (Resource res : remote.multiGet(resources)) {
|
for (Resource res : remote.multiGet(resources)) {
|
||||||
Log.d(TAG, "Adding " + res.getName());
|
Log.d(TAG, "Adding " + res.getName());
|
||||||
local.add(res);
|
local.add(res);
|
||||||
local.commit();
|
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
return count;
|
return count;
|
||||||
@ -207,7 +198,6 @@ public class SyncManager {
|
|||||||
for (Resource res : remote.multiGet(resources)) {
|
for (Resource res : remote.multiGet(resources)) {
|
||||||
Log.i(TAG, "Updating " + res.getName());
|
Log.i(TAG, "Updating " + res.getName());
|
||||||
local.updateByRemoteName(res);
|
local.updateByRemoteName(res);
|
||||||
local.commit();
|
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
return count;
|
return count;
|
||||||
|
@ -61,7 +61,7 @@ public class TasksSyncAdapterService extends Service {
|
|||||||
boolean preemptive = settings.getPreemptiveAuth();
|
boolean preemptive = settings.getPreemptiveAuth();
|
||||||
|
|
||||||
try {
|
try {
|
||||||
Map<LocalCollection<?>, RemoteCollection<?>> map = new HashMap<LocalCollection<?>, RemoteCollection<?>>();
|
Map<LocalCollection<?>, RemoteCollection<?>> map = new HashMap<>();
|
||||||
|
|
||||||
for (LocalTaskList calendar : LocalTaskList.findAll(account, provider)) {
|
for (LocalTaskList calendar : LocalTaskList.findAll(account, provider)) {
|
||||||
RemoteCollection<?> dav = new CalDavTaskList(httpClient, calendar.getUrl(), userName, password, preemptive);
|
RemoteCollection<?> dav = new CalDavTaskList(httpClient, calendar.getUrl(), userName, password, preemptive);
|
||||||
|
@ -22,8 +22,8 @@ import android.widget.TextView;
|
|||||||
|
|
||||||
import at.bitfire.davdroid.Constants;
|
import at.bitfire.davdroid.Constants;
|
||||||
import at.bitfire.davdroid.R;
|
import at.bitfire.davdroid.R;
|
||||||
import at.bitfire.davdroid.ui.setup.AddAccountActivity;
|
|
||||||
import at.bitfire.davdroid.ui.settings.SettingsActivity;
|
import at.bitfire.davdroid.ui.settings.SettingsActivity;
|
||||||
|
import at.bitfire.davdroid.ui.setup.AddAccountActivity;
|
||||||
|
|
||||||
public class MainActivity extends Activity {
|
public class MainActivity extends Activity {
|
||||||
|
|
||||||
|
@ -12,7 +12,6 @@ import android.accounts.Account;
|
|||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.FragmentManager;
|
import android.app.FragmentManager;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import at.bitfire.davdroid.R;
|
import at.bitfire.davdroid.R;
|
||||||
|
|
||||||
|
@ -9,7 +9,6 @@
|
|||||||
package at.bitfire.davdroid.ui.settings;
|
package at.bitfire.davdroid.ui.settings;
|
||||||
|
|
||||||
import android.accounts.Account;
|
import android.accounts.Account;
|
||||||
import android.os.Build;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.preference.CheckBoxPreference;
|
import android.preference.CheckBoxPreference;
|
||||||
import android.preference.EditTextPreference;
|
import android.preference.EditTextPreference;
|
||||||
@ -20,13 +19,10 @@ import android.preference.SwitchPreference;
|
|||||||
import android.provider.CalendarContract;
|
import android.provider.CalendarContract;
|
||||||
import android.provider.ContactsContract;
|
import android.provider.ContactsContract;
|
||||||
|
|
||||||
import org.dmfs.provider.tasks.TaskContract;
|
|
||||||
|
|
||||||
import at.bitfire.davdroid.R;
|
import at.bitfire.davdroid.R;
|
||||||
import at.bitfire.davdroid.resource.LocalTaskList;
|
import at.bitfire.davdroid.resource.LocalTaskList;
|
||||||
import at.bitfire.davdroid.syncadapter.AccountSettings;
|
import at.bitfire.davdroid.syncadapter.AccountSettings;
|
||||||
import ezvcard.VCardVersion;
|
import ezvcard.VCardVersion;
|
||||||
import lombok.Setter;
|
|
||||||
|
|
||||||
public class AccountFragment extends PreferenceFragment {
|
public class AccountFragment extends PreferenceFragment {
|
||||||
final static String ARG_ACCOUNT = "account";
|
final static String ARG_ACCOUNT = "account";
|
||||||
|
@ -11,10 +11,8 @@ package at.bitfire.davdroid.ui.settings;
|
|||||||
import android.accounts.Account;
|
import android.accounts.Account;
|
||||||
import android.app.Activity;
|
import android.app.Activity;
|
||||||
import android.app.FragmentTransaction;
|
import android.app.FragmentTransaction;
|
||||||
import android.app.ListFragment;
|
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.widget.ListView;
|
|
||||||
|
|
||||||
import at.bitfire.davdroid.R;
|
import at.bitfire.davdroid.R;
|
||||||
|
|
||||||
|
@ -32,7 +32,7 @@ public class SettingsScopeFragment extends ListFragment {
|
|||||||
final String[] accountNames = new String[accounts.length];
|
final String[] accountNames = new String[accounts.length];
|
||||||
for (int i = 0; i < accounts.length; i++)
|
for (int i = 0; i < accounts.length; i++)
|
||||||
accountNames[i] = accounts[i].name;
|
accountNames[i] = accounts[i].name;
|
||||||
setListAdapter(new ArrayAdapter<String>(getActivity(), android.R.layout.simple_list_item_activated_1, accountNames));
|
setListAdapter(new ArrayAdapter<>(getActivity(), android.R.layout.simple_list_item_activated_1, accountNames));
|
||||||
|
|
||||||
return super.onCreateView(inflater, container, savedInstanceState);
|
return super.onCreateView(inflater, container, savedInstanceState);
|
||||||
}
|
}
|
||||||
|
@ -142,8 +142,7 @@ public class AccountDetailsFragment extends Fragment implements TextWatcher {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPrepareOptionsMenu(Menu menu) {
|
public void onPrepareOptionsMenu(Menu menu) {
|
||||||
boolean ok = false;
|
boolean ok = editAccountName.getText().length() > 0;
|
||||||
ok = editAccountName.getText().length() > 0;
|
|
||||||
MenuItem item = menu.findItem(R.id.add_account);
|
MenuItem item = menu.findItem(R.id.add_account);
|
||||||
item.setEnabled(ok);
|
item.setEnabled(ok);
|
||||||
}
|
}
|
||||||
|
@ -14,7 +14,6 @@ import android.os.Bundle;
|
|||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuInflater;
|
import android.view.MenuInflater;
|
||||||
import android.view.MenuItem;
|
import android.view.MenuItem;
|
||||||
import android.view.View;
|
|
||||||
|
|
||||||
import at.bitfire.davdroid.Constants;
|
import at.bitfire.davdroid.Constants;
|
||||||
import at.bitfire.davdroid.R;
|
import at.bitfire.davdroid.R;
|
||||||
@ -45,11 +44,6 @@ public class AddAccountActivity extends Activity {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public void installTasksApp(View view) {
|
|
||||||
final Intent intent = new Intent(Intent.ACTION_VIEW).setData(Uri.parse("market://details?id=org.dmfs.tasks"));
|
|
||||||
startActivity(intent);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void showHelp(MenuItem item) {
|
public void showHelp(MenuItem item) {
|
||||||
startActivityForResult(new Intent(Intent.ACTION_VIEW, Uri.parse(Constants.WEB_URL_HELP)), 0);
|
startActivityForResult(new Intent(Intent.ACTION_VIEW, Uri.parse(Constants.WEB_URL_HELP)), 0);
|
||||||
}
|
}
|
||||||
|
@ -8,20 +8,11 @@
|
|||||||
|
|
||||||
package at.bitfire.davdroid.ui.setup;
|
package at.bitfire.davdroid.ui.setup;
|
||||||
|
|
||||||
import android.app.DialogFragment;
|
|
||||||
import android.app.Fragment;
|
import android.app.Fragment;
|
||||||
import android.app.FragmentManager;
|
import android.app.FragmentManager;
|
||||||
import android.app.FragmentTransaction;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.content.pm.ApplicationInfo;
|
|
||||||
import android.content.pm.PackageManager;
|
|
||||||
import android.graphics.drawable.Drawable;
|
|
||||||
import android.net.Uri;
|
|
||||||
import android.os.Bundle;
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
|
||||||
import android.text.Html;
|
import android.text.Html;
|
||||||
import android.text.method.LinkMovementMethod;
|
import android.text.method.LinkMovementMethod;
|
||||||
import android.util.Log;
|
|
||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.Menu;
|
import android.view.Menu;
|
||||||
import android.view.MenuInflater;
|
import android.view.MenuInflater;
|
||||||
@ -30,13 +21,9 @@ import android.view.View;
|
|||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.TextView;
|
import android.widget.TextView;
|
||||||
|
|
||||||
import at.bitfire.davdroid.Constants;
|
|
||||||
import at.bitfire.davdroid.R;
|
import at.bitfire.davdroid.R;
|
||||||
import at.bitfire.davdroid.resource.LocalTaskList;
|
|
||||||
|
|
||||||
public class InstallAppsFragment extends Fragment {
|
public class InstallAppsFragment extends Fragment {
|
||||||
private static final String TAG = "davdroid.setup";
|
|
||||||
|
|
||||||
// https://code.google.com/p/android/issues/detail?id=25906
|
// https://code.google.com/p/android/issues/detail?id=25906
|
||||||
|
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||||
@ -68,8 +55,6 @@ public class InstallAppsFragment extends Fragment {
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void skip() {
|
protected void skip() {
|
||||||
FragmentManager fm = getFragmentManager();
|
|
||||||
|
|
||||||
getFragmentManager().beginTransaction()
|
getFragmentManager().beginTransaction()
|
||||||
.replace(R.id.right_pane, new SelectCollectionsFragment())
|
.replace(R.id.right_pane, new SelectCollectionsFragment())
|
||||||
.addToBackStack(null)
|
.addToBackStack(null)
|
||||||
|
@ -21,7 +21,7 @@ import at.bitfire.davdroid.R;
|
|||||||
|
|
||||||
public class LoginTypeFragment extends Fragment {
|
public class LoginTypeFragment extends Fragment {
|
||||||
|
|
||||||
protected RadioButton btnTypeEmail, btnTypeURL;
|
protected RadioButton btnTypeEmail;
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -29,8 +29,7 @@ public class LoginTypeFragment extends Fragment {
|
|||||||
View v = inflater.inflate(R.layout.setup_login_type, container, false);
|
View v = inflater.inflate(R.layout.setup_login_type, container, false);
|
||||||
|
|
||||||
btnTypeEmail = (RadioButton)v.findViewById(R.id.login_type_email);
|
btnTypeEmail = (RadioButton)v.findViewById(R.id.login_type_email);
|
||||||
btnTypeURL = (RadioButton)v.findViewById(R.id.login_type_url);
|
|
||||||
|
|
||||||
setHasOptionsMenu(true);
|
setHasOptionsMenu(true);
|
||||||
|
|
||||||
return v;
|
return v;
|
||||||
|
@ -21,13 +21,12 @@ import android.view.View;
|
|||||||
import android.view.ViewGroup;
|
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.CheckBox;
|
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;
|
||||||
|
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.net.URISyntaxException;
|
import java.net.URISyntaxException;
|
||||||
@ -40,8 +39,7 @@ public class LoginURLFragment extends Fragment implements TextWatcher {
|
|||||||
protected TextView textHttpWarning;
|
protected TextView textHttpWarning;
|
||||||
protected EditText editBaseURI, editUserName, editPassword;
|
protected EditText editBaseURI, editUserName, editPassword;
|
||||||
protected CheckBox checkboxPreemptive;
|
protected CheckBox checkboxPreemptive;
|
||||||
protected Button btnNext;
|
|
||||||
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||||
|
@ -18,10 +18,9 @@ import android.util.Log;
|
|||||||
import android.view.LayoutInflater;
|
import android.view.LayoutInflater;
|
||||||
import android.view.View;
|
import android.view.View;
|
||||||
import android.view.ViewGroup;
|
import android.view.ViewGroup;
|
||||||
import android.widget.ProgressBar;
|
|
||||||
import android.widget.Toast;
|
import android.widget.Toast;
|
||||||
|
|
||||||
import org.apache.commons.lang.exception.ExceptionUtils;
|
import org.apache.commons.lang3.exception.ExceptionUtils;
|
||||||
import org.apache.http.HttpException;
|
import org.apache.http.HttpException;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
@ -43,9 +42,7 @@ public class QueryServerDialogFragment extends DialogFragment implements LoaderC
|
|||||||
EXTRA_USER_NAME = "user_name",
|
EXTRA_USER_NAME = "user_name",
|
||||||
EXTRA_PASSWORD = "password",
|
EXTRA_PASSWORD = "password",
|
||||||
EXTRA_AUTH_PREEMPTIVE = "auth_preemptive";
|
EXTRA_AUTH_PREEMPTIVE = "auth_preemptive";
|
||||||
|
|
||||||
ProgressBar progressBar;
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate(Bundle savedInstanceState) {
|
public void onCreate(Bundle savedInstanceState) {
|
||||||
super.onCreate(savedInstanceState);
|
super.onCreate(savedInstanceState);
|
||||||
|
@ -44,8 +44,8 @@ public class SelectCollectionsAdapter extends BaseAdapter implements ListAdapter
|
|||||||
TYPE_TASK_LISTS_HEADING = 4,
|
TYPE_TASK_LISTS_HEADING = 4,
|
||||||
TYPE_TASK_LISTS_ROW = 5;
|
TYPE_TASK_LISTS_ROW = 5;
|
||||||
|
|
||||||
protected Context context;
|
final protected Context context;
|
||||||
protected ServerInfo serverInfo;
|
final protected ServerInfo serverInfo;
|
||||||
@Getter protected int
|
@Getter protected int
|
||||||
nAddressBooks, nAddressBookHeadings,
|
nAddressBooks, nAddressBookHeadings,
|
||||||
nCalendars, nCalendarHeadings,
|
nCalendars, nCalendarHeadings,
|
||||||
@ -160,7 +160,6 @@ public class SelectCollectionsAdapter extends BaseAdapter implements ListAdapter
|
|||||||
}
|
}
|
||||||
|
|
||||||
// step 2: fill view with content
|
// step 2: fill view with content
|
||||||
int collectionIcon;
|
|
||||||
switch (viewType) {
|
switch (viewType) {
|
||||||
case TYPE_ADDRESS_BOOKS_ROW:
|
case TYPE_ADDRESS_BOOKS_ROW:
|
||||||
setContent((CheckedTextView)v, R.drawable.addressbook, (ServerInfo.ResourceInfo)getItem(position));
|
setContent((CheckedTextView)v, R.drawable.addressbook, (ServerInfo.ResourceInfo)getItem(position));
|
||||||
|
@ -1,63 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright © 2013 – 2015 Ricki Hirner (bitfire web engineering).
|
|
||||||
* All rights reserved. This program and the accompanying materials
|
|
||||||
* are made available under the terms of the GNU Public License v3.0
|
|
||||||
* which accompanies this distribution, and is available at
|
|
||||||
* http://www.gnu.org/licenses/gpl.html
|
|
||||||
*/
|
|
||||||
package at.bitfire.davdroid.ui.setup;
|
|
||||||
|
|
||||||
import android.content.Context;
|
|
||||||
import android.view.LayoutInflater;
|
|
||||||
import android.view.View;
|
|
||||||
import android.view.ViewGroup;
|
|
||||||
import android.widget.BaseAdapter;
|
|
||||||
import android.widget.TextView;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import at.bitfire.davdroid.webdav.WebDavResource;
|
|
||||||
|
|
||||||
public class WebDavResourceAdapter extends BaseAdapter {
|
|
||||||
protected int viewId;
|
|
||||||
protected LayoutInflater inflater;
|
|
||||||
WebDavResource[] items;
|
|
||||||
|
|
||||||
public WebDavResourceAdapter(Context context, int textViewResourceId, List<WebDavResource> objects) {
|
|
||||||
viewId = textViewResourceId;
|
|
||||||
inflater = LayoutInflater.from(context);
|
|
||||||
items = objects.toArray(new WebDavResource[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public View getView(int position, View view, ViewGroup parent) {
|
|
||||||
WebDavResource item = items[position];
|
|
||||||
View itemView = (View)inflater.inflate(viewId, null);
|
|
||||||
|
|
||||||
TextView textName = (TextView) itemView.findViewById(android.R.id.text1);
|
|
||||||
textName.setText(item.getDisplayName());
|
|
||||||
|
|
||||||
TextView textDescription = (TextView) itemView.findViewById(android.R.id.text2);
|
|
||||||
String description = item.getDescription();
|
|
||||||
if (description == null)
|
|
||||||
description = item.getLocation().getPath();
|
|
||||||
textDescription.setText(description);
|
|
||||||
|
|
||||||
return itemView;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public int getCount() {
|
|
||||||
return items.length;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Object getItem(int position) {
|
|
||||||
return items[position];
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public long getItemId(int position) {
|
|
||||||
return position;
|
|
||||||
}
|
|
||||||
}
|
|
@ -11,7 +11,6 @@ package at.bitfire.davdroid.webdav;
|
|||||||
import org.simpleframework.xml.Attribute;
|
import org.simpleframework.xml.Attribute;
|
||||||
import org.simpleframework.xml.Element;
|
import org.simpleframework.xml.Element;
|
||||||
import org.simpleframework.xml.Namespace;
|
import org.simpleframework.xml.Namespace;
|
||||||
import org.simpleframework.xml.Root;
|
|
||||||
|
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
@ -23,7 +22,7 @@ public class DavCompFilter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Attribute(required=false)
|
@Attribute(required=false)
|
||||||
String name;
|
final String name;
|
||||||
|
|
||||||
@Element(required=false,name="comp-filter")
|
@Element(required=false,name="comp-filter")
|
||||||
@Getter @Setter DavCompFilter compFilter;
|
@Getter @Setter DavCompFilter compFilter;
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
*/
|
*/
|
||||||
package at.bitfire.davdroid.webdav;
|
package at.bitfire.davdroid.webdav;
|
||||||
|
|
||||||
import org.apache.commons.lang.ArrayUtils;
|
import org.apache.commons.lang3.ArrayUtils;
|
||||||
import org.apache.http.HttpRequest;
|
import org.apache.http.HttpRequest;
|
||||||
import org.apache.http.impl.client.DefaultHttpRequestRetryHandlerHC4;
|
import org.apache.http.impl.client.DefaultHttpRequestRetryHandlerHC4;
|
||||||
|
|
||||||
|
@ -49,7 +49,7 @@ public class DavMultiget {
|
|||||||
multiget.prop.calendarData = new DavProp.CalendarData();
|
multiget.prop.calendarData = new DavProp.CalendarData();
|
||||||
}
|
}
|
||||||
|
|
||||||
multiget.hrefs = new ArrayList<DavHref>(names.length);
|
multiget.hrefs = new ArrayList<>(names.length);
|
||||||
for (String name : names)
|
for (String name : names)
|
||||||
multiget.hrefs.add(new DavHref(name));
|
multiget.hrefs.add(new DavHref(name));
|
||||||
|
|
||||||
|
@ -13,8 +13,6 @@ import org.simpleframework.xml.Root;
|
|||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import lombok.Getter;
|
|
||||||
|
|
||||||
@Root(strict=false)
|
@Root(strict=false)
|
||||||
public class DavResponse {
|
public class DavResponse {
|
||||||
@Element
|
@Element
|
||||||
|
@ -56,19 +56,19 @@ public class HttpPropfind extends HttpEntityEnclosingRequestBaseHC4 {
|
|||||||
depth = 1;
|
depth = 1;
|
||||||
propfind.prop.displayname = new DavProp.DisplayName();
|
propfind.prop.displayname = new DavProp.DisplayName();
|
||||||
propfind.prop.resourcetype = new DavProp.ResourceType();
|
propfind.prop.resourcetype = new DavProp.ResourceType();
|
||||||
propfind.prop.currentUserPrivilegeSet = new LinkedList<DavProp.Privilege>();
|
propfind.prop.currentUserPrivilegeSet = new LinkedList<>();
|
||||||
propfind.prop.addressbookDescription = new DavProp.AddressbookDescription();
|
propfind.prop.addressbookDescription = new DavProp.AddressbookDescription();
|
||||||
propfind.prop.supportedAddressData = new LinkedList<DavProp.AddressDataType>();
|
propfind.prop.supportedAddressData = new LinkedList<>();
|
||||||
break;
|
break;
|
||||||
case CALDAV_COLLECTIONS:
|
case CALDAV_COLLECTIONS:
|
||||||
depth = 1;
|
depth = 1;
|
||||||
propfind.prop.displayname = new DavProp.DisplayName();
|
propfind.prop.displayname = new DavProp.DisplayName();
|
||||||
propfind.prop.resourcetype = new DavProp.ResourceType();
|
propfind.prop.resourcetype = new DavProp.ResourceType();
|
||||||
propfind.prop.currentUserPrivilegeSet = new LinkedList<DavProp.Privilege>();
|
propfind.prop.currentUserPrivilegeSet = new LinkedList<>();
|
||||||
propfind.prop.calendarDescription = new DavProp.CalendarDescription();
|
propfind.prop.calendarDescription = new DavProp.CalendarDescription();
|
||||||
propfind.prop.calendarColor = new DavProp.CalendarColor();
|
propfind.prop.calendarColor = new DavProp.CalendarColor();
|
||||||
propfind.prop.calendarTimezone = new DavProp.CalendarTimezone();
|
propfind.prop.calendarTimezone = new DavProp.CalendarTimezone();
|
||||||
propfind.prop.supportedCalendarComponentSet = new LinkedList<DavProp.Comp>();
|
propfind.prop.supportedCalendarComponentSet = new LinkedList<>();
|
||||||
break;
|
break;
|
||||||
case COLLECTION_CTAG:
|
case COLLECTION_CTAG:
|
||||||
propfind.prop.getctag = new DavProp.GetCTag();
|
propfind.prop.getctag = new DavProp.GetCTag();
|
||||||
|
@ -11,7 +11,7 @@ package at.bitfire.davdroid.webdav;
|
|||||||
import android.os.Build;
|
import android.os.Build;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.http.conn.ssl.BrowserCompatHostnameVerifierHC4;
|
import org.apache.http.conn.ssl.BrowserCompatHostnameVerifierHC4;
|
||||||
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
|
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
|
||||||
import org.apache.http.conn.ssl.X509HostnameVerifier;
|
import org.apache.http.conn.ssl.X509HostnameVerifier;
|
||||||
@ -28,7 +28,7 @@ import javax.net.ssl.SSLSocketFactory;
|
|||||||
import lombok.Cleanup;
|
import lombok.Cleanup;
|
||||||
|
|
||||||
public class TlsSniSocketFactory extends SSLConnectionSocketFactory {
|
public class TlsSniSocketFactory extends SSLConnectionSocketFactory {
|
||||||
private static final String TAG = "davdroid.TlsSniSocketFactory";
|
private static final String TAG = "davdroid.TLS_SNI";
|
||||||
|
|
||||||
public static TlsSniSocketFactory getSocketFactory() {
|
public static TlsSniSocketFactory getSocketFactory() {
|
||||||
return new TlsSniSocketFactory(
|
return new TlsSniSocketFactory(
|
||||||
@ -48,41 +48,39 @@ public class TlsSniSocketFactory extends SSLConnectionSocketFactory {
|
|||||||
/* set reasonable protocol versions */
|
/* set reasonable protocol versions */
|
||||||
// - enable all supported protocols (enables TLSv1.1 and TLSv1.2 on Android <5.0)
|
// - enable all supported protocols (enables TLSv1.1 and TLSv1.2 on Android <5.0)
|
||||||
// - remove all SSL versions (especially SSLv3) because they're insecure now
|
// - remove all SSL versions (especially SSLv3) because they're insecure now
|
||||||
List<String> protocols = new LinkedList<String>();
|
List<String> protocols = new LinkedList<>();
|
||||||
for (String protocol : socket.getSupportedProtocols())
|
for (String protocol : socket.getSupportedProtocols())
|
||||||
if (!protocol.toUpperCase().contains("SSL"))
|
if (!protocol.toUpperCase().contains("SSL"))
|
||||||
protocols.add(protocol);
|
protocols.add(protocol);
|
||||||
Log.v(TAG, "Setting allowed TLS protocols: " + StringUtils.join(protocols, ", "));
|
Log.v(TAG, "Setting allowed TLS protocols: " + StringUtils.join(protocols, ", "));
|
||||||
TlsSniSocketFactory.protocols = protocols.toArray(new String[0]);
|
TlsSniSocketFactory.protocols = protocols.toArray(new String[protocols.size()]);
|
||||||
|
|
||||||
/* set reasonable cipher suites */
|
/* set reasonable cipher suites */
|
||||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
|
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) {
|
||||||
// choose secure cipher suites
|
// choose secure cipher suites
|
||||||
List<String> allowedCiphers = Arrays.asList(new String[]{
|
List<String> allowedCiphers = Arrays.asList(
|
||||||
// allowed secure ciphers according to NIST.SP.800-52r1.pdf Section 3.3.1 (see docs directory)
|
// TLS 1.2
|
||||||
// TLS 1.2
|
"TLS_RSA_WITH_AES_256_GCM_SHA384",
|
||||||
"TLS_RSA_WITH_AES_256_GCM_SHA384",
|
"TLS_RSA_WITH_AES_128_GCM_SHA256",
|
||||||
"TLS_RSA_WITH_AES_128_GCM_SHA256",
|
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
|
||||||
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256",
|
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
|
||||||
"TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
|
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
|
||||||
"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
|
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
|
||||||
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256",
|
"TLS_ECHDE_RSA_WITH_AES_128_GCM_SHA256",
|
||||||
"TLS_ECHDE_RSA_WITH_AES_128_GCM_SHA256",
|
// maximum interoperability
|
||||||
// maximum interoperability
|
"TLS_RSA_WITH_3DES_EDE_CBC_SHA",
|
||||||
"TLS_RSA_WITH_3DES_EDE_CBC_SHA",
|
"TLS_RSA_WITH_AES_128_CBC_SHA",
|
||||||
"TLS_RSA_WITH_AES_128_CBC_SHA",
|
// additionally
|
||||||
// additionally
|
"TLS_RSA_WITH_AES_256_CBC_SHA",
|
||||||
"TLS_RSA_WITH_AES_256_CBC_SHA",
|
"TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA",
|
||||||
"TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA",
|
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
|
||||||
"TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
|
"TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA",
|
||||||
"TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA",
|
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA");
|
||||||
"TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
|
|
||||||
});
|
|
||||||
|
|
||||||
List<String> availableCiphers = Arrays.asList(socket.getSupportedCipherSuites());
|
List<String> availableCiphers = Arrays.asList(socket.getSupportedCipherSuites());
|
||||||
|
|
||||||
// preferred ciphers = allowed Ciphers \ availableCiphers
|
// preferred ciphers = allowed Ciphers \ availableCiphers
|
||||||
HashSet<String> preferredCiphers = new HashSet<String>(allowedCiphers);
|
HashSet<String> preferredCiphers = new HashSet<>(allowedCiphers);
|
||||||
preferredCiphers.retainAll(availableCiphers);
|
preferredCiphers.retainAll(availableCiphers);
|
||||||
|
|
||||||
// add preferred ciphers to enabled ciphers
|
// add preferred ciphers to enabled ciphers
|
||||||
@ -90,10 +88,10 @@ public class TlsSniSocketFactory extends SSLConnectionSocketFactory {
|
|||||||
// but I guess for the security level of DAVdroid, disabling of insecure
|
// but I guess for the security level of DAVdroid, disabling of insecure
|
||||||
// ciphers should be a server-side task
|
// ciphers should be a server-side task
|
||||||
HashSet<String> enabledCiphers = preferredCiphers;
|
HashSet<String> enabledCiphers = preferredCiphers;
|
||||||
enabledCiphers.addAll(new HashSet<String>(Arrays.asList(socket.getEnabledCipherSuites())));
|
enabledCiphers.addAll(new HashSet<>(Arrays.asList(socket.getEnabledCipherSuites())));
|
||||||
|
|
||||||
Log.v(TAG, "Setting allowed TLS ciphers: " + StringUtils.join(enabledCiphers, ", "));
|
Log.v(TAG, "Setting allowed TLS ciphers: " + StringUtils.join(enabledCiphers, ", "));
|
||||||
TlsSniSocketFactory.cipherSuites = enabledCiphers.toArray(new String[0]);
|
TlsSniSocketFactory.cipherSuites = enabledCiphers.toArray(new String[enabledCiphers.size()]);
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
}
|
}
|
||||||
|
@ -9,7 +9,7 @@ package at.bitfire.davdroid.webdav;
|
|||||||
|
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
import org.apache.commons.lang.StringUtils;
|
import org.apache.commons.lang3.StringUtils;
|
||||||
import org.apache.http.Header;
|
import org.apache.http.Header;
|
||||||
import org.apache.http.HttpEntity;
|
import org.apache.http.HttpEntity;
|
||||||
import org.apache.http.HttpHost;
|
import org.apache.http.HttpHost;
|
||||||
@ -25,7 +25,6 @@ import org.apache.http.client.methods.HttpGetHC4;
|
|||||||
import org.apache.http.client.methods.HttpOptionsHC4;
|
import org.apache.http.client.methods.HttpOptionsHC4;
|
||||||
import org.apache.http.client.methods.HttpPutHC4;
|
import org.apache.http.client.methods.HttpPutHC4;
|
||||||
import org.apache.http.client.protocol.HttpClientContext;
|
import org.apache.http.client.protocol.HttpClientContext;
|
||||||
import org.apache.http.client.utils.URIUtilsHC4;
|
|
||||||
import org.apache.http.entity.ByteArrayEntityHC4;
|
import org.apache.http.entity.ByteArrayEntityHC4;
|
||||||
import org.apache.http.impl.auth.BasicSchemeHC4;
|
import org.apache.http.impl.auth.BasicSchemeHC4;
|
||||||
import org.apache.http.impl.client.BasicAuthCache;
|
import org.apache.http.impl.client.BasicAuthCache;
|
||||||
@ -83,11 +82,11 @@ public class WebDavResource {
|
|||||||
@Getter protected URI location;
|
@Getter protected URI location;
|
||||||
|
|
||||||
// DAV capabilities (DAV: header) and allowed DAV methods (set for OPTIONS request)
|
// DAV capabilities (DAV: header) and allowed DAV methods (set for OPTIONS request)
|
||||||
protected Set<String> capabilities = new HashSet<String>(),
|
protected Set<String> capabilities = new HashSet<>(),
|
||||||
methods = new HashSet<String>();
|
methods = new HashSet<>();
|
||||||
|
|
||||||
// DAV properties
|
// DAV properties
|
||||||
protected HashMap<Property, String> properties = new HashMap<Property, String>();
|
protected HashMap<Property, String> properties = new HashMap<>();
|
||||||
@Getter protected List<String> supportedComponents;
|
@Getter protected List<String> supportedComponents;
|
||||||
|
|
||||||
// list of members (only for collections)
|
// list of members (only for collections)
|
||||||
@ -294,13 +293,13 @@ public class WebDavResource {
|
|||||||
// so we have to handle redirections manually and create a new request for the new location
|
// so we have to handle redirections manually and create a new request for the new location
|
||||||
for (int i = context.getRequestConfig().getMaxRedirects(); i > 0; i--) {
|
for (int i = context.getRequestConfig().getMaxRedirects(); i > 0; i--) {
|
||||||
// build multi-get XML request
|
// build multi-get XML request
|
||||||
List<String> hrefs = new LinkedList<String>();
|
List<String> hrefs = new LinkedList<>();
|
||||||
for (String name : names)
|
for (String name : names)
|
||||||
// name may contain "%" which have to be encoded → use non-quoting URI constructor and getRawPath()
|
// name may contain "%" which have to be encoded → use non-quoting URI constructor and getRawPath()
|
||||||
// name may also contain ":", so prepend "./" because even the non-quoting URI constructor parses after constructing
|
// name may also contain ":", so prepend "./" because even the non-quoting URI constructor parses after constructing
|
||||||
// DAVdroid ensures that collections always have a trailing slash, so "./" won't go down in directory hierarchy
|
// DAVdroid ensures that collections always have a trailing slash, so "./" won't go down in directory hierarchy
|
||||||
hrefs.add(location.resolve(new URI(null, null, "./" + name, null)).getRawPath());
|
hrefs.add(location.resolve(new URI(null, null, "./" + name, null)).getRawPath());
|
||||||
DavMultiget multiget = DavMultiget.newRequest(type, hrefs.toArray(new String[0]));
|
DavMultiget multiget = DavMultiget.newRequest(type, hrefs.toArray(new String[hrefs.size()]));
|
||||||
|
|
||||||
StringWriter writer = new StringWriter();
|
StringWriter writer = new StringWriter();
|
||||||
try {
|
try {
|
||||||
@ -456,7 +455,7 @@ public class WebDavResource {
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
// member list will be built from response
|
// member list will be built from response
|
||||||
List<WebDavResource> members = new LinkedList<WebDavResource>();
|
List<WebDavResource> members = new LinkedList<>();
|
||||||
|
|
||||||
// iterate through all resources (either ourselves or member)
|
// iterate through all resources (either ourselves or member)
|
||||||
for (DavResponse singleResponse : multiStatus.response) {
|
for (DavResponse singleResponse : multiStatus.response) {
|
||||||
@ -470,7 +469,7 @@ public class WebDavResource {
|
|||||||
Log.d(TAG, "Processing multi-status element: " + href);
|
Log.d(TAG, "Processing multi-status element: " + href);
|
||||||
|
|
||||||
// process known properties
|
// process known properties
|
||||||
HashMap<Property, String> properties = new HashMap<Property, String>();
|
HashMap<Property, String> properties = new HashMap<>();
|
||||||
List<String> supportedComponents = null;
|
List<String> supportedComponents = null;
|
||||||
byte[] data = null;
|
byte[] data = null;
|
||||||
|
|
||||||
@ -551,7 +550,7 @@ public class WebDavResource {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (prop.supportedCalendarComponentSet != null) {
|
if (prop.supportedCalendarComponentSet != null) {
|
||||||
supportedComponents = new LinkedList<String>();
|
supportedComponents = new LinkedList<>();
|
||||||
for (Comp component : prop.supportedCalendarComponentSet)
|
for (Comp component : prop.supportedCalendarComponentSet)
|
||||||
supportedComponents.add(component.getName());
|
supportedComponents.add(component.getName());
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user