mirror of
https://github.com/beemdevelopment/Aegis.git
synced 2025-04-21 14:29:13 +00:00
parent
b33c9383fe
commit
ad1d3f04a6
13 changed files with 391 additions and 67 deletions
|
@ -29,6 +29,7 @@ android {
|
|||
}
|
||||
|
||||
dependencies {
|
||||
def libsuVersion = '2.3.2'
|
||||
implementation fileTree(dir: 'libs', include: ['*.jar'])
|
||||
implementation 'com.amulyakhare:com.amulyakhare.textdrawable:1.0.1'
|
||||
implementation 'androidx.appcompat:appcompat:1.0.2'
|
||||
|
@ -45,5 +46,7 @@ dependencies {
|
|||
implementation 'com.mattprecious.swirl:swirl:1.0.0'
|
||||
implementation 'de.hdodenhof:circleimageview:2.2.0'
|
||||
implementation 'me.dm7.barcodescanner:zxing:1.9'
|
||||
implementation "com.github.topjohnwu.libsu:core:${libsuVersion}"
|
||||
implementation "com.github.topjohnwu.libsu:io:${libsuVersion}"
|
||||
testImplementation 'junit:junit:4.12'
|
||||
}
|
||||
|
|
|
@ -1,5 +1,7 @@
|
|||
package com.beemdevelopment.aegis.importers;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.util.List;
|
||||
|
@ -12,12 +14,12 @@ import com.beemdevelopment.aegis.db.DatabaseFileCredentials;
|
|||
import com.beemdevelopment.aegis.db.DatabaseFileException;
|
||||
import com.beemdevelopment.aegis.util.ByteInputStream;
|
||||
|
||||
public class AegisImporter extends DatabaseImporter {
|
||||
public class AegisFileImporter extends DatabaseFileImporter {
|
||||
private DatabaseFileCredentials _creds;
|
||||
private DatabaseFile _file;
|
||||
|
||||
public AegisImporter(ByteInputStream stream) {
|
||||
super(stream);
|
||||
public AegisFileImporter(Context context, ByteInputStream stream) {
|
||||
super(context, stream);
|
||||
}
|
||||
|
||||
@Override
|
|
@ -1,5 +1,7 @@
|
|||
package com.beemdevelopment.aegis.importers;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
@ -17,11 +19,11 @@ import com.beemdevelopment.aegis.otp.OtpInfoException;
|
|||
import com.beemdevelopment.aegis.otp.TotpInfo;
|
||||
import com.beemdevelopment.aegis.util.ByteInputStream;
|
||||
|
||||
public class AndOtpImporter extends DatabaseImporter {
|
||||
public class AndOtpFileImporter extends DatabaseFileImporter {
|
||||
private JSONArray _obj;
|
||||
|
||||
public AndOtpImporter(ByteInputStream stream) {
|
||||
super(stream);
|
||||
public AndOtpFileImporter(Context context, ByteInputStream stream) {
|
||||
super(context, stream);
|
||||
}
|
||||
|
||||
@Override
|
|
@ -0,0 +1,50 @@
|
|||
package com.beemdevelopment.aegis.importers;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import com.beemdevelopment.aegis.db.DatabaseEntry;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public abstract class DatabaseAppImporter implements DatabaseImporter {
|
||||
private static Map<String, Class<? extends DatabaseAppImporter>> _importers;
|
||||
static {
|
||||
// note: keep this list sorted alphabetically
|
||||
LinkedHashMap<String, Class<? extends DatabaseAppImporter>> importers = new LinkedHashMap<>();
|
||||
importers.put("Google Authenticator", GoogleAuthAppImporter.class);
|
||||
_importers = Collections.unmodifiableMap(importers);
|
||||
}
|
||||
|
||||
private Context _context;
|
||||
|
||||
protected DatabaseAppImporter(Context context) {
|
||||
_context = context;
|
||||
}
|
||||
|
||||
public abstract void parse() throws DatabaseImporterException;
|
||||
|
||||
public abstract List<DatabaseEntry> convert() throws DatabaseImporterException;
|
||||
|
||||
public abstract boolean isEncrypted();
|
||||
|
||||
public Context getContext() {
|
||||
return _context;
|
||||
}
|
||||
|
||||
public static DatabaseAppImporter create(Context context, Class<? extends DatabaseAppImporter> type) {
|
||||
try {
|
||||
return type.getConstructor(Context.class).newInstance(context);
|
||||
} catch (IllegalAccessException | InstantiationException
|
||||
| NoSuchMethodException | InvocationTargetException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static Map<String, Class<? extends DatabaseAppImporter>> getImporters() {
|
||||
return _importers;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
package com.beemdevelopment.aegis.importers;
|
||||
|
||||
import android.content.Context;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import com.beemdevelopment.aegis.db.DatabaseEntry;
|
||||
import com.beemdevelopment.aegis.util.ByteInputStream;
|
||||
|
||||
public abstract class DatabaseFileImporter implements DatabaseImporter {
|
||||
private static Map<String, Class<? extends DatabaseFileImporter>> _importers;
|
||||
static {
|
||||
// note: keep this list sorted alphabetically
|
||||
LinkedHashMap<String, Class<? extends DatabaseFileImporter>> importers = new LinkedHashMap<>();
|
||||
importers.put("Aegis", AegisFileImporter.class);
|
||||
importers.put("andOTP", AndOtpFileImporter.class);
|
||||
importers.put("FreeOTP", FreeOtpFileImporter.class);
|
||||
_importers = Collections.unmodifiableMap(importers);
|
||||
}
|
||||
|
||||
private Context _context;
|
||||
protected ByteInputStream _stream;
|
||||
|
||||
protected DatabaseFileImporter(Context context, ByteInputStream stream) {
|
||||
_context = context;
|
||||
_stream = stream;
|
||||
}
|
||||
|
||||
public abstract void parse() throws DatabaseImporterException;
|
||||
|
||||
public abstract List<DatabaseEntry> convert() throws DatabaseImporterException;
|
||||
|
||||
public abstract boolean isEncrypted();
|
||||
|
||||
public Context getContext() {
|
||||
return _context;
|
||||
}
|
||||
|
||||
public static DatabaseFileImporter create(Context context, ByteInputStream stream, Class<? extends DatabaseFileImporter> type) {
|
||||
try {
|
||||
return type.getConstructor(Context.class, ByteInputStream.class).newInstance(context, stream);
|
||||
} catch (IllegalAccessException | InstantiationException
|
||||
| NoSuchMethodException | InvocationTargetException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static Map<String, Class<? extends DatabaseFileImporter>> getImporters() {
|
||||
return _importers;
|
||||
}
|
||||
}
|
|
@ -1,47 +1,14 @@
|
|||
package com.beemdevelopment.aegis.importers;
|
||||
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.util.Collections;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import android.content.Context;
|
||||
|
||||
import com.beemdevelopment.aegis.db.DatabaseEntry;
|
||||
import com.beemdevelopment.aegis.util.ByteInputStream;
|
||||
|
||||
public abstract class DatabaseImporter {
|
||||
private static Map<String, Class<? extends DatabaseImporter>> _importers;
|
||||
static {
|
||||
// note: keep this list sorted alphabetically
|
||||
LinkedHashMap<String, Class<? extends DatabaseImporter>> importers = new LinkedHashMap<>();
|
||||
importers.put("Aegis", AegisImporter.class);
|
||||
importers.put("andOTP", AndOtpImporter.class);
|
||||
importers.put("FreeOTP", FreeOtpImporter.class);
|
||||
_importers = Collections.unmodifiableMap(importers);
|
||||
}
|
||||
import java.util.List;
|
||||
|
||||
protected ByteInputStream _stream;
|
||||
|
||||
protected DatabaseImporter(ByteInputStream stream) {
|
||||
_stream = stream;
|
||||
}
|
||||
|
||||
public abstract void parse() throws DatabaseImporterException;
|
||||
|
||||
public abstract List<DatabaseEntry> convert() throws DatabaseImporterException;
|
||||
|
||||
public abstract boolean isEncrypted();
|
||||
|
||||
public static DatabaseImporter create(ByteInputStream stream, Class<? extends DatabaseImporter> type) {
|
||||
try {
|
||||
return type.getConstructor(ByteInputStream.class).newInstance(stream);
|
||||
} catch (IllegalAccessException | InstantiationException
|
||||
| NoSuchMethodException | InvocationTargetException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static Map<String, Class<? extends DatabaseImporter>> getImporters() {
|
||||
return _importers;
|
||||
}
|
||||
public interface DatabaseImporter {
|
||||
void parse() throws DatabaseImporterException;
|
||||
List<DatabaseEntry> convert() throws DatabaseImporterException;
|
||||
boolean isEncrypted();
|
||||
Context getContext();
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package com.beemdevelopment.aegis.importers;
|
||||
|
||||
import android.content.Context;
|
||||
import android.util.Xml;
|
||||
|
||||
import org.json.JSONArray;
|
||||
|
@ -19,11 +20,11 @@ import com.beemdevelopment.aegis.otp.OtpInfoException;
|
|||
import com.beemdevelopment.aegis.otp.TotpInfo;
|
||||
import com.beemdevelopment.aegis.util.ByteInputStream;
|
||||
|
||||
public class FreeOtpImporter extends DatabaseImporter {
|
||||
public class FreeOtpFileImporter extends DatabaseFileImporter {
|
||||
private List<XmlEntry> _xmlEntries;
|
||||
|
||||
public FreeOtpImporter(ByteInputStream stream) {
|
||||
super(stream);
|
||||
public FreeOtpFileImporter(Context context, ByteInputStream stream) {
|
||||
super(context, stream);
|
||||
}
|
||||
|
||||
private static class XmlEntry {
|
|
@ -0,0 +1,124 @@
|
|||
package com.beemdevelopment.aegis.importers;
|
||||
|
||||
import android.annotation.SuppressLint;
|
||||
import android.content.Context;
|
||||
import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteException;
|
||||
|
||||
import com.beemdevelopment.aegis.db.DatabaseEntry;
|
||||
import com.beemdevelopment.aegis.encoding.Base32;
|
||||
import com.beemdevelopment.aegis.encoding.Base32Exception;
|
||||
import com.beemdevelopment.aegis.otp.HotpInfo;
|
||||
import com.beemdevelopment.aegis.otp.OtpInfo;
|
||||
import com.beemdevelopment.aegis.otp.OtpInfoException;
|
||||
import com.beemdevelopment.aegis.otp.TotpInfo;
|
||||
import com.topjohnwu.superuser.ShellUtils;
|
||||
import com.topjohnwu.superuser.io.SuFile;
|
||||
import com.topjohnwu.superuser.io.SuFileInputStream;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static android.database.sqlite.SQLiteDatabase.OPEN_READONLY;
|
||||
|
||||
public class GoogleAuthAppImporter extends DatabaseAppImporter {
|
||||
private static final int TYPE_TOTP = 0;
|
||||
private static final int TYPE_HOTP = 1;
|
||||
|
||||
@SuppressLint("SdCardPath")
|
||||
private static final String _filename = "/data/data/com.google.android.apps.authenticator2/databases/databases";
|
||||
|
||||
private List<DatabaseEntry> _entries = new ArrayList<>();
|
||||
|
||||
public GoogleAuthAppImporter(Context context) {
|
||||
super(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void parse() throws DatabaseImporterException {
|
||||
File file;
|
||||
|
||||
try {
|
||||
// create a temporary copy of the database so that SQLiteDatabase can open it
|
||||
file = File.createTempFile("google-import-", "", getContext().getCacheDir());
|
||||
try (SuFileInputStream in = new SuFileInputStream(new SuFile(_filename))) {
|
||||
try (FileOutputStream out = new FileOutputStream(file)) {
|
||||
ShellUtils.pump(in, out);
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
throw new DatabaseImporterException(e);
|
||||
}
|
||||
|
||||
try (SQLiteDatabase db = SQLiteDatabase.openDatabase(file.getAbsolutePath(), null, OPEN_READONLY, null)) {
|
||||
try (Cursor cursor = db.rawQuery("SELECT * FROM accounts", null)) {
|
||||
if (!cursor.moveToFirst()) {
|
||||
return;
|
||||
}
|
||||
|
||||
do {
|
||||
int type = getInt(cursor, "type");
|
||||
byte[] secret = Base32.decode(getString(cursor, "secret").toCharArray());
|
||||
|
||||
OtpInfo info;
|
||||
switch (type) {
|
||||
case TYPE_TOTP:
|
||||
info = new TotpInfo(secret);
|
||||
break;
|
||||
case TYPE_HOTP:
|
||||
info = new HotpInfo(secret, getInt(cursor, "counter"));
|
||||
break;
|
||||
default:
|
||||
throw new DatabaseImporterException("unsupported otp type: " + type);
|
||||
}
|
||||
|
||||
String name = getString(cursor, "email", "");
|
||||
String issuer = getString(cursor, "issuer", "");
|
||||
|
||||
String[] parts = name.split(":");
|
||||
if (parts.length == 2) {
|
||||
name = parts[1];
|
||||
}
|
||||
|
||||
DatabaseEntry entry = new DatabaseEntry(info, name, issuer);
|
||||
_entries.add(entry);
|
||||
} while(cursor.moveToNext());
|
||||
}
|
||||
} catch (SQLiteException | OtpInfoException | Base32Exception e) {
|
||||
throw new DatabaseImporterException(e);
|
||||
} finally {
|
||||
// always delete the temporary file
|
||||
file.delete();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<DatabaseEntry> convert() {
|
||||
return _entries;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEncrypted() {
|
||||
return false;
|
||||
}
|
||||
|
||||
private static String getString(Cursor cursor, String columnName) {
|
||||
return getString(cursor, columnName, null);
|
||||
}
|
||||
|
||||
private static String getString(Cursor cursor, String columnName, String def) {
|
||||
String res = cursor.getString(cursor.getColumnIndex(columnName));
|
||||
if (res == null) {
|
||||
return def;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
private static int getInt(Cursor cursor, String columnName) {
|
||||
return cursor.getInt(cursor.getColumnIndex(columnName));
|
||||
}
|
||||
}
|
|
@ -11,9 +11,13 @@ import java.security.NoSuchAlgorithmException;
|
|||
public class HotpInfo extends OtpInfo {
|
||||
private long _counter;
|
||||
|
||||
public HotpInfo(byte[] secret) throws OtpInfoException {
|
||||
public HotpInfo(byte[] secret, long counter) throws OtpInfoException {
|
||||
super(secret);
|
||||
setCounter(0);
|
||||
setCounter(counter);
|
||||
}
|
||||
|
||||
public HotpInfo(byte[] secret) throws OtpInfoException {
|
||||
this(secret, 0);
|
||||
}
|
||||
|
||||
public HotpInfo(byte[] secret, String algorithm, int digits, long counter) throws OtpInfoException {
|
||||
|
|
|
@ -16,7 +16,9 @@ import android.widget.Toast;
|
|||
import com.beemdevelopment.aegis.db.DatabaseFileCredentials;
|
||||
import com.beemdevelopment.aegis.helpers.FingerprintHelper;
|
||||
import com.beemdevelopment.aegis.helpers.PermissionHelper;
|
||||
import com.beemdevelopment.aegis.importers.AegisImporter;
|
||||
import com.beemdevelopment.aegis.importers.AegisFileImporter;
|
||||
import com.beemdevelopment.aegis.importers.DatabaseAppImporter;
|
||||
import com.beemdevelopment.aegis.importers.DatabaseFileImporter;
|
||||
import com.beemdevelopment.aegis.importers.DatabaseImporter;
|
||||
import com.beemdevelopment.aegis.importers.DatabaseImporterException;
|
||||
import com.beemdevelopment.aegis.ui.preferences.SwitchPreference;
|
||||
|
@ -46,6 +48,7 @@ import com.beemdevelopment.aegis.db.slots.PasswordSlot;
|
|||
import com.beemdevelopment.aegis.db.slots.Slot;
|
||||
import com.beemdevelopment.aegis.db.slots.SlotException;
|
||||
import com.beemdevelopment.aegis.db.slots.SlotList;
|
||||
import com.topjohnwu.superuser.Shell;
|
||||
|
||||
public class PreferencesFragment extends PreferenceFragmentCompat {
|
||||
// activity request codes
|
||||
|
@ -63,8 +66,8 @@ public class PreferencesFragment extends PreferenceFragmentCompat {
|
|||
|
||||
// this is used to keep a reference to a database converter
|
||||
// while the user provides credentials to decrypt it
|
||||
private DatabaseImporter _importer;
|
||||
private Class<? extends DatabaseImporter> _importerType;
|
||||
private DatabaseFileImporter _importer;
|
||||
private Class<? extends DatabaseFileImporter> _importerType;
|
||||
|
||||
private SwitchPreference _encryptionPreference;
|
||||
private SwitchPreference _fingerprintPreference;
|
||||
|
@ -92,8 +95,8 @@ public class PreferencesFragment extends PreferenceFragmentCompat {
|
|||
}
|
||||
});
|
||||
|
||||
Preference exportPreference = findPreference("pref_import");
|
||||
exportPreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
|
||||
Preference importPreference = findPreference("pref_import");
|
||||
importPreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
|
||||
@Override
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
onImport();
|
||||
|
@ -101,8 +104,18 @@ public class PreferencesFragment extends PreferenceFragmentCompat {
|
|||
}
|
||||
});
|
||||
|
||||
Preference importPreference = findPreference("pref_export");
|
||||
importPreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
|
||||
Preference importAppPreference = findPreference("pref_import_app");
|
||||
importAppPreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
|
||||
@Override
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
onImportApp();
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
Preference exportPreference = findPreference("pref_export");
|
||||
exportPreference.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
|
||||
@Override
|
||||
public boolean onPreferenceClick(Preference preference) {
|
||||
onExport();
|
||||
|
@ -277,7 +290,7 @@ public class PreferencesFragment extends PreferenceFragmentCompat {
|
|||
return;
|
||||
}
|
||||
|
||||
Map<String, Class<? extends DatabaseImporter>> importers = DatabaseImporter.getImporters();
|
||||
Map<String, Class<? extends DatabaseFileImporter>> importers = DatabaseFileImporter.getImporters();
|
||||
String[] names = importers.keySet().toArray(new String[importers.size()]);
|
||||
|
||||
Dialogs.showSecureDialog(new AlertDialog.Builder(getActivity())
|
||||
|
@ -296,6 +309,43 @@ public class PreferencesFragment extends PreferenceFragmentCompat {
|
|||
.create());
|
||||
}
|
||||
|
||||
private void onImportApp() {
|
||||
Map<String, Class<? extends DatabaseAppImporter>> importers = DatabaseAppImporter.getImporters();
|
||||
String[] names = importers.keySet().toArray(new String[importers.size()]);
|
||||
|
||||
Dialogs.showSecureDialog(new AlertDialog.Builder(getActivity())
|
||||
.setTitle(getString(R.string.choose_application))
|
||||
.setSingleChoiceItems(names, 0, null)
|
||||
.setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
int i = ((AlertDialog) dialog).getListView().getCheckedItemPosition();
|
||||
try {
|
||||
DatabaseAppImporter importer;
|
||||
// obtain the global root shell and close it immediately after we're done
|
||||
// TODO: find a way to use SuFileInputStream with Shell.newInstance()
|
||||
try (Shell shell = Shell.getShell()) {
|
||||
if (!shell.isRoot()) {
|
||||
Toast.makeText(getActivity(), getString(R.string.root_error), Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
importer = DatabaseAppImporter.create(getContext(), importers.get(names[i]));
|
||||
importer.parse();
|
||||
} catch (IOException e) {
|
||||
Toast.makeText(getActivity(), getString(R.string.root_error), Toast.LENGTH_SHORT).show();
|
||||
return;
|
||||
}
|
||||
importDatabase(importer);
|
||||
} catch (DatabaseImporterException e) {
|
||||
e.printStackTrace();
|
||||
|
||||
String msg = String.format("%s: %s", getString(R.string.parsing_file_error), e.getMessage());
|
||||
Toast.makeText(getActivity(), msg, Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
}
|
||||
})
|
||||
.create());
|
||||
}
|
||||
|
||||
private void onImportDecryptResult(int resultCode, Intent data) {
|
||||
if (resultCode != Activity.RESULT_OK) {
|
||||
_importer = null;
|
||||
|
@ -303,7 +353,7 @@ public class PreferencesFragment extends PreferenceFragmentCompat {
|
|||
}
|
||||
|
||||
DatabaseFileCredentials creds = (DatabaseFileCredentials) data.getSerializableExtra("creds");
|
||||
((AegisImporter)_importer).setCredentials(creds);
|
||||
((AegisFileImporter)_importer).setCredentials(creds);
|
||||
|
||||
try {
|
||||
importDatabase(_importer);
|
||||
|
@ -337,15 +387,15 @@ public class PreferencesFragment extends PreferenceFragmentCompat {
|
|||
}
|
||||
|
||||
try {
|
||||
DatabaseImporter importer = DatabaseImporter.create(stream, _importerType);
|
||||
DatabaseFileImporter importer = DatabaseFileImporter.create(getContext(), stream, _importerType);
|
||||
importer.parse();
|
||||
|
||||
// special case to decrypt encrypted aegis databases
|
||||
if (importer.isEncrypted() && importer instanceof AegisImporter) {
|
||||
if (importer.isEncrypted() && importer instanceof AegisFileImporter) {
|
||||
_importer = importer;
|
||||
|
||||
Intent intent = new Intent(getActivity(), AuthActivity.class);
|
||||
intent.putExtra("slots", ((AegisImporter)_importer).getFile().getHeader().getSlots());
|
||||
intent.putExtra("slots", ((AegisFileImporter)_importer).getFile().getHeader().getSlots());
|
||||
startActivityForResult(intent, CODE_IMPORT_DECRYPT);
|
||||
return;
|
||||
}
|
||||
|
|
58
app/src/main/java/me/impy/aegis/db/DatabaseEntryGroup.java
Normal file
58
app/src/main/java/me/impy/aegis/db/DatabaseEntryGroup.java
Normal file
|
@ -0,0 +1,58 @@
|
|||
package me.impy.aegis.db;
|
||||
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.UUID;
|
||||
|
||||
public class DatabaseEntryGroup implements Serializable {
|
||||
private UUID _uuid;
|
||||
private String _name;
|
||||
|
||||
private DatabaseEntryGroup(UUID uuid, String name) {
|
||||
_uuid = uuid;
|
||||
_name = name;
|
||||
}
|
||||
|
||||
public DatabaseEntryGroup(String name) {
|
||||
this(UUID.randomUUID(), name);
|
||||
}
|
||||
|
||||
public JSONObject toJson() {
|
||||
JSONObject obj = new JSONObject();
|
||||
|
||||
try {
|
||||
obj.put("uuid", _uuid.toString());
|
||||
obj.put("name", _name);
|
||||
} catch (JSONException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
|
||||
return obj;
|
||||
}
|
||||
|
||||
public static DatabaseEntryGroup fromJson(JSONObject obj) throws JSONException {
|
||||
// if there is no uuid, generate a new one
|
||||
UUID uuid;
|
||||
if (!obj.has("uuid")) {
|
||||
uuid = UUID.randomUUID();
|
||||
} else {
|
||||
uuid = UUID.fromString(obj.getString("uuid"));
|
||||
}
|
||||
|
||||
return new DatabaseEntryGroup(uuid, obj.getString("name"));
|
||||
}
|
||||
|
||||
public UUID getUUID() {
|
||||
return _uuid;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return _name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
_name = name;
|
||||
}
|
||||
}
|
|
@ -19,8 +19,10 @@
|
|||
<string name="pref_timeout_summary">Automatically lock the database after %1$s seconds of inactivity</string>
|
||||
<string name="pref_slots_title">Key slots</string>
|
||||
<string name="pref_slots_summary">Manage the list of keys that can decrypt the database</string>
|
||||
<string name="pref_import_title">Import</string>
|
||||
<string name="pref_import_summary">Import a database</string>
|
||||
<string name="pref_import_file_title">Import from file</string>
|
||||
<string name="pref_import_file_summary">Import a database from a file</string>
|
||||
<string name="pref_import_app_title">Import from app</string>
|
||||
<string name="pref_import_app_summary">Import a database from an app (requires root access)</string>
|
||||
<string name="pref_export_title">Export</string>
|
||||
<string name="pref_export_summary">Export the database</string>
|
||||
<string name="pref_secure_screen_title">Screen security</string>
|
||||
|
@ -121,6 +123,7 @@
|
|||
<string name="parsing_file_error">An error occurred while trying to parse the file</string>
|
||||
<string name="file_not_found">Error: File not found</string>
|
||||
<string name="reading_file_error">An error occurred while trying to read the file</string>
|
||||
<string name="root_error">Error: unable to obtain root access</string>
|
||||
<string name="imported_entries_count">Imported %d entries</string>
|
||||
<string name="exporting_database_error">An error occurred while trying to export the database</string>
|
||||
<string name="export_database_location">The database has been exported to:</string>
|
||||
|
|
|
@ -78,8 +78,13 @@
|
|||
app:iconSpaceReserved="false">
|
||||
<Preference
|
||||
android:key="pref_import"
|
||||
android:title="@string/pref_import_title"
|
||||
android:summary="@string/pref_import_summary"
|
||||
android:title="@string/pref_import_file_title"
|
||||
android:summary="@string/pref_import_file_summary"
|
||||
app:iconSpaceReserved="false"/>
|
||||
<Preference
|
||||
android:key="pref_import_app"
|
||||
android:title="@string/pref_import_app_title"
|
||||
android:summary="@string/pref_import_app_summary"
|
||||
app:iconSpaceReserved="false"/>
|
||||
<Preference
|
||||
android:key="pref_export"
|
||||
|
|
Loading…
Add table
Reference in a new issue