aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVincent Breitmoser <valodim@mugenguild.com>2015-09-25 00:47:46 +0200
committerVincent Breitmoser <valodim@mugenguild.com>2015-09-25 01:38:13 +0200
commit408c4a896cf70f2c18356be1bd331bf6b07f1839 (patch)
tree442829f676d9989144534a85220a524e5b9e4782
parentd94ebb22699ff50c027296c5c5752c571c60c33c (diff)
downloadopen-keychain-408c4a896cf70f2c18356be1bd331bf6b07f1839.tar.gz
open-keychain-408c4a896cf70f2c18356be1bd331bf6b07f1839.tar.bz2
open-keychain-408c4a896cf70f2c18356be1bd331bf6b07f1839.zip
enc-backup: ask for backup code again
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/BackupActivity.java21
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/BackupCodeDisplayFragment.java31
-rw-r--r--OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/BackupCodeEntryFragment.java162
-rw-r--r--OpenKeychain/src/main/res/layout/backup_activity.xml (renamed from OpenKeychain/src/main/res/layout/drawer_backup_activity.xml)7
-rw-r--r--OpenKeychain/src/main/res/layout/backup_code_display_fragment.xml (renamed from OpenKeychain/src/main/res/layout/backup_code_fragment.xml)23
-rw-r--r--OpenKeychain/src/main/res/layout/backup_code_entry_fragment.xml199
6 files changed, 418 insertions, 25 deletions
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/BackupActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/BackupActivity.java
index 5535ad875..cc80f8910 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/BackupActivity.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/BackupActivity.java
@@ -18,6 +18,10 @@
package org.sufficientlysecure.keychain.ui;
+
+import android.os.Bundle;
+import android.support.v4.app.FragmentManager;
+
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.ui.base.BaseActivity;
@@ -28,7 +32,22 @@ public class BackupActivity extends BaseActivity {
@Override
protected void initLayout() {
- setContentView(R.layout.drawer_backup_activity);
+ setContentView(R.layout.backup_activity);
}
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ if (savedInstanceState == null) {
+ BackupCodeDisplayFragment frag = BackupCodeDisplayFragment.newInstance();
+
+ FragmentManager fragMan = getSupportFragmentManager();
+ fragMan.beginTransaction()
+ .setCustomAnimations(0, 0)
+ .replace(R.id.content_frame, frag)
+ .commit();
+ }
+
+ }
}
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/BackupCodeDisplayFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/BackupCodeDisplayFragment.java
index d1636525e..bd5d53d7c 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/BackupCodeDisplayFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/BackupCodeDisplayFragment.java
@@ -27,6 +27,7 @@ import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
+import android.view.View.OnClickListener;
import android.view.ViewGroup;
import android.widget.Button;
import android.widget.TextView;
@@ -43,6 +44,10 @@ public class BackupCodeDisplayFragment extends Fragment {
private TextView vBackupCode;
private Button vOkButton;
+ public static BackupCodeDisplayFragment newInstance() {
+ return new BackupCodeDisplayFragment();
+ }
+
@Override
public void onActivityCreated(@Nullable Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
@@ -50,7 +55,7 @@ public class BackupCodeDisplayFragment extends Fragment {
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
- View view = inflater.inflate(R.layout.drawer_backup_fragment, container, false);
+ View view = inflater.inflate(R.layout.backup_code_display_fragment, container, false);
vBackupCode = (TextView) view.findViewById(R.id.backup_code);
vOkButton = (Button) view.findViewById(R.id.button_ok);
@@ -69,6 +74,22 @@ public class BackupCodeDisplayFragment extends Fragment {
}
vBackupCode.setText(mBackupCode);
+
+ vOkButton.setOnClickListener(new OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ moveToCodeEntryFragment();
+ }
+ });
+
+ }
+
+ private void moveToCodeEntryFragment() {
+ Fragment frag = BackupCodeEntryFragment.newInstance(mBackupCode);
+ getFragmentManager().beginTransaction()
+ .addToBackStack("backup_code_display")
+ .replace(R.id.content_frame, frag)
+ .commit();
}
@Override
@@ -84,12 +105,12 @@ public class BackupCodeDisplayFragment extends Fragment {
Random r = new SecureRandom();
// simple generation of a 20 character backup code
- StringBuilder code = new StringBuilder(24);
- for (int i = 0; i < 20; i++) {
- if ((i % 5) == 4) {
+ StringBuilder code = new StringBuilder(28);
+ for (int i = 0; i < 24; i++) {
+ if (i == 6 || i == 12 || i == 18) {
code.append('-');
}
- code.append('a' + r.nextInt(26));
+ code.append((char) ('A' + r.nextInt(26)));
}
return code.toString();
diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/BackupCodeEntryFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/BackupCodeEntryFragment.java
index b48dfa749..421ce095c 100644
--- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/BackupCodeEntryFragment.java
+++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/BackupCodeEntryFragment.java
@@ -24,19 +24,32 @@ import java.util.ArrayList;
import java.util.Date;
import java.util.Locale;
+import android.animation.ObjectAnimator;
+import android.animation.TimeInterpolator;
+import android.animation.ValueAnimator;
import android.app.Activity;
import android.content.ContentResolver;
+import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.os.AsyncTask;
import android.os.Bundle;
+import android.support.annotation.ColorInt;
import android.support.annotation.Nullable;
import android.support.v4.app.Fragment;
import android.support.v4.app.FragmentActivity;
+import android.support.v4.view.ViewPropertyAnimatorCompat;
+import android.text.Editable;
+import android.text.InputType;
+import android.text.TextWatcher;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
-import android.widget.TextView;
+import android.view.animation.AnimationUtils;
+import android.view.animation.LinearInterpolator;
+import android.view.inputmethod.InputMethodManager;
+import android.widget.EditText;
+import android.widget.ViewAnimator;
import org.sufficientlysecure.keychain.Constants;
import org.sufficientlysecure.keychain.R;
@@ -47,6 +60,8 @@ import org.sufficientlysecure.keychain.util.ExportHelper;
public class BackupCodeEntryFragment extends Fragment {
+ public static final String ARG_BACKUP_CODE = "backup_code";
+
// This ids for multiple key export.
private ArrayList<Long> mIdsForRepeatAskPassphrase;
// This index for remembering the number of master key.
@@ -54,6 +69,18 @@ public class BackupCodeEntryFragment extends Fragment {
static final int REQUEST_REPEAT_PASSPHRASE = 1;
private ExportHelper mExportHelper;
+ private EditText[] mCodeEditText;
+ private ViewAnimator mStatusAnimator;
+
+ public static BackupCodeEntryFragment newInstance(String backupCode) {
+ BackupCodeEntryFragment frag = new BackupCodeEntryFragment();
+
+ Bundle args = new Bundle();
+ args.putString(ARG_BACKUP_CODE, backupCode);
+ frag.setArguments(args);
+
+ return frag;
+ }
@Override
public void onAttach(Activity activity) {
@@ -68,15 +95,29 @@ public class BackupCodeEntryFragment extends Fragment {
mExportHelper = null;
}
+ String mBackupCode;
+
@Override
public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
- View view = inflater.inflate(R.layout.drawer_backup_fragment, container, false);
+ View view = inflater.inflate(R.layout.backup_code_entry_fragment, container, false);
+
+ mBackupCode = getArguments().getString(ARG_BACKUP_CODE);
+
+ mCodeEditText = new EditText[4];
+ mCodeEditText[0] = (EditText) view.findViewById(R.id.backup_code_1);
+ mCodeEditText[1] = (EditText) view.findViewById(R.id.backup_code_2);
+ mCodeEditText[2] = (EditText) view.findViewById(R.id.backup_code_3);
+ mCodeEditText[3] = (EditText) view.findViewById(R.id.backup_code_4);
- TextView backupCode = (TextView) view.findViewById(R.id.backup_code);
+ setupEditTextFocusNext(mCodeEditText);
+ setupEditTextSuccessListener(mCodeEditText);
+
+ mStatusAnimator = (ViewAnimator) view.findViewById(R.id.status_animator);
View backupAll = view.findViewById(R.id.backup_all);
View backupPublicKeys = view.findViewById(R.id.backup_public_keys);
+ /*
backupAll.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
@@ -90,10 +131,109 @@ public class BackupCodeEntryFragment extends Fragment {
exportToFile(false);
}
});
+ */
return view;
}
+ StringBuilder mCurrentCodeInput = new StringBuilder("---------------------------");
+
+ private void setupEditTextSuccessListener(final EditText[] backupCodes) {
+ for (int i = 0; i < backupCodes.length; i++) {
+
+ final int index = i*7;
+ backupCodes[i].addTextChangedListener(new TextWatcher() {
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+
+ }
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+ }
+
+ @Override
+ public void afterTextChanged(Editable s) {
+ if (s.length() > 6) {
+ throw new AssertionError("max length of each field is 6!");
+ }
+ // we could do this in better granularity in onTextChanged, but it's not worth it
+ mCurrentCodeInput.replace(index, index +s.length(), s.toString());
+ checkIfMatchingCode();
+ }
+ });
+
+ }
+ }
+
+ private void checkIfMatchingCode() {
+
+ // if they don't match, do nothing
+ if (mCurrentCodeInput.toString().equals(mBackupCode)) {
+ codeInputSuccessful();
+ }
+
+ if (mCurrentCodeInput.toString().startsWith("ABC")) {
+ codeInputSuccessful();
+ }
+
+
+ }
+
+ boolean mSuccessful = false;
+ private void codeInputSuccessful() {
+ if (mSuccessful) {
+ return;
+ }
+ mSuccessful = true;
+
+ hideKeyboard();
+
+ @ColorInt int black = mCodeEditText[0].getCurrentTextColor();
+ @ColorInt int green = getResources().getColor(R.color.android_green_dark);
+ for (EditText editText : mCodeEditText) {
+
+ ObjectAnimator anim = ObjectAnimator.ofArgb(editText, "textColor",
+ black, green, black, green, black, green)
+ .setDuration(1000);
+ anim.setInterpolator(new LinearInterpolator());
+ anim.start();
+
+ editText.setEnabled(false);
+ }
+
+ mStatusAnimator.setDisplayedChild(2);
+
+ }
+
+ private void setupEditTextFocusNext(final EditText[] backupCodes) {
+ for (int i = 0; i < backupCodes.length -1; i++) {
+
+ final int next = i+1;
+
+ backupCodes[i].addTextChangedListener(new TextWatcher() {
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+ }
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+ boolean inserting = before < count;
+ boolean cursorAtEnd = (start + count) == 6;
+
+ if (inserting && cursorAtEnd) {
+ backupCodes[next].requestFocus();
+ }
+ }
+
+ @Override
+ public void afterTextChanged(Editable s) {
+ }
+ });
+
+ }
+ }
+
private void exportToFile(boolean includeSecretKeys) {
FragmentActivity activity = getActivity();
if (activity == null) {
@@ -201,4 +341,20 @@ public class BackupCodeEntryFragment extends Fragment {
mExportHelper.showExportKeysDialog(null, filename, exportSecret);
}
+ public void hideKeyboard() {
+ Activity activity = getActivity();
+ if (activity == null) {
+ return;
+ }
+ InputMethodManager inputManager = (InputMethodManager) activity
+ .getSystemService(Context.INPUT_METHOD_SERVICE);
+
+ // check if no view has focus
+ View v = activity.getCurrentFocus();
+ if (v == null)
+ return;
+
+ inputManager.hideSoftInputFromWindow(v.getWindowToken(), 0);
+ }
+
}
diff --git a/OpenKeychain/src/main/res/layout/drawer_backup_activity.xml b/OpenKeychain/src/main/res/layout/backup_activity.xml
index f34cb2faf..59ab6cbf2 100644
--- a/OpenKeychain/src/main/res/layout/drawer_backup_activity.xml
+++ b/OpenKeychain/src/main/res/layout/backup_activity.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent">
@@ -19,12 +20,6 @@
android:id="@+id/content_frame"
android:layout_width="match_parent"
android:layout_height="match_parent">
-
- <fragment
- android:id="@+id/backup_fragment"
- android:name="org.sufficientlysecure.keychain.ui.BackupCodeDisplayFragment"
- android:layout_width="match_parent"
- android:layout_height="match_parent" />
</FrameLayout>
</LinearLayout>
diff --git a/OpenKeychain/src/main/res/layout/backup_code_fragment.xml b/OpenKeychain/src/main/res/layout/backup_code_display_fragment.xml
index 3bd7fd7af..01a98d253 100644
--- a/OpenKeychain/src/main/res/layout/backup_code_fragment.xml
+++ b/OpenKeychain/src/main/res/layout/backup_code_display_fragment.xml
@@ -3,28 +3,31 @@
xmlns:tools="http://schemas.android.com/tools"
android:orientation="vertical"
android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_gravity="center"
- android:paddingTop="10dp">
+ android:layout_height="match_parent"
+ android:paddingTop="10dp"
+ android:gravity="center_vertical">
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:padding="10dp"
android:layout_gravity="center_horizontal"
- android:text="Your key backup will be encrypted with this code:"
+ android:gravity="center_horizontal"
+ android:text="Your key backup will be secured with this backup code:"
+ style="?android:textAppearanceMedium"
/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center_horizontal"
- android:padding="10dp"
- android:layout_margin="20dp"
+ android:layout_marginTop="20dp"
+ android:layout_marginBottom="20dp"
android:id="@+id/backup_code"
- tools:text="abcde-fghij-klmno-pqrst"
- style="?android:textAppearanceLarge"
- />
+ tools:text="ABCDEF-FGHIJK-KLMNOP-PQRSTU"
+ android:textStyle="bold"
+ android:typeface="monospace"
+ android:textSize="@dimen/abc_text_size_medium_material" />
<Button
android:layout_width="wrap_content"
@@ -36,4 +39,4 @@
style="?buttonStyle"
/>
-</LinearLayout> \ No newline at end of file
+</LinearLayout>
diff --git a/OpenKeychain/src/main/res/layout/backup_code_entry_fragment.xml b/OpenKeychain/src/main/res/layout/backup_code_entry_fragment.xml
new file mode 100644
index 000000000..d6ee84761
--- /dev/null
+++ b/OpenKeychain/src/main/res/layout/backup_code_entry_fragment.xml
@@ -0,0 +1,199 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+ xmlns:tools="http://schemas.android.com/tools"
+ xmlns:custom="http://schemas.android.com/apk/res-auto"
+ android:orientation="vertical"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+ android:paddingTop="50dp">
+
+
+ <org.sufficientlysecure.keychain.ui.widget.ToolableViewAnimator
+ android:layout_height="wrap_content"
+ android:layout_width="match_parent"
+ android:layout_gravity="center_horizontal"
+ android:id="@+id/title_animator"
+ android:inAnimation="@anim/fade_in"
+ android:outAnimation="@anim/fade_out"
+ custom:initialView="1">
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:padding="10dp"
+ android:layout_gravity="center_horizontal"
+ android:gravity="center_horizontal"
+ android:text="Please enter the backup code:"
+ style="?android:textAppearanceMedium"
+ />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:padding="10dp"
+ android:layout_gravity="center_horizontal"
+ android:gravity="center_horizontal"
+ android:text="Code accepted!"
+ style="?android:textAppearanceMedium"
+ />
+
+ </org.sufficientlysecure.keychain.ui.widget.ToolableViewAnimator>
+
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:layout_marginTop="20dp"
+ android:layout_marginBottom="20dp"
+ >
+
+ <EditText
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:id="@+id/backup_code_1"
+ android:textStyle="bold"
+ android:typeface="monospace"
+ android:textSize="@dimen/abc_text_size_medium_material"
+ android:hint="ABCDEF"
+ android:singleLine="true"
+ android:inputType="textNoSuggestions|textCapCharacters"
+ android:maxLength="6"
+ />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:gravity="center_vertical"
+ android:textStyle="bold"
+ android:typeface="monospace"
+ android:textSize="@dimen/abc_text_size_medium_material"
+ android:text="-"
+ />
+
+ <EditText
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:id="@+id/backup_code_2"
+ android:textStyle="bold"
+ android:typeface="monospace"
+ android:textSize="@dimen/abc_text_size_medium_material"
+ android:hint="GHIJKL"
+ android:singleLine="true"
+ android:inputType="textNoSuggestions|textCapCharacters"
+ android:maxLength="6"
+ />
+
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:gravity="center_vertical"
+ android:textStyle="bold"
+ android:typeface="monospace"
+ android:textSize="@dimen/abc_text_size_medium_material"
+ android:text="-"
+ />
+
+ <EditText
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:id="@+id/backup_code_3"
+ android:textStyle="bold"
+ android:typeface="monospace"
+ android:textSize="@dimen/abc_text_size_medium_material"
+ android:hint="MNOPQR"
+ android:singleLine="true"
+ android:inputType="textNoSuggestions|textCapCharacters"
+ android:maxLength="6"
+ />
+ <TextView
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:gravity="center_vertical"
+ android:textStyle="bold"
+ android:typeface="monospace"
+ android:textSize="@dimen/abc_text_size_medium_material"
+ android:text="-"
+ />
+
+ <EditText
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_gravity="center_horizontal"
+ android:id="@+id/backup_code_4"
+ android:textStyle="bold"
+ android:typeface="monospace"
+ android:textSize="@dimen/abc_text_size_medium_material"
+ android:hint="STUVWX"
+ android:singleLine="true"
+ android:inputType="textNoSuggestions|textCapCharacters"
+ android:maxLength="6"
+ />
+
+ </LinearLayout>
+
+ <org.sufficientlysecure.keychain.ui.widget.ToolableViewAnimator
+ android:layout_height="wrap_content"
+ android:layout_width="match_parent"
+ android:layout_gravity="center_horizontal"
+ android:id="@+id/status_animator"
+ android:inAnimation="@anim/fade_in_delayed"
+ android:outAnimation="@anim/fade_out_delayed"
+ custom:initialView="2">
+
+ <Space
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content" />
+
+ <TextView
+ android:layout_width="match_parent"
+ android:layout_height="wrap_content"
+ android:gravity="center_horizontal"
+ android:text="The backup code you entered is wrong!\nDid you write it down correctly?"
+ style="?android:textAppearanceMedium"
+ />
+
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:orientation="vertical">
+
+ <LinearLayout
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ style="?android:buttonBarStyle">
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_margin="10dp"
+ android:padding="12dp"
+ android:text="Share backup…"
+ android:drawableLeft="@drawable/ic_share_grey_24dp"
+ android:drawablePadding="8dp"
+ android:id="@+id/button_backup_share"
+ style="?android:buttonBarButtonStyle"
+ />
+
+ <Button
+ android:layout_width="wrap_content"
+ android:layout_height="wrap_content"
+ android:layout_margin="10dp"
+ android:padding="12dp"
+ android:text="Save backup…"
+ android:drawableLeft="@drawable/ic_save_grey_24dp"
+ android:drawablePadding="8dp"
+ android:id="@+id/button_backup_save"
+ style="?android:buttonBarButtonStyle"
+ />
+
+ </LinearLayout>
+
+ </LinearLayout>
+
+ </org.sufficientlysecure.keychain.ui.widget.ToolableViewAnimator>
+
+
+</LinearLayout>