improve logging in export backup service. closes #3672
This commit is contained in:
parent
0391e78832
commit
4bc43af690
|
@ -14,6 +14,8 @@ import android.os.IBinder;
|
||||||
import android.support.v4.app.NotificationCompat;
|
import android.support.v4.app.NotificationCompat;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
|
|
||||||
|
import com.google.common.base.Strings;
|
||||||
|
|
||||||
import java.io.DataOutputStream;
|
import java.io.DataOutputStream;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
import java.io.FileOutputStream;
|
||||||
|
@ -70,7 +72,7 @@ public class ExportBackupService extends Service {
|
||||||
if (Compatibility.runsAndTargetsTwentyFour(context)) {
|
if (Compatibility.runsAndTargetsTwentyFour(context)) {
|
||||||
openIntent.setType("resource/folder");
|
openIntent.setType("resource/folder");
|
||||||
} else {
|
} else {
|
||||||
openIntent.setDataAndType(Uri.parse("file://"+path),"resource/folder");
|
openIntent.setDataAndType(Uri.parse("file://" + path), "resource/folder");
|
||||||
}
|
}
|
||||||
openIntent.putExtra("org.openintents.extra.ABSOLUTE_PATH", path);
|
openIntent.putExtra("org.openintents.extra.ABSOLUTE_PATH", path);
|
||||||
|
|
||||||
|
@ -87,7 +89,7 @@ public class ExportBackupService extends Service {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void accountExport(SQLiteDatabase db, String uuid, PrintWriter writer) {
|
private static void accountExport(final SQLiteDatabase db, final String uuid, final PrintWriter writer) {
|
||||||
final StringBuilder builder = new StringBuilder();
|
final StringBuilder builder = new StringBuilder();
|
||||||
final Cursor accountCursor = db.query(Account.TABLENAME, null, Account.UUID + "=?", new String[]{uuid}, null, null, null);
|
final Cursor accountCursor = db.query(Account.TABLENAME, null, Account.UUID + "=?", new String[]{uuid}, null, null, null);
|
||||||
while (accountCursor != null && accountCursor.moveToNext()) {
|
while (accountCursor != null && accountCursor.moveToNext()) {
|
||||||
|
@ -136,27 +138,28 @@ public class ExportBackupService extends Service {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static byte[] getKey(String password, byte[] salt) {
|
public static byte[] getKey(final String password, final byte[] salt) throws InvalidKeySpecException {
|
||||||
|
final SecretKeyFactory factory;
|
||||||
try {
|
try {
|
||||||
SecretKeyFactory factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
|
factory = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA1");
|
||||||
return factory.generateSecret(new PBEKeySpec(password.toCharArray(), salt, 1024, 128)).getEncoded();
|
} catch (NoSuchAlgorithmException e) {
|
||||||
} catch (NoSuchAlgorithmException | InvalidKeySpecException e) {
|
throw new IllegalStateException(e);
|
||||||
throw new AssertionError(e);
|
|
||||||
}
|
}
|
||||||
|
return factory.generateSecret(new PBEKeySpec(password.toCharArray(), salt, 1024, 128)).getEncoded();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String cursorToString(String tablename, Cursor cursor, int max) {
|
private static String cursorToString(final String table, final Cursor cursor, final int max) {
|
||||||
return cursorToString(tablename, cursor, max, false);
|
return cursorToString(table, cursor, max, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String cursorToString(final String tablename, final Cursor cursor, int max, boolean ignore) {
|
private static String cursorToString(final String table, final Cursor cursor, int max, boolean ignore) {
|
||||||
final boolean identities = SQLiteAxolotlStore.IDENTITIES_TABLENAME.equals(tablename);
|
final boolean identities = SQLiteAxolotlStore.IDENTITIES_TABLENAME.equals(table);
|
||||||
StringBuilder builder = new StringBuilder();
|
StringBuilder builder = new StringBuilder();
|
||||||
builder.append("INSERT ");
|
builder.append("INSERT ");
|
||||||
if (ignore) {
|
if (ignore) {
|
||||||
builder.append("OR IGNORE ");
|
builder.append("OR IGNORE ");
|
||||||
}
|
}
|
||||||
builder.append("INTO ").append(tablename).append("(");
|
builder.append("INTO ").append(table).append("(");
|
||||||
int skipColumn = -1;
|
int skipColumn = -1;
|
||||||
for (int i = 0; i < cursor.getColumnCount(); ++i) {
|
for (int i = 0; i < cursor.getColumnCount(); ++i) {
|
||||||
final String name = cursor.getColumnName(i);
|
final String name = cursor.getColumnName(i);
|
||||||
|
@ -222,7 +225,8 @@ public class ExportBackupService extends Service {
|
||||||
try {
|
try {
|
||||||
files = export();
|
files = export();
|
||||||
success = true;
|
success = true;
|
||||||
} catch (Exception e) {
|
} catch (final Exception e) {
|
||||||
|
Log.d(Config.LOGTAG, "unable to create backup", e);
|
||||||
success = false;
|
success = false;
|
||||||
files = Collections.emptyList();
|
files = Collections.emptyList();
|
||||||
}
|
}
|
||||||
|
@ -234,6 +238,8 @@ public class ExportBackupService extends Service {
|
||||||
stopSelf();
|
stopSelf();
|
||||||
}).start();
|
}).start();
|
||||||
return START_STICKY;
|
return START_STICKY;
|
||||||
|
} else {
|
||||||
|
Log.d(Config.LOGTAG, "ExportBackupService. ignoring start command because already running");
|
||||||
}
|
}
|
||||||
return START_NOT_STICKY;
|
return START_NOT_STICKY;
|
||||||
}
|
}
|
||||||
|
@ -241,7 +247,7 @@ public class ExportBackupService extends Service {
|
||||||
private void messageExport(SQLiteDatabase db, String uuid, PrintWriter writer, Progress progress) {
|
private void messageExport(SQLiteDatabase db, String uuid, PrintWriter writer, Progress progress) {
|
||||||
Cursor cursor = db.rawQuery("select messages.* from messages join conversations on conversations.uuid=messages.conversationUuid where conversations.accountUuid=?", new String[]{uuid});
|
Cursor cursor = db.rawQuery("select messages.* from messages join conversations on conversations.uuid=messages.conversationUuid where conversations.accountUuid=?", new String[]{uuid});
|
||||||
int size = cursor != null ? cursor.getCount() : 0;
|
int size = cursor != null ? cursor.getCount() : 0;
|
||||||
Log.d(Config.LOGTAG, "exporting " + size + " messages");
|
Log.d(Config.LOGTAG, "exporting " + size + " messages for account " + uuid);
|
||||||
int i = 0;
|
int i = 0;
|
||||||
int p = 0;
|
int p = 0;
|
||||||
while (cursor != null && cursor.moveToNext()) {
|
while (cursor != null && cursor.moveToNext()) {
|
||||||
|
@ -272,7 +278,14 @@ public class ExportBackupService extends Service {
|
||||||
final int max = this.mAccounts.size();
|
final int max = this.mAccounts.size();
|
||||||
final SecureRandom secureRandom = new SecureRandom();
|
final SecureRandom secureRandom = new SecureRandom();
|
||||||
final List<File> files = new ArrayList<>();
|
final List<File> files = new ArrayList<>();
|
||||||
for (Account account : this.mAccounts) {
|
Log.d(Config.LOGTAG, "starting backup for " + max + " accounts");
|
||||||
|
for (final Account account : this.mAccounts) {
|
||||||
|
final String password = account.getPassword();
|
||||||
|
if (Strings.nullToEmpty(password).trim().isEmpty()) {
|
||||||
|
Log.d(Config.LOGTAG, String.format("skipping backup for %s because password is empty. unable to encrypt", account.getJid().asBareJid()));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
Log.d(Config.LOGTAG, String.format("exporting data for account %s (%s)", account.getJid().asBareJid(), account.getUuid()));
|
||||||
final byte[] IV = new byte[12];
|
final byte[] IV = new byte[12];
|
||||||
final byte[] salt = new byte[16];
|
final byte[] salt = new byte[16];
|
||||||
secureRandom.nextBytes(IV);
|
secureRandom.nextBytes(IV);
|
||||||
|
@ -281,8 +294,9 @@ public class ExportBackupService extends Service {
|
||||||
final Progress progress = new Progress(mBuilder, max, count);
|
final Progress progress = new Progress(mBuilder, max, count);
|
||||||
final File file = new File(FileBackend.getBackupDirectory(this) + account.getJid().asBareJid().toEscapedString() + ".ceb");
|
final File file = new File(FileBackend.getBackupDirectory(this) + account.getJid().asBareJid().toEscapedString() + ".ceb");
|
||||||
files.add(file);
|
files.add(file);
|
||||||
if (file.getParentFile().mkdirs()) {
|
final File directory = file.getParentFile();
|
||||||
Log.d(Config.LOGTAG, "created backup directory " + file.getParentFile().getAbsolutePath());
|
if (directory != null && directory.mkdirs()) {
|
||||||
|
Log.d(Config.LOGTAG, "created backup directory " + directory.getAbsolutePath());
|
||||||
}
|
}
|
||||||
final FileOutputStream fileOutputStream = new FileOutputStream(file);
|
final FileOutputStream fileOutputStream = new FileOutputStream(file);
|
||||||
final DataOutputStream dataOutputStream = new DataOutputStream(fileOutputStream);
|
final DataOutputStream dataOutputStream = new DataOutputStream(fileOutputStream);
|
||||||
|
@ -290,8 +304,7 @@ public class ExportBackupService extends Service {
|
||||||
dataOutputStream.flush();
|
dataOutputStream.flush();
|
||||||
|
|
||||||
final Cipher cipher = Compatibility.twentyEight() ? Cipher.getInstance(CIPHERMODE) : Cipher.getInstance(CIPHERMODE, PROVIDER);
|
final Cipher cipher = Compatibility.twentyEight() ? Cipher.getInstance(CIPHERMODE) : Cipher.getInstance(CIPHERMODE, PROVIDER);
|
||||||
byte[] key = getKey(account.getPassword(), salt);
|
final byte[] key = getKey(password, salt);
|
||||||
Log.d(Config.LOGTAG, backupFileHeader.toString());
|
|
||||||
SecretKeySpec keySpec = new SecretKeySpec(key, KEYTYPE);
|
SecretKeySpec keySpec = new SecretKeySpec(key, KEYTYPE);
|
||||||
IvParameterSpec ivSpec = new IvParameterSpec(IV);
|
IvParameterSpec ivSpec = new IvParameterSpec(IV);
|
||||||
cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
|
cipher.init(Cipher.ENCRYPT_MODE, keySpec, ivSpec);
|
||||||
|
@ -315,7 +328,7 @@ public class ExportBackupService extends Service {
|
||||||
return files;
|
return files;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void notifySuccess(List<File> files) {
|
private void notifySuccess(final List<File> files) {
|
||||||
final String path = FileBackend.getBackupDirectory(this);
|
final String path = FileBackend.getBackupDirectory(this);
|
||||||
|
|
||||||
PendingIntent openFolderIntent = null;
|
PendingIntent openFolderIntent = null;
|
||||||
|
@ -331,14 +344,14 @@ public class ExportBackupService extends Service {
|
||||||
if (files.size() > 0) {
|
if (files.size() > 0) {
|
||||||
final Intent intent = new Intent(Intent.ACTION_SEND_MULTIPLE);
|
final Intent intent = new Intent(Intent.ACTION_SEND_MULTIPLE);
|
||||||
ArrayList<Uri> uris = new ArrayList<>();
|
ArrayList<Uri> uris = new ArrayList<>();
|
||||||
for(File file : files) {
|
for (File file : files) {
|
||||||
uris.add(FileBackend.getUriForFile(this, file));
|
uris.add(FileBackend.getUriForFile(this, file));
|
||||||
}
|
}
|
||||||
intent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris);
|
intent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, uris);
|
||||||
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
|
||||||
intent.setType(MIME_TYPE);
|
intent.setType(MIME_TYPE);
|
||||||
final Intent chooser = Intent.createChooser(intent, getString(R.string.share_backup_files));
|
final Intent chooser = Intent.createChooser(intent, getString(R.string.share_backup_files));
|
||||||
shareFilesIntent = PendingIntent.getActivity(this,190, chooser, PendingIntent.FLAG_UPDATE_CURRENT);
|
shareFilesIntent = PendingIntent.getActivity(this, 190, chooser, PendingIntent.FLAG_UPDATE_CURRENT);
|
||||||
}
|
}
|
||||||
|
|
||||||
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(getBaseContext(), "backup");
|
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(getBaseContext(), "backup");
|
||||||
|
@ -361,7 +374,7 @@ public class ExportBackupService extends Service {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private class Progress {
|
private static class Progress {
|
||||||
private final NotificationCompat.Builder builder;
|
private final NotificationCompat.Builder builder;
|
||||||
private final int max;
|
private final int max;
|
||||||
private final int count;
|
private final int count;
|
||||||
|
|
Loading…
Reference in a new issue