From d097131a3dcdf806608f43e49e0be96cf34f5c64 Mon Sep 17 00:00:00 2001 From: Daniel Ramos Date: Tue, 14 Apr 2015 03:40:59 +0100 Subject: -Improved email sanity verifications when adding emails when creating a new Key -fixed a few NFC crashes -fixed a few instances when showing the keyboard would crash the Activity -fixed a case where adding new emails would crash the app if the user went back and forth between the Add Email fragment and the Add Name fragment. --- .../keychain/ui/CreateKeyEmailFragment.java | 95 ++++++++++++++++------ .../keychain/ui/base/BaseNfcActivity.java | 6 +- .../keychain/ui/dialog/AddEmailDialogFragment.java | 8 +- .../src/main/res/layout/add_email_dialog.xml | 1 + .../main/res/layout/create_key_email_fragment.xml | 1 + OpenKeychain/src/main/res/values/strings.xml | 1 + 6 files changed, 82 insertions(+), 30 deletions(-) diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java index 85e2f8e9d..26c307957 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java @@ -18,7 +18,6 @@ package org.sufficientlysecure.keychain.ui; import android.app.Activity; -import android.content.Context; import android.os.Bundle; import android.os.Handler; import android.os.Message; @@ -27,6 +26,7 @@ import android.support.v4.app.Fragment; import android.support.v7.widget.DefaultItemAnimator; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; +import android.util.Patterns; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -44,6 +44,7 @@ import org.sufficientlysecure.keychain.ui.widget.EmailEditText; import java.util.ArrayList; import java.util.List; +import java.util.regex.Pattern; public class CreateKeyEmailFragment extends Fragment { @@ -73,14 +74,13 @@ public class CreateKeyEmailFragment extends Fragment { * Checks if text of given EditText is not empty. If it is empty an error is * set and the EditText gets the focus. * - * @param context * @param editText * @return true if EditText is not empty */ - private static boolean isEditTextNotEmpty(Context context, EditText editText) { + private boolean isMainEmailValid(EditText editText) { boolean output = true; - if (editText.getText().length() == 0) { - editText.setError(context.getString(R.string.create_key_empty)); + if (!checkEmail(editText.getText().toString(), false)) { + editText.setError(getString(R.string.create_key_empty)); editText.requestFocus(); output = false; } else { @@ -125,7 +125,7 @@ public class CreateKeyEmailFragment extends Fragment { // initial values if (mAdditionalEmailModels == null) { mAdditionalEmailModels = new ArrayList<>(); - if (mCreateKeyActivity.mAdditionalEmails != null) { + if (mCreateKeyActivity.mAdditionalEmails != null && mEmailAdapter != null) { mEmailAdapter.addAll(mCreateKeyActivity.mAdditionalEmails); } } @@ -144,6 +144,65 @@ public class CreateKeyEmailFragment extends Fragment { return view; } + /** + * Checks if a given email is valid + * + * @param email + * @param additionalEmail + * @return + */ + private boolean checkEmail(String email, boolean additionalEmail) { + //check for email format or if the user did any input + if (!isEmailFormatValid(email)) { + Notify.create(getActivity(), + getString(R.string.create_key_email_invalid_email), + Notify.LENGTH_LONG, Notify.Style.ERROR).show(); + return false; + } + + //check for duplicated emails + if (!additionalEmail && isEmailDuplicatedInsideAdapter(email) || additionalEmail && + mEmailEdit.getText().length() > 0 && email.equals(mEmailEdit.getText().toString())) { + Notify.create(getActivity(), + getString(R.string.create_key_email_already_exists_text), + Notify.LENGTH_LONG, Notify.Style.ERROR).show(); + return false; + } + + return true; + } + + /** + * Checks the email format + * Uses the default Android Email Pattern + * + * @param email + * @return + */ + private boolean isEmailFormatValid(String email) { + Pattern emailPattern = Patterns.EMAIL_ADDRESS; + + //check for email format or if the user did any input + return !(email.length() == 0 || !emailPattern.matcher(email).matches()); + } + + /** + * Checks for duplicated emails inside the additional email adapter. + * + * @param email + * @return + */ + private boolean isEmailDuplicatedInsideAdapter(String email) { + //check for duplicated emails inside the adapter + for (EmailAdapter.ViewModel model : mAdditionalEmailModels) { + if (email.equals(model.email)) { + return true; + } + } + + return false; + } + private void addEmail() { Handler returnHandler = new Handler() { @Override @@ -152,26 +211,10 @@ public class CreateKeyEmailFragment extends Fragment { Bundle data = message.getData(); String email = data.getString(AddEmailDialogFragment.MESSAGE_DATA_EMAIL); - - if (email.length() > 0 && mEmailEdit.getText().length() > 0 && - email.equals(mEmailEdit.getText().toString())) { - Notify.create(getActivity(), - getString(R.string.create_key_email_already_exists_text), - Notify.LENGTH_LONG, Notify.Style.ERROR).show(); - return; - } - //check for duplicated emails inside the adapter - for (EmailAdapter.ViewModel model : mAdditionalEmailModels) { - if (email.equals(model.email)) { - Notify.create(getActivity(), - getString(R.string.create_key_email_already_exists_text), - Notify.LENGTH_LONG, Notify.Style.ERROR).show(); - return; - } + if (checkEmail(email, true)) { + // add new user id + mEmailAdapter.add(email); } - - // add new user id - mEmailAdapter.add(email); } } }; @@ -191,7 +234,7 @@ public class CreateKeyEmailFragment extends Fragment { } private void nextClicked() { - if (isEditTextNotEmpty(getActivity(), mEmailEdit)) { + if (isMainEmailValid(mEmailEdit)) { // save state mCreateKeyActivity.mEmail = mEmailEdit.getText().toString(); mCreateKeyActivity.mAdditionalEmails = getAdditionalEmails(); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseNfcActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseNfcActivity.java index 9b10ccdb1..4f6d5807e 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseNfcActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/base/BaseNfcActivity.java @@ -451,6 +451,8 @@ public abstract class BaseNfcActivity extends BaseActivity { */ public void enableNfcForegroundDispatch() { mNfcAdapter = NfcAdapter.getDefaultAdapter(this); + if(mNfcAdapter == null) return; + Intent nfcI = new Intent(this, getClass()) .addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP); PendingIntent nfcPendingIntent = PendingIntent.getActivity(this, 0, nfcI, PendingIntent.FLAG_CANCEL_CURRENT); @@ -472,7 +474,9 @@ public abstract class BaseNfcActivity extends BaseActivity { * Disable foreground dispatch in onPause! */ public void disableNfcForegroundDispatch() { - mNfcAdapter.disableForegroundDispatch(this); + if(mNfcAdapter != null) { + mNfcAdapter.disableForegroundDispatch(this); + } Log.d(Constants.TAG, "NfcForegroundDispatch has been disabled!"); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddEmailDialogFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddEmailDialogFragment.java index 5d5ca533e..5b91b9d37 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddEmailDialogFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/AddEmailDialogFragment.java @@ -112,9 +112,11 @@ public class AddEmailDialogFragment extends DialogFragment implements OnEditorAc mEmail.post(new Runnable() { @Override public void run() { - InputMethodManager imm = (InputMethodManager) getActivity() - .getSystemService(Context.INPUT_METHOD_SERVICE); - imm.showSoftInput(mEmail, InputMethodManager.SHOW_IMPLICIT); + if(getActivity() != null) { + InputMethodManager imm = (InputMethodManager) getActivity() + .getSystemService(Context.INPUT_METHOD_SERVICE); + imm.showSoftInput(mEmail, InputMethodManager.SHOW_IMPLICIT); + } } }); } diff --git a/OpenKeychain/src/main/res/layout/add_email_dialog.xml b/OpenKeychain/src/main/res/layout/add_email_dialog.xml index 68d895145..2de657a40 100644 --- a/OpenKeychain/src/main/res/layout/add_email_dialog.xml +++ b/OpenKeychain/src/main/res/layout/add_email_dialog.xml @@ -21,6 +21,7 @@ android:layout_marginTop="16dp" android:hint="@string/label_email" android:imeOptions="actionNext" + android:inputType="textEmailAddress" android:textAppearance="?android:attr/textAppearanceMedium" /> diff --git a/OpenKeychain/src/main/res/layout/create_key_email_fragment.xml b/OpenKeychain/src/main/res/layout/create_key_email_fragment.xml index 17cfe54ac..7b9cffec4 100644 --- a/OpenKeychain/src/main/res/layout/create_key_email_fragment.xml +++ b/OpenKeychain/src/main/res/layout/create_key_email_fragment.xml @@ -32,6 +32,7 @@ android:layout_marginTop="16dp" android:layout_marginBottom="8dp" android:imeOptions="actionNext" + android:inputType="textEmailAddress" android:hint="@string/label_email" android:ems="10" /> diff --git a/OpenKeychain/src/main/res/values/strings.xml b/OpenKeychain/src/main/res/values/strings.xml index c1e3b51f9..c1ff5a1d1 100644 --- a/OpenKeychain/src/main/res/values/strings.xml +++ b/OpenKeychain/src/main/res/values/strings.xml @@ -631,6 +631,7 @@ "Add email address" "Additional email addresses are also associated to this key and can be used for secure communication." "Email address has already been added" + "Email address format is invalid" "Revoked: Key must not be used anymore!" -- cgit v1.2.3 From d9cabf8dc4a4de0153ab6a07919ae8d7614cfc9d Mon Sep 17 00:00:00 2001 From: Daniel Ramos Date: Fri, 24 Apr 2015 03:35:30 +0100 Subject: -Fixed a crash while recreating CreateKeyEmailFragment -Email data is properly restored while rotating the Activity. -Added necessary logic to guarantee that an email is actually valid before continuing, there are verifications for empty, duplicated and invalid formatted emails for both additional and main email. --- .../keychain/ui/CreateKeyEmailFragment.java | 32 +++++++++++----------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java index 26c307957..8fdfb35cb 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java @@ -47,16 +47,13 @@ import java.util.List; import java.util.regex.Pattern; public class CreateKeyEmailFragment extends Fragment { - - CreateKeyActivity mCreateKeyActivity; - EmailEditText mEmailEdit; - RecyclerView mEmailsRecyclerView; - View mBackButton; - View mNextButton; - - ArrayList mAdditionalEmailModels; - - EmailAdapter mEmailAdapter; + private CreateKeyActivity mCreateKeyActivity; + private EmailEditText mEmailEdit; + private RecyclerView mEmailsRecyclerView; + private View mBackButton; + private View mNextButton; + private ArrayList mAdditionalEmailModels; + private EmailAdapter mEmailAdapter; /** * Creates new instance of this fragment @@ -125,9 +122,6 @@ public class CreateKeyEmailFragment extends Fragment { // initial values if (mAdditionalEmailModels == null) { mAdditionalEmailModels = new ArrayList<>(); - if (mCreateKeyActivity.mAdditionalEmails != null && mEmailAdapter != null) { - mEmailAdapter.addAll(mCreateKeyActivity.mAdditionalEmails); - } } if (mEmailAdapter == null) { @@ -137,6 +131,10 @@ public class CreateKeyEmailFragment extends Fragment { addEmail(); } }); + + if (mCreateKeyActivity.mAdditionalEmails != null) { + mEmailAdapter.addAll(mCreateKeyActivity.mAdditionalEmails); + } } mEmailsRecyclerView.setAdapter(mEmailAdapter); @@ -203,6 +201,9 @@ public class CreateKeyEmailFragment extends Fragment { return false; } + /** + * Displays a dialog fragment for the user to input a valid email. + */ private void addEmail() { Handler returnHandler = new Handler() { @Override @@ -218,12 +219,11 @@ public class CreateKeyEmailFragment extends Fragment { } } }; - // Create a new Messenger for the communication back - Messenger messenger = new Messenger(returnHandler); + Messenger messenger = new Messenger(returnHandler); AddEmailDialogFragment addEmailDialog = AddEmailDialogFragment.newInstance(messenger); - + addEmailDialog.setTargetFragment(this, -1); addEmailDialog.show(getActivity().getSupportFragmentManager(), "addEmailDialog"); } -- cgit v1.2.3 From ef52a3319a5931c46d5ae5e83f96c503782c805a Mon Sep 17 00:00:00 2001 From: Manoj Khanna Date: Fri, 24 Apr 2015 00:06:35 +0530 Subject: Espresso test for CreateKeyActivity --- OpenKeychain/build.gradle | 12 ++ .../keychain/CreateKeyActivityTest.java | 194 +++++++++++++++++++++ .../keychain/matcher/EditTextMatchers.java | 74 ++++++++ .../keychain/ui/CreateKeyEmailFragment.java | 11 +- 4 files changed, 286 insertions(+), 5 deletions(-) create mode 100644 OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/CreateKeyActivityTest.java create mode 100644 OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/matcher/EditTextMatchers.java diff --git a/OpenKeychain/build.gradle b/OpenKeychain/build.gradle index c47e650cb..cc5e01aca 100644 --- a/OpenKeychain/build.gradle +++ b/OpenKeychain/build.gradle @@ -11,6 +11,12 @@ dependencies { compile 'com.android.support:recyclerview-v7:22.0.0' compile 'com.android.support:cardview-v7:22.0.0' + // UI testing libs + androidTestCompile 'com.android.support.test:runner:0.2' + androidTestCompile 'com.android.support.test:rules:0.2' + androidTestCompile 'com.android.support.test.espresso:espresso-core:2.1' + androidTestCompile 'com.android.support.test.espresso:espresso-contrib:2.1' + // JCenter etc. compile 'com.eftimoff:android-patternview:1.0.1@aar' compile 'com.journeyapps:zxing-android-embedded:2.3.0@aar' @@ -85,6 +91,8 @@ android { defaultConfig { minSdkVersion 15 targetSdkVersion 22 + + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" } compileOptions { @@ -135,6 +143,10 @@ android { dexOptions { preDexLibraries = false } + + packagingOptions { + exclude 'LICENSE.txt' + } } // NOTE: This disables Lint! diff --git a/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/CreateKeyActivityTest.java b/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/CreateKeyActivityTest.java new file mode 100644 index 000000000..c3741fdef --- /dev/null +++ b/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/CreateKeyActivityTest.java @@ -0,0 +1,194 @@ +/* + * Copyright (C) 2015 Dominik Schürmann + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.sufficientlysecure.keychain; + +import android.support.test.rule.ActivityTestRule; +import android.support.test.runner.AndroidJUnit4; +import android.text.method.HideReturnsTransformationMethod; +import android.text.method.PasswordTransformationMethod; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.sufficientlysecure.keychain.ui.CreateKeyActivity; + +import static android.support.test.espresso.Espresso.onView; +import static android.support.test.espresso.action.ViewActions.click; +import static android.support.test.espresso.action.ViewActions.swipeLeft; +import static android.support.test.espresso.action.ViewActions.typeText; +import static android.support.test.espresso.assertion.ViewAssertions.doesNotExist; +import static android.support.test.espresso.assertion.ViewAssertions.matches; +import static android.support.test.espresso.matcher.RootMatchers.isDialog; +import static android.support.test.espresso.matcher.ViewMatchers.hasDescendant; +import static android.support.test.espresso.matcher.ViewMatchers.hasSibling; +import static android.support.test.espresso.matcher.ViewMatchers.isDisplayed; +import static android.support.test.espresso.matcher.ViewMatchers.withId; +import static android.support.test.espresso.matcher.ViewMatchers.withText; +import static org.hamcrest.Matchers.allOf; +import static org.sufficientlysecure.keychain.matcher.EditTextMatchers.withError; +import static org.sufficientlysecure.keychain.matcher.EditTextMatchers.withTransformationMethod; + +@RunWith(AndroidJUnit4.class) +public class CreateKeyActivityTest { + + public static final String SAMPLE_NAME = "Sample Name"; + public static final String SAMPLE_EMAIL = "sample_email@gmail.com"; + public static final String SAMPLE_ADDITIONAL_EMAIL = "sample_additional_email@gmail.com"; + public static final String SAMPLE_PASSWORD = "sample_password"; + + @Rule + public ActivityTestRule mActivityRule = new ActivityTestRule<>(CreateKeyActivity.class); + + @Test + public void testCreateMyKey() { + // Clicks create my key + onView(withId(R.id.create_key_create_key_button)) + .perform(click()); + + // Clicks next with empty name + onView(withId(R.id.create_key_next_button)) + .perform(click()); + onView(withId(R.id.create_key_name)) + .check(matches(withError(R.string.create_key_empty))); + + // Types name and clicks next + onView(withId(R.id.create_key_name)) + .perform(typeText(SAMPLE_NAME)); + onView(withId(R.id.create_key_next_button)) + .perform(click()); + + // Clicks next with empty email + onView(withId(R.id.create_key_next_button)) + .perform(click()); + onView(withId(R.id.create_key_email)) + .check(matches(withError(R.string.create_key_empty))); + + // Types email + onView(withId(R.id.create_key_email)) + .perform(typeText(SAMPLE_EMAIL)); + + // Adds same email as additional email and dismisses the snackbar + onView(withId(R.id.create_key_add_email)) + .perform(click()); + onView(withId(R.id.add_email_address)) + .perform(typeText(SAMPLE_EMAIL)); + onView(withText(android.R.string.ok)) + .inRoot(isDialog()) + .perform(click()); + onView(allOf(withId(R.id.sb__text), withText(R.string.create_key_email_already_exists_text))) + .check(matches(isDisplayed())); + onView(allOf(withId(R.id.sb__text), withText(R.string.create_key_email_already_exists_text))) + .perform(swipeLeft()); + + // Adds additional email + onView(withId(R.id.create_key_add_email)) + .perform(click()); + onView(withId(R.id.add_email_address)) + .perform(typeText(SAMPLE_ADDITIONAL_EMAIL)); + onView(withText(android.R.string.ok)) + .inRoot(isDialog()) + .perform(click()); + onView(withId(R.id.create_key_emails)) + .check(matches(hasDescendant(allOf(withId(R.id.create_key_email_item_email), withText(SAMPLE_ADDITIONAL_EMAIL))))); + + // Removes additional email and clicks next + onView(allOf(withId(R.id.create_key_email_item_delete_button), hasSibling(allOf(withId(R.id.create_key_email_item_email), withText(SAMPLE_ADDITIONAL_EMAIL))))) + .perform(click()) + .check(doesNotExist()); + onView(withId(R.id.create_key_next_button)) + .perform(click(click())); + + // Clicks next with empty password + onView(withId(R.id.create_key_next_button)) + .perform(click()); + onView(withId(R.id.create_key_passphrase)) + .check(matches(withError(R.string.create_key_empty))); + + // Types password + onView(withId(R.id.create_key_passphrase)) + .perform(typeText(SAMPLE_PASSWORD)); + + // Clicks next with empty confirm password + onView(withId(R.id.create_key_next_button)) + .perform(click()); + onView(withId(R.id.create_key_passphrase_again)) + .check(matches(withError(R.string.create_key_passphrases_not_equal))); + + // Types confirm password + onView(withId(R.id.create_key_passphrase_again)) + .perform(typeText(SAMPLE_PASSWORD)); + + // Clicks show password twice and clicks next + onView(withId(R.id.create_key_show_passphrase)) + .perform(click()); + onView(withId(R.id.create_key_passphrase)) + .check(matches(withTransformationMethod(HideReturnsTransformationMethod.class))); + onView(withId(R.id.create_key_passphrase_again)) + .check(matches(withTransformationMethod(HideReturnsTransformationMethod.class))); + onView(withId(R.id.create_key_show_passphrase)) + .perform(click()); + onView(withId(R.id.create_key_passphrase)) + .check(matches(withTransformationMethod(PasswordTransformationMethod.class))); + onView(withId(R.id.create_key_passphrase_again)) + .check(matches(withTransformationMethod(PasswordTransformationMethod.class))); + onView(withId(R.id.create_key_next_button)) + .perform(click()); + + // Verifies name and email + onView(withId(R.id.name)) + .check(matches(withText(SAMPLE_NAME))); + onView(withId(R.id.email)) + .check(matches(withText(SAMPLE_EMAIL))); + + // Verifies backstack + onView(withId(R.id.create_key_back_button)) + .perform(click()); + onView(withId(R.id.create_key_back_button)) + .perform(click()); + onView(withId(R.id.create_key_back_button)) + .perform(click()); + + onView(withId(R.id.create_key_name)) + .check(matches(withText(SAMPLE_NAME))); + onView(withId(R.id.create_key_next_button)) + .perform(click()); + + onView(withId(R.id.create_key_email)) + .check(matches(withText(SAMPLE_EMAIL))); + onView(withId(R.id.create_key_next_button)) + .perform(click()); + + // TODO: Uncomment when fixed in main +// onView(withId(R.id.create_key_passphrase)) +// .check(matches(withText(SAMPLE_PASSWORD))); +// onView(withId(R.id.create_key_passphrase_again)) +// .check(matches(withText(SAMPLE_PASSWORD))); + onView(withId(R.id.create_key_next_button)) + .perform(click()); + + onView(withId(R.id.name)) + .check(matches(withText(SAMPLE_NAME))); + onView(withId(R.id.email)) + .check(matches(withText(SAMPLE_EMAIL))); + + // Clicks create key + onView(withId(R.id.create_key_next_button)) + .perform(click()); + } + +} diff --git a/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/matcher/EditTextMatchers.java b/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/matcher/EditTextMatchers.java new file mode 100644 index 000000000..7f2a7953b --- /dev/null +++ b/OpenKeychain/src/androidTest/java/org/sufficientlysecure/keychain/matcher/EditTextMatchers.java @@ -0,0 +1,74 @@ +/* + * Copyright (C) 2015 Dominik Schürmann + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.sufficientlysecure.keychain.matcher; + +import android.content.Context; +import android.text.method.TransformationMethod; +import android.view.View; +import android.widget.EditText; + +import org.hamcrest.Description; +import org.hamcrest.TypeSafeMatcher; + +public class EditTextMatchers { + + public static TypeSafeMatcher withError(final int errorResId) { + return new TypeSafeMatcher() { + + @Override + public boolean matchesSafely(View view) { + Context context = view.getContext(); + + if (view instanceof EditText) { + CharSequence error = ((EditText) view).getError(); + return error != null && error.equals(context.getString(errorResId)); + } + + return false; + } + + @Override + public void describeTo(Description description) { + description.appendText("EditText with error"); + } + + }; + } + + public static TypeSafeMatcher withTransformationMethod(final Class transformationClass) { + return new TypeSafeMatcher() { + + @Override + public boolean matchesSafely(View view) { + if (view instanceof EditText) { + TransformationMethod transformation = ((EditText) view).getTransformationMethod(); + return transformation != null && transformationClass.isInstance(transformation); + } + + return false; + } + + @Override + public void describeTo(Description description) { + description.appendText("EditText with transformation method"); + } + + }; + } + +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java index 85e2f8e9d..ff0bf65be 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java @@ -125,9 +125,6 @@ public class CreateKeyEmailFragment extends Fragment { // initial values if (mAdditionalEmailModels == null) { mAdditionalEmailModels = new ArrayList<>(); - if (mCreateKeyActivity.mAdditionalEmails != null) { - mEmailAdapter.addAll(mCreateKeyActivity.mAdditionalEmails); - } } if (mEmailAdapter == null) { @@ -137,6 +134,10 @@ public class CreateKeyEmailFragment extends Fragment { addEmail(); } }); + + if (mCreateKeyActivity.mAdditionalEmails != null) { + mEmailAdapter.addAll(mCreateKeyActivity.mAdditionalEmails); + } } mEmailsRecyclerView.setAdapter(mEmailAdapter); @@ -157,7 +158,7 @@ public class CreateKeyEmailFragment extends Fragment { email.equals(mEmailEdit.getText().toString())) { Notify.create(getActivity(), getString(R.string.create_key_email_already_exists_text), - Notify.LENGTH_LONG, Notify.Style.ERROR).show(); + Notify.LENGTH_LONG, Notify.Style.ERROR).show(CreateKeyEmailFragment.this); return; } //check for duplicated emails inside the adapter @@ -165,7 +166,7 @@ public class CreateKeyEmailFragment extends Fragment { if (email.equals(model.email)) { Notify.create(getActivity(), getString(R.string.create_key_email_already_exists_text), - Notify.LENGTH_LONG, Notify.Style.ERROR).show(); + Notify.LENGTH_LONG, Notify.Style.ERROR).show(CreateKeyEmailFragment.this); return; } } -- cgit v1.2.3 From d0d4149e8695b833eb12e959ebe0ea1a861dd375 Mon Sep 17 00:00:00 2001 From: vectorijk Date: Sat, 25 Apr 2015 15:33:30 -0700 Subject: update lib MaterialDrawer to latest(2.8.2) --- OpenKeychain/build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenKeychain/build.gradle b/OpenKeychain/build.gradle index 09f3b589e..9530c3279 100644 --- a/OpenKeychain/build.gradle +++ b/OpenKeychain/build.gradle @@ -22,7 +22,7 @@ dependencies { compile "com.splitwise:tokenautocomplete:1.3.3@aar" compile 'se.emilsjolander:stickylistheaders:2.6.0' compile 'org.sufficientlysecure:html-textview:1.1' - compile 'com.mikepenz.materialdrawer:library:2.7.9@aar' + compile 'com.mikepenz.materialdrawer:library:2.8.2@aar' compile 'com.mikepenz.iconics:library:0.9.1@aar' compile 'com.mikepenz.iconics:octicons-typeface:2.2.0@aar' compile 'com.mikepenz.iconics:meteocons-typeface:1.1.1@aar' @@ -59,7 +59,7 @@ dependencyVerification { 'com.splitwise:tokenautocomplete:20bee71cc59b3828eb000b684d46ddf738efd56b8fee453a509cd16fda42c8cb', 'se.emilsjolander:stickylistheaders:8c05981ec5725be33f7cee5e68c13f3db49cd5c75f1aaeb04024920b1ef96ad4', 'org.sufficientlysecure:html-textview:ca24b1522be88378634093815ce9ff1b4920c72e7513a045a7846e14069ef988', - 'com.mikepenz.materialdrawer:library:3ef80c6e1ca1b29cfcbb27fa7927c02b2246e068c17fe52283703c4897449923', + 'com.mikepenz.materialdrawer:library:970317ed1a3cb96317f7b8d62ff592b3103eb46dfd68d9b244e7143623dc6d7a', 'com.mikepenz.iconics:library:4698a36ee4c2af765d0a85779c61474d755b90d66a59020105b6760a8a909e9e', 'com.mikepenz.iconics:octicons-typeface:67ed7d456a9ce5f5307b85f955797bfb3dd674e2f6defb31c6b8bbe2ede290be', 'com.mikepenz.iconics:meteocons-typeface:39a8a9e70cd8287cdb119af57a672a41dd09240dba6697f5a0dbda1ccc33298b', -- cgit v1.2.3 From 4c74dbe11e39e5d227b661fd1ee9a08a74aebfc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Sun, 26 Apr 2015 01:28:29 +0200 Subject: UI fixes for Android < 5 --- OpenKeychain/build.gradle | 10 +++++----- .../keychain/ui/CreateKeyEmailFragment.java | 7 +++---- .../keychain/ui/CreateKeyPassphraseFragment.java | 8 ++------ .../sufficientlysecure/keychain/ui/MainActivity.java | 2 +- OpenKeychain/src/main/res/layout/main_activity.xml | 17 ++++++++++++----- OpenKeychain/src/main/res/values/themes.xml | 7 +------ 6 files changed, 24 insertions(+), 27 deletions(-) diff --git a/OpenKeychain/build.gradle b/OpenKeychain/build.gradle index 09f3b589e..2d4e8a4d3 100644 --- a/OpenKeychain/build.gradle +++ b/OpenKeychain/build.gradle @@ -6,8 +6,8 @@ dependencies { // NOTE: libraries are pinned to a specific build, see below // from local Android SDK - compile 'com.android.support:support-v4:22.1.0' - compile 'com.android.support:appcompat-v7:22.1.0' + compile 'com.android.support:support-v4:22.1.1' + compile 'com.android.support:appcompat-v7:22.1.1' compile 'com.android.support:recyclerview-v7:22.1.0' compile 'com.android.support:cardview-v7:22.1.0' @@ -45,8 +45,8 @@ dependencies { // Comment out the libs referenced as git submodules! dependencyVerification { verify = [ - 'com.android.support:support-v4:74cb322740317b11a785eee1a94969426fade946123c4ae3f471276adaaaf54b', - 'com.android.support:appcompat-v7:6cc7fc2df4be0676f78ecfc5d3cda388e59890d11308811944f54efd84b047b7', + 'com.android.support:support-v4:1e2e4d35ac7fd30db5ce3bc177b92e4d5af86acef2ef93e9221599d733346f56', + 'com.android.support:appcompat-v7:9a2355537c2f01cf0b95523605c18606b8d824017e6e94a05c77b0cfc8f21c96', 'com.android.support:recyclerview-v7:522d323079a29bcd76173bd9bc7535223b4af3e5eefef9d9287df1f9e54d0c10', 'com.android.support:cardview-v7:8dc99af71fec000baa4470c3907755264f15f816920861bc015b2babdbb49807', 'com.eftimoff:android-patternview:cec80e7265b8d8278b3c55b5fcdf551e4600ac2c8bf60d8dd76adca538af0b1e', @@ -74,7 +74,7 @@ dependencyVerification { // 'OpenKeychain.extern.KeybaseLib:Lib:c91cda4a75692d8664644cd17d8ac962ce5bc0e266ea26673a639805f1eccbdf', // 'OpenKeychain.extern:safeslinger-exchange:d222721bb35408daaab9f46449364b2657112705ee571d7532f81cbeb9c4a73f', // 'OpenKeychain.extern.snackbar:lib:52357426e5275412e2063bdf6f0e6b957a3ea74da45e0aef35d22d9afc542e23', - 'com.android.support:support-annotations:9c59286413a2bb93e199c73261e58d5af32da7ae0a12cbd075f581a5de1fb446', + 'com.android.support:support-annotations:7bc07519aa613b186001160403bcfd68260fa82c61cc7e83adeedc9b862b94ae', ] } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java index 85e2f8e9d..3d7b31905 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java @@ -125,11 +125,7 @@ public class CreateKeyEmailFragment extends Fragment { // initial values if (mAdditionalEmailModels == null) { mAdditionalEmailModels = new ArrayList<>(); - if (mCreateKeyActivity.mAdditionalEmails != null) { - mEmailAdapter.addAll(mCreateKeyActivity.mAdditionalEmails); - } } - if (mEmailAdapter == null) { mEmailAdapter = new EmailAdapter(mAdditionalEmailModels, new View.OnClickListener() { @Override @@ -138,6 +134,9 @@ public class CreateKeyEmailFragment extends Fragment { } }); } + if (mAdditionalEmailModels.isEmpty() && mCreateKeyActivity.mAdditionalEmails != null) { + mEmailAdapter.addAll(mCreateKeyActivity.mAdditionalEmails); + } mEmailsRecyclerView.setAdapter(mEmailAdapter); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyPassphraseFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyPassphraseFragment.java index 32173edf7..3379e0a6d 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyPassphraseFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyPassphraseFragment.java @@ -21,7 +21,6 @@ import android.app.Activity; import android.content.Context; import android.os.Bundle; import android.support.v4.app.Fragment; -import android.text.Editable; import android.text.method.HideReturnsTransformationMethod; import android.text.method.PasswordTransformationMethod; import android.view.LayoutInflater; @@ -37,9 +36,6 @@ import org.sufficientlysecure.keychain.ui.CreateKeyActivity.FragAction; import org.sufficientlysecure.keychain.ui.widget.PassphraseEditText; import org.sufficientlysecure.keychain.util.Passphrase; -import java.util.ArrayList; -import java.util.Arrays; - public class CreateKeyPassphraseFragment extends Fragment { // view @@ -111,8 +107,8 @@ public class CreateKeyPassphraseFragment extends Fragment { // initial values // TODO: using String here is unsafe... if (mCreateKeyActivity.mPassphrase != null) { - mPassphraseEdit.setText(Arrays.toString(mCreateKeyActivity.mPassphrase.getCharArray())); - mPassphraseEditAgain.setText(Arrays.toString(mCreateKeyActivity.mPassphrase.getCharArray())); + mPassphraseEdit.setText(new String(mCreateKeyActivity.mPassphrase.getCharArray())); + mPassphraseEditAgain.setText(new String(mCreateKeyActivity.mPassphrase.getCharArray())); } mPassphraseEdit.requestFocus(); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/MainActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/MainActivity.java index 05cf64092..f571ba1e6 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/MainActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/MainActivity.java @@ -64,7 +64,7 @@ public class MainActivity extends AppCompatActivity implements FabContainer { transaction.replace(R.id.main_fragment_container, mainFragment); transaction.commit(); - mToolbar = (Toolbar) findViewById(R.id.activity_main_toolbar); + mToolbar = (Toolbar) findViewById(R.id.toolbar); mToolbar.setTitle(R.string.app_name); setSupportActionBar(mToolbar); diff --git a/OpenKeychain/src/main/res/layout/main_activity.xml b/OpenKeychain/src/main/res/layout/main_activity.xml index 4a07053ea..45df0df71 100644 --- a/OpenKeychain/src/main/res/layout/main_activity.xml +++ b/OpenKeychain/src/main/res/layout/main_activity.xml @@ -1,19 +1,26 @@ + android:background="?attr/colorPrimary" + android:minHeight="?attr/actionBarSize" + app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar" + app:popupTheme="@style/ThemeOverlay.AppCompat.Light" + tools:ignore="UnusedAttribute" /> + android:layout_width="match_parent" /> \ No newline at end of file diff --git a/OpenKeychain/src/main/res/values/themes.xml b/OpenKeychain/src/main/res/values/themes.xml index 96d09151d..6ac09c5d7 100644 --- a/OpenKeychain/src/main/res/values/themes.xml +++ b/OpenKeychain/src/main/res/values/themes.xml @@ -8,17 +8,12 @@ @color/primary_dark @color/accent + true - false true @style/MySearchViewStyle - - - @style/ThemeOverlay.AppCompat.Dark - - @style/ThemeOverlay.AppCompat.Light -- cgit v1.2.3 From 08d25f3685cffb7402bb6dd824bc0666bfe9a1c2 Mon Sep 17 00:00:00 2001 From: Daniel Ramos Date: Sun, 26 Apr 2015 18:56:37 +0100 Subject: -removed unneeded code from previous commits. I tested on a KitKat(4.4.2) and Lollipop (5.1) phone and everything seems to be preserved as expected. --- .../org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java index ed4cf5b8a..473383e22 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java @@ -135,9 +135,6 @@ public class CreateKeyEmailFragment extends Fragment { mEmailAdapter.addAll(mCreateKeyActivity.mAdditionalEmails); } } - if (mAdditionalEmailModels.isEmpty() && mCreateKeyActivity.mAdditionalEmails != null) { - mEmailAdapter.addAll(mCreateKeyActivity.mAdditionalEmails); - } mEmailsRecyclerView.setAdapter(mEmailAdapter); -- cgit v1.2.3 From c0fbafde688f2f60f475121bf8c8b8ef2a59ce6d Mon Sep 17 00:00:00 2001 From: Daniel Ramos Date: Sun, 26 Apr 2015 19:11:51 +0100 Subject: -Removed unneeded view references from the fragment class since they are not used outside of createView. -cleanup --- .../sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java index 473383e22..035945af3 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java @@ -49,9 +49,6 @@ import java.util.regex.Pattern; public class CreateKeyEmailFragment extends Fragment { private CreateKeyActivity mCreateKeyActivity; private EmailEditText mEmailEdit; - private RecyclerView mEmailsRecyclerView; - private View mBackButton; - private View mNextButton; private ArrayList mAdditionalEmailModels; private EmailAdapter mEmailAdapter; @@ -92,9 +89,9 @@ public class CreateKeyEmailFragment extends Fragment { View view = inflater.inflate(R.layout.create_key_email_fragment, container, false); mEmailEdit = (EmailEditText) view.findViewById(R.id.create_key_email); - mBackButton = view.findViewById(R.id.create_key_back_button); - mNextButton = view.findViewById(R.id.create_key_next_button); - mEmailsRecyclerView = (RecyclerView) view.findViewById(R.id.create_key_emails); + View mBackButton = view.findViewById(R.id.create_key_back_button); + View mNextButton = view.findViewById(R.id.create_key_next_button); + RecyclerView mEmailsRecyclerView = (RecyclerView) view.findViewById(R.id.create_key_emails); // initial values mEmailEdit.setText(mCreateKeyActivity.mEmail); @@ -222,7 +219,6 @@ public class CreateKeyEmailFragment extends Fragment { Messenger messenger = new Messenger(returnHandler); AddEmailDialogFragment addEmailDialog = AddEmailDialogFragment.newInstance(messenger); - addEmailDialog.setTargetFragment(this, -1); addEmailDialog.show(getActivity().getSupportFragmentManager(), "addEmailDialog"); } -- cgit v1.2.3 From 8dbb82a8b61922e788e844e747b43f1838e6e58f Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Mon, 27 Apr 2015 13:51:39 +0200 Subject: profiling says: caching qrCode bitmaps is a good idea --- .../keychain/KeychainApplication.java | 14 +++++++ .../keychain/ui/util/QrCodeUtils.java | 48 +++++++++++++--------- 2 files changed, 43 insertions(+), 19 deletions(-) diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java index d26ccbe57..710dbf8aa 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/KeychainApplication.java @@ -24,6 +24,7 @@ import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.res.Resources; +import android.graphics.Bitmap; import android.graphics.PorterDuff; import android.graphics.drawable.Drawable; import android.os.Build; @@ -40,6 +41,8 @@ import org.sufficientlysecure.keychain.util.Preferences; import org.sufficientlysecure.keychain.util.TlsHelper; import java.security.Security; +import java.util.HashMap; + public class KeychainApplication extends Application { @@ -100,6 +103,17 @@ public class KeychainApplication extends Application { checkConsolidateRecovery(); } + public static HashMap qrCodeCache = new HashMap<>(); + + @Override + public void onTrimMemory(int level) { + super.onTrimMemory(level); + + if (level >= TRIM_MEMORY_UI_HIDDEN) { + qrCodeCache.clear(); + } + } + /** * Restart consolidate process if it has been interruped before */ diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/QrCodeUtils.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/QrCodeUtils.java index b8d4ea7d2..5f71abdab 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/QrCodeUtils.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/QrCodeUtils.java @@ -29,6 +29,7 @@ import com.google.zxing.qrcode.QRCodeWriter; import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel; import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.KeychainApplication; import org.sufficientlysecure.keychain.util.Log; import java.util.Hashtable; @@ -40,36 +41,45 @@ public class QrCodeUtils { /** * Generate Bitmap with QR Code based on input. - * - * @param input - * @param size * @return QR Code as Bitmap */ public static Bitmap getQRCodeBitmap(final String input, final int size) { + try { - final Hashtable hints = new Hashtable<>(); - hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M); - final BitMatrix result = new QRCodeWriter().encode(input, BarcodeFormat.QR_CODE, size, - size, hints); - - final int width = result.getWidth(); - final int height = result.getHeight(); - final int[] pixels = new int[width * height]; - - for (int y = 0; y < height; y++) { - final int offset = y * width; - for (int x = 0; x < width; x++) { - pixels[offset + x] = result.get(x, y) ? Color.BLACK : Color.TRANSPARENT; + + // the qrCodeCache is handled in KeychainApplication so we can + // properly react to onTrimMemory calls + Bitmap bitmap = KeychainApplication.qrCodeCache.get(input); + if (bitmap == null) { + + Hashtable hints = new Hashtable<>(); + hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.M); + BitMatrix result = new QRCodeWriter().encode(input, BarcodeFormat.QR_CODE, size, + size, hints); + + int width = result.getWidth(); + int height = result.getHeight(); + int[] pixels = new int[width * height]; + + for (int y = 0; y < height; y++) { + final int offset = y * width; + for (int x = 0; x < width; x++) { + pixels[offset + x] = result.get(x, y) ? Color.BLACK : Color.TRANSPARENT; + } } + + bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); + bitmap.setPixels(pixels, 0, width, 0, 0, width, height); + + KeychainApplication.qrCodeCache.put(input, bitmap); } - final Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888); - bitmap.setPixels(pixels, 0, width, 0, 0, width, height); return bitmap; - } catch (final WriterException e) { + } catch (WriterException e) { Log.e(Constants.TAG, "QrCodeUtils", e); return null; } + } } -- cgit v1.2.3 From 40834d1fcd2208bdaf3a2faff1184e168f3c2e3f Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Mon, 27 Apr 2015 14:40:52 +0200 Subject: add distinct status for messages signed by "your" key --- .../org/sufficientlysecure/keychain/ui/DecryptFragment.java | 13 +++++++++++++ OpenKeychain/src/main/res/values/strings.xml | 1 + 2 files changed, 14 insertions(+) diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java index 651b56ab0..9c51893ce 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java @@ -231,6 +231,7 @@ public abstract class DecryptFragment extends CryptoOperationFragment implements KeychainContract.KeyRings.IS_REVOKED, KeychainContract.KeyRings.IS_EXPIRED, KeychainContract.KeyRings.VERIFIED, + KeychainContract.KeyRings.HAS_ANY_SECRET, }; @SuppressWarnings("unused") @@ -239,6 +240,7 @@ public abstract class DecryptFragment extends CryptoOperationFragment implements static final int INDEX_IS_REVOKED = 3; static final int INDEX_IS_EXPIRED = 4; static final int INDEX_VERIFIED = 5; + static final int INDEX_HAS_ANY_SECRET = 6; @Override public Loader onCreateLoader(int id, Bundle args) { @@ -283,6 +285,7 @@ public abstract class DecryptFragment extends CryptoOperationFragment implements boolean isRevoked = data.getInt(INDEX_IS_REVOKED) != 0; boolean isExpired = data.getInt(INDEX_IS_EXPIRED) != 0; boolean isVerified = data.getInt(INDEX_VERIFIED) > 0; + boolean isYours = data.getInt(INDEX_HAS_ANY_SECRET) != 0; if (isRevoked) { mSignatureText.setText(R.string.decrypt_result_signature_revoked_key); @@ -302,6 +305,16 @@ public abstract class DecryptFragment extends CryptoOperationFragment implements onVerifyLoaded(true); + } else if (isYours) { + + mSignatureText.setText(R.string.decrypt_result_signature_secret); + KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, State.VERIFIED); + + setSignatureLayoutVisibility(View.VISIBLE); + setShowAction(signatureKeyId); + + onVerifyLoaded(true); + } else if (isVerified) { mSignatureText.setText(R.string.decrypt_result_signature_certified); KeyFormattingUtils.setStatusImage(getActivity(), mSignatureIcon, mSignatureText, State.VERIFIED); diff --git a/OpenKeychain/src/main/res/values/strings.xml b/OpenKeychain/src/main/res/values/strings.xml index 4d92dac20..ffdd86259 100644 --- a/OpenKeychain/src/main/res/values/strings.xml +++ b/OpenKeychain/src/main/res/values/strings.xml @@ -287,6 +287,7 @@ "Not Signed" "Invalid signature!" "Signed by unconfirmed key" + "Signed by your key" "Signed by confirmed key" "Signed by expired key!" "Signed by revoked key!" -- cgit v1.2.3 From 4ba2e4bcdd9c3b5f472b1502e55bcf753ee44b58 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Mon, 27 Apr 2015 17:45:50 +0200 Subject: display creation dates for ambiguous user ids --- .../keychain/ui/adapter/KeyAdapter.java | 21 ++++++++++++++++++++- .../ui/adapter/SelectKeyCursorAdapter.java | 22 +++++++++------------- OpenKeychain/src/main/res/layout/key_list_item.xml | 16 ++++++++++++++-- OpenKeychain/src/main/res/values/strings.xml | 2 +- 4 files changed, 44 insertions(+), 17 deletions(-) diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyAdapter.java index 6f19fc6ed..f09dc1a4f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyAdapter.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyAdapter.java @@ -27,6 +27,7 @@ import android.database.Cursor; import android.graphics.PorterDuff; import android.support.v4.widget.CursorAdapter; import android.text.format.DateFormat; +import android.text.format.DateUtils; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -88,6 +89,7 @@ public class KeyAdapter extends CursorAdapter { public Long mMasterKeyId; public TextView mMainUserId; public TextView mMainUserIdRest; + public TextView mCreationDate; public ImageView mStatus; public View mSlinger; public ImageButton mSlingerButton; @@ -98,6 +100,7 @@ public class KeyAdapter extends CursorAdapter { mStatus = (ImageView) view.findViewById(R.id.key_list_item_status_icon); mSlinger = view.findViewById(R.id.key_list_item_slinger_view); mSlingerButton = (ImageButton) view.findViewById(R.id.key_list_item_slinger_button); + mCreationDate = (TextView) view.findViewById(R.id.key_list_item_creation); } public void setData(Context context, Cursor cursor, Highlighter highlighter) { @@ -125,7 +128,7 @@ public class KeyAdapter extends CursorAdapter { boolean isRevoked = cursor.getInt(INDEX_IS_REVOKED) > 0; boolean isExpired = cursor.getInt(INDEX_IS_EXPIRED) != 0; boolean isVerified = cursor.getInt(INDEX_VERIFIED) > 0; - // boolean hasDuplicate = cursor.getInt(INDEX_HAS_DUPLICATE_USER_ID) == 1; + boolean hasDuplicate = cursor.getInt(INDEX_HAS_DUPLICATE_USER_ID) != 0; mMasterKeyId = masterKeyId; @@ -165,6 +168,22 @@ public class KeyAdapter extends CursorAdapter { mMainUserId.setTextColor(context.getResources().getColor(R.color.black)); mMainUserIdRest.setTextColor(context.getResources().getColor(R.color.black)); } + + if (hasDuplicate) { + String dateTime = DateUtils.formatDateTime(context, + cursor.getLong(INDEX_CREATION) * 1000, + DateUtils.FORMAT_SHOW_DATE + | DateUtils.FORMAT_SHOW_TIME + | DateUtils.FORMAT_SHOW_YEAR + | DateUtils.FORMAT_ABBREV_MONTH); + + mCreationDate.setText(context.getString(R.string.label_creation, + dateTime)); + mCreationDate.setVisibility(View.VISIBLE); + } else { + mCreationDate.setVisibility(View.GONE); + } + } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SelectKeyCursorAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SelectKeyCursorAdapter.java index 3308a4500..1ccb910d0 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SelectKeyCursorAdapter.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SelectKeyCursorAdapter.java @@ -20,7 +20,7 @@ package org.sufficientlysecure.keychain.ui.adapter; import android.content.Context; import android.database.Cursor; import android.support.v4.widget.CursorAdapter; -import android.text.format.DateFormat; +import android.text.format.DateUtils; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -36,10 +36,6 @@ import org.sufficientlysecure.keychain.ui.util.Highlighter; import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils; import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils.State; -import java.util.Calendar; -import java.util.Date; -import java.util.TimeZone; - /** * Yes this class is abstract! @@ -138,14 +134,14 @@ abstract public class SelectKeyCursorAdapter extends CursorAdapter { boolean duplicate = cursor.getLong(mIndexDuplicateUserId) > 0; if (duplicate) { - Date creationDate = new Date(cursor.getLong(mIndexCreation) * 1000); - Calendar creationCal = Calendar.getInstance(TimeZone.getTimeZone("UTC")); - creationCal.setTime(creationDate); - // convert from UTC to time zone of device - creationCal.setTimeZone(TimeZone.getDefault()); - - h.creation.setText(context.getString(R.string.label_creation) + ": " - + DateFormat.getDateFormat(context).format(creationCal.getTime())); + String dateTime = DateUtils.formatDateTime(context, + cursor.getLong(mIndexCreation) * 1000, + DateUtils.FORMAT_SHOW_DATE + | DateUtils.FORMAT_SHOW_TIME + | DateUtils.FORMAT_SHOW_YEAR + | DateUtils.FORMAT_ABBREV_MONTH); + + h.creation.setText(context.getString(R.string.label_creation, dateTime)); h.creation.setVisibility(View.VISIBLE); } else { h.creation.setVisibility(View.GONE); diff --git a/OpenKeychain/src/main/res/layout/key_list_item.xml b/OpenKeychain/src/main/res/layout/key_list_item.xml index fbe5f1326..6078b898f 100644 --- a/OpenKeychain/src/main/res/layout/key_list_item.xml +++ b/OpenKeychain/src/main/res/layout/key_list_item.xml @@ -26,7 +26,7 @@ android:id="@+id/key_list_item_name" android:layout_width="wrap_content" android:layout_height="wrap_content" - android:text="@string/label_main_user_id" + tools:text="@string/label_main_user_id" android:textAppearance="?android:attr/textAppearanceMedium" /> + + + "File compression" "Keyservers" "Key ID" - "Creation" + "Key created %s" "Expiry" "Usage" "Key Size" -- cgit v1.2.3 From 91b774d22334b91c1867b867c515d1fcd31e34da Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Mon, 27 Apr 2015 19:48:58 +0200 Subject: prevent crashes in EncryptKeyCompletionView --- .../keychain/ui/widget/EncryptKeyCompletionView.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionView.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionView.java index 3d2e8b9df..4e691d962 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionView.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionView.java @@ -110,7 +110,7 @@ public class EncryptKeyCompletionView extends TokenCompleteTextView if (getContext() instanceof FragmentActivity) { mLoaderManager = ((FragmentActivity) getContext()).getSupportLoaderManager(); - mLoaderManager.initLoader(hashCode(), null, this); + mLoaderManager.initLoader(0, null, this); } else { Log.e(Constants.TAG, "EncryptKeyCompletionView must be attached to a FragmentActivity, this is " + getContext().getClass()); } @@ -154,6 +154,14 @@ public class EncryptKeyCompletionView extends TokenCompleteTextView mAdapter.swapCursor(null); } + @Override + public void showDropDown() { + if (mAdapter.getCursor().isClosed()) { + return; + } + super.showDropDown(); + } + @Override public void onFocusChanged(boolean hasFocus, int direction, Rect previous) { super.onFocusChanged(hasFocus, direction, previous); @@ -171,7 +179,7 @@ public class EncryptKeyCompletionView extends TokenCompleteTextView } Bundle args = new Bundle(); args.putString(ARG_QUERY, text.subSequence(start, end).toString()); - mLoaderManager.restartLoader(hashCode(), args, this); + mLoaderManager.restartLoader(0, args, this); } } -- cgit v1.2.3 From 2b6bb57c1c1c6202ab5d00d6351424e1ac0fb1b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Tue, 28 Apr 2015 11:06:54 +0200 Subject: Display development build status --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 48b649b22..b9621f19f 100644 --- a/README.md +++ b/README.md @@ -3,9 +3,9 @@ OpenKeychain is an OpenPGP implementation for Android. For a more detailed description and installation instructions go to http://www.openkeychain.org . -### Travis CI Build Status +### Travis CI Build Status of development branch -[![Build Status](https://travis-ci.org/open-keychain/open-keychain.png?branch=master)](https://travis-ci.org/open-keychain/open-keychain) +[![Build Status](https://travis-ci.org/open-keychain/open-keychain.png?branch=development)](https://travis-ci.org/open-keychain/open-keychain) ## How to help the project? -- cgit v1.2.3 From 871764219897d0105797fd59fe47fba41aba012b Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Tue, 28 Apr 2015 18:18:14 +0200 Subject: fix "select all" in key list multi-select --- .../main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java index 96ce101b5..1355bd3e6 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/KeyListFragment.java @@ -240,7 +240,7 @@ public class KeyListFragment extends LoaderFragment } case R.id.menu_key_list_multi_select_all: { // select all - for (int i = 0; i < mStickyList.getCount(); i++) { + for (int i = 0; i < mAdapter.getCount(); i++) { mStickyList.setItemChecked(i, true); } break; -- cgit v1.2.3 From cd55871950571035088823846739e04cac8ca432 Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Tue, 28 Apr 2015 18:18:42 +0200 Subject: display unknown keys red rather than orange For an unknown key, there is no indication of the state the key is in. To indicate both immediate action required, and to make this status equal to its worst case (rather than *better* than its worst case), the status is displayed in red. At some point, we will probably want to download unknown keys automatically, at which point an unknown key will actually be an error state. This is an intermediate solution until then. --- .../org/sufficientlysecure/keychain/ui/util/KeyFormattingUtils.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/KeyFormattingUtils.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/KeyFormattingUtils.java index ae66b59d4..91a7d361a 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/KeyFormattingUtils.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/util/KeyFormattingUtils.java @@ -475,7 +475,7 @@ public class KeyFormattingUtils { statusIcon.setImageDrawable( context.getResources().getDrawable(R.drawable.status_signature_unknown_cutout_24dp)); if (color == KeyFormattingUtils.DEFAULT_COLOR) { - color = R.color.android_orange_light; + color = R.color.android_red_light; } statusIcon.setColorFilter(context.getResources().getColor(color), PorterDuff.Mode.SRC_IN); -- cgit v1.2.3 From 8ab49b076603ade77785a9bfb4a0f7a13bad483a Mon Sep 17 00:00:00 2001 From: Vincent Breitmoser Date: Tue, 28 Apr 2015 18:21:51 +0200 Subject: fix crash when moving focus from EncryptKeyCompletionView with unknown text --- .../sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionView.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionView.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionView.java index 4e691d962..525bc26ca 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionView.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionView.java @@ -101,7 +101,7 @@ public class EncryptKeyCompletionView extends TokenCompleteTextView /*if (completionText.startsWith("0x")) { }*/ - return null; + return ""; } @Override -- cgit v1.2.3 From c9e0acec50268b2338e860ec49d4613adfeeea1e Mon Sep 17 00:00:00 2001 From: William Faulk Date: Tue, 28 Apr 2015 19:10:45 -0400 Subject: Update README.md with new build info --- README.md | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/README.md b/README.md index b9621f19f..7c4dce0af 100644 --- a/README.md +++ b/README.md @@ -30,19 +30,20 @@ Development mailinglist at http://groups.google.com/d/forum/openpgp-keychain-dev ### Build with Gradle -1. Get all external submodules with ``git submodule update --init --recursive`` -2. Have Android SDK "tools", "platform-tools", and "build-tools" directories in your PATH (http://developer.android.com/sdk/index.html) -3. Open the Android SDK Manager (shell command: ``android``). -Expand the Tools directory and select "Android SDK Build-tools (Version 21.1.1)". +1. Clone the project from GitHub +2. Get all external submodules with ``git submodule update --init --recursive`` +3. Have Android SDK "tools", "platform-tools", and "build-tools" directories in your PATH (http://developer.android.com/sdk/index.html) +4. Open the Android SDK Manager (shell command: ``android``). +Expand the Tools directory and select "Android SDK Build-tools (Version 21.1.2)". Expand the Extras directory and install "Android Support Repository" -Select everything for the newest SDK Platform (API-Level 21) -4. Export ANDROID_HOME pointing to your Android SDK -5. Execute ``./gradlew build`` -6. You can install the app with ``adb install -r OpenKeychain/build/outputs/apk/OpenKeychain-debug-unaligned.apk`` +Select everything for the newest SDK Platform, API 22, and also API 21 +5. Export ANDROID_HOME pointing to your Android SDK +6. Execute ``./gradlew build`` +7. You can install the app with ``adb install -r OpenKeychain/build/outputs/apk/OpenKeychain-debug-unaligned.apk`` ### Run Tests 1. Use OpenJDK instead of Oracle JDK -3. Execute ``./gradlew test`` +2. Execute ``./gradlew test`` ### Build API Demo with Gradle @@ -55,7 +56,8 @@ Select everything for the newest SDK Platform (API-Level 21) We are using the newest [Android Studio](http://developer.android.com/sdk/installing/studio.html) for development. Development with Eclipse is currently not possible because we are using the new [project structure](http://developer.android.com/sdk/installing/studio-tips.html). 1. Clone the project from Github -2. From Android Studio: File -> Import Project -> Select the cloned top folder +2. Get all external submodules with ``git submodule update --init --recursive`` +3. From Android Studio: File -> Import Project -> Select the cloned top folder ## Libraries -- cgit v1.2.3 From 41968206d3deed789dd5b35468a8d8487755234c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Wed, 29 Apr 2015 20:43:46 +0200 Subject: Use own gradle wrapper to verify downloaded gradle package via SHA-256 sum. See https://github.com/gradle/gradle/pull/448 --- gradle/wrapper/gradle-wrapper.jar | Bin 52141 -> 53322 bytes gradle/wrapper/gradle-wrapper.properties | 1 + 2 files changed, 1 insertion(+) diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 085a1cdc2..497f80dd6 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 8308df30c..6e00d9230 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -4,3 +4,4 @@ distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists distributionUrl=https\://services.gradle.org/distributions/gradle-2.3-bin.zip +distributionSha256Sum=010dd9f31849abc3d5644e282943b1c1c355f8e2635c5789833979ce590a3774 \ No newline at end of file -- cgit v1.2.3 From 14921e783f66b8cbdec428e0bc8a57961d9cf62a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Wed, 29 Apr 2015 22:56:49 +0200 Subject: Update wrapper to verify local cache --- gradle/wrapper/gradle-wrapper.jar | Bin 53322 -> 53323 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 497f80dd6..cb5ccd9f1 100644 Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ -- cgit v1.2.3 From f623411fb635f106946960b5e6a05767f15fb598 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Thu, 30 Apr 2015 00:59:57 +0200 Subject: Update snackbar --- extern/snackbar | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/extern/snackbar b/extern/snackbar index 97cda0806..12e1e8b7e 160000 --- a/extern/snackbar +++ b/extern/snackbar @@ -1 +1 @@ -Subproject commit 97cda0806d9ead9a3aacf3d4f7275ac0e38d960c +Subproject commit 12e1e8b7e88a09249aed68a48a6c4d06c401e00f -- cgit v1.2.3 From e159e619d299c0e91f3f9527186e50649657dd73 Mon Sep 17 00:00:00 2001 From: Daniel Ramos Date: Thu, 30 Apr 2015 00:44:01 +0100 Subject: -removed unneeded inputType attribute from xml files (+1 squashed commits) Squashed commits: [ef54e68] -code style fixing --- .../keychain/ui/CreateKeyEmailFragment.java | 20 ++++++++++---------- .../src/main/res/layout/add_email_dialog.xml | 1 - .../main/res/layout/create_key_email_fragment.xml | 1 - 3 files changed, 10 insertions(+), 12 deletions(-) diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java index 035945af3..078135772 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java @@ -89,9 +89,9 @@ public class CreateKeyEmailFragment extends Fragment { View view = inflater.inflate(R.layout.create_key_email_fragment, container, false); mEmailEdit = (EmailEditText) view.findViewById(R.id.create_key_email); - View mBackButton = view.findViewById(R.id.create_key_back_button); - View mNextButton = view.findViewById(R.id.create_key_next_button); - RecyclerView mEmailsRecyclerView = (RecyclerView) view.findViewById(R.id.create_key_emails); + View backButton = view.findViewById(R.id.create_key_back_button); + View nextButton = view.findViewById(R.id.create_key_next_button); + RecyclerView emailsRecyclerView = (RecyclerView) view.findViewById(R.id.create_key_emails); // initial values mEmailEdit.setText(mCreateKeyActivity.mEmail); @@ -100,21 +100,21 @@ public class CreateKeyEmailFragment extends Fragment { if (mCreateKeyActivity.mEmail == null) { mEmailEdit.requestFocus(); } - mBackButton.setOnClickListener(new View.OnClickListener() { + backButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { mCreateKeyActivity.loadFragment(null, FragAction.TO_LEFT); } }); - mNextButton.setOnClickListener(new View.OnClickListener() { + nextButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { nextClicked(); } }); - mEmailsRecyclerView.setHasFixedSize(true); - mEmailsRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity())); - mEmailsRecyclerView.setItemAnimator(new DefaultItemAnimator()); + emailsRecyclerView.setHasFixedSize(true); + emailsRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity())); + emailsRecyclerView.setItemAnimator(new DefaultItemAnimator()); // initial values if (mAdditionalEmailModels == null) { @@ -133,7 +133,7 @@ public class CreateKeyEmailFragment extends Fragment { } } - mEmailsRecyclerView.setAdapter(mEmailAdapter); + emailsRecyclerView.setAdapter(mEmailAdapter); return view; } @@ -216,7 +216,7 @@ public class CreateKeyEmailFragment extends Fragment { } }; // Create a new Messenger for the communication back - Messenger messenger = new Messenger(returnHandler); + Messenger messenger = new Messenger(returnHandler); AddEmailDialogFragment addEmailDialog = AddEmailDialogFragment.newInstance(messenger); addEmailDialog.show(getActivity().getSupportFragmentManager(), "addEmailDialog"); diff --git a/OpenKeychain/src/main/res/layout/add_email_dialog.xml b/OpenKeychain/src/main/res/layout/add_email_dialog.xml index 2de657a40..68d895145 100644 --- a/OpenKeychain/src/main/res/layout/add_email_dialog.xml +++ b/OpenKeychain/src/main/res/layout/add_email_dialog.xml @@ -21,7 +21,6 @@ android:layout_marginTop="16dp" android:hint="@string/label_email" android:imeOptions="actionNext" - android:inputType="textEmailAddress" android:textAppearance="?android:attr/textAppearanceMedium" /> diff --git a/OpenKeychain/src/main/res/layout/create_key_email_fragment.xml b/OpenKeychain/src/main/res/layout/create_key_email_fragment.xml index 7b9cffec4..17cfe54ac 100644 --- a/OpenKeychain/src/main/res/layout/create_key_email_fragment.xml +++ b/OpenKeychain/src/main/res/layout/create_key_email_fragment.xml @@ -32,7 +32,6 @@ android:layout_marginTop="16dp" android:layout_marginBottom="8dp" android:imeOptions="actionNext" - android:inputType="textEmailAddress" android:hint="@string/label_email" android:ems="10" /> -- cgit v1.2.3 From 7c275fed9d93e0c45b2fb00d94bde702b44c8811 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Thu, 30 Apr 2015 18:45:43 +0200 Subject: API: Allow selection of decryption keys when decryption fails --- OpenKeychain/src/main/AndroidManifest.xml | 5 + .../keychain/remote/OpenPgpService.java | 34 ++++-- .../keychain/remote/ui/RemoteServiceActivity.java | 1 + .../remote/ui/SelectAllowedKeysActivity.java | 115 +++++++++++++++++++++ .../res/layout/api_remote_select_allowed_keys.xml | 38 +++++++ OpenKeychain/src/main/res/values/strings.xml | 1 + 6 files changed, 188 insertions(+), 6 deletions(-) create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/SelectAllowedKeysActivity.java create mode 100644 OpenKeychain/src/main/res/layout/api_remote_select_allowed_keys.xml diff --git a/OpenKeychain/src/main/AndroidManifest.xml b/OpenKeychain/src/main/AndroidManifest.xml index 8c66176fd..6bc61460a 100644 --- a/OpenKeychain/src/main/AndroidManifest.xml +++ b/OpenKeychain/src/main/AndroidManifest.xml @@ -740,6 +740,11 @@ android:exported="false" android:label="@string/app_name" android:launchMode="singleTop" /> + allowedKeyIds; + Set allowedKeyIds = mProviderHelper.getAllowedKeyIdsForApp( + KeychainContract.ApiAllowedKeys.buildBaseUri(currentPkg)); + if (data.getIntExtra(OpenPgpApi.EXTRA_API_VERSION, -1) < 7) { - allowedKeyIds = mProviderHelper.getAllKeyIdsForApp( - ApiAccounts.buildBaseUri(currentPkg)); - } else { - allowedKeyIds = mProviderHelper.getAllowedKeyIdsForApp( - KeychainContract.ApiAllowedKeys.buildBaseUri(currentPkg)); + allowedKeyIds.addAll(mProviderHelper.getAllKeyIdsForApp( + ApiAccounts.buildBaseUri(currentPkg))); } long inputLength = is.available(); @@ -575,6 +588,15 @@ public class OpenPgpService extends RemoteService { return result; } else { LogEntryParcel errorMsg = pgpResult.getLog().getLast(); + + if (errorMsg.mType == OperationResult.LogType.MSG_DC_ERROR_NO_KEY) { + // allow user to select allowed keys + Intent result = new Intent(); + result.putExtra(OpenPgpApi.RESULT_INTENT, getSelectAllowedKeysIntent(data)); + result.putExtra(OpenPgpApi.RESULT_CODE, OpenPgpApi.RESULT_CODE_USER_INTERACTION_REQUIRED); + return result; + } + throw new Exception(getString(errorMsg.mType.getMsgId())); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/RemoteServiceActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/RemoteServiceActivity.java index f312c0d44..5facde64f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/RemoteServiceActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/RemoteServiceActivity.java @@ -45,6 +45,7 @@ import org.sufficientlysecure.keychain.util.Log; import java.util.ArrayList; +// TODO: make extensible BaseRemoteServiceActivity and extend these cases from it public class RemoteServiceActivity extends BaseActivity { public static final String ACTION_REGISTER = Constants.INTENT_PREFIX + "API_ACTIVITY_REGISTER"; diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/SelectAllowedKeysActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/SelectAllowedKeysActivity.java new file mode 100644 index 000000000..767106ff0 --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/remote/ui/SelectAllowedKeysActivity.java @@ -0,0 +1,115 @@ +/* + * Copyright (C) 2015 Dominik Schürmann + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.sufficientlysecure.keychain.remote.ui; + +import android.app.Activity; +import android.content.Intent; +import android.net.Uri; +import android.os.Bundle; +import android.view.View; + +import org.sufficientlysecure.keychain.Constants; +import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.provider.KeychainContract; +import org.sufficientlysecure.keychain.ui.base.BaseActivity; +import org.sufficientlysecure.keychain.util.Log; + +public class SelectAllowedKeysActivity extends BaseActivity { + + public static final String EXTRA_SERVICE_INTENT = "data"; + + private Uri mAppUri; + + private AppSettingsAllowedKeysListFragment mAllowedKeysFragment; + + Intent mServiceData; + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + // Inflate a "Done" custom action bar + setFullScreenDialogDoneClose(R.string.api_settings_save, + new View.OnClickListener() { + @Override + public void onClick(View v) { + save(); + } + }, + new View.OnClickListener() { + @Override + public void onClick(View v) { + cancel(); + } + }); + + Intent intent = getIntent(); + mServiceData = intent.getParcelableExtra(EXTRA_SERVICE_INTENT); + mAppUri = intent.getData(); + if (mAppUri == null) { + Log.e(Constants.TAG, "Intent data missing. Should be Uri of app!"); + finish(); + return; + } else { + Log.d(Constants.TAG, "uri: " + mAppUri); + loadData(savedInstanceState, mAppUri); + } + } + + @Override + protected void initLayout() { + setContentView(R.layout.api_remote_select_allowed_keys); + } + + private void save() { + mAllowedKeysFragment.saveAllowedKeys(); + setResult(Activity.RESULT_OK, mServiceData); + finish(); + } + + private void cancel() { + setResult(Activity.RESULT_CANCELED); + finish(); + } + + private void loadData(Bundle savedInstanceState, Uri appUri) { + Uri allowedKeysUri = appUri.buildUpon().appendPath(KeychainContract.PATH_ALLOWED_KEYS).build(); + Log.d(Constants.TAG, "allowedKeysUri: " + allowedKeysUri); + startListFragments(savedInstanceState, allowedKeysUri); + } + + private void startListFragments(Bundle savedInstanceState, Uri allowedKeysUri) { + // However, if we're being restored from a previous state, + // then we don't need to do anything and should return or else + // we could end up with overlapping fragments. + if (savedInstanceState != null) { + return; + } + + // Create an instance of the fragments + mAllowedKeysFragment = AppSettingsAllowedKeysListFragment.newInstance(allowedKeysUri); + // Add the fragment to the 'fragment_container' FrameLayout + // NOTE: We use commitAllowingStateLoss() to prevent weird crashes! + getSupportFragmentManager().beginTransaction() + .replace(R.id.api_allowed_keys_list_fragment, mAllowedKeysFragment) + .commitAllowingStateLoss(); + // do it immediately! + getSupportFragmentManager().executePendingTransactions(); + } + +} diff --git a/OpenKeychain/src/main/res/layout/api_remote_select_allowed_keys.xml b/OpenKeychain/src/main/res/layout/api_remote_select_allowed_keys.xml new file mode 100644 index 000000000..e052ff333 --- /dev/null +++ b/OpenKeychain/src/main/res/layout/api_remote_select_allowed_keys.xml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/OpenKeychain/src/main/res/values/strings.xml b/OpenKeychain/src/main/res/values/strings.xml index f72bdb7fc..d274a5ca3 100644 --- a/OpenKeychain/src/main/res/values/strings.xml +++ b/OpenKeychain/src/main/res/values/strings.xml @@ -521,6 +521,7 @@ "Please select the recipients!" "Signature check failed! Have you installed this app from a different source? If you are sure that this is not an attack, revoke this app's registration in OpenKeychain and then register the app again." "Please select one of your existing keys or create a new one." + "None of the allowed keys is able to decrypt the content. Please select the allowed keys." "Share with QR Code" -- cgit v1.2.3 From c88d2e42b747fac700ab6ac47beeae91c76bdbd2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Thu, 30 Apr 2015 18:57:51 +0200 Subject: Fix key creation string and display --- .../keychain/ui/adapter/KeyAdapter.java | 17 +---------------- .../keychain/ui/adapter/SelectKeyCursorAdapter.java | 2 +- .../keychain/ui/widget/KeySpinner.java | 16 ++++++++-------- OpenKeychain/src/main/res/values/strings.xml | 5 +++-- 4 files changed, 13 insertions(+), 27 deletions(-) diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyAdapter.java index f09dc1a4f..eef44a94b 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyAdapter.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/KeyAdapter.java @@ -173,11 +173,10 @@ public class KeyAdapter extends CursorAdapter { String dateTime = DateUtils.formatDateTime(context, cursor.getLong(INDEX_CREATION) * 1000, DateUtils.FORMAT_SHOW_DATE - | DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_SHOW_YEAR | DateUtils.FORMAT_ABBREV_MONTH); - mCreationDate.setText(context.getString(R.string.label_creation, + mCreationDate.setText(context.getString(R.string.label_key_created, dateTime)); mCreationDate.setVisibility(View.VISIBLE); } else { @@ -281,20 +280,6 @@ public class KeyAdapter extends CursorAdapter { } } - public boolean hasDuplicate() { - return mHasDuplicate; - } - - public String getCreationDate(Context context) { - Calendar creationCal = Calendar.getInstance(TimeZone.getTimeZone("UTC")); - creationCal.setTime(mCreation); - // convert from UTC to time zone of device - creationCal.setTimeZone(TimeZone.getDefault()); - - return context.getString(R.string.label_creation) + ": " - + DateFormat.getDateFormat(context).format(creationCal.getTime()); - } - } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SelectKeyCursorAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SelectKeyCursorAdapter.java index 1ccb910d0..68c59f647 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SelectKeyCursorAdapter.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SelectKeyCursorAdapter.java @@ -141,7 +141,7 @@ abstract public class SelectKeyCursorAdapter extends CursorAdapter { | DateUtils.FORMAT_SHOW_YEAR | DateUtils.FORMAT_ABBREV_MONTH); - h.creation.setText(context.getString(R.string.label_creation, dateTime)); + h.creation.setText(context.getString(R.string.label_key_created, dateTime)); h.creation.setVisibility(View.VISIBLE); } else { h.creation.setVisibility(View.GONE); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java index fc5ecd76a..aecc81604 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/KeySpinner.java @@ -26,6 +26,7 @@ import android.support.v4.content.Loader; import android.support.v4.widget.CursorAdapter; import android.support.v7.widget.AppCompatSpinner; import android.text.format.DateFormat; +import android.text.format.DateUtils; import android.util.AttributeSet; import android.view.View; import android.view.ViewGroup; @@ -167,14 +168,13 @@ public abstract class KeySpinner extends AppCompatSpinner implements LoaderManag boolean duplicate = cursor.getLong(mIndexDuplicate) > 0; if (duplicate) { - Date creationDate = new Date(cursor.getLong(mIndexCreationDate) * 1000); - Calendar creationCal = Calendar.getInstance(TimeZone.getTimeZone("UTC")); - creationCal.setTime(creationDate); - // convert from UTC to time zone of device - creationCal.setTimeZone(TimeZone.getDefault()); - - vDuplicate.setText(context.getString(R.string.label_creation) + ": " - + DateFormat.getDateFormat(context).format(creationCal.getTime())); + String dateTime = DateUtils.formatDateTime(context, + cursor.getLong(mIndexCreationDate) * 1000, + DateUtils.FORMAT_SHOW_DATE + | DateUtils.FORMAT_SHOW_YEAR + | DateUtils.FORMAT_ABBREV_MONTH); + + vDuplicate.setText(context.getString(R.string.label_key_created, dateTime)); vDuplicate.setVisibility(View.VISIBLE); } else { vDuplicate.setVisibility(View.GONE); diff --git a/OpenKeychain/src/main/res/values/strings.xml b/OpenKeychain/src/main/res/values/strings.xml index d274a5ca3..1a862de7a 100644 --- a/OpenKeychain/src/main/res/values/strings.xml +++ b/OpenKeychain/src/main/res/values/strings.xml @@ -137,7 +137,8 @@ "File compression" "Keyservers" "Key ID" - "Key created %s" + "Key created %s" + "Creation" "Expiry" "Usage" "Key Size" @@ -503,7 +504,7 @@ "Delete account" "Package Name" "SHA-256 of Package Signature" - "Accounts (deprecated API)" + "Accounts (old API)" "Extended Information" "Allowed Keys" "Settings" -- cgit v1.2.3 From 5ad50b99a21642e466cad0d9e23976793f7cf765 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Thu, 30 Apr 2015 19:02:33 +0200 Subject: Remove time from key creation display --- .../sufficientlysecure/keychain/ui/adapter/SelectKeyCursorAdapter.java | 1 - 1 file changed, 1 deletion(-) diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SelectKeyCursorAdapter.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SelectKeyCursorAdapter.java index 68c59f647..a6cb52977 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SelectKeyCursorAdapter.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/adapter/SelectKeyCursorAdapter.java @@ -137,7 +137,6 @@ abstract public class SelectKeyCursorAdapter extends CursorAdapter { String dateTime = DateUtils.formatDateTime(context, cursor.getLong(mIndexCreation) * 1000, DateUtils.FORMAT_SHOW_DATE - | DateUtils.FORMAT_SHOW_TIME | DateUtils.FORMAT_SHOW_YEAR | DateUtils.FORMAT_ABBREV_MONTH); -- cgit v1.2.3 From e91dc022fbd5d616c2ac1b5bbd47a693b9f8f8d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Fri, 1 May 2015 14:36:22 +0200 Subject: Fix nullpointer in EncryptKeyCompletionView --- .../keychain/ui/widget/EncryptKeyCompletionView.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionView.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionView.java index 525bc26ca..df6b82978 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionView.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionView.java @@ -136,7 +136,7 @@ public class EncryptKeyCompletionView extends TokenCompleteTextView where += " AND " + KeyRings.USER_ID + " LIKE ?"; return new CursorLoader(getContext(), baseUri, KeyAdapter.PROJECTION, where, - new String[] { "%" + query + "%" }, null); + new String[]{"%" + query + "%"}, null); } mAdapter.setSearchQuery(null); @@ -156,7 +156,7 @@ public class EncryptKeyCompletionView extends TokenCompleteTextView @Override public void showDropDown() { - if (mAdapter.getCursor().isClosed()) { + if (mAdapter == null || mAdapter.getCursor().isClosed()) { return; } super.showDropDown(); -- cgit v1.2.3 From f3870cee290a7f8f996c14d457cba3be4127cd3e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Fri, 1 May 2015 14:44:40 +0200 Subject: More nullpointer fixes --- .../sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionView.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionView.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionView.java index df6b82978..63a1aade9 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionView.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/widget/EncryptKeyCompletionView.java @@ -156,7 +156,7 @@ public class EncryptKeyCompletionView extends TokenCompleteTextView @Override public void showDropDown() { - if (mAdapter == null || mAdapter.getCursor().isClosed()) { + if (mAdapter == null || mAdapter.getCursor() == null || mAdapter.getCursor().isClosed()) { return; } super.showDropDown(); -- cgit v1.2.3 From aa68c41f5a3867d98c2539698546d5ff6de8391c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Fri, 1 May 2015 14:48:57 +0200 Subject: Fix yubikey strings --- .../src/main/res/layout/create_yubikey_wait_fragment.xml | 3 +-- OpenKeychain/src/main/res/values/strings.xml | 11 ++++++----- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/OpenKeychain/src/main/res/layout/create_yubikey_wait_fragment.xml b/OpenKeychain/src/main/res/layout/create_yubikey_wait_fragment.xml index c7f9821eb..4e4b53118 100644 --- a/OpenKeychain/src/main/res/layout/create_yubikey_wait_fragment.xml +++ b/OpenKeychain/src/main/res/layout/create_yubikey_wait_fragment.xml @@ -22,8 +22,7 @@ android:layout_marginTop="16dp" android:layout_marginLeft="8dp" android:textAppearance="?android:attr/textAppearanceMedium" - android:text="Hold Yubikey against device dawg" - /> + android:text="@string/yubikey_create" /> "Identities" - "Yubikey" + "YubiKey" "Linked System Contact" "Should you trust this key?" Proof verification @@ -1280,11 +1280,12 @@ "Serial No: %s" "Key holder: " "Key holder: <unset>" - "Yubikey matches and is bound to key" - "Yubikey matches, can be bound to key" - "Yubikey matches, partly bound to key" + "YubiKey matches and is bound to key" + "YubiKey matches, can be bound to key" + "YubiKey matches, partly bound to key" + "Hold YubiKey against the back of your device." "Import" - Different key stored on Yubikey! + Different key stored on YubiKey! "NFC Error: %s" Default PIN was rejected! -- cgit v1.2.3 From 971ceb07d4fd8cba92a1ec32cc2a163cf11c3559 Mon Sep 17 00:00:00 2001 From: William Faulk Date: Sun, 3 May 2015 14:06:01 -0700 Subject: updated robolectric to support new android support libs --- OpenKeychain-Test/build.gradle | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/OpenKeychain-Test/build.gradle b/OpenKeychain-Test/build.gradle index 1c87fcb4d..2bf35b3d1 100644 --- a/OpenKeychain-Test/build.gradle +++ b/OpenKeychain-Test/build.gradle @@ -17,7 +17,8 @@ dependencies { testCompile 'junit:junit:4.11' testCompile 'com.google.android:android:4.1.1.4' testCompile('com.squareup:fest-android:1.0.8') { exclude module: 'support-v4' } - testCompile ('org.robolectric:robolectric:2.3') { + testCompile 'org.apache.maven:maven-ant-tasks:2.1.3' + testCompile ('org.robolectric:robolectric:2.4') { exclude module: 'classworlds' exclude module: 'maven-artifact' exclude module: 'maven-artifact-manager' -- cgit v1.2.3 From 4e425495e6d69cbe54840f926e659eb12e79eefe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Mon, 4 May 2015 13:57:43 +0200 Subject: Apply patch from https://github.com/open-keychain/open-keychain/issues/1240 with db upgrade --- .../provider/TemporaryStorageProvider.java | 30 ++++++++++++++++------ 1 file changed, 22 insertions(+), 8 deletions(-) diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/TemporaryStorageProvider.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/TemporaryStorageProvider.java index a65d222da..6dd4a1633 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/TemporaryStorageProvider.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/provider/TemporaryStorageProvider.java @@ -31,10 +31,12 @@ import android.provider.OpenableColumns; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.util.DatabaseUtil; +import org.sufficientlysecure.keychain.util.Log; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; +import java.util.UUID; public class TemporaryStorageProvider extends ContentProvider { @@ -44,7 +46,7 @@ public class TemporaryStorageProvider extends ContentProvider { private static final String COLUMN_NAME = "name"; private static final String COLUMN_TIME = "time"; private static final Uri BASE_URI = Uri.parse("content://org.sufficientlysecure.keychain.tempstorage/"); - private static final int DB_VERSION = 1; + private static final int DB_VERSION = 2; public static Uri createFile(Context context, String targetName) { ContentValues contentValues = new ContentValues(); @@ -66,7 +68,7 @@ public class TemporaryStorageProvider extends ContentProvider { @Override public void onCreate(SQLiteDatabase db) { db.execSQL("CREATE TABLE IF NOT EXISTS " + TABLE_FILES + " (" + - COLUMN_ID + " INTEGER PRIMARY KEY AUTOINCREMENT, " + + COLUMN_ID + " TEXT PRIMARY KEY, " + COLUMN_NAME + " TEXT, " + COLUMN_TIME + " INTEGER" + ");"); @@ -74,7 +76,17 @@ public class TemporaryStorageProvider extends ContentProvider { @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { - + Log.d(Constants.TAG, "Upgrading files db from " + oldVersion + " to " + newVersion); + + switch (oldVersion) { + case 1: + db.execSQL("DROP TABLE IF EXISTS files"); + db.execSQL("CREATE TABLE IF NOT EXISTS " + TABLE_FILES + " (" + + COLUMN_ID + " TEXT PRIMARY KEY, " + + COLUMN_NAME + " TEXT, " + + COLUMN_TIME + " INTEGER" + + ");"); + } } } @@ -82,13 +94,13 @@ public class TemporaryStorageProvider extends ContentProvider { private File getFile(Uri uri) throws FileNotFoundException { try { - return getFile(Integer.parseInt(uri.getLastPathSegment())); + return getFile(uri.getLastPathSegment()); } catch (NumberFormatException e) { throw new FileNotFoundException(); } } - private File getFile(int id) { + private File getFile(String id) { return new File(getContext().getCacheDir(), "temp/" + id); } @@ -133,13 +145,15 @@ public class TemporaryStorageProvider extends ContentProvider { if (!values.containsKey(COLUMN_TIME)) { values.put(COLUMN_TIME, System.currentTimeMillis()); } + String uuid = UUID.randomUUID().toString(); + values.put(COLUMN_ID, uuid); int insert = (int) db.getWritableDatabase().insert(TABLE_FILES, null, values); try { - getFile(insert).createNewFile(); + getFile(uuid).createNewFile(); } catch (IOException e) { return null; } - return Uri.withAppendedPath(BASE_URI, Long.toString(insert)); + return Uri.withAppendedPath(BASE_URI, uuid); } @Override @@ -152,7 +166,7 @@ public class TemporaryStorageProvider extends ContentProvider { selectionArgs, null, null, null); if (files != null) { while (files.moveToNext()) { - getFile(files.getInt(0)).delete(); + getFile(files.getString(0)).delete(); } files.close(); return db.getWritableDatabase().delete(TABLE_FILES, selection, selectionArgs); -- cgit v1.2.3 From 51bb96742f95b5b3b1ce68aef76fb5b0ddc5575d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Mon, 4 May 2015 14:01:34 +0200 Subject: Apply patch from https://github.com/open-keychain/open-keychain/issues/1222#issuecomment-98582938 --- .../keychain/pgp/PgpSignEncryptOperation.java | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java index 8ecb30cdd..9073e81b9 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptOperation.java @@ -178,13 +178,20 @@ public class PgpSignEncryptOperation extends BaseOperation { case PIN: case PATTERN: case PASSPHRASE: { - if (cryptoInput.getPassphrase() == null) { + Passphrase localPassphrase = cryptoInput.getPassphrase(); + if (localPassphrase == null) { + try { + localPassphrase = getCachedPassphrase(signingKeyRing.getMasterKeyId(), signingKey.getKeyId()); + } catch (PassphraseCacheInterface.NoSecretKeyException ignored) { + } + } + if (localPassphrase == null) { log.add(LogType.MSG_PSE_PENDING_PASSPHRASE, indent + 1); return new PgpSignEncryptResult(log, RequiredInputParcel.createRequiredSignPassphrase( signingKeyRing.getMasterKeyId(), signingKey.getKeyId(), cryptoInput.getSignatureTime())); } - if (!signingKey.unlock(cryptoInput.getPassphrase())) { + if (!signingKey.unlock(localPassphrase)) { log.add(LogType.MSG_PSE_ERROR_BAD_PASSPHRASE, indent); return new PgpSignEncryptResult(PgpSignEncryptResult.RESULT_ERROR, log); } -- cgit v1.2.3 From b726dea244f020660d5260d3211d6500655fe680 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Mon, 4 May 2015 14:12:42 +0200 Subject: license header for PgpCertifyOperation --- .../keychain/pgp/PgpCertifyOperation.java | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpCertifyOperation.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpCertifyOperation.java index 90ec3053f..bf2349734 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpCertifyOperation.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpCertifyOperation.java @@ -1,3 +1,21 @@ +/* + * Copyright (C) 2015 Dominik Schürmann + * Copyright (C) 2015 Vincent Breitmoser + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + package org.sufficientlysecure.keychain.pgp; @@ -32,7 +50,7 @@ public class PgpCertifyOperation { OperationLog log, int indent, CertifyAction action, - Map signedHashes, + Map signedHashes, Date creationTimestamp) { if (!secretKey.isMasterKey()) { -- cgit v1.2.3 From dedda1603c73b66276931dacf8a7c5d1798db4a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Mon, 4 May 2015 14:19:16 +0200 Subject: Fix dublicated code in CreateKeyEmailFragment --- .../org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java index f338a53a6..552fe6954 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java @@ -133,10 +133,6 @@ public class CreateKeyEmailFragment extends Fragment { addEmail(); } }); - - if (mCreateKeyActivity.mAdditionalEmails != null) { - mEmailAdapter.addAll(mCreateKeyActivity.mAdditionalEmails); - } } if (mAdditionalEmailModels.isEmpty() && mCreateKeyActivity.mAdditionalEmails != null) { mEmailAdapter.addAll(mCreateKeyActivity.mAdditionalEmails); -- cgit v1.2.3 From eb9019c78ce3ec19d5faed1c48734e3eb1bde043 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Mon, 4 May 2015 14:29:47 +0200 Subject: Temporary fix for gradle dependency bug --- OpenKeychain/build.gradle | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/OpenKeychain/build.gradle b/OpenKeychain/build.gradle index 14d82ec46..2a0779125 100644 --- a/OpenKeychain/build.gradle +++ b/OpenKeychain/build.gradle @@ -17,6 +17,12 @@ dependencies { androidTestCompile 'com.android.support.test.espresso:espresso-core:2.1' androidTestCompile 'com.android.support.test.espresso:espresso-contrib:2.1' + // Temporary workaround for bug: https://code.google.com/p/android-test-kit/issues/detail?id=136 + // from https://github.com/googlesamples/android-testing/blob/master/build.gradle#L21 + configurations.all { + resolutionStrategy.force 'com.android.support:support-annotations:22.1.1' + } + // JCenter etc. compile 'com.eftimoff:android-patternview:1.0.1@aar' compile 'com.journeyapps:zxing-android-embedded:2.3.0@aar' -- cgit v1.2.3 From e1ca612bc43475e8a0d6a289c978d226a9ab78c0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Mon, 4 May 2015 14:55:56 +0200 Subject: Use more simple email validation regex --- .../keychain/ui/CreateKeyEmailFragment.java | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java index aeae8a1ad..0a9ddf382 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java @@ -26,7 +26,6 @@ import android.support.v4.app.Fragment; import android.support.v7.widget.DefaultItemAnimator; import android.support.v7.widget.LinearLayoutManager; import android.support.v7.widget.RecyclerView; -import android.util.Patterns; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -52,6 +51,10 @@ public class CreateKeyEmailFragment extends Fragment { private ArrayList mAdditionalEmailModels; private EmailAdapter mEmailAdapter; + // NOTE: Do not use more complicated pattern like defined in android.util.Patterns.EMAIL_ADDRESS + // EMAIL_ADDRESS fails for mails with umlauts for example + private static final Pattern EMAIL_PATTERN = Pattern.compile(".[\\S]+@.[\\S]+\\.[a-z]+"); + /** * Creates new instance of this fragment */ @@ -146,7 +149,7 @@ public class CreateKeyEmailFragment extends Fragment { * @return */ private boolean checkEmail(String email, boolean additionalEmail) { - //check for email format or if the user did any input + // check for email format or if the user did any input if (!isEmailFormatValid(email)) { Notify.create(getActivity(), getString(R.string.create_key_email_invalid_email), @@ -154,7 +157,7 @@ public class CreateKeyEmailFragment extends Fragment { return false; } - //check for duplicated emails + // check for duplicated emails if (!additionalEmail && isEmailDuplicatedInsideAdapter(email) || additionalEmail && mEmailEdit.getText().length() > 0 && email.equals(mEmailEdit.getText().toString())) { Notify.create(getActivity(), @@ -174,10 +177,8 @@ public class CreateKeyEmailFragment extends Fragment { * @return */ private boolean isEmailFormatValid(String email) { - Pattern emailPattern = Patterns.EMAIL_ADDRESS; - - //check for email format or if the user did any input - return !(email.length() == 0 || !emailPattern.matcher(email).matches()); + // check for email format or if the user did any input + return !(email.length() == 0 || !EMAIL_PATTERN.matcher(email).matches()); } /** -- cgit v1.2.3 From 2cd1cf9192aee76a0f2481281148783519d208a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Mon, 4 May 2015 15:27:19 +0200 Subject: Fix email pattern --- .../java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java index 0a9ddf382..64dc71785 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java @@ -53,7 +53,7 @@ public class CreateKeyEmailFragment extends Fragment { // NOTE: Do not use more complicated pattern like defined in android.util.Patterns.EMAIL_ADDRESS // EMAIL_ADDRESS fails for mails with umlauts for example - private static final Pattern EMAIL_PATTERN = Pattern.compile(".[\\S]+@.[\\S]+\\.[a-z]+"); + private static final Pattern EMAIL_PATTERN = Pattern.compile("^[\\S]+@[\\S]+\\.[a-z]+$"); /** * Creates new instance of this fragment -- cgit v1.2.3 From f3090f2939ede5db92afbd5fd52e9a509556a15f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Mon, 4 May 2015 15:34:48 +0200 Subject: Display notify above keyboard in CreateKeyEmailFragment --- .../org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java index 64dc71785..dbff4fb9f 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyEmailFragment.java @@ -153,7 +153,7 @@ public class CreateKeyEmailFragment extends Fragment { if (!isEmailFormatValid(email)) { Notify.create(getActivity(), getString(R.string.create_key_email_invalid_email), - Notify.LENGTH_LONG, Notify.Style.ERROR).show(); + Notify.LENGTH_LONG, Notify.Style.ERROR).show(CreateKeyEmailFragment.this); return false; } @@ -162,7 +162,7 @@ public class CreateKeyEmailFragment extends Fragment { mEmailEdit.getText().length() > 0 && email.equals(mEmailEdit.getText().toString())) { Notify.create(getActivity(), getString(R.string.create_key_email_already_exists_text), - Notify.LENGTH_LONG, Notify.Style.ERROR).show(); + Notify.LENGTH_LONG, Notify.Style.ERROR).show(CreateKeyEmailFragment.this); return false; } -- cgit v1.2.3 From 2583f77f07708b388043991c0dd6c9ef1d14f523 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Mon, 4 May 2015 20:47:19 +0200 Subject: Fix cancel/skip in create key wizard --- .../keychain/ui/CreateKeyActivity.java | 2 +- .../keychain/ui/CreateKeyStartFragment.java | 83 +++++++++------------- .../keychain/ui/CreateKeyYubiKeyWaitFragment.java | 58 +++++++++++++++ .../keychain/ui/CreateKeyYubiWaitFragment.java | 58 --------------- 4 files changed, 92 insertions(+), 109 deletions(-) create mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyYubiKeyWaitFragment.java delete mode 100644 OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyYubiWaitFragment.java diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyActivity.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyActivity.java index 0b203614b..dfb94ebb9 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyActivity.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyActivity.java @@ -99,7 +99,7 @@ public class CreateKeyActivity extends BaseNfcActivity { if (mFirstTime) { setTitle(R.string.app_name); - setActionBarIcon(R.drawable.ic_launcher); + mToolbar.setNavigationIcon(null); mToolbar.setNavigationOnClickListener(null); } else { setTitle(R.string.title_manage_my_keys); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyStartFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyStartFragment.java index 3f56949f5..1a844e6e4 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyStartFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyStartFragment.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 Dominik Schürmann + * Copyright (C) 2014-2015 Dominik Schürmann * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -18,37 +18,20 @@ package org.sufficientlysecure.keychain.ui; import android.app.Activity; -import android.content.Context; import android.content.Intent; import android.os.Bundle; -import android.os.Handler; -import android.os.Message; -import android.os.Messenger; import android.support.v4.app.Fragment; -import android.support.v7.widget.DefaultItemAnimator; -import android.support.v7.widget.LinearLayoutManager; -import android.support.v7.widget.RecyclerView; -import android.view.KeyEvent; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; -import android.widget.Button; -import android.widget.EditText; -import android.widget.ImageButton; import android.widget.TextView; import org.sufficientlysecure.keychain.Constants; import org.sufficientlysecure.keychain.R; import org.sufficientlysecure.keychain.ui.CreateKeyActivity.FragAction; -import org.sufficientlysecure.keychain.ui.dialog.AddEmailDialogFragment; -import org.sufficientlysecure.keychain.ui.dialog.SetPassphraseDialogFragment; -import org.sufficientlysecure.keychain.ui.widget.EmailEditText; import org.sufficientlysecure.keychain.util.Log; import org.sufficientlysecure.keychain.util.Preferences; -import java.util.ArrayList; -import java.util.List; - public class CreateKeyStartFragment extends Fragment { CreateKeyActivity mCreateKeyActivity; @@ -56,8 +39,8 @@ public class CreateKeyStartFragment extends Fragment { View mCreateKey; View mImportKey; View mYubiKey; - TextView mCancel; - public static final int REQUEST_CODE_CREATE_OR_IMPORT_KEY = 0x00007012; + TextView mSkipOrCancel; + public static final int REQUEST_CODE_IMPORT_KEY = 0x00007012; /** * Creates new instance of this fragment @@ -79,12 +62,12 @@ public class CreateKeyStartFragment extends Fragment { mCreateKey = view.findViewById(R.id.create_key_create_key_button); mImportKey = view.findViewById(R.id.create_key_import_button); mYubiKey = view.findViewById(R.id.create_key_yubikey_button); - mCancel = (TextView) view.findViewById(R.id.create_key_cancel); + mSkipOrCancel = (TextView) view.findViewById(R.id.create_key_cancel); if (mCreateKeyActivity.mFirstTime) { - mCancel.setText(R.string.first_time_skip); + mSkipOrCancel.setText(R.string.first_time_skip); } else { - mCancel.setText(R.string.btn_do_not_save); + mSkipOrCancel.setText(R.string.btn_do_not_save); } mCreateKey.setOnClickListener(new View.OnClickListener() { @@ -98,7 +81,7 @@ public class CreateKeyStartFragment extends Fragment { mYubiKey.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - CreateKeyYubiWaitFragment frag = new CreateKeyYubiWaitFragment(); + CreateKeyYubiKeyWaitFragment frag = new CreateKeyYubiKeyWaitFragment(); mCreateKeyActivity.loadFragment(frag, FragAction.TO_RIGHT); } }); @@ -108,48 +91,48 @@ public class CreateKeyStartFragment extends Fragment { public void onClick(View v) { Intent intent = new Intent(mCreateKeyActivity, ImportKeysActivity.class); intent.setAction(ImportKeysActivity.ACTION_IMPORT_KEY_FROM_FILE_AND_RETURN); - startActivityForResult(intent, REQUEST_CODE_CREATE_OR_IMPORT_KEY); + startActivityForResult(intent, REQUEST_CODE_IMPORT_KEY); } }); - mCancel.setOnClickListener(new View.OnClickListener() { + mSkipOrCancel.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - finishSetup(null); + if (mCreateKeyActivity.mFirstTime) { + Preferences prefs = Preferences.getPreferences(mCreateKeyActivity); + prefs.setFirstTime(false); + Intent intent = new Intent(mCreateKeyActivity, MainActivity.class); + startActivity(intent); + mCreateKeyActivity.finish(); + } else { + // just finish activity and return data + mCreateKeyActivity.setResult(Activity.RESULT_CANCELED); + mCreateKeyActivity.finish(); + } } }); return view; } - - private void finishSetup(Intent srcData) { - if (mCreateKeyActivity.mFirstTime) { - Preferences prefs = Preferences.getPreferences(mCreateKeyActivity); - prefs.setFirstTime(false); - } - Intent intent = new Intent(mCreateKeyActivity, MainActivity.class); - // give intent through to display notify - if (srcData != null) { - intent.putExtras(srcData); - } - startActivity(intent); - mCreateKeyActivity.finish(); - } - - // workaround for https://code.google.com/p/android/issues/detail?id=61394 -// @Override -// public boolean onKeyDown(int keyCode, KeyEvent event) { -// return keyCode == KeyEvent.KEYCODE_MENU || super.onKeyDown(keyCode, event); -// } - @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); - if (requestCode == REQUEST_CODE_CREATE_OR_IMPORT_KEY) { + if (requestCode == REQUEST_CODE_IMPORT_KEY) { if (resultCode == Activity.RESULT_OK) { - finishSetup(data); + if (mCreateKeyActivity.mFirstTime) { + Preferences prefs = Preferences.getPreferences(mCreateKeyActivity); + prefs.setFirstTime(false); + Intent intent = new Intent(mCreateKeyActivity, MainActivity.class); + intent.putExtras(data); + startActivity(intent); + mCreateKeyActivity.finish(); + } else { + // just finish activity and return data + mCreateKeyActivity.setResult(Activity.RESULT_OK, data); + mCreateKeyActivity.finish(); + } } } else { Log.e(Constants.TAG, "No valid request code!"); diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyYubiKeyWaitFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyYubiKeyWaitFragment.java new file mode 100644 index 000000000..0b8586c0a --- /dev/null +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyYubiKeyWaitFragment.java @@ -0,0 +1,58 @@ +/* + * Copyright (C) 2014 Dominik Schürmann + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +package org.sufficientlysecure.keychain.ui; + +import android.app.Activity; +import android.os.Bundle; +import android.support.v4.app.Fragment; +import android.view.LayoutInflater; +import android.view.View; +import android.view.ViewGroup; + +import org.sufficientlysecure.keychain.R; +import org.sufficientlysecure.keychain.ui.CreateKeyActivity.FragAction; + + +public class CreateKeyYubiKeyWaitFragment extends Fragment { + + CreateKeyActivity mCreateKeyActivity; + View mBackButton; + + @Override + public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { + View view = inflater.inflate(R.layout.create_yubikey_wait_fragment, container, false); + + mBackButton = view.findViewById(R.id.create_key_back_button); + + mBackButton.setOnClickListener(new View.OnClickListener() { + @Override + public void onClick(View v) { + mCreateKeyActivity.loadFragment(null, FragAction.TO_LEFT); + } + }); + + return view; + } + + @Override + public void onAttach(Activity activity) { + super.onAttach(activity); + mCreateKeyActivity = (CreateKeyActivity) getActivity(); + } + +} diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyYubiWaitFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyYubiWaitFragment.java deleted file mode 100644 index 579dddf79..000000000 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CreateKeyYubiWaitFragment.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright (C) 2014 Dominik Schürmann - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -package org.sufficientlysecure.keychain.ui; - -import android.app.Activity; -import android.os.Bundle; -import android.support.v4.app.Fragment; -import android.view.LayoutInflater; -import android.view.View; -import android.view.ViewGroup; - -import org.sufficientlysecure.keychain.R; -import org.sufficientlysecure.keychain.ui.CreateKeyActivity.FragAction; - - -public class CreateKeyYubiWaitFragment extends Fragment { - - CreateKeyActivity mCreateKeyActivity; - View mBackButton; - - @Override - public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - View view = inflater.inflate(R.layout.create_yubikey_wait_fragment, container, false); - - mBackButton = view.findViewById(R.id.create_key_back_button); - - mBackButton.setOnClickListener(new View.OnClickListener() { - @Override - public void onClick(View v) { - mCreateKeyActivity.loadFragment(null, FragAction.TO_LEFT); - } - }); - - return view; - } - - @Override - public void onAttach(Activity activity) { - super.onAttach(activity); - mCreateKeyActivity = (CreateKeyActivity) getActivity(); - } - -} -- cgit v1.2.3 From 291f95db5ad2028ef252448e47b4ad22a297bf33 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Dominik=20Sch=C3=BCrmann?= Date: Mon, 4 May 2015 21:13:07 +0200 Subject: Fix revoked/expired state in decrypt activity --- .../keychain/ui/DecryptFilesFragment.java | 2 +- .../keychain/ui/DecryptFragment.java | 26 ++++++------------- .../keychain/ui/DecryptTextFragment.java | 30 +++++++++++----------- .../src/main/res/layout/decrypt_text_fragment.xml | 6 ++--- 4 files changed, 27 insertions(+), 37 deletions(-) diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesFragment.java index 6c1902af1..e5ddcbbd6 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFilesFragment.java @@ -309,7 +309,7 @@ public class DecryptFilesFragment extends DecryptFragment { } @Override - protected void onVerifyLoaded(boolean verified) { + protected void onVerifyLoaded(boolean hideErrorOverlay) { } } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java index 9c51893ce..230f478ae 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptFragment.java @@ -55,7 +55,6 @@ import org.sufficientlysecure.keychain.ui.util.Notify; import org.sufficientlysecure.keychain.ui.util.Notify.Style; import org.sufficientlysecure.keychain.util.Preferences; - public abstract class DecryptFragment extends CryptoOperationFragment implements LoaderManager.LoaderCallbacks { @@ -91,7 +90,6 @@ public abstract class DecryptFragment extends CryptoOperationFragment implements mSignatureName = (TextView) getActivity().findViewById(R.id.result_signature_name); mSignatureEmail = (TextView) getActivity().findViewById(R.id.result_signature_email); mSignatureAction = (TextView) getActivity().findViewById(R.id.result_signature_action); - } private void lookupUnknownKey(long unknownKeyId) { @@ -113,12 +111,9 @@ public abstract class DecryptFragment extends CryptoOperationFragment implements final ImportKeyResult result = returnData.getParcelable(OperationResult.EXTRA_RESULT); - // if (!result.success()) { - result.createNotify(getActivity()).show(); - // } + result.createNotify(getActivity()).show(); getLoaderManager().restartLoader(LOADER_ID_UNIFIED, null, DecryptFragment.this); - } } }; @@ -153,7 +148,6 @@ public abstract class DecryptFragment extends CryptoOperationFragment implements intent.putExtra(KeychainIntentService.EXTRA_MESSENGER, messenger); getActivity().startService(intent); - } private void showKey(long keyId) { @@ -205,7 +199,6 @@ public abstract class DecryptFragment extends CryptoOperationFragment implements } getLoaderManager().restartLoader(LOADER_ID_UNIFIED, null, this); - } private void setSignatureLayoutVisibility(int visibility) { @@ -228,8 +221,6 @@ public abstract class DecryptFragment extends CryptoOperationFragment implements KeychainContract.KeyRings._ID, KeychainContract.KeyRings.MASTER_KEY_ID, KeychainContract.KeyRings.USER_ID, - KeychainContract.KeyRings.IS_REVOKED, - KeychainContract.KeyRings.IS_EXPIRED, KeychainContract.KeyRings.VERIFIED, KeychainContract.KeyRings.HAS_ANY_SECRET, }; @@ -237,10 +228,8 @@ public abstract class DecryptFragment extends CryptoOperationFragment implements @SuppressWarnings("unused") static final int INDEX_MASTER_KEY_ID = 1; static final int INDEX_USER_ID = 2; - static final int INDEX_IS_REVOKED = 3; - static final int INDEX_IS_EXPIRED = 4; - static final int INDEX_VERIFIED = 5; - static final int INDEX_HAS_ANY_SECRET = 6; + static final int INDEX_VERIFIED = 3; + static final int INDEX_HAS_ANY_SECRET = 4; @Override public Loader onCreateLoader(int id, Bundle args) { @@ -282,8 +271,10 @@ public abstract class DecryptFragment extends CryptoOperationFragment implements getActivity(), mSignatureResult.getKeyId())); } - boolean isRevoked = data.getInt(INDEX_IS_REVOKED) != 0; - boolean isExpired = data.getInt(INDEX_IS_EXPIRED) != 0; + // NOTE: Don't use revoked and expired fields from database, they don't show + // revoked/expired subkeys + boolean isRevoked = mSignatureResult.getStatus() == OpenPgpSignatureResult.SIGNATURE_KEY_REVOKED; + boolean isExpired = mSignatureResult.getStatus() == OpenPgpSignatureResult.SIGNATURE_KEY_EXPIRED; boolean isVerified = data.getInt(INDEX_VERIFIED) > 0; boolean isYours = data.getInt(INDEX_HAS_ANY_SECRET) != 0; @@ -344,7 +335,6 @@ public abstract class DecryptFragment extends CryptoOperationFragment implements } setSignatureLayoutVisibility(View.GONE); - } private void showUnknownKeyStatus() { @@ -407,6 +397,6 @@ public abstract class DecryptFragment extends CryptoOperationFragment implements } - protected abstract void onVerifyLoaded(boolean verified); + protected abstract void onVerifyLoaded(boolean hideErrorOverlay); } diff --git a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextFragment.java b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextFragment.java index 6f576a112..b8f1aee63 100644 --- a/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextFragment.java +++ b/OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/DecryptTextFragment.java @@ -50,8 +50,8 @@ public class DecryptTextFragment extends DecryptFragment { public static final String ARG_CIPHERTEXT = "ciphertext"; // view - private LinearLayout mValidLayout; - private LinearLayout mInvalidLayout; + private LinearLayout mContentLayout; + private LinearLayout mErrorOverlayLayout; private TextView mText; // model @@ -78,16 +78,16 @@ public class DecryptTextFragment extends DecryptFragment { @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { View view = inflater.inflate(R.layout.decrypt_text_fragment, container, false); - mValidLayout = (LinearLayout) view.findViewById(R.id.decrypt_text_valid); - mInvalidLayout = (LinearLayout) view.findViewById(R.id.decrypt_text_invalid); + mContentLayout = (LinearLayout) view.findViewById(R.id.decrypt_content); + mErrorOverlayLayout = (LinearLayout) view.findViewById(R.id.decrypt_error_overlay); mText = (TextView) view.findViewById(R.id.decrypt_text_plaintext); - Button vInvalidButton = (Button) view.findViewById(R.id.decrypt_text_invalid_button); - vInvalidButton.setOnClickListener(new View.OnClickListener() { + Button vErrorOverlayButton = (Button) view.findViewById(R.id.decrypt_error_overlay_button); + vErrorOverlayButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { - mInvalidLayout.setVisibility(View.GONE); - mValidLayout.setVisibility(View.VISIBLE); + mErrorOverlayLayout.setVisibility(View.GONE); + mContentLayout.setVisibility(View.VISIBLE); } }); @@ -244,17 +244,17 @@ public class DecryptTextFragment extends DecryptFragment { } @Override - protected void onVerifyLoaded(boolean verified) { + protected void onVerifyLoaded(boolean hideErrorOverlay) { - mShowMenuOptions = verified; + mShowMenuOptions = hideErrorOverlay; getActivity().supportInvalidateOptionsMenu(); - if (verified) { - mInvalidLayout.setVisibility(View.GONE); - mValidLayout.setVisibility(View.VISIBLE); + if (hideErrorOverlay) { + mErrorOverlayLayout.setVisibility(View.GONE); + mContentLayout.setVisibility(View.VISIBLE); } else { - mInvalidLayout.setVisibility(View.VISIBLE); - mValidLayout.setVisibility(View.GONE); + mErrorOverlayLayout.setVisibility(View.VISIBLE); + mContentLayout.setVisibility(View.GONE); } } diff --git a/OpenKeychain/src/main/res/layout/decrypt_text_fragment.xml b/OpenKeychain/src/main/res/layout/decrypt_text_fragment.xml index 5b74905e7..ea6be462f 100644 --- a/OpenKeychain/src/main/res/layout/decrypt_text_fragment.xml +++ b/OpenKeychain/src/main/res/layout/decrypt_text_fragment.xml @@ -6,7 +6,7 @@ @@ -36,7 +36,7 @@