Commit c37c219a authored by Ricki Hirner's avatar Ricki Hirner 🐑

Synchronization logging to external file

* use ExternalFileLogger to log synchronization, if enabled in Settings
* new settings: log to external file / log verbose
* DavResource: check for well-known even if service type of user-given URL can't be determined
* remove oblsete testing assets
parent c99ab384
BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//hacksw/handcal//NONSGML v1.0//EN
BEGIN:VEVENT
UID:[email protected]
DTSTAMP:20140101T000000Z
DTSTART;VALUE=DATE:19970714
DTEND;VALUE=DATE:19970714
SUMMARY:0 Sec Event
END:VEVENT
END:VCALENDAR
\ No newline at end of file
BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//hacksw/handcal//NONSGML v1.0//EN
BEGIN:VEVENT
UID:[email protected]
DTSTAMP:20140101T000000Z
DTSTART;VALUE=DATE:19970714
DTEND;VALUE=DATE:19970724
SUMMARY:All-Day 10 Days
END:VEVENT
END:VCALENDAR
\ No newline at end of file
BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//hacksw/handcal//NONSGML v1.0//EN
BEGIN:VEVENT
UID:[email protected]
DTSTAMP:20140101T000000Z
DTSTART;VALUE=DATE:19970714
DTEND;VALUE=DATE:19970714
SUMMARY:All-Day 1 Day
END:VEVENT
END:VCALENDAR
\ No newline at end of file
BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//hacksw/handcal//NONSGML v1.0//EN
BEGIN:VEVENT
UID:[email protected]
DTSTAMP:19970714T170000Z
ORGANIZER;CN=John Doe:MAILTO:[email protected]
DTSTART;VALUE=DATE:19970714
SUMMARY:Bastille Day Party
END:VEVENT
END:VCALENDAR
\ No newline at end of file
BEGIN:VCARD
VERSION:3.0
UID:2de59c6cc9
PRODID:-//ownCloud//NONSGML Contacts 0.2.5//EN
REV:2013-12-08T00:04:30+00:00
FN:test mctest
N:mctest;test;;;
IMPP;TYPE=WORK;X-SERVICE-TYPE=jabber:[email protected]
END:VCARD
BEGIN:VCARD
VERSION:3.0
FN:VCard with invalid unknown properties
[email protected]:MUST-NOT_CONTAIN?OTHER*LETTERS;
END:VCARD
\ No newline at end of file
BEGIN:VCARD
VERSION:3.0
N:uek;zkan
FN:zkan uek
END:VCARD
BEGIN:VCALENDAR
VERSION:2.0
BEGIN:VEVENT
UID:fcb42e4d-bc6e-4499-97f0-6616a02da7bc
SUMMARY:Recurring event with one exception
RRULE:FREQ=DAILY;COUNT=5
DTSTART;VALUE=DATE:20150501
DTEND;VALUE=DATE:20150502
END:VEVENT
BEGIN:VEVENT
UID:fcb42e4d-bc6e-4499-97f0-6616a02da7bc
RECURRENCE-ID;VALUE=DATE:20150503
DTSTART;VALUE=DATE:20150503
DTEND;VALUE=DATE:20150504
SUMMARY:Another summary for the third day
END:VEVENT
END:VCALENDAR
\ No newline at end of file
BEGIN:VCARD
VERSION:3.0
N:Gümp;Förrest;Mr.
FN:Förrest Gümp
ORG:Bubba Gump Shrimpß Co.
TITLE:Shrimp Man
PHOTO;VALUE=URL;TYPE=PNG:http://192.168.0.11:3000/assets/davdroid-logo-192.png
TEL;TYPE=WORK,VOICE:(111) 555-1212
TEL;TYPE=HOME,VOICE:(404) 555-1212
ADR;TYPE=WORK:;;100 Waters Edge;Baytown;LA;30314;United States of America
LABEL;TYPE=WORK:100 Waters Edge\nBaytown, LA 30314\nUnited States of America
ADR;TYPE=HOME:;;42 Plantation St.;Baytown;LA;30314;United States of America
LABEL;TYPE=HOME:42 Plantation St.\nBaytown, LA 30314\nUnited States of America
EMAIL;TYPE=PREF,INTERNET:[email protected]
REV:2008-04-24T19:52:43Z
END:VCARD
BEGIN:VCALENDAR
VERSION:2.0
PRODID:Blabla
BEGIN:VEVENT
CLASS:PUBLIC
CREATED;VALUE=DATE-TIME:20131008T205713
LAST-MODIFIED;VALUE=DATE-TIME:20131008T205740
SUMMARY:online Anmeldung
DESCRIPTION:http://www.tgbornheim.de/index.php?sessionid=&page=&id=&sportce
ntergroup=&day=6
UID:b99c41704b
DTSTART;VALUE=DATE-TIME;TZID=Europe/Berlin:20131019T060000
END:VEVENT
END:VCALENDAR
BEGIN:VCARD
VERSION:3.0
N:Gump;Forrest
FN:Forrest Gump
ORG:Bubba Gump Shrimp Co.
TITLE:Shrimp Man
PHOTO;VALUE=URL;TYPE=GIF:http://www.example.com/dir_photos/my_photo.gif
TEL;TYPE=WORK,VOICE:(111) 555-1212
TEL;TYPE=HOME,VOICE:(404) 555-1212
ADR;TYPE=WORK:;;100 Waters Edge;Baytown;LA;30314;United States of America
LABEL;TYPE=WORK:100 Waters Edge\nBaytown, LA 30314\nUnited States of America
ADR;TYPE=HOME:;;42 Plantation St.;Baytown;LA;30314;United States of America
LABEL;TYPE=HOME:42 Plantation St.\nBaytown, LA 30314\nUnited States of America
EMAIL;TYPE=PREF,INTERNET:[email protected]
REV:2008-04-24T19:52:43Z
END:VCARD
\ No newline at end of file
BEGIN:VCALENDAR
PRODID:-//Ximian//NONSGML Evolution Calendar//EN
VERSION:2.0
METHOD:PUBLISH
BEGIN:VTIMEZONE
TZID:/freeassociation.sourceforge.net/Tzfile/Europe/Vienna
X-LIC-LOCATION:Europe/Vienna
BEGIN:STANDARD
TZNAME:CET
DTSTART:19701027T030000
RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=10
TZOFFSETFROM:+0200
TZOFFSETTO:+0100
END:STANDARD
BEGIN:DAYLIGHT
TZNAME:CEST
DTSTART:19700331T020000
RRULE:FREQ=YEARLY;BYDAY=-1SU;BYMONTH=3
TZOFFSETFROM:+0100
TZOFFSETTO:+0200
END:DAYLIGHT
END:VTIMEZONE
BEGIN:VEVENT
UID:c252087c-7354-4722-aea9-0e7d86c01a25
DTSTAMP:20130926T151211Z
SUMMARY:Test-Ereignis im schönen Wien
DTSTART;TZID=/freeassociation.sourceforge.net/Tzfile/Europe/Vienna:20131009T170000
DTEND;TZID=/freeassociation.sourceforge.net/Tzfile/Europe/Vienna:20131009T180000
X-RADICALE-NAME:97929342-291a-434e-bf1a-fa1749bf99d0.ics
X-EVOLUTION-CALDAV-HREF:/radicale/rfc2822/default.ics/97929342-291a-434e-bf1a-fa1749bf99d0.ics
X-EVOLUTION-CALDAV-ETAG:\"-3264224243575339985\"
END:VEVENT
END:VCALENDAR
......@@ -20,6 +20,7 @@
<uses-permission android:name="android.permission.WRITE_CALENDAR" />
<uses-permission android:name="android.permission.READ_SYNC_SETTINGS" />
<uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="18" />
<uses-permission android:name="org.dmfs.permission.READ_TASKS" />
<uses-permission android:name="org.dmfs.permission.WRITE_TASKS" />
......
......@@ -21,6 +21,8 @@ import com.squareup.okhttp.Response;
import com.squareup.okhttp.internal.tls.OkHostnameVerifier;
import com.squareup.okhttp.logging.HttpLoggingInterceptor;
import org.slf4j.Logger;
import java.io.IOException;
import java.net.Proxy;
import java.security.KeyManagementException;
......@@ -39,18 +41,7 @@ import de.duenndns.ssl.MemorizingTrustManager;
import lombok.RequiredArgsConstructor;
public class HttpClient extends OkHttpClient {
protected static final String HEADER_AUTHORIZATION = "Authorization";
final static UserAgentInterceptor userAgentInterceptor = new UserAgentInterceptor();
final static HttpLoggingInterceptor loggingInterceptor = new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
@Override
public void log(String message) {
Constants.log.trace(message);
}
});
static {
loggingInterceptor.setLevel(HttpLoggingInterceptor.Level.BODY);
}
static final String userAgent;
static {
......@@ -58,12 +49,14 @@ public class HttpClient extends OkHttpClient {
userAgent = "DAVdroid/" + BuildConfig.VERSION_NAME + " (" + date + "; dav4android) Android/" + Build.VERSION.RELEASE;
}
final Logger log;
final Context context;
protected String username, password;
protected HttpClient(Context context) {
protected HttpClient(final Logger log, Context context) {
super();
this.log = (log != null) ? log : Constants.log;
this.context = context;
if (context != null) {
......@@ -90,12 +83,20 @@ public class HttpClient extends OkHttpClient {
networkInterceptors().add(userAgentInterceptor);
// enable verbose logs, if requested
if (Constants.log.isTraceEnabled())
enableLogs();
if (log.isTraceEnabled()) {
HttpLoggingInterceptor logger = new HttpLoggingInterceptor(new HttpLoggingInterceptor.Logger() {
@Override
public void log(String message) {
log.trace(message);
}
});
logger.setLevel(HttpLoggingInterceptor.Level.BODY);
interceptors().add(logger);
}
}
public HttpClient(Context context, String username, String password, boolean preemptive) {
this(context);
public HttpClient(Logger log, Context context, String username, String password, boolean preemptive) {
this(log, context);
// authentication
this.username = username;
......@@ -113,8 +114,8 @@ public class HttpClient extends OkHttpClient {
* @param client user name and password from this client will be used
* @param host authentication will be restricted to this host
*/
public HttpClient(HttpClient client, String host) {
this(client.context);
public HttpClient(Logger log, HttpClient client, String host) {
this(log, client.context);
username = client.username;
password = client.password;
......@@ -123,12 +124,7 @@ public class HttpClient extends OkHttpClient {
// for testing (mock server doesn't need auth)
protected HttpClient() {
this(null, null, null, false);
}
protected void enableLogs() {
interceptors().add(loggingInterceptor);
this(null, null, null, null, false);
}
......@@ -142,7 +138,6 @@ public class HttpClient extends OkHttpClient {
}
}
@RequiredArgsConstructor
static class PreemptiveAuthenticationInterceptor implements Interceptor {
final String username, password;
......
/*
* 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.log;
import org.slf4j.Logger;
import org.slf4j.Marker;
/**
* A DAVdroid logger base class that wraps all calls around some standard log() calls.
* @throws UnsupportedOperationException for all methods with Marker
* arguments (as Markers are not used by DAVdroid logging).
*/
public abstract class CustomLogger implements Logger {
private static final String
PREFIX_ERROR = "[error] ",
PREFIX_WARN = "[warn ] ",
PREFIX_INFO = "[info ] ",
PREFIX_DEBUG = "[debug] ",
PREFIX_TRACE = "[trace] ";
protected boolean verbose;
protected abstract void log(String prefix, String msg);
protected abstract void log(String prefix, String format, Object arg);
protected abstract void log(String prefix, String format, Object arg1, Object arg2);
protected abstract void log(String prefix, String format, Object... args);
protected abstract void log(String prefix, String msg, Throwable t);
// STANDARD CALLS
@Override
public boolean isTraceEnabled() {
return verbose;
}
@Override
public void trace(String msg) {
if (verbose)
log(PREFIX_TRACE, msg);
}
@Override
public void trace(String format, Object arg) {
if (verbose)
log(PREFIX_TRACE, format, arg);
}
@Override
public void trace(String format, Object arg1, Object arg2) {
if (verbose) log(PREFIX_TRACE, format, arg1, arg2);
}
@Override
public void trace(String format, Object... arguments) {
if (verbose)
log(PREFIX_TRACE, format, arguments);
}
@Override
public void trace(String msg, Throwable t) {
if (verbose)
log(PREFIX_TRACE, msg, t);
}
@Override
public boolean isDebugEnabled() {
return true;
}
@Override
public void debug(String msg) {
log(PREFIX_DEBUG, msg);
}
@Override
public void debug(String format, Object arg) {
log(PREFIX_DEBUG, format, arg);
}
@Override
public void debug(String format, Object arg1, Object arg2) {
log(PREFIX_DEBUG, format, arg1, arg2);
}
@Override
public void debug(String format, Object... arguments) {
log(PREFIX_DEBUG, format, arguments);
}
@Override
public void debug(String msg, Throwable t) {
log(PREFIX_DEBUG, msg, t);
}
@Override
public boolean isInfoEnabled() {
return true;
}
@Override
public void info(String msg) {
log(PREFIX_INFO, msg);
}
@Override
public void info(String format, Object arg) {
log(PREFIX_INFO, format, arg);
}
@Override
public void info(String format, Object arg1, Object arg2) {
log(PREFIX_INFO, format, arg1, arg2);
}
@Override
public void info(String format, Object... arguments) {
log(PREFIX_INFO, format, arguments);
}
@Override
public void info(String msg, Throwable t) {
log(PREFIX_INFO, msg, t);
}
@Override
public boolean isWarnEnabled() {
return true;
}
@Override
public void warn(String msg) {
log(PREFIX_WARN, msg);
}
@Override
public void warn(String format, Object arg) {
log(PREFIX_WARN, format, arg);
}
@Override
public void warn(String format, Object... arguments) {
log(PREFIX_WARN, format, arguments);
}
@Override
public void warn(String format, Object arg1, Object arg2) {
log(PREFIX_WARN, format, arg1, arg2);
}
@Override
public void warn(String msg, Throwable t) {
log(PREFIX_WARN, msg, t);
}
@Override
public boolean isErrorEnabled() {
return true;
}
@Override
public void error(String msg) {
log(PREFIX_ERROR, msg);
}
@Override
public void error(String format, Object arg) {
log(PREFIX_ERROR, format, arg);
}
@Override
public void error(String format, Object arg1, Object arg2) {
log(PREFIX_ERROR, format, arg1, arg2);
}
@Override
public void error(String format, Object... arguments) {
log(PREFIX_ERROR, format, arguments);
}
@Override
public void error(String msg, Throwable t) {
log(PREFIX_ERROR, msg, t);
}
// CALLS WITH MARKER
@Override
public boolean isTraceEnabled(Marker marker) {
throw new UnsupportedOperationException();
}
@Override
public void trace(Marker marker, String msg) {
throw new UnsupportedOperationException();
}
@Override
public void trace(Marker marker, String format, Object arg) {
throw new UnsupportedOperationException();
}
@Override
public void trace(Marker marker, String format, Object arg1, Object arg2) {
throw new UnsupportedOperationException();
}
@Override
public void trace(Marker marker, String format, Object... argArray) {
throw new UnsupportedOperationException();
}
@Override
public void trace(Marker marker, String msg, Throwable t) {
throw new UnsupportedOperationException();
}
@Override
public boolean isDebugEnabled(Marker marker) {
throw new UnsupportedOperationException();
}
@Override
public void debug(Marker marker, String msg) {
throw new UnsupportedOperationException();
}
@Override
public void debug(Marker marker, String format, Object arg) {
throw new UnsupportedOperationException();
}
@Override
public void debug(Marker marker, String format, Object arg1, Object arg2) {
throw new UnsupportedOperationException();
}
@Override
public void debug(Marker marker, String format, Object... arguments) {
throw new UnsupportedOperationException();
}
@Override
public void debug(Marker marker, String msg, Throwable t) {
throw new UnsupportedOperationException();
}
@Override
public boolean isInfoEnabled(Marker marker) {
throw new UnsupportedOperationException();
}
@Override
public void info(Marker marker, String msg) {
throw new UnsupportedOperationException();
}
@Override
public void info(Marker marker, String format, Object arg) {
throw new UnsupportedOperationException();
}
@Override
public void info(Marker marker, String format, Object arg1, Object arg2) {
throw new UnsupportedOperationException();
}
@Override
public void info(Marker marker, String format, Object... arguments) {
throw new UnsupportedOperationException();
}
@Override
public void info(Marker marker, String msg, Throwable t) {
throw new UnsupportedOperationException();
}
@Override
public boolean isWarnEnabled(Marker marker) {
throw new UnsupportedOperationException();
}
@Override
public void warn(Marker marker, String msg) {
throw new UnsupportedOperationException();
}
@Override
public void warn(Marker marker, String format, Object arg) {
throw new UnsupportedOperationException();
}
@Override
public void warn(Marker marker, String format, Object arg1, Object arg2) {
throw new UnsupportedOperationException();
}
@Override
public void warn(Marker marker, String format, Object... arguments) {
throw new UnsupportedOperationException();
}
@Override
public void warn(Marker marker, String msg, Throwable t) {
throw new UnsupportedOperationException();
}
@Override
public boolean isErrorEnabled(Marker marker) {
throw new UnsupportedOperationException();
}
@Override
public void error(Marker marker, String msg) {
throw new UnsupportedOperationException();
}
@Override
public void error(Marker marker, String format, Object arg) {
throw new UnsupportedOperationException();
}
@Override
public void error(Marker marker, String format, Object arg1, Object arg2) {
throw new UnsupportedOperationException();
}
@Override
public void error(Marker marker, String format, Object... arguments) {
throw new UnsupportedOperationException();
}
@Override
public void error(Marker marker, String msg, Throwable t) {
throw new UnsupportedOperationException();
}
}
/*
* 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.log;
import android.content.Context;
import org.apache.commons.lang3.exception.ExceptionUtils;
import java.io.Closeable;
import java.io.File;
import java.io.IOException;
import java.io.PrintWriter;
import lombok.Getter;
public class ExternalFileLogger extends CustomLogger implements Closeable {
@Getter protected final String name;
protected final PrintWriter writer;
public ExternalFileLogger(Context context, String fileName, boolean verbose) throws IOException {
this.verbose = verbose;
File dir = context.getExternalFilesDir(null);
if (dir == null)
throw new IOException("External media not available for log creation");
File log = new File(dir, name = fileName);
writer = new PrintWriter(log);
}
@Override
public void close() throws IOException {
writer.close();
}
@Override
protected void log(String prefix, String msg) {
writer.write(prefix + msg + "\n");
}
@Override
protected void log(String prefix, String format, Object arg) {
writer.write(prefix + format.replace("{}", arg.toString()) + "\n");
}
@Override
protected void log(String prefix, String format, Object arg1, Object arg2) {
writer.write(prefix + format.replaceFirst("\\{\\}", arg1.toString()).replaceFirst("\\{\\}", arg2.toString()) + "\n");
}
@Override
protected void log(String prefix, String format, Object... args) {
String message = prefix;
for (Object arg : args)
format.replaceFirst("\\{\\}", arg.toString());