1
0
Fork 0
mirror of https://github.com/M66B/FairEmail.git synced 2025-01-02 21:24:34 +00:00

Cloud sync: logging

This commit is contained in:
M66B 2023-01-20 22:05:09 +01:00
parent cea8fd0bfb
commit 3e49722d86
2 changed files with 61 additions and 44 deletions

View file

@ -83,15 +83,20 @@ public class CloudSync {
JSONObject jrequest = new JSONObject();
EntityLog.log(context, EntityLog.Type.Cloud, "Cloud command=" + command);
if ("sync".equals(command)) {
long lrevision = prefs.getLong("cloud_lrevision", 0);
Log.i("Cloud local revision=" + lrevision + " (" + new Date(lrevision) + ")");
EntityLog.log(context, EntityLog.Type.Cloud,
"Cloud local revision=" + lrevision + " (" + new Date(lrevision) + ")");
Long lastUpdate = updateSyncdata(context);
Log.i("Cloud last update=" + (lastUpdate == null ? null : new Date(lastUpdate)));
EntityLog.log(context, EntityLog.Type.Cloud,
"Cloud last update=" + (lastUpdate == null ? null : new Date(lastUpdate)));
if (lastUpdate != null && lrevision > lastUpdate) {
Log.w("Cloud invalid local revision" +
" lrevision=" + lrevision + " last=" + lastUpdate);
String msg = "Cloud invalid local revision" +
" lrevision=" + lrevision + " last=" + lastUpdate;
Log.w(msg);
EntityLog.log(context, EntityLog.Type.Cloud, msg);
lrevision = lastUpdate;
prefs.edit().putLong("cloud_lrevision", lrevision).apply();
}
@ -109,19 +114,20 @@ public class CloudSync {
jitems = jresponse.getJSONArray("items");
if (jitems.length() == 0) {
Log.i("Cloud server is empty");
EntityLog.log(context, EntityLog.Type.Cloud, "Cloud server is empty");
sendLocalData(context, user, password, lrevision == 0
? (lastUpdate == null ? new Date().getTime() : lastUpdate)
: lrevision);
} else if (jitems.length() == 1) {
Log.i("Cloud sync check");
EntityLog.log(context, EntityLog.Type.Cloud, "Cloud sync check");
jsyncstatus = jitems.getJSONObject(0);
long rrevision = jsyncstatus.getLong("rev");
JSONObject jstatus = new JSONObject(jsyncstatus.getString("val"));
int sync_version = jstatus.optInt("sync.version", 0);
int app_version = jstatus.optInt("app.version", 0);
Log.i("Cloud version sync=" + sync_version + " app=" + app_version +
" local=" + lrevision + " last=" + lastUpdate + " remote=" + rrevision);
EntityLog.log(context, EntityLog.Type.Cloud,
"Cloud version sync=" + sync_version + " app=" + app_version +
" local=" + lrevision + " last=" + lastUpdate + " remote=" + rrevision);
// last > local (local mods) && remote > local (remote mods) = CONFLICT
// local > last = ignorable ERROR
@ -132,8 +138,9 @@ public class CloudSync {
sendLocalData(context, user, password, lastUpdate);
else if (rrevision > lrevision) // remote changes
if (lastUpdate != null && lastUpdate > lrevision) { // local changes
Log.w("Cloud conflict" +
" lrevision=" + lrevision + " last=" + lastUpdate + " rrevision=" + rrevision);
EntityLog.log(context, EntityLog.Type.Cloud,
"Cloud conflict" +
" lrevision=" + lrevision + " last=" + lastUpdate + " rrevision=" + rrevision);
if (manual)
if (lastUpdate >= rrevision)
sendLocalData(context, user, password, lastUpdate);
@ -218,16 +225,15 @@ public class CloudSync {
boolean cloud_send = prefs.getBoolean("cloud_send", true);
if (!cloud_send) {
Log.w("Cloud skip send");
EntityLog.log(context, EntityLog.Type.Cloud, "Cloud skip send");
return;
}
List<EntityAccount> accounts = db.account().getSynchronizingAccounts(null);
Log.i("Cloud accounts=" + (accounts == null ? null : accounts.size()));
if (accounts == null || accounts.size() == 0) {
Log.i("Cloud no accounts");
EntityLog.log(context, EntityLog.Type.Cloud,
"Cloud accounts=" + (accounts == null ? null : accounts.size()));
if (accounts == null || accounts.size() == 0)
return;
}
JSONArray jupload = new JSONArray();
@ -308,7 +314,7 @@ public class CloudSync {
boolean cloud_receive = prefs.getBoolean("cloud_receive", true);
if (!cloud_receive) {
Log.w("Cloud skip receive");
EntityLog.log(context, EntityLog.Type.Cloud, "Cloud skip receive");
return;
}
@ -325,17 +331,17 @@ public class CloudSync {
jaccountkv.put("key", "account." + uuid);
jaccountkv.put("rev", lrevision);
jdownload.put(jaccountkv);
Log.i("Cloud account uuid=" + uuid);
EntityLog.log(context, EntityLog.Type.Cloud, "Cloud account uuid=" + uuid);
}
if (jdownload.length() > 0) {
Log.i("Cloud getting accounts");
EntityLog.log(context, EntityLog.Type.Cloud, "Cloud getting accounts");
JSONObject jrequest = new JSONObject();
jrequest.put("items", jdownload);
JSONObject jresponse = call(context, user, password, "sync", jrequest);
// Process accounts
Log.i("Cloud processing accounts");
EntityLog.log(context, EntityLog.Type.Cloud, "Cloud processing accounts");
JSONArray jitems = jresponse.getJSONArray("items");
jdownload = new JSONArray();
for (int i = 0; i < jitems.length(); i++) {
@ -363,15 +369,17 @@ public class CloudSync {
right.type = jaccount.getString("swipe_right_type");
}
Log.i("Cloud account " + raccount.uuid + "=" +
(laccount == null ? "insert" :
(EntityAccount.areEqual(raccount, laccount, laccount.auth_type == ServiceAuthenticator.AUTH_TYPE_PASSWORD, true)
? "equal" : "update")) +
" rev=" + revision +
" left=" + (left == null ? null : left.name + ":" + left.type) +
" right=" + (right == null ? null : right.name + ":" + right.type) +
" identities=" + jidentities +
" size=" + value.length());
EntityLog.log(context, EntityLog.Type.Cloud,
"Cloud account " + raccount.uuid + "=" +
(laccount == null ? "insert" :
(EntityAccount.areEqual(raccount, laccount,
laccount.auth_type == ServiceAuthenticator.AUTH_TYPE_PASSWORD, true)
? "equal" : "update")) +
" rev=" + revision +
" left=" + (left == null ? null : left.name + ":" + left.type) +
" right=" + (right == null ? null : right.name + ":" + right.type) +
" identities=" + jidentities +
" size=" + value.length());
raccount.id = null;
@ -448,12 +456,12 @@ public class CloudSync {
if (jdownload.length() > 0) {
// Get identities
Log.i("Cloud getting identities");
EntityLog.log(context, EntityLog.Type.Cloud, "Cloud getting identities");
jrequest.put("items", jdownload);
jresponse = call(context, user, password, "sync", jrequest);
// Process identities
Log.i("Cloud processing identities");
EntityLog.log(context, EntityLog.Type.Cloud, "Cloud processing identities");
jitems = jresponse.getJSONArray("items");
for (int i = 0; i < jitems.length(); i++) {
JSONObject jidentitykv = jitems.getJSONObject(i);
@ -463,12 +471,14 @@ public class CloudSync {
EntityIdentity ridentity = EntityIdentity.fromJSON(jidentity);
EntityIdentity lidentity = db.identity().getIdentityByUUID(ridentity.uuid);
Log.i("Cloud identity " + ridentity.uuid + "=" +
(lidentity == null ? "insert" :
(EntityIdentity.areEqual(ridentity, lidentity, lidentity.auth_type == ServiceAuthenticator.AUTH_TYPE_PASSWORD, true)
? "equal" : "update")) +
" rev=" + revision +
" size=" + value.length());
EntityLog.log(context, EntityLog.Type.Cloud,
"Cloud identity " + ridentity.uuid + "=" +
(lidentity == null ? "insert" :
(EntityIdentity.areEqual(ridentity, lidentity,
lidentity.auth_type == ServiceAuthenticator.AUTH_TYPE_PASSWORD, true)
? "equal" : "update")) +
" rev=" + revision +
" size=" + value.length());
ridentity.id = null;
ridentity.primary = false;
@ -504,7 +514,7 @@ public class CloudSync {
}
}
Log.i("Cloud set lrevision=" + rrevision);
EntityLog.log(context, EntityLog.Type.Cloud, "Cloud set lrevision=" + rrevision);
prefs.edit().putLong("cloud_lrevision", rrevision).apply();
if (updates)
@ -515,7 +525,8 @@ public class CloudSync {
public static JSONObject call(Context context, String user, String password, String command, JSONObject jrequest)
throws GeneralSecurityException, JSONException, IOException {
Log.i("Cloud command=" + command);
EntityLog.log(context, EntityLog.Type.Cloud, "Cloud command=" + command);
jrequest.put("command", command);
List<JSONObject> responses = new ArrayList<>();
for (JSONArray batch : partition(jrequest.getJSONArray("items"))) {
@ -550,13 +561,13 @@ public class CloudSync {
key = keyCache.get(lookup);
}
if (key == null) {
Log.i("Cloud generating key");
EntityLog.log(context, EntityLog.Type.Cloud, "Cloud generating key");
key = getKeyPair(salt, password);
synchronized (keyCache) {
keyCache.put(lookup, key);
}
} else {
Log.i("Cloud using cached key");
EntityLog.log(context, EntityLog.Type.Cloud, "Cloud using cached key");
}
String cloudPassword = Base64.encodeToString(key.first, Base64.NO_PADDING | Base64.NO_WRAP);
@ -587,7 +598,8 @@ public class CloudSync {
}
String request = jrequest.toString();
Log.i("Cloud request length=" + request.length());
EntityLog.log(context, EntityLog.Type.Cloud,
"Cloud request length=" + request.length());
URL url = new URL(BuildConfig.CLOUD_URI);
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
@ -609,7 +621,9 @@ public class CloudSync {
if (status != HttpsURLConnection.HTTP_OK) {
String error = "Error " + status + ": " + connection.getResponseMessage();
String detail = Helper.readStream(connection.getErrorStream());
Log.w("Cloud error=" + error + " detail=" + detail);
String msg = "Cloud error=" + error + " detail=" + detail;
Log.e(msg);
EntityLog.log(context, EntityLog.Type.Cloud, msg);
JSONObject jerror = new JSONObject(detail);
if (status == HttpsURLConnection.HTTP_FORBIDDEN)
throw new SecurityException(jerror.optString("error"));
@ -618,7 +632,8 @@ public class CloudSync {
}
String response = Helper.readStream(connection.getInputStream());
Log.i("Cloud response length=" + response.length());
EntityLog.log(context, EntityLog.Type.Cloud,
"Cloud response length=" + response.length());
JSONObject jresponse = new JSONObject(response);
if (jresponse.has("account")) {

View file

@ -64,7 +64,7 @@ public class EntityLog {
@NonNull
public String data;
public enum Type {General, Statistics, Scheduling, Network, Account, Protocol, Classification, Notification, Rules, Debug}
public enum Type {General, Statistics, Scheduling, Network, Account, Protocol, Classification, Notification, Rules, Cloud, Debug}
static void log(final Context context, String data) {
log(context, Type.General, data);
@ -229,6 +229,8 @@ public class EntityLog {
return ContextCompat.getColor(context, R.color.solarizedBlue);
case Rules:
return ContextCompat.getColor(context, R.color.solarizedCyan);
case Cloud:
return ContextCompat.getColor(context, R.color.solarizedRed);
case Debug:
return Helper.resolveColor(context, R.attr.colorWarning);
default: