diff --git a/app/src/main/java/me/impy/aegis/importers/AegisImporter.java b/app/src/main/java/me/impy/aegis/importers/AegisImporter.java index 49109e50..e3f79727 100644 --- a/app/src/main/java/me/impy/aegis/importers/AegisImporter.java +++ b/app/src/main/java/me/impy/aegis/importers/AegisImporter.java @@ -61,9 +61,4 @@ public class AegisImporter extends DatabaseImporter { public DatabaseFile getFile() { return _file; } - - @Override - public String getName() { - return "Aegis"; - } } diff --git a/app/src/main/java/me/impy/aegis/importers/AndOTPImporter.java b/app/src/main/java/me/impy/aegis/importers/AndOTPImporter.java index 0599ca24..e94bf608 100644 --- a/app/src/main/java/me/impy/aegis/importers/AndOTPImporter.java +++ b/app/src/main/java/me/impy/aegis/importers/AndOTPImporter.java @@ -75,9 +75,4 @@ public class AndOTPImporter extends DatabaseImporter { public boolean isEncrypted() { return false; } - - @Override - public String getName() { - return "andOTP"; - } } diff --git a/app/src/main/java/me/impy/aegis/importers/DatabaseImporter.java b/app/src/main/java/me/impy/aegis/importers/DatabaseImporter.java index 40f0f242..286bcdd4 100644 --- a/app/src/main/java/me/impy/aegis/importers/DatabaseImporter.java +++ b/app/src/main/java/me/impy/aegis/importers/DatabaseImporter.java @@ -2,21 +2,24 @@ package me.impy.aegis.importers; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; -import java.util.Arrays; import java.util.Collections; +import java.util.LinkedHashMap; import java.util.List; +import java.util.Map; import me.impy.aegis.db.DatabaseEntry; import me.impy.aegis.util.ByteInputStream; public abstract class DatabaseImporter { - private static List> _converters = Collections.unmodifiableList( - new ArrayList<>(Arrays.asList( - AegisImporter.class, - FreeOTPImporter.class, - AndOTPImporter.class - )) - ); + private static Map> _importers; + static { + // note: keep this list sorted alphabetically + LinkedHashMap> importers = new LinkedHashMap<>(); + importers.put("Aegis", AegisImporter.class); + importers.put("andOTP", AndOTPImporter.class); + importers.put("FreeOTP", FreeOTPImporter.class); + _importers = Collections.unmodifiableMap(importers); + } protected ByteInputStream _stream; @@ -30,8 +33,6 @@ public abstract class DatabaseImporter { public abstract boolean isEncrypted(); - public abstract String getName(); - public static DatabaseImporter create(ByteInputStream stream, Class type) { try { return type.getConstructor(ByteInputStream.class).newInstance(stream); @@ -43,9 +44,13 @@ public abstract class DatabaseImporter { public static List create(ByteInputStream stream) { List list = new ArrayList<>(); - for (Class type : _converters) { + for (Class type : _importers.values()) { list.add(create(stream, type)); } return list; } + + public static Map> getImporters() { + return _importers; + } } diff --git a/app/src/main/java/me/impy/aegis/importers/FreeOTPImporter.java b/app/src/main/java/me/impy/aegis/importers/FreeOTPImporter.java index e368e59e..4624f946 100644 --- a/app/src/main/java/me/impy/aegis/importers/FreeOTPImporter.java +++ b/app/src/main/java/me/impy/aegis/importers/FreeOTPImporter.java @@ -50,11 +50,6 @@ public class FreeOTPImporter extends DatabaseImporter { return false; } - @Override - public String getName() { - return "FreeOTP"; - } - private static List parse(XmlPullParser parser) throws IOException, XmlPullParserException, JSONException, KeyInfoException { List entries = new ArrayList<>(); diff --git a/app/src/main/java/me/impy/aegis/ui/PreferencesFragment.java b/app/src/main/java/me/impy/aegis/ui/PreferencesFragment.java index 2b2eda0c..2a8fdc64 100644 --- a/app/src/main/java/me/impy/aegis/ui/PreferencesFragment.java +++ b/app/src/main/java/me/impy/aegis/ui/PreferencesFragment.java @@ -20,6 +20,7 @@ import java.io.IOException; import java.io.InputStream; import java.util.List; import java.util.Locale; +import java.util.Map; import me.impy.aegis.AegisApplication; import me.impy.aegis.R; @@ -49,7 +50,8 @@ public class PreferencesFragment extends PreferenceFragment { // this is used to keep a reference to a database converter // while the user provides credentials to decrypt it - private DatabaseImporter _converter; + private DatabaseImporter _importer; + private Class _importerType; @Override public void onCreate(Bundle savedInstanceState) { @@ -185,30 +187,46 @@ public class PreferencesFragment extends PreferenceFragment { } private void onImport() { - if (PermissionHelper.request(getActivity(), CODE_PERM_IMPORT, Manifest.permission.READ_EXTERNAL_STORAGE)) { - Intent intent = new Intent(Intent.ACTION_GET_CONTENT); - intent.setType("*/*"); - startActivityForResult(intent, CODE_IMPORT); - } + Map> importers = DatabaseImporter.getImporters(); + String[] names = importers.keySet().toArray(new String[importers.size()]); + + new AlertDialog.Builder(getActivity()) + .setTitle("Select the application you'd like to import a database from") + .setSingleChoiceItems(names, 0, null) + .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + dialog.dismiss(); + + int i = ((AlertDialog) dialog).getListView().getCheckedItemPosition(); + _importerType = importers.get(names[i]); + + if (PermissionHelper.request(getActivity(), CODE_PERM_IMPORT, Manifest.permission.READ_EXTERNAL_STORAGE)) { + Intent intent = new Intent(Intent.ACTION_GET_CONTENT); + intent.setType("*/*"); + startActivityForResult(intent, CODE_IMPORT); + } + } + }) + .show(); } private void onImportDecryptResult(int resultCode, Intent data) { if (resultCode != Activity.RESULT_OK) { - _converter = null; + _importer = null; return; } MasterKey key = (MasterKey) data.getSerializableExtra("key"); - ((AegisImporter)_converter).setKey(key); + ((AegisImporter)_importer).setKey(key); try { - importDatabase(_converter); + importDatabase(_importer); } catch (DatabaseImporterException e) { e.printStackTrace(); Toast.makeText(getActivity(), "An error occurred while trying to parse the file", Toast.LENGTH_SHORT).show(); } - _converter = null; + _importer = null; } private void onImportResult(int resultCode, Intent data) { @@ -239,37 +257,29 @@ public class PreferencesFragment extends PreferenceFragment { } } - boolean imported = false; - for (DatabaseImporter converter : DatabaseImporter.create(stream)) { - try { - converter.parse(); + try { + DatabaseImporter importer = DatabaseImporter.create(stream, _importerType); + importer.parse(); - // special case to decrypt encrypted aegis databases - if (converter.isEncrypted() && converter instanceof AegisImporter) { - _converter = converter; + // special case to decrypt encrypted aegis databases + if (importer.isEncrypted() && importer instanceof AegisImporter) { + _importer = importer; - Intent intent = new Intent(getActivity(), AuthActivity.class); - intent.putExtra("slots", ((AegisImporter)_converter).getFile().getSlots()); - startActivityForResult(intent, CODE_IMPORT_DECRYPT); - return; - } - - importDatabase(converter); - imported = true; - break; - } catch (DatabaseImporterException e) { - e.printStackTrace(); - stream.reset(); + Intent intent = new Intent(getActivity(), AuthActivity.class); + intent.putExtra("slots", ((AegisImporter)_importer).getFile().getSlots()); + startActivityForResult(intent, CODE_IMPORT_DECRYPT); + return; } - } - if (!imported) { + importDatabase(importer); + } catch (DatabaseImporterException e) { + e.printStackTrace(); Toast.makeText(getActivity(), "An error occurred while trying to parse the file", Toast.LENGTH_SHORT).show(); } } - private void importDatabase(DatabaseImporter converter) throws DatabaseImporterException { - List entries = converter.convert(); + private void importDatabase(DatabaseImporter importer) throws DatabaseImporterException { + List entries = importer.convert(); for (DatabaseEntry entry : entries) { _db.addKey(entry); }