diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index c769b8c0..559d0315 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -3,8 +3,8 @@
package="me.impy.aegis">
-
+
convert() throws Exception {
+ List keys = new ArrayList<>();
+
+ XmlPullParser parser = Xml.newPullParser();
+ parser.setFeature(XmlPullParser.FEATURE_PROCESS_NAMESPACES, false);
+ parser.setInput(_stream, null);
+ parser.nextTag();
+ return parse(parser);
+ }
+
+ private static List parse(XmlPullParser parser) throws IOException, XmlPullParserException, JSONException {
+ List entries = new ArrayList<>();
+
+ parser.require(XmlPullParser.START_TAG, null, "map");
+ while (parser.next() != XmlPullParser.END_TAG) {
+ if (parser.getEventType() != XmlPullParser.START_TAG) {
+ continue;
+ }
+
+ if (!parser.getName().equals("string")) {
+ skip(parser);
+ continue;
+ }
+
+ entries.add(parseEntry(parser));
+ }
+
+ List profiles = new ArrayList<>();
+
+ for (Entry entry : entries) {
+ if (entry.Name.equals("tokenOrder")) {
+ // TODO: order
+ JSONArray array = new JSONArray(entry.Value);
+ } else {
+ JSONObject obj = new JSONObject(entry.Value);
+
+ KeyInfo key = new KeyInfo();
+ key.setAlgorithm(obj.getString("algo"));
+ key.setCounter(obj.getLong("counter"));
+ key.setDigits(obj.getInt("digits"));
+ key.setIssuer(obj.getString("issuerExt"));
+ key.setAccountName(obj.optString("label"));
+ key.setPeriod(obj.getInt("period"));
+ key.setType(obj.getString("type"));
+ byte[] secret = toBytes(obj.getJSONArray("secret"));
+ key.setSecret(secret);
+
+ KeyProfile profile = new KeyProfile();
+ profile.Info = key;
+ profiles.add(profile);
+ }
+ }
+
+ return profiles;
+ }
+
+ private static byte[] toBytes(JSONArray array) throws JSONException {
+ byte[] bytes = new byte[array.length()];
+ for (int i = 0; i < array.length(); i++) {
+ bytes[i] = (byte)array.getInt(i);
+ }
+ return bytes;
+ }
+
+ private static Entry parseEntry(XmlPullParser parser) throws IOException, XmlPullParserException {
+ KeyProfile profile = new KeyProfile();
+ parser.require(XmlPullParser.START_TAG, null, "string");
+ String name = parser.getAttributeValue(null, "name");
+ String value = parseText(parser);
+ parser.require(XmlPullParser.END_TAG, null, "string");
+ return new Entry() {{ Name = name; Value = value; }};
+ }
+
+ private static String parseText(XmlPullParser parser) throws IOException, XmlPullParserException {
+ String text = "";
+ if (parser.next() == XmlPullParser.TEXT) {
+ text = parser.getText();
+ parser.nextTag();
+ }
+ return text;
+ }
+
+ private static void skip(XmlPullParser parser) throws IOException, XmlPullParserException {
+ // source: https://developer.android.com/training/basics/network-ops/xml.html
+ if (parser.getEventType() != XmlPullParser.START_TAG) {
+ throw new IllegalStateException();
+ }
+
+ int depth = 1;
+ while (depth != 0) {
+ switch (parser.next()) {
+ case XmlPullParser.END_TAG:
+ depth--;
+ break;
+ case XmlPullParser.START_TAG:
+ depth++;
+ break;
+ }
+ }
+ }
+}
diff --git a/app/src/main/java/me/impy/aegis/ext/KeyConverter.java b/app/src/main/java/me/impy/aegis/ext/KeyConverter.java
new file mode 100644
index 00000000..2366c9f3
--- /dev/null
+++ b/app/src/main/java/me/impy/aegis/ext/KeyConverter.java
@@ -0,0 +1,16 @@
+package me.impy.aegis.ext;
+
+import java.io.InputStream;
+import java.util.List;
+
+import me.impy.aegis.KeyProfile;
+
+public abstract class KeyConverter {
+ protected InputStream _stream;
+
+ public KeyConverter(InputStream stream) {
+ _stream = stream;
+ }
+
+ public abstract List convert() throws Exception;
+}
diff --git a/app/src/main/res/menu/menu_main.xml b/app/src/main/res/menu/menu_main.xml
index 6d6a31c1..7abb682e 100644
--- a/app/src/main/res/menu/menu_main.xml
+++ b/app/src/main/res/menu/menu_main.xml
@@ -7,6 +7,11 @@
android:icon="@drawable/ic_lock"
app:showAsAction="ifRoom"
android:title=""/>
+
-
Aegis
Settings
+ Import
IntroActivity
Preferences
Night mode