Merge remote-tracking branch 'origin/development' into development
Conflicts: OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/CertifyOperation.java OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/EditKeyOperation.java OpenKeychain/src/main/java/org/sufficientlysecure/keychain/operations/results/PgpSignEncryptResult.java OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/CanonicalizedSecretKey.java OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpKeyOperation.java OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/PgpSignEncryptInputParcel.java OpenKeychain/src/main/java/org/sufficientlysecure/keychain/pgp/SignEncryptParcel.java OpenKeychain/src/main/java/org/sufficientlysecure/keychain/service/KeychainIntentService.java OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/CertifyKeyFragment.java OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EditKeyFragment.java OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/EncryptActivity.java OpenKeychain/src/main/java/org/sufficientlysecure/keychain/ui/dialog/SetPassphraseDialogFragment.java
This commit is contained in:
@@ -62,6 +62,7 @@ import org.sufficientlysecure.keychain.ui.util.Notify;
|
||||
import org.sufficientlysecure.keychain.ui.widget.CertifyKeySpinner;
|
||||
import org.sufficientlysecure.keychain.ui.widget.KeySpinner;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
import org.sufficientlysecure.keychain.util.Passphrase;
|
||||
import org.sufficientlysecure.keychain.util.Preferences;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
@@ -20,31 +20,74 @@ package org.sufficientlysecure.keychain.ui;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentTransaction;
|
||||
import android.view.View;
|
||||
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.util.Passphrase;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public class CreateKeyActivity extends BaseActivity {
|
||||
|
||||
public static final String EXTRA_NAME = "name";
|
||||
public static final String EXTRA_EMAIL = "email";
|
||||
public static final String EXTRA_FIRST_TIME = "first_time";
|
||||
public static final String EXTRA_ADDITIONAL_EMAILS = "additional_emails";
|
||||
public static final String EXTRA_PASSPHRASE = "passphrase";
|
||||
|
||||
public static enum FragAction {
|
||||
START,
|
||||
TO_RIGHT,
|
||||
TO_LEFT
|
||||
}
|
||||
public static final String FRAGMENT_TAG = "currentFragment";
|
||||
|
||||
String mName;
|
||||
String mEmail;
|
||||
ArrayList<String> mAdditionalEmails;
|
||||
Passphrase mPassphrase;
|
||||
boolean mFirstTime;
|
||||
|
||||
Fragment mCurrentFragment;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
// pass extras into fragment
|
||||
CreateKeyNameFragment frag =
|
||||
CreateKeyNameFragment.newInstance(
|
||||
getIntent().getStringExtra(EXTRA_NAME),
|
||||
getIntent().getStringExtra(EXTRA_EMAIL)
|
||||
);
|
||||
loadFragment(null, frag, FragAction.START);
|
||||
// Check whether we're recreating a previously destroyed instance
|
||||
if (savedInstanceState != null) {
|
||||
// Restore value of members from saved state
|
||||
mName = savedInstanceState.getString(EXTRA_NAME);
|
||||
mEmail = savedInstanceState.getString(EXTRA_EMAIL);
|
||||
mAdditionalEmails = savedInstanceState.getStringArrayList(EXTRA_ADDITIONAL_EMAILS);
|
||||
mPassphrase = savedInstanceState.getParcelable(EXTRA_PASSPHRASE);
|
||||
mFirstTime = savedInstanceState.getBoolean(EXTRA_FIRST_TIME);
|
||||
|
||||
mCurrentFragment = getSupportFragmentManager().findFragmentByTag(FRAGMENT_TAG);
|
||||
} else {
|
||||
// Initialize members with default values for a new instance
|
||||
mName = getIntent().getStringExtra(EXTRA_NAME);
|
||||
mEmail = getIntent().getStringExtra(EXTRA_EMAIL);
|
||||
mFirstTime = getIntent().getBooleanExtra(EXTRA_FIRST_TIME, false);
|
||||
|
||||
// Start with first fragment of wizard
|
||||
CreateKeyStartFragment frag = CreateKeyStartFragment.newInstance();
|
||||
loadFragment(frag, FragAction.START);
|
||||
}
|
||||
|
||||
if (mFirstTime) {
|
||||
setTitle(R.string.app_name);
|
||||
setActionBarIcon(R.drawable.ic_launcher);
|
||||
mToolbar.setNavigationOnClickListener(null);
|
||||
} else {
|
||||
setTitle(R.string.title_manage_my_keys);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
|
||||
outState.putString(EXTRA_NAME, mName);
|
||||
outState.putString(EXTRA_EMAIL, mEmail);
|
||||
outState.putStringArrayList(EXTRA_ADDITIONAL_EMAILS, mAdditionalEmails);
|
||||
outState.putParcelable(EXTRA_PASSPHRASE, mPassphrase);
|
||||
outState.putBoolean(EXTRA_FIRST_TIME, mFirstTime);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -52,23 +95,23 @@ public class CreateKeyActivity extends BaseActivity {
|
||||
setContentView(R.layout.create_key_activity);
|
||||
}
|
||||
|
||||
public void loadFragment(Bundle savedInstanceState, Fragment fragment, FragAction action) {
|
||||
// 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;
|
||||
}
|
||||
public static enum FragAction {
|
||||
START,
|
||||
TO_RIGHT,
|
||||
TO_LEFT
|
||||
}
|
||||
|
||||
public void loadFragment(Fragment fragment, FragAction action) {
|
||||
mCurrentFragment = fragment;
|
||||
|
||||
// Add the fragment to the 'fragment_container' FrameLayout
|
||||
// NOTE: We use commitAllowingStateLoss() to prevent weird crashes!
|
||||
FragmentTransaction transaction = getSupportFragmentManager().beginTransaction();
|
||||
|
||||
switch (action) {
|
||||
case START:
|
||||
transaction.setCustomAnimations(0, 0);
|
||||
transaction.replace(R.id.create_key_fragment_container, fragment)
|
||||
.commitAllowingStateLoss();
|
||||
transaction.replace(R.id.create_key_fragment_container, fragment, FRAGMENT_TAG)
|
||||
.commit();
|
||||
break;
|
||||
case TO_LEFT:
|
||||
getSupportFragmentManager().popBackStackImmediate();
|
||||
@@ -77,8 +120,8 @@ public class CreateKeyActivity extends BaseActivity {
|
||||
transaction.setCustomAnimations(R.anim.frag_slide_in_from_right, R.anim.frag_slide_out_to_left,
|
||||
R.anim.frag_slide_in_from_left, R.anim.frag_slide_out_to_right);
|
||||
transaction.addToBackStack(null);
|
||||
transaction.replace(R.id.create_key_fragment_container, fragment)
|
||||
.commitAllowingStateLoss();
|
||||
transaction.replace(R.id.create_key_fragment_container, fragment, FRAGMENT_TAG)
|
||||
.commit();
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
@@ -46,16 +46,12 @@ import java.util.List;
|
||||
|
||||
public class CreateKeyEmailFragment extends Fragment {
|
||||
|
||||
public static final String ARG_NAME = "name";
|
||||
public static final String ARG_EMAIL = "email";
|
||||
|
||||
CreateKeyActivity mCreateKeyActivity;
|
||||
EmailEditText mEmailEdit;
|
||||
RecyclerView mEmailsRecyclerView;
|
||||
View mBackButton;
|
||||
View mNextButton;
|
||||
|
||||
String mName;
|
||||
ArrayList<EmailAdapter.ViewModel> mAdditionalEmailModels;
|
||||
|
||||
EmailAdapter mEmailAdapter;
|
||||
@@ -63,13 +59,10 @@ public class CreateKeyEmailFragment extends Fragment {
|
||||
/**
|
||||
* Creates new instance of this fragment
|
||||
*/
|
||||
public static CreateKeyEmailFragment newInstance(String name, String email) {
|
||||
public static CreateKeyEmailFragment newInstance() {
|
||||
CreateKeyEmailFragment frag = new CreateKeyEmailFragment();
|
||||
|
||||
Bundle args = new Bundle();
|
||||
args.putString(ARG_NAME, name);
|
||||
args.putString(ARG_EMAIL, email);
|
||||
|
||||
frag.setArguments(args);
|
||||
|
||||
return frag;
|
||||
@@ -85,7 +78,7 @@ public class CreateKeyEmailFragment extends Fragment {
|
||||
*/
|
||||
private static boolean isEditTextNotEmpty(Context context, EditText editText) {
|
||||
boolean output = true;
|
||||
if (editText.getText().toString().length() == 0) {
|
||||
if (editText.getText().length() == 0) {
|
||||
editText.setError(context.getString(R.string.create_key_empty));
|
||||
editText.requestFocus();
|
||||
output = false;
|
||||
@@ -106,31 +99,33 @@ public class CreateKeyEmailFragment extends Fragment {
|
||||
mEmailsRecyclerView = (RecyclerView) view.findViewById(R.id.create_key_emails);
|
||||
|
||||
// initial values
|
||||
mName = getArguments().getString(ARG_NAME);
|
||||
String email = getArguments().getString(ARG_EMAIL);
|
||||
mEmailEdit.setText(email);
|
||||
mEmailEdit.setText(mCreateKeyActivity.mEmail);
|
||||
|
||||
// focus empty edit fields
|
||||
if (email == null) {
|
||||
if (mCreateKeyActivity.mEmail == null) {
|
||||
mEmailEdit.requestFocus();
|
||||
}
|
||||
mBackButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
mCreateKeyActivity.loadFragment(null, null, FragAction.TO_LEFT);
|
||||
mCreateKeyActivity.loadFragment(null, FragAction.TO_LEFT);
|
||||
}
|
||||
});
|
||||
mNextButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
createKeyCheck();
|
||||
nextClicked();
|
||||
}
|
||||
});
|
||||
mEmailsRecyclerView.setHasFixedSize(true);
|
||||
mEmailsRecyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
|
||||
mEmailsRecyclerView.setItemAnimator(new DefaultItemAnimator());
|
||||
|
||||
// initial values
|
||||
mAdditionalEmailModels = new ArrayList<>();
|
||||
if (mCreateKeyActivity.mAdditionalEmails != null) {
|
||||
setAdditionalEmails(mCreateKeyActivity.mAdditionalEmails);
|
||||
}
|
||||
mEmailAdapter = new EmailAdapter(mAdditionalEmailModels, new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
@@ -171,25 +166,38 @@ public class CreateKeyEmailFragment extends Fragment {
|
||||
mCreateKeyActivity = (CreateKeyActivity) getActivity();
|
||||
}
|
||||
|
||||
private void createKeyCheck() {
|
||||
private void nextClicked() {
|
||||
if (isEditTextNotEmpty(getActivity(), mEmailEdit)) {
|
||||
// save state
|
||||
mCreateKeyActivity.mEmail = mEmailEdit.getText().toString();
|
||||
mCreateKeyActivity.mAdditionalEmails = getAdditionalEmails();
|
||||
|
||||
ArrayList<String> emails = new ArrayList<>();
|
||||
for (EmailAdapter.ViewModel holder : mAdditionalEmailModels) {
|
||||
emails.add(holder.toString());
|
||||
}
|
||||
|
||||
CreateKeyPassphraseFragment frag =
|
||||
CreateKeyPassphraseFragment.newInstance(
|
||||
mName,
|
||||
mEmailEdit.getText().toString(),
|
||||
emails
|
||||
);
|
||||
|
||||
mCreateKeyActivity.loadFragment(null, frag, FragAction.TO_RIGHT);
|
||||
CreateKeyPassphraseFragment frag = CreateKeyPassphraseFragment.newInstance();
|
||||
mCreateKeyActivity.loadFragment(frag, FragAction.TO_RIGHT);
|
||||
}
|
||||
}
|
||||
|
||||
private ArrayList<String> getAdditionalEmails() {
|
||||
ArrayList<String> emails = new ArrayList<>();
|
||||
for (EmailAdapter.ViewModel holder : mAdditionalEmailModels) {
|
||||
emails.add(holder.toString());
|
||||
}
|
||||
return emails;
|
||||
}
|
||||
|
||||
private void setAdditionalEmails(ArrayList<String> emails) {
|
||||
for (String email : emails) {
|
||||
mAdditionalEmailModels.add(new EmailAdapter.ViewModel(email));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSaveInstanceState(Bundle outState) {
|
||||
super.onSaveInstanceState(outState);
|
||||
// save state in activity
|
||||
mCreateKeyActivity.mAdditionalEmails = getAdditionalEmails();
|
||||
}
|
||||
|
||||
public static class EmailAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
|
||||
private List<ViewModel> mDataset;
|
||||
private View.OnClickListener mFooterOnClickListener;
|
||||
|
||||
@@ -45,6 +45,7 @@ import org.sufficientlysecure.keychain.service.SaveKeyringParcel.Algorithm;
|
||||
import org.sufficientlysecure.keychain.service.SaveKeyringParcel.ChangeUnlockParcel;
|
||||
import org.sufficientlysecure.keychain.ui.CreateKeyActivity.FragAction;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
import org.sufficientlysecure.keychain.util.Passphrase;
|
||||
import org.sufficientlysecure.keychain.util.Preferences;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -64,32 +65,15 @@ public class CreateKeyFinalFragment extends Fragment {
|
||||
TextView mEditText;
|
||||
View mEditButton;
|
||||
|
||||
public static final String ARG_NAME = "name";
|
||||
public static final String ARG_EMAIL = "email";
|
||||
public static final String ARG_ADDITIONAL_EMAILS = "emails";
|
||||
public static final String ARG_PASSPHRASE = "passphrase";
|
||||
|
||||
String mName;
|
||||
String mEmail;
|
||||
ArrayList<String> mAdditionalEmails;
|
||||
String mPassphrase;
|
||||
|
||||
SaveKeyringParcel mSaveKeyringParcel;
|
||||
|
||||
/**
|
||||
* Creates new instance of this fragment
|
||||
*/
|
||||
public static CreateKeyFinalFragment newInstance(String name, String email,
|
||||
ArrayList<String> additionalEmails,
|
||||
String passphrase) {
|
||||
public static CreateKeyFinalFragment newInstance() {
|
||||
CreateKeyFinalFragment frag = new CreateKeyFinalFragment();
|
||||
|
||||
Bundle args = new Bundle();
|
||||
args.putString(ARG_NAME, name);
|
||||
args.putString(ARG_EMAIL, email);
|
||||
args.putStringArrayList(ARG_ADDITIONAL_EMAILS, additionalEmails);
|
||||
args.putString(ARG_PASSPHRASE, passphrase);
|
||||
|
||||
frag.setArguments(args);
|
||||
|
||||
return frag;
|
||||
@@ -107,17 +91,11 @@ public class CreateKeyFinalFragment extends Fragment {
|
||||
mEditText = (TextView) view.findViewById(R.id.create_key_edit_text);
|
||||
mEditButton = view.findViewById(R.id.create_key_edit_button);
|
||||
|
||||
// get args
|
||||
mName = getArguments().getString(ARG_NAME);
|
||||
mEmail = getArguments().getString(ARG_EMAIL);
|
||||
mAdditionalEmails = getArguments().getStringArrayList(ARG_ADDITIONAL_EMAILS);
|
||||
mPassphrase = getArguments().getString(ARG_PASSPHRASE);
|
||||
|
||||
// set values
|
||||
mNameEdit.setText(mName);
|
||||
if (mAdditionalEmails != null && mAdditionalEmails.size() > 0) {
|
||||
String emailText = mEmail + ", ";
|
||||
Iterator<?> it = mAdditionalEmails.iterator();
|
||||
mNameEdit.setText(mCreateKeyActivity.mName);
|
||||
if (mCreateKeyActivity.mAdditionalEmails != null && mCreateKeyActivity.mAdditionalEmails.size() > 0) {
|
||||
String emailText = mCreateKeyActivity.mEmail + ", ";
|
||||
Iterator<?> it = mCreateKeyActivity.mAdditionalEmails.iterator();
|
||||
while (it.hasNext()) {
|
||||
Object next = it.next();
|
||||
emailText += next;
|
||||
@@ -127,7 +105,7 @@ public class CreateKeyFinalFragment extends Fragment {
|
||||
}
|
||||
mEmailEdit.setText(emailText);
|
||||
} else {
|
||||
mEmailEdit.setText(mEmail);
|
||||
mEmailEdit.setText(mCreateKeyActivity.mEmail);
|
||||
}
|
||||
|
||||
mCreateButton.setOnClickListener(new View.OnClickListener() {
|
||||
@@ -140,7 +118,7 @@ public class CreateKeyFinalFragment extends Fragment {
|
||||
mBackButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
mCreateKeyActivity.loadFragment(null, null, FragAction.TO_LEFT);
|
||||
mCreateKeyActivity.loadFragment(null, FragAction.TO_LEFT);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -156,6 +134,12 @@ public class CreateKeyFinalFragment extends Fragment {
|
||||
return view;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(Activity activity) {
|
||||
super.onAttach(activity);
|
||||
mCreateKeyActivity = (CreateKeyActivity) getActivity();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
switch (requestCode) {
|
||||
@@ -186,17 +170,22 @@ public class CreateKeyFinalFragment extends Fragment {
|
||||
Algorithm.RSA, 4096, null, KeyFlags.SIGN_DATA, 0L));
|
||||
mSaveKeyringParcel.mAddSubKeys.add(new SaveKeyringParcel.SubkeyAdd(
|
||||
Algorithm.RSA, 4096, null, KeyFlags.ENCRYPT_COMMS | KeyFlags.ENCRYPT_STORAGE, 0L));
|
||||
String userId = KeyRing.createUserId(new KeyRing.UserId(mName, mEmail, null));
|
||||
String userId = KeyRing.createUserId(
|
||||
new KeyRing.UserId(mCreateKeyActivity.mName, mCreateKeyActivity.mEmail, null)
|
||||
);
|
||||
mSaveKeyringParcel.mAddUserIds.add(userId);
|
||||
mSaveKeyringParcel.mChangePrimaryUserId = userId;
|
||||
if (mAdditionalEmails != null && mAdditionalEmails.size() > 0) {
|
||||
for (String email : mAdditionalEmails) {
|
||||
String thisUserId = KeyRing.createUserId(new KeyRing.UserId(mName, email, null));
|
||||
if (mCreateKeyActivity.mAdditionalEmails != null
|
||||
&& mCreateKeyActivity.mAdditionalEmails.size() > 0) {
|
||||
for (String email : mCreateKeyActivity.mAdditionalEmails) {
|
||||
String thisUserId = KeyRing.createUserId(
|
||||
new KeyRing.UserId(mCreateKeyActivity.mName, email, null)
|
||||
);
|
||||
mSaveKeyringParcel.mAddUserIds.add(thisUserId);
|
||||
}
|
||||
}
|
||||
mSaveKeyringParcel.mNewUnlock = mPassphrase != null
|
||||
? new ChangeUnlockParcel(mPassphrase, null)
|
||||
mSaveKeyringParcel.mNewUnlock = mCreateKeyActivity.mPassphrase != null
|
||||
? new ChangeUnlockParcel(mCreateKeyActivity.mPassphrase, null)
|
||||
: null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,34 +24,26 @@ import android.support.v4.app.Fragment;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
import android.widget.EditText;
|
||||
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.ui.CreateKeyActivity.FragAction;
|
||||
import org.sufficientlysecure.keychain.ui.widget.EmailEditText;
|
||||
import org.sufficientlysecure.keychain.ui.widget.NameEditText;
|
||||
|
||||
public class CreateKeyNameFragment extends Fragment {
|
||||
|
||||
public static final String ARG_NAME = "name";
|
||||
public static final String ARG_EMAIL = "email";
|
||||
|
||||
CreateKeyActivity mCreateKeyActivity;
|
||||
NameEditText mNameEdit;
|
||||
View mBackButton;
|
||||
View mNextButton;
|
||||
|
||||
String mEmail;
|
||||
|
||||
/**
|
||||
* Creates new instance of this fragment
|
||||
*/
|
||||
public static CreateKeyNameFragment newInstance(String name, String email) {
|
||||
public static CreateKeyNameFragment newInstance() {
|
||||
CreateKeyNameFragment frag = new CreateKeyNameFragment();
|
||||
|
||||
Bundle args = new Bundle();
|
||||
args.putString(ARG_NAME, name);
|
||||
args.putString(ARG_EMAIL, email);
|
||||
|
||||
frag.setArguments(args);
|
||||
|
||||
@@ -68,7 +60,7 @@ public class CreateKeyNameFragment extends Fragment {
|
||||
*/
|
||||
private static boolean isEditTextNotEmpty(Context context, EditText editText) {
|
||||
boolean output = true;
|
||||
if (editText.getText().toString().length() == 0) {
|
||||
if (editText.getText().length() == 0) {
|
||||
editText.setError(context.getString(R.string.create_key_empty));
|
||||
editText.requestFocus();
|
||||
output = false;
|
||||
@@ -79,39 +71,31 @@ public class CreateKeyNameFragment extends Fragment {
|
||||
return output;
|
||||
}
|
||||
|
||||
private static boolean areEditTextsEqual(Context context, EditText editText1, EditText editText2) {
|
||||
boolean output = true;
|
||||
if (!editText1.getText().toString().equals(editText2.getText().toString())) {
|
||||
editText2.setError(context.getString(R.string.create_key_passphrases_not_equal));
|
||||
editText2.requestFocus();
|
||||
output = false;
|
||||
} else {
|
||||
editText2.setError(null);
|
||||
}
|
||||
|
||||
return output;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.create_key_name_fragment, container, false);
|
||||
|
||||
mNameEdit = (NameEditText) view.findViewById(R.id.create_key_name);
|
||||
mBackButton = view.findViewById(R.id.create_key_back_button);
|
||||
mNextButton = view.findViewById(R.id.create_key_next_button);
|
||||
|
||||
// initial values
|
||||
String name = getArguments().getString(ARG_NAME);
|
||||
mEmail = getArguments().getString(ARG_EMAIL);
|
||||
mNameEdit.setText(name);
|
||||
mNameEdit.setText(mCreateKeyActivity.mName);
|
||||
|
||||
// focus empty edit fields
|
||||
if (name == null) {
|
||||
if (mCreateKeyActivity.mName == null) {
|
||||
mNameEdit.requestFocus();
|
||||
}
|
||||
mBackButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
mCreateKeyActivity.loadFragment(null, FragAction.TO_LEFT);
|
||||
}
|
||||
});
|
||||
mNextButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
createKeyCheck();
|
||||
nextClicked();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -124,16 +108,13 @@ public class CreateKeyNameFragment extends Fragment {
|
||||
mCreateKeyActivity = (CreateKeyActivity) getActivity();
|
||||
}
|
||||
|
||||
private void createKeyCheck() {
|
||||
private void nextClicked() {
|
||||
if (isEditTextNotEmpty(getActivity(), mNameEdit)) {
|
||||
// save state
|
||||
mCreateKeyActivity.mName = mNameEdit.getText().toString();
|
||||
|
||||
CreateKeyEmailFragment frag =
|
||||
CreateKeyEmailFragment.newInstance(
|
||||
mNameEdit.getText().toString(),
|
||||
mEmail
|
||||
);
|
||||
|
||||
mCreateKeyActivity.loadFragment(null, frag, FragAction.TO_RIGHT);
|
||||
CreateKeyEmailFragment frag = CreateKeyEmailFragment.newInstance();
|
||||
mCreateKeyActivity.loadFragment(frag, FragAction.TO_RIGHT);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,6 +21,7 @@ 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;
|
||||
@@ -34,20 +35,13 @@ import android.widget.EditText;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
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 {
|
||||
|
||||
public static final String ARG_NAME = "name";
|
||||
public static final String ARG_EMAIL = "email";
|
||||
public static final String ARG_ADDITIONAL_EMAILS = "emails";
|
||||
|
||||
// model
|
||||
String mName;
|
||||
String mEmail;
|
||||
ArrayList<String> mAdditionalEmails;
|
||||
|
||||
// view
|
||||
CreateKeyActivity mCreateKeyActivity;
|
||||
PassphraseEditText mPassphraseEdit;
|
||||
@@ -59,15 +53,10 @@ public class CreateKeyPassphraseFragment extends Fragment {
|
||||
/**
|
||||
* Creates new instance of this fragment
|
||||
*/
|
||||
public static CreateKeyPassphraseFragment newInstance(String name, String email,
|
||||
ArrayList<String> additionalEmails) {
|
||||
public static CreateKeyPassphraseFragment newInstance() {
|
||||
CreateKeyPassphraseFragment frag = new CreateKeyPassphraseFragment();
|
||||
|
||||
Bundle args = new Bundle();
|
||||
args.putString(ARG_NAME, name);
|
||||
args.putString(ARG_EMAIL, email);
|
||||
args.putStringArrayList(ARG_ADDITIONAL_EMAILS, additionalEmails);
|
||||
|
||||
frag.setArguments(args);
|
||||
|
||||
return frag;
|
||||
@@ -83,7 +72,7 @@ public class CreateKeyPassphraseFragment extends Fragment {
|
||||
*/
|
||||
private static boolean isEditTextNotEmpty(Context context, EditText editText) {
|
||||
boolean output = true;
|
||||
if (editText.getText().toString().length() == 0) {
|
||||
if (editText.getText().length() == 0) {
|
||||
editText.setError(context.getString(R.string.create_key_empty));
|
||||
editText.requestFocus();
|
||||
output = false;
|
||||
@@ -95,11 +84,13 @@ public class CreateKeyPassphraseFragment extends Fragment {
|
||||
}
|
||||
|
||||
private static boolean areEditTextsEqual(Context context, EditText editText1, EditText editText2) {
|
||||
boolean output = true;
|
||||
if (!editText1.getText().toString().equals(editText2.getText().toString())) {
|
||||
Passphrase p1 = new Passphrase(editText1);
|
||||
Passphrase p2 = new Passphrase(editText2);
|
||||
boolean output = (p1.equals(p2));
|
||||
|
||||
if (!output) {
|
||||
editText2.setError(context.getString(R.string.create_key_passphrases_not_equal));
|
||||
editText2.requestFocus();
|
||||
output = false;
|
||||
} else {
|
||||
editText2.setError(null);
|
||||
}
|
||||
@@ -118,9 +109,12 @@ public class CreateKeyPassphraseFragment extends Fragment {
|
||||
mNextButton = view.findViewById(R.id.create_key_next_button);
|
||||
|
||||
// initial values
|
||||
mName = getArguments().getString(ARG_NAME);
|
||||
mEmail = getArguments().getString(ARG_EMAIL);
|
||||
mAdditionalEmails = getArguments().getStringArrayList(ARG_ADDITIONAL_EMAILS);
|
||||
// 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.requestFocus();
|
||||
mBackButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
@@ -131,7 +125,7 @@ public class CreateKeyPassphraseFragment extends Fragment {
|
||||
mNextButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
createKeyCheck();
|
||||
nextClicked();
|
||||
}
|
||||
});
|
||||
mShowPassphrase.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
|
||||
@@ -159,23 +153,19 @@ public class CreateKeyPassphraseFragment extends Fragment {
|
||||
|
||||
private void back() {
|
||||
hideKeyboard();
|
||||
mCreateKeyActivity.loadFragment(null, null, FragAction.TO_LEFT);
|
||||
mCreateKeyActivity.loadFragment(null, FragAction.TO_LEFT);
|
||||
}
|
||||
|
||||
private void createKeyCheck() {
|
||||
private void nextClicked() {
|
||||
if (isEditTextNotEmpty(getActivity(), mPassphraseEdit)
|
||||
&& areEditTextsEqual(getActivity(), mPassphraseEdit, mPassphraseEditAgain)) {
|
||||
|
||||
CreateKeyFinalFragment frag =
|
||||
CreateKeyFinalFragment.newInstance(
|
||||
mName,
|
||||
mEmail,
|
||||
mAdditionalEmails,
|
||||
mPassphraseEdit.getText().toString()
|
||||
);
|
||||
// save state
|
||||
mCreateKeyActivity.mPassphrase = new Passphrase(mPassphraseEdit);
|
||||
|
||||
CreateKeyFinalFragment frag = CreateKeyFinalFragment.newInstance();
|
||||
hideKeyboard();
|
||||
mCreateKeyActivity.loadFragment(null, frag, FragAction.TO_RIGHT);
|
||||
mCreateKeyActivity.loadFragment(frag, FragAction.TO_RIGHT);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
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;
|
||||
|
||||
View mCreateKey;
|
||||
View mImportKey;
|
||||
View mYubiKey;
|
||||
TextView mCancel;
|
||||
public static final int REQUEST_CODE_CREATE_OR_IMPORT_KEY = 0x00007012;
|
||||
|
||||
/**
|
||||
* Creates new instance of this fragment
|
||||
*/
|
||||
public static CreateKeyStartFragment newInstance() {
|
||||
CreateKeyStartFragment frag = new CreateKeyStartFragment();
|
||||
|
||||
Bundle args = new Bundle();
|
||||
|
||||
frag.setArguments(args);
|
||||
|
||||
return frag;
|
||||
}
|
||||
|
||||
@Override
|
||||
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
|
||||
View view = inflater.inflate(R.layout.create_key_start_fragment, container, false);
|
||||
|
||||
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);
|
||||
|
||||
if (mCreateKeyActivity.mFirstTime) {
|
||||
mCancel.setText(R.string.first_time_skip);
|
||||
} else {
|
||||
mCancel.setText(R.string.btn_do_not_save);
|
||||
}
|
||||
|
||||
mCreateKey.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
CreateKeyNameFragment frag = CreateKeyNameFragment.newInstance();
|
||||
mCreateKeyActivity.loadFragment(frag, FragAction.TO_RIGHT);
|
||||
}
|
||||
});
|
||||
|
||||
mImportKey.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
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);
|
||||
}
|
||||
});
|
||||
|
||||
mCancel.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
finishSetup(null);
|
||||
}
|
||||
});
|
||||
|
||||
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 (resultCode == Activity.RESULT_OK) {
|
||||
finishSetup(data);
|
||||
}
|
||||
} else {
|
||||
Log.e(Constants.TAG, "No valid request code!");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAttach(Activity activity) {
|
||||
super.onAttach(activity);
|
||||
mCreateKeyActivity = (CreateKeyActivity) getActivity();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -191,7 +191,7 @@ public class DecryptFilesFragment extends DecryptFragment {
|
||||
data.putInt(KeychainIntentService.TARGET, IOType.URI.ordinal());
|
||||
data.putParcelable(KeychainIntentService.ENCRYPT_DECRYPT_OUTPUT_URI, mOutputUri);
|
||||
|
||||
data.putString(KeychainIntentService.DECRYPT_PASSPHRASE, mPassphrase);
|
||||
data.putParcelable(KeychainIntentService.DECRYPT_PASSPHRASE, mPassphrase);
|
||||
data.putByteArray(KeychainIntentService.DECRYPT_NFC_DECRYPTED_SESSION_KEY, mNfcDecryptedSessionKey);
|
||||
|
||||
intent.putExtra(KeychainIntentService.EXTRA_DATA, data);
|
||||
@@ -265,7 +265,7 @@ public class DecryptFilesFragment extends DecryptFragment {
|
||||
data.putInt(KeychainIntentService.TARGET, IOType.URI.ordinal());
|
||||
data.putParcelable(KeychainIntentService.ENCRYPT_DECRYPT_OUTPUT_URI, mOutputUri);
|
||||
|
||||
data.putString(KeychainIntentService.DECRYPT_PASSPHRASE, mPassphrase);
|
||||
data.putParcelable(KeychainIntentService.DECRYPT_PASSPHRASE, mPassphrase);
|
||||
data.putByteArray(KeychainIntentService.DECRYPT_NFC_DECRYPTED_SESSION_KEY, mNfcDecryptedSessionKey);
|
||||
|
||||
intent.putExtra(KeychainIntentService.EXTRA_DATA, data);
|
||||
@@ -341,7 +341,7 @@ public class DecryptFilesFragment extends DecryptFragment {
|
||||
switch (requestCode) {
|
||||
case REQUEST_CODE_PASSPHRASE: {
|
||||
if (resultCode == Activity.RESULT_OK && data != null) {
|
||||
mPassphrase = data.getStringExtra(PassphraseDialogActivity.MESSAGE_DATA_PASSPHRASE);
|
||||
mPassphrase = data.getParcelableExtra(PassphraseDialogActivity.MESSAGE_DATA_PASSPHRASE);
|
||||
decryptOriginalFilename();
|
||||
}
|
||||
return;
|
||||
|
||||
@@ -32,6 +32,7 @@ import org.sufficientlysecure.keychain.pgp.KeyRing;
|
||||
import org.sufficientlysecure.keychain.provider.KeychainContract;
|
||||
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
|
||||
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils.State;
|
||||
import org.sufficientlysecure.keychain.util.Passphrase;
|
||||
|
||||
public abstract class DecryptFragment extends Fragment {
|
||||
private static final int RESULT_CODE_LOOKUP_KEY = 0x00007006;
|
||||
@@ -57,7 +58,7 @@ public abstract class DecryptFragment extends Fragment {
|
||||
|
||||
|
||||
// State
|
||||
protected String mPassphrase;
|
||||
protected Passphrase mPassphrase;
|
||||
protected byte[] mNfcDecryptedSessionKey;
|
||||
|
||||
@Override
|
||||
@@ -100,7 +101,7 @@ public abstract class DecryptFragment extends Fragment {
|
||||
startActivityForResult(intent, REQUEST_CODE_PASSPHRASE);
|
||||
}
|
||||
|
||||
protected void startNfcDecrypt(long subKeyId, String pin, byte[] encryptedSessionKey) {
|
||||
protected void startNfcDecrypt(long subKeyId, Passphrase pin, byte[] encryptedSessionKey) {
|
||||
// build PendingIntent for Yubikey NFC operations
|
||||
Intent intent = new Intent(getActivity(), NfcActivity.class);
|
||||
intent.setAction(NfcActivity.ACTION_DECRYPT_SESSION_KEY);
|
||||
|
||||
@@ -161,7 +161,7 @@ public class DecryptTextFragment extends DecryptFragment {
|
||||
// data
|
||||
data.putInt(KeychainIntentService.TARGET, IOType.BYTES.ordinal());
|
||||
data.putByteArray(KeychainIntentService.DECRYPT_CIPHERTEXT_BYTES, mCiphertext.getBytes());
|
||||
data.putString(KeychainIntentService.DECRYPT_PASSPHRASE, mPassphrase);
|
||||
data.putParcelable(KeychainIntentService.DECRYPT_PASSPHRASE, mPassphrase);
|
||||
data.putByteArray(KeychainIntentService.DECRYPT_NFC_DECRYPTED_SESSION_KEY, mNfcDecryptedSessionKey);
|
||||
|
||||
intent.putExtra(KeychainIntentService.EXTRA_DATA, data);
|
||||
@@ -247,7 +247,7 @@ public class DecryptTextFragment extends DecryptFragment {
|
||||
|
||||
case REQUEST_CODE_PASSPHRASE: {
|
||||
if (resultCode == Activity.RESULT_OK && data != null) {
|
||||
mPassphrase = data.getStringExtra(PassphraseDialogActivity.MESSAGE_DATA_PASSPHRASE);
|
||||
mPassphrase = data.getParcelableExtra(PassphraseDialogActivity.MESSAGE_DATA_PASSPHRASE);
|
||||
decryptStart();
|
||||
} else {
|
||||
getActivity().finish();
|
||||
|
||||
@@ -69,6 +69,8 @@ import org.sufficientlysecure.keychain.ui.dialog.EditUserIdDialogFragment;
|
||||
import org.sufficientlysecure.keychain.ui.dialog.SetPassphraseDialogFragment;
|
||||
import org.sufficientlysecure.keychain.ui.util.Notify;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
import org.sufficientlysecure.keychain.util.Passphrase;
|
||||
|
||||
|
||||
public class EditKeyFragment extends CryptoOperationFragment implements
|
||||
LoaderManager.LoaderCallbacks<Cursor> {
|
||||
@@ -337,7 +339,7 @@ public class EditKeyFragment extends CryptoOperationFragment implements
|
||||
|
||||
// cache new returned passphrase!
|
||||
mSaveKeyringParcel.mNewUnlock = new ChangeUnlockParcel(
|
||||
data.getString(SetPassphraseDialogFragment.MESSAGE_NEW_PASSPHRASE),
|
||||
(Passphrase) data.getParcelable(SetPassphraseDialogFragment.MESSAGE_NEW_PASSPHRASE),
|
||||
null
|
||||
);
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ import org.sufficientlysecure.keychain.service.KeychainIntentService;
|
||||
import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
|
||||
import org.sufficientlysecure.keychain.service.input.CryptoInputParcel;
|
||||
import org.sufficientlysecure.keychain.service.input.RequiredInputParcel;
|
||||
import org.sufficientlysecure.keychain.util.Passphrase;
|
||||
|
||||
|
||||
public abstract class EncryptActivity extends BaseActivity {
|
||||
@@ -41,7 +42,7 @@ public abstract class EncryptActivity extends BaseActivity {
|
||||
public static final int REQUEST_CODE_NFC = 0x00008002;
|
||||
|
||||
// For NFC data
|
||||
protected String mSigningKeyPassphrase = null;
|
||||
protected Passphrase mSigningKeyPassphrase = null;
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
@@ -76,7 +77,7 @@ public abstract class EncryptActivity extends BaseActivity {
|
||||
switch (requestCode) {
|
||||
case REQUEST_CODE_PASSPHRASE: {
|
||||
if (resultCode == RESULT_OK && data != null) {
|
||||
mSigningKeyPassphrase = data.getStringExtra(PassphraseDialogActivity.MESSAGE_DATA_PASSPHRASE);
|
||||
mSigningKeyPassphrase = data.getParcelableExtra(PassphraseDialogActivity.MESSAGE_DATA_PASSPHRASE);
|
||||
startEncrypt();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -19,6 +19,8 @@ package org.sufficientlysecure.keychain.ui;
|
||||
|
||||
import android.net.Uri;
|
||||
|
||||
import org.sufficientlysecure.keychain.util.Passphrase;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
public interface EncryptActivityInterface {
|
||||
@@ -39,7 +41,7 @@ public interface EncryptActivityInterface {
|
||||
public void setEncryptionKeys(long[] encryptionKeys);
|
||||
public void setEncryptionUsers(String[] encryptionUsers);
|
||||
|
||||
public void setPassphrase(String passphrase);
|
||||
public void setPassphrase(Passphrase passphrase);
|
||||
|
||||
// ArrayList on purpose as only those are parcelable
|
||||
public ArrayList<Uri> getInputUris();
|
||||
|
||||
@@ -36,6 +36,7 @@ import org.sufficientlysecure.keychain.pgp.SignEncryptParcel;
|
||||
import org.sufficientlysecure.keychain.ui.dialog.DeleteFileDialogFragment;
|
||||
import org.sufficientlysecure.keychain.ui.util.Notify;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
import org.sufficientlysecure.keychain.util.Passphrase;
|
||||
import org.sufficientlysecure.keychain.util.ShareHelper;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -72,7 +73,7 @@ public class EncryptFilesActivity extends EncryptActivity implements EncryptActi
|
||||
private long mEncryptionKeyIds[] = null;
|
||||
private String mEncryptionUserIds[] = null;
|
||||
private long mSigningKeyId = Constants.key.none;
|
||||
private String mPassphrase = "";
|
||||
private Passphrase mPassphrase = new Passphrase();
|
||||
|
||||
private ArrayList<Uri> mInputUris;
|
||||
private ArrayList<Uri> mOutputUris;
|
||||
@@ -136,7 +137,7 @@ public class EncryptFilesActivity extends EncryptActivity implements EncryptActi
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPassphrase(String passphrase) {
|
||||
public void setPassphrase(Passphrase passphrase) {
|
||||
mPassphrase = passphrase;
|
||||
}
|
||||
|
||||
@@ -243,8 +244,8 @@ public class EncryptFilesActivity extends EncryptActivity implements EncryptActi
|
||||
|
||||
if (isModeSymmetric()) {
|
||||
Log.d(Constants.TAG, "Symmetric encryption enabled!");
|
||||
String passphrase = mPassphrase;
|
||||
if (passphrase.length() == 0) {
|
||||
Passphrase passphrase = mPassphrase;
|
||||
if (passphrase.isEmpty()) {
|
||||
passphrase = null;
|
||||
}
|
||||
data.setSymmetricPassphrase(passphrase);
|
||||
|
||||
@@ -28,6 +28,7 @@ import android.view.ViewGroup;
|
||||
import android.widget.EditText;
|
||||
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.util.Passphrase;
|
||||
|
||||
public class EncryptSymmetricFragment extends Fragment implements EncryptActivityInterface.UpdateListener {
|
||||
|
||||
@@ -67,8 +68,13 @@ public class EncryptSymmetricFragment extends Fragment implements EncryptActivit
|
||||
@Override
|
||||
public void afterTextChanged(Editable s) {
|
||||
// update passphrase in EncryptActivity
|
||||
if (mPassphrase.getText().toString().equals(mPassphraseAgain.getText().toString())) {
|
||||
mEncryptInterface.setPassphrase(s.toString());
|
||||
Passphrase p1 = new Passphrase(mPassphrase.getText());
|
||||
Passphrase p2 = new Passphrase(mPassphraseAgain.getText());
|
||||
boolean passesEquals = (p1.equals(p2));
|
||||
p1.removeFromMemory();
|
||||
p2.removeFromMemory();
|
||||
if (passesEquals) {
|
||||
mEncryptInterface.setPassphrase(new Passphrase(mPassphrase.getText()));
|
||||
} else {
|
||||
mEncryptInterface.setPassphrase(null);
|
||||
}
|
||||
|
||||
@@ -36,6 +36,7 @@ import org.sufficientlysecure.keychain.pgp.PgpConstants;
|
||||
import org.sufficientlysecure.keychain.pgp.SignEncryptParcel;
|
||||
import org.sufficientlysecure.keychain.ui.util.Notify;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
import org.sufficientlysecure.keychain.util.Passphrase;
|
||||
import org.sufficientlysecure.keychain.util.ShareHelper;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -70,7 +71,7 @@ public class EncryptTextActivity extends EncryptActivity implements EncryptActiv
|
||||
private String mEncryptionUserIds[] = null;
|
||||
// TODO Constants.key.none? What's wrong with a null value?
|
||||
private long mSigningKeyId = Constants.key.none;
|
||||
private String mPassphrase = "";
|
||||
private Passphrase mPassphrase = new Passphrase();
|
||||
|
||||
private ArrayList<Uri> mInputUris;
|
||||
private ArrayList<Uri> mOutputUris;
|
||||
@@ -134,7 +135,8 @@ public class EncryptTextActivity extends EncryptActivity implements EncryptActiv
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setPassphrase(String passphrase) {
|
||||
public void setPassphrase(Passphrase passphrase) {
|
||||
mPassphrase.removeFromMemory();
|
||||
mPassphrase = passphrase;
|
||||
}
|
||||
|
||||
@@ -223,8 +225,8 @@ public class EncryptTextActivity extends EncryptActivity implements EncryptActiv
|
||||
|
||||
if (isModeSymmetric()) {
|
||||
Log.d(Constants.TAG, "Symmetric encryption enabled!");
|
||||
String passphrase = mPassphrase;
|
||||
if (passphrase.length() == 0) {
|
||||
Passphrase passphrase = mPassphrase;
|
||||
if (passphrase.isEmpty()) {
|
||||
passphrase = null;
|
||||
}
|
||||
data.setSymmetricPassphrase(passphrase);
|
||||
|
||||
@@ -1,110 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 Dominik Schürmann <dominik@dominikschuermann.de>
|
||||
*
|
||||
* 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 <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package org.sufficientlysecure.keychain.ui;
|
||||
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.View;
|
||||
import android.view.Window;
|
||||
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
import org.sufficientlysecure.keychain.util.Preferences;
|
||||
|
||||
public class FirstTimeActivity extends BaseActivity {
|
||||
|
||||
View mCreateKey;
|
||||
View mImportKey;
|
||||
View mSkipSetup;
|
||||
|
||||
public static final int REQUEST_CODE_CREATE_OR_IMPORT_KEY = 0x00007012;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
supportRequestWindowFeature(Window.FEATURE_NO_TITLE);
|
||||
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
mCreateKey = findViewById(R.id.first_time_create_key);
|
||||
mImportKey = findViewById(R.id.first_time_import_key);
|
||||
mSkipSetup = findViewById(R.id.first_time_cancel);
|
||||
|
||||
mSkipSetup.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
finishSetup(null);
|
||||
}
|
||||
});
|
||||
|
||||
mImportKey.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Intent intent = new Intent(FirstTimeActivity.this, ImportKeysActivity.class);
|
||||
intent.setAction(ImportKeysActivity.ACTION_IMPORT_KEY_FROM_FILE_AND_RETURN);
|
||||
startActivityForResult(intent, REQUEST_CODE_CREATE_OR_IMPORT_KEY);
|
||||
}
|
||||
});
|
||||
|
||||
mCreateKey.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
Intent intent = new Intent(FirstTimeActivity.this, CreateKeyActivity.class);
|
||||
startActivityForResult(intent, REQUEST_CODE_CREATE_OR_IMPORT_KEY);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void initLayout() {
|
||||
setContentView(R.layout.first_time_activity);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
super.onActivityResult(requestCode, resultCode, data);
|
||||
|
||||
if (requestCode == REQUEST_CODE_CREATE_OR_IMPORT_KEY) {
|
||||
if (resultCode == RESULT_OK) {
|
||||
finishSetup(data);
|
||||
}
|
||||
} else {
|
||||
Log.e(Constants.TAG, "No valid request code!");
|
||||
}
|
||||
}
|
||||
|
||||
private void finishSetup(Intent srcData) {
|
||||
Preferences prefs = Preferences.getPreferences(this);
|
||||
prefs.setFirstTime(false);
|
||||
Intent intent = new Intent(this, MainActivity.class);
|
||||
// give intent through to display notify
|
||||
if (srcData != null) {
|
||||
intent.putExtras(srcData);
|
||||
}
|
||||
startActivity(intent);
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -489,7 +489,8 @@ public class KeyListFragment extends LoaderFragment
|
||||
case R.id.menu_key_list_debug_first_time:
|
||||
Preferences prefs = Preferences.getPreferences(getActivity());
|
||||
prefs.setFirstTime(true);
|
||||
Intent intent = new Intent(getActivity(), FirstTimeActivity.class);
|
||||
Intent intent = new Intent(getActivity(), CreateKeyActivity.class);
|
||||
intent.putExtra(CreateKeyActivity.EXTRA_FIRST_TIME, true);
|
||||
startActivity(intent);
|
||||
getActivity().finish();
|
||||
return true;
|
||||
|
||||
@@ -54,7 +54,9 @@ public class MainActivity extends MaterialNavigationDrawer implements FabContain
|
||||
// if this is the first time show first time activity
|
||||
Preferences prefs = Preferences.getPreferences(this);
|
||||
if (prefs.isFirstTime()) {
|
||||
startActivity(new Intent(this, FirstTimeActivity.class));
|
||||
Intent intent = new Intent(this, CreateKeyActivity.class);
|
||||
intent.putExtra(CreateKeyActivity.EXTRA_FIRST_TIME, true);
|
||||
startActivity(intent);
|
||||
finish();
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -59,6 +59,7 @@ import org.sufficientlysecure.keychain.service.input.RequiredInputParcel;
|
||||
import org.sufficientlysecure.keychain.service.input.RequiredInputParcel.RequiredInputType;
|
||||
import org.sufficientlysecure.keychain.ui.dialog.CustomAlertDialogBuilder;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
import org.sufficientlysecure.keychain.util.Passphrase;
|
||||
import org.sufficientlysecure.keychain.util.Preferences;
|
||||
|
||||
/**
|
||||
@@ -333,7 +334,7 @@ public class PassphraseDialogActivity extends FragmentActivity {
|
||||
positive.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
final String passphrase = mPassphraseEditText.getText().toString();
|
||||
final Passphrase passphrase = new Passphrase(mPassphraseEditText);
|
||||
|
||||
// Early breakout if we are dealing with a symmetric key
|
||||
if (mSecretRing == null) {
|
||||
@@ -410,7 +411,7 @@ public class PassphraseDialogActivity extends FragmentActivity {
|
||||
});
|
||||
}
|
||||
|
||||
private void finishCaching(String passphrase) {
|
||||
private void finishCaching(Passphrase passphrase) {
|
||||
// any indication this isn't needed anymore, don't do it.
|
||||
if (mIsCancelled || getActivity() == null) {
|
||||
return;
|
||||
|
||||
@@ -21,18 +21,12 @@ package org.sufficientlysecure.keychain.ui;
|
||||
import android.animation.ArgbEvaluator;
|
||||
import android.animation.ObjectAnimator;
|
||||
import android.annotation.SuppressLint;
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.Activity;
|
||||
import android.app.ActivityOptions;
|
||||
import android.content.Intent;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.database.Cursor;
|
||||
import android.graphics.Bitmap;
|
||||
import android.net.Uri;
|
||||
import android.nfc.NdefMessage;
|
||||
import android.nfc.NdefRecord;
|
||||
import android.nfc.NfcAdapter;
|
||||
import android.nfc.NfcEvent;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
@@ -40,7 +34,6 @@ import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.os.Messenger;
|
||||
import android.provider.ContactsContract;
|
||||
import android.provider.Settings;
|
||||
import android.support.v4.app.ActivityCompat;
|
||||
import android.support.v4.app.LoaderManager;
|
||||
import android.support.v4.content.CursorLoader;
|
||||
@@ -58,9 +51,7 @@ import android.widget.ImageView;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.getbase.floatingactionbutton.FloatingActionButton;
|
||||
|
||||
import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.keyimport.ParcelableKeyRing;
|
||||
@@ -74,6 +65,8 @@ import org.sufficientlysecure.keychain.provider.ProviderHelper;
|
||||
import org.sufficientlysecure.keychain.service.KeychainIntentService;
|
||||
import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler;
|
||||
import org.sufficientlysecure.keychain.service.KeychainIntentServiceHandler.MessageStatus;
|
||||
import org.sufficientlysecure.keychain.service.PassphraseCacheService;
|
||||
import org.sufficientlysecure.keychain.ui.dialog.DeleteKeyDialogFragment;
|
||||
import org.sufficientlysecure.keychain.ui.util.FormattingUtils;
|
||||
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
|
||||
import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils.State;
|
||||
@@ -82,6 +75,7 @@ import org.sufficientlysecure.keychain.ui.util.QrCodeUtils;
|
||||
import org.sufficientlysecure.keychain.util.ContactHelper;
|
||||
import org.sufficientlysecure.keychain.util.ExportHelper;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
import org.sufficientlysecure.keychain.util.NfcHelper;
|
||||
import org.sufficientlysecure.keychain.util.Preferences;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -91,8 +85,8 @@ public class ViewKeyActivity extends BaseActivity implements
|
||||
LoaderManager.LoaderCallbacks<Cursor> {
|
||||
|
||||
static final int REQUEST_QR_FINGERPRINT = 1;
|
||||
static final int REQUEST_DELETE= 2;
|
||||
static final int REQUEST_EXPORT= 3;
|
||||
static final int REQUEST_DELETE = 2;
|
||||
static final int REQUEST_EXPORT = 3;
|
||||
|
||||
ExportHelper mExportHelper;
|
||||
ProviderHelper mProviderHelper;
|
||||
@@ -113,11 +107,7 @@ public class ViewKeyActivity extends BaseActivity implements
|
||||
private CardView mQrCodeLayout;
|
||||
|
||||
// NFC
|
||||
private NfcAdapter mNfcAdapter;
|
||||
private NfcAdapter.CreateNdefMessageCallback mNdefCallback;
|
||||
private NfcAdapter.OnNdefPushCompleteCallback mNdefCompleteCallback;
|
||||
private byte[] mNfcKeyringBytes;
|
||||
private static final int NFC_SENT = 1;
|
||||
private NfcHelper mNfcHelper;
|
||||
|
||||
private static final int LOADER_ID_UNIFIED = 0;
|
||||
|
||||
@@ -254,7 +244,7 @@ public class ViewKeyActivity extends BaseActivity implements
|
||||
mActionNfc.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
invokeNfcBeam();
|
||||
mNfcHelper.invokeNfcBeam();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -262,7 +252,8 @@ public class ViewKeyActivity extends BaseActivity implements
|
||||
// or start new ones.
|
||||
getSupportLoaderManager().initLoader(LOADER_ID_UNIFIED, null, this);
|
||||
|
||||
initNfc(mDataUri);
|
||||
mNfcHelper = new NfcHelper(this, mProviderHelper);
|
||||
mNfcHelper.initNfc(mDataUri);
|
||||
|
||||
startFragment(savedInstanceState, mDataUri);
|
||||
}
|
||||
@@ -310,31 +301,31 @@ public class ViewKeyActivity extends BaseActivity implements
|
||||
return true;
|
||||
}
|
||||
case R.id.menu_key_view_export_file: {
|
||||
Intent mIntent = new Intent(this,PassphraseDialogActivity.class);
|
||||
long keyId=0;
|
||||
try {
|
||||
keyId = new ProviderHelper(this)
|
||||
.getCachedPublicKeyRing(mDataUri)
|
||||
.extractOrGetMasterKeyId();
|
||||
} catch (PgpKeyNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
if (PassphraseCacheService.getCachedPassphrase(this, mMasterKeyId, mMasterKeyId) != null) {
|
||||
exportToFile(mDataUri, mExportHelper, mProviderHelper);
|
||||
return true;
|
||||
}
|
||||
|
||||
startPassphraseActivity(REQUEST_EXPORT);
|
||||
} catch (PassphraseCacheService.KeyNotFoundException e) {
|
||||
// This happens when the master key is stripped
|
||||
exportToFile(mDataUri, mExportHelper, mProviderHelper);
|
||||
}
|
||||
mIntent.putExtra(PassphraseDialogActivity.EXTRA_SUBKEY_ID,keyId);
|
||||
startActivityForResult(mIntent,REQUEST_EXPORT);
|
||||
return true;
|
||||
}
|
||||
case R.id.menu_key_view_delete: {
|
||||
Intent mIntent = new Intent(this,PassphraseDialogActivity.class);
|
||||
long keyId=0;
|
||||
try {
|
||||
keyId = new ProviderHelper(this)
|
||||
.getCachedPublicKeyRing(mDataUri)
|
||||
.extractOrGetMasterKeyId();
|
||||
} catch (PgpKeyNotFoundException e) {
|
||||
e.printStackTrace();
|
||||
if (PassphraseCacheService.getCachedPassphrase(this, mMasterKeyId, mMasterKeyId) != null) {
|
||||
deleteKey();
|
||||
return true;
|
||||
}
|
||||
|
||||
startPassphraseActivity(REQUEST_DELETE);
|
||||
} catch (PassphraseCacheService.KeyNotFoundException e) {
|
||||
// This happens when the master key is stripped
|
||||
deleteKey();
|
||||
}
|
||||
mIntent.putExtra(PassphraseDialogActivity.EXTRA_SUBKEY_ID,keyId);
|
||||
startActivityForResult(mIntent,REQUEST_DELETE);
|
||||
return true;
|
||||
}
|
||||
case R.id.menu_key_view_advanced: {
|
||||
@@ -373,41 +364,6 @@ public class ViewKeyActivity extends BaseActivity implements
|
||||
return true;
|
||||
}
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.LOLLIPOP)
|
||||
private void invokeNfcBeam() {
|
||||
// Check if device supports NFC
|
||||
if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_NFC)) {
|
||||
Notify.createNotify(this, R.string.no_nfc_support, Notify.LENGTH_LONG, Notify.Style.ERROR).show();
|
||||
return;
|
||||
}
|
||||
// Check for available NFC Adapter
|
||||
mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
|
||||
if (mNfcAdapter == null || !mNfcAdapter.isEnabled()) {
|
||||
Notify.createNotify(this, R.string.error_nfc_needed, Notify.LENGTH_LONG, Notify.Style.ERROR, new Notify.ActionListener() {
|
||||
@Override
|
||||
public void onAction() {
|
||||
Intent intentSettings = new Intent(Settings.ACTION_NFC_SETTINGS);
|
||||
startActivity(intentSettings);
|
||||
}
|
||||
}, R.string.menu_nfc_preferences).show();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (!mNfcAdapter.isNdefPushEnabled()) {
|
||||
Notify.createNotify(this, R.string.error_beam_needed, Notify.LENGTH_LONG, Notify.Style.ERROR, new Notify.ActionListener() {
|
||||
@Override
|
||||
public void onAction() {
|
||||
Intent intentSettings = new Intent(Settings.ACTION_NFCSHARING_SETTINGS);
|
||||
startActivity(intentSettings);
|
||||
}
|
||||
}, R.string.menu_beam_preferences).show();
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
mNfcAdapter.invokeBeam(this);
|
||||
}
|
||||
|
||||
private void scanQrCode() {
|
||||
Intent scanQrCode = new Intent(this, ImportKeysProxyActivity.class);
|
||||
@@ -424,7 +380,7 @@ public class ViewKeyActivity extends BaseActivity implements
|
||||
|
||||
private void certifyImmediate() {
|
||||
Intent intent = new Intent(this, CertifyKeyActivity.class);
|
||||
intent.putExtra(CertifyKeyActivity.EXTRA_KEY_IDS, new long[]{mMasterKeyId});
|
||||
intent.putExtra(CertifyKeyActivity.EXTRA_KEY_IDS, new long[] {mMasterKeyId});
|
||||
|
||||
startCertifyIntent(intent);
|
||||
}
|
||||
@@ -473,22 +429,32 @@ public class ViewKeyActivity extends BaseActivity implements
|
||||
ActivityCompat.startActivity(this, qrCodeIntent, opts);
|
||||
}
|
||||
|
||||
private void exportToFile(Uri dataUri, ExportHelper exportHelper, ProviderHelper providerHelper)
|
||||
throws ProviderHelper.NotFoundException {
|
||||
Uri baseUri = KeychainContract.KeyRings.buildUnifiedKeyRingUri(dataUri);
|
||||
|
||||
HashMap<String, Object> data = providerHelper.getGenericData(
|
||||
baseUri,
|
||||
new String[]{KeychainContract.Keys.MASTER_KEY_ID, KeychainContract.KeyRings.HAS_SECRET},
|
||||
new int[]{ProviderHelper.FIELD_TYPE_INTEGER, ProviderHelper.FIELD_TYPE_INTEGER});
|
||||
|
||||
exportHelper.showExportKeysDialog(
|
||||
new long[]{(Long) data.get(KeychainContract.KeyRings.MASTER_KEY_ID)},
|
||||
Constants.Path.APP_DIR_FILE, ((Long) data.get(KeychainContract.KeyRings.HAS_SECRET) != 0)
|
||||
);
|
||||
private void startPassphraseActivity(int requestCode) {
|
||||
Intent intent = new Intent(this, PassphraseDialogActivity.class);
|
||||
intent.putExtra(PassphraseDialogActivity.EXTRA_SUBKEY_ID, mMasterKeyId);
|
||||
startActivityForResult(intent, requestCode);
|
||||
}
|
||||
|
||||
private void deleteKey(Uri dataUri, ExportHelper exportHelper) {
|
||||
private void exportToFile(Uri dataUri, ExportHelper exportHelper, ProviderHelper providerHelper) {
|
||||
try {
|
||||
Uri baseUri = KeychainContract.KeyRings.buildUnifiedKeyRingUri(dataUri);
|
||||
|
||||
HashMap<String, Object> data = providerHelper.getGenericData(
|
||||
baseUri,
|
||||
new String[] {KeychainContract.Keys.MASTER_KEY_ID, KeychainContract.KeyRings.HAS_SECRET},
|
||||
new int[] {ProviderHelper.FIELD_TYPE_INTEGER, ProviderHelper.FIELD_TYPE_INTEGER});
|
||||
|
||||
exportHelper.showExportKeysDialog(
|
||||
new long[] {(Long) data.get(KeychainContract.KeyRings.MASTER_KEY_ID)},
|
||||
Constants.Path.APP_DIR_FILE, ((Long) data.get(KeychainContract.KeyRings.HAS_SECRET) != 0)
|
||||
);
|
||||
} catch (ProviderHelper.NotFoundException e) {
|
||||
Notify.showNotify(this, R.string.error_key_not_found, Notify.Style.ERROR);
|
||||
Log.e(Constants.TAG, "Key not found", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void deleteKey() {
|
||||
// Message is received after key is deleted
|
||||
Handler returnHandler = new Handler() {
|
||||
@Override
|
||||
@@ -500,7 +466,11 @@ public class ViewKeyActivity extends BaseActivity implements
|
||||
}
|
||||
};
|
||||
|
||||
exportHelper.deleteKey(dataUri, returnHandler);
|
||||
// Create a new Messenger for the communication back
|
||||
Messenger messenger = new Messenger(returnHandler);
|
||||
DeleteKeyDialogFragment deleteKeyDialog = DeleteKeyDialogFragment.newInstance(messenger,
|
||||
new long[] {mMasterKeyId});
|
||||
deleteKeyDialog.show(getSupportFragmentManager(), "deleteKeyDialog");
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -530,18 +500,13 @@ public class ViewKeyActivity extends BaseActivity implements
|
||||
return;
|
||||
}
|
||||
|
||||
if (requestCode == REQUEST_DELETE && resultCode == Activity.RESULT_OK){
|
||||
deleteKey(mDataUri, mExportHelper);
|
||||
}
|
||||
if (requestCode == REQUEST_EXPORT && resultCode == Activity.RESULT_OK){
|
||||
try {
|
||||
exportToFile(mDataUri, mExportHelper, mProviderHelper);
|
||||
} catch (ProviderHelper.NotFoundException e) {
|
||||
Notify.showNotify(this, R.string.error_key_not_found, Notify.Style.ERROR);
|
||||
Log.e(Constants.TAG, "Key not found", e);
|
||||
}
|
||||
if (requestCode == REQUEST_DELETE && resultCode == Activity.RESULT_OK) {
|
||||
deleteKey();
|
||||
}
|
||||
|
||||
if (requestCode == REQUEST_EXPORT && resultCode == Activity.RESULT_OK) {
|
||||
exportToFile(mDataUri, mExportHelper, mProviderHelper);
|
||||
}
|
||||
|
||||
if (data != null && data.hasExtra(OperationResult.EXTRA_RESULT)) {
|
||||
OperationResult result = data.getParcelableExtra(OperationResult.EXTRA_RESULT);
|
||||
@@ -561,7 +526,7 @@ public class ViewKeyActivity extends BaseActivity implements
|
||||
long keyId = new ProviderHelper(this)
|
||||
.getCachedPublicKeyRing(dataUri)
|
||||
.extractOrGetMasterKeyId();
|
||||
long[] encryptionKeyIds = new long[]{keyId};
|
||||
long[] encryptionKeyIds = new long[] {keyId};
|
||||
Intent intent;
|
||||
if (text) {
|
||||
intent = new Intent(this, EncryptTextActivity.class);
|
||||
@@ -699,98 +664,9 @@ public class ViewKeyActivity extends BaseActivity implements
|
||||
loadTask.execute();
|
||||
}
|
||||
|
||||
/**
|
||||
* NFC: Initialize NFC sharing if OS and device supports it
|
||||
*/
|
||||
@TargetApi(Build.VERSION_CODES.JELLY_BEAN)
|
||||
private void initNfc(final Uri dataUri) {
|
||||
// check if NFC Beam is supported (>= Android 4.1)
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
|
||||
|
||||
// Implementation for the CreateNdefMessageCallback interface
|
||||
mNdefCallback = new NfcAdapter.CreateNdefMessageCallback() {
|
||||
@Override
|
||||
public NdefMessage createNdefMessage(NfcEvent event) {
|
||||
/*
|
||||
* When a device receives a push with an AAR in it, the application specified in the AAR is
|
||||
* guaranteed to run. The AAR overrides the tag dispatch system. You can add it back in to
|
||||
* guarantee that this activity starts when receiving a beamed message. For now, this code
|
||||
* uses the tag dispatch system.
|
||||
*/
|
||||
return new NdefMessage(NdefRecord.createMime(Constants.NFC_MIME,
|
||||
mNfcKeyringBytes), NdefRecord.createApplicationRecord(Constants.PACKAGE_NAME));
|
||||
}
|
||||
};
|
||||
|
||||
// Implementation for the OnNdefPushCompleteCallback interface
|
||||
mNdefCompleteCallback = new NfcAdapter.OnNdefPushCompleteCallback() {
|
||||
@Override
|
||||
public void onNdefPushComplete(NfcEvent event) {
|
||||
// A handler is needed to send messages to the activity when this
|
||||
// callback occurs, because it happens from a binder thread
|
||||
mNfcHandler.obtainMessage(NFC_SENT).sendToTarget();
|
||||
}
|
||||
};
|
||||
|
||||
// Check for available NFC Adapter
|
||||
mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
|
||||
if (mNfcAdapter != null) {
|
||||
/*
|
||||
* Retrieve mNfcKeyringBytes here asynchronously (to not block the UI)
|
||||
* and init nfc adapter afterwards.
|
||||
* mNfcKeyringBytes can not be retrieved in createNdefMessage, because this process
|
||||
* has no permissions to query the Uri.
|
||||
*/
|
||||
AsyncTask<Void, Void, Void> initTask =
|
||||
new AsyncTask<Void, Void, Void>() {
|
||||
protected Void doInBackground(Void... unused) {
|
||||
try {
|
||||
Uri blobUri =
|
||||
KeychainContract.KeyRingData.buildPublicKeyRingUri(dataUri);
|
||||
mNfcKeyringBytes = (byte[]) mProviderHelper.getGenericData(
|
||||
blobUri,
|
||||
KeychainContract.KeyRingData.KEY_RING_DATA,
|
||||
ProviderHelper.FIELD_TYPE_BLOB);
|
||||
} catch (ProviderHelper.NotFoundException e) {
|
||||
Log.e(Constants.TAG, "key not found!", e);
|
||||
}
|
||||
|
||||
// no AsyncTask return (Void)
|
||||
return null;
|
||||
}
|
||||
|
||||
protected void onPostExecute(Void unused) {
|
||||
// Register callback to set NDEF message
|
||||
mNfcAdapter.setNdefPushMessageCallback(mNdefCallback,
|
||||
ViewKeyActivity.this);
|
||||
// Register callback to listen for message-sent success
|
||||
mNfcAdapter.setOnNdefPushCompleteCallback(mNdefCompleteCallback,
|
||||
ViewKeyActivity.this);
|
||||
}
|
||||
};
|
||||
|
||||
initTask.execute();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* NFC: This handler receives a message from onNdefPushComplete
|
||||
*/
|
||||
private final Handler mNfcHandler = new Handler() {
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
switch (msg.what) {
|
||||
case NFC_SENT:
|
||||
Notify.showNotify(
|
||||
ViewKeyActivity.this, R.string.nfc_successful, Notify.Style.INFO);
|
||||
break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
// These are the rows that we will retrieve.
|
||||
static final String[] PROJECTION = new String[]{
|
||||
static final String[] PROJECTION = new String[] {
|
||||
KeychainContract.KeyRings._ID,
|
||||
KeychainContract.KeyRings.MASTER_KEY_ID,
|
||||
KeychainContract.KeyRings.USER_ID,
|
||||
@@ -1007,4 +883,4 @@ public class ViewKeyActivity extends BaseActivity implements
|
||||
public void onLoaderReset(Loader<Cursor> loader) {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -52,6 +52,7 @@ import org.sufficientlysecure.keychain.ui.util.KeyFormattingUtils;
|
||||
import org.sufficientlysecure.keychain.ui.util.Notify;
|
||||
import org.sufficientlysecure.keychain.ui.util.QrCodeUtils;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
import org.sufficientlysecure.keychain.util.NfcHelper;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
@@ -68,10 +69,12 @@ public class ViewKeyAdvShareFragment extends LoaderFragment implements
|
||||
private View mFingerprintClipboardButton;
|
||||
private View mKeyShareButton;
|
||||
private View mKeyClipboardButton;
|
||||
private View mKeyNfcButton;
|
||||
private ImageButton mKeySafeSlingerButton;
|
||||
private View mKeyUploadButton;
|
||||
|
||||
ProviderHelper mProviderHelper;
|
||||
NfcHelper mNfcHelper;
|
||||
|
||||
private static final int LOADER_ID_UNIFIED = 0;
|
||||
|
||||
@@ -83,6 +86,7 @@ public class ViewKeyAdvShareFragment extends LoaderFragment implements
|
||||
View view = inflater.inflate(R.layout.view_key_adv_share_fragment, getContainer());
|
||||
|
||||
mProviderHelper = new ProviderHelper(ViewKeyAdvShareFragment.this.getActivity());
|
||||
mNfcHelper = new NfcHelper(getActivity(), mProviderHelper);
|
||||
|
||||
mFingerprint = (TextView) view.findViewById(R.id.view_key_fingerprint);
|
||||
mQrCode = (ImageView) view.findViewById(R.id.view_key_qr_code);
|
||||
@@ -90,6 +94,7 @@ public class ViewKeyAdvShareFragment extends LoaderFragment implements
|
||||
mFingerprintShareButton = view.findViewById(R.id.view_key_action_fingerprint_share);
|
||||
mFingerprintClipboardButton = view.findViewById(R.id.view_key_action_fingerprint_clipboard);
|
||||
mKeyShareButton = view.findViewById(R.id.view_key_action_key_share);
|
||||
mKeyNfcButton = view.findViewById(R.id.view_key_action_key_nfc);
|
||||
mKeyClipboardButton = view.findViewById(R.id.view_key_action_key_clipboard);
|
||||
mKeySafeSlingerButton = (ImageButton) view.findViewById(R.id.view_key_action_key_safeslinger);
|
||||
mKeyUploadButton = view.findViewById(R.id.view_key_action_upload);
|
||||
@@ -128,6 +133,14 @@ public class ViewKeyAdvShareFragment extends LoaderFragment implements
|
||||
share(mDataUri, mProviderHelper, false, true);
|
||||
}
|
||||
});
|
||||
|
||||
mKeyNfcButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
mNfcHelper.invokeNfcBeam();
|
||||
}
|
||||
});
|
||||
|
||||
mKeySafeSlingerButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
@@ -255,9 +268,12 @@ public class ViewKeyAdvShareFragment extends LoaderFragment implements
|
||||
// Prepare the loaders. Either re-connect with an existing ones,
|
||||
// or start new ones.
|
||||
getLoaderManager().initLoader(LOADER_ID_UNIFIED, null, this);
|
||||
|
||||
// Prepare the NfcHelper
|
||||
mNfcHelper.initNfc(mDataUri);
|
||||
}
|
||||
|
||||
static final String[] UNIFIED_PROJECTION = new String[]{
|
||||
static final String[] UNIFIED_PROJECTION = new String[] {
|
||||
KeyRings._ID, KeyRings.MASTER_KEY_ID, KeyRings.HAS_ANY_SECRET,
|
||||
KeyRings.USER_ID, KeyRings.FINGERPRINT,
|
||||
KeyRings.ALGORITHM, KeyRings.KEY_SIZE, KeyRings.CREATION, KeyRings.IS_EXPIRED,
|
||||
@@ -362,4 +378,5 @@ public class ViewKeyAdvShareFragment extends LoaderFragment implements
|
||||
startActivityForResult(uploadIntent, 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -45,6 +45,7 @@ import org.sufficientlysecure.keychain.Constants;
|
||||
import org.sufficientlysecure.keychain.R;
|
||||
import org.sufficientlysecure.keychain.ui.widget.PassphraseEditText;
|
||||
import org.sufficientlysecure.keychain.util.Log;
|
||||
import org.sufficientlysecure.keychain.util.Passphrase;
|
||||
|
||||
public class SetPassphraseDialogFragment extends DialogFragment implements OnEditorActionListener {
|
||||
private static final String ARG_MESSENGER = "messenger";
|
||||
@@ -113,12 +114,12 @@ public class SetPassphraseDialogFragment extends DialogFragment implements OnEdi
|
||||
public void onClick(DialogInterface dialog, int id) {
|
||||
dismiss();
|
||||
|
||||
String passphrase1;
|
||||
Passphrase passphrase1 = new Passphrase();
|
||||
if (mNoPassphraseCheckBox.isChecked()) {
|
||||
passphrase1 = "";
|
||||
passphrase1.setEmpty();
|
||||
} else {
|
||||
passphrase1 = mPassphraseEditText.getText().toString();
|
||||
String passphrase2 = mPassphraseAgainEditText.getText().toString();
|
||||
passphrase1 = new Passphrase(mPassphraseEditText);
|
||||
Passphrase passphrase2 = new Passphrase(mPassphraseAgainEditText);
|
||||
if (!passphrase1.equals(passphrase2)) {
|
||||
Toast.makeText(
|
||||
activity,
|
||||
@@ -129,7 +130,7 @@ public class SetPassphraseDialogFragment extends DialogFragment implements OnEdi
|
||||
return;
|
||||
}
|
||||
|
||||
if (passphrase1.equals("")) {
|
||||
if (passphrase1.isEmpty()) {
|
||||
Toast.makeText(
|
||||
activity,
|
||||
getString(R.string.error_message,
|
||||
@@ -142,7 +143,7 @@ public class SetPassphraseDialogFragment extends DialogFragment implements OnEdi
|
||||
|
||||
// return resulting data back to activity
|
||||
Bundle data = new Bundle();
|
||||
data.putString(MESSAGE_NEW_PASSPHRASE, passphrase1);
|
||||
data.putParcelable(MESSAGE_NEW_PASSPHRASE, passphrase1);
|
||||
|
||||
sendMessageToHandler(MESSAGE_OKAY, data);
|
||||
}
|
||||
|
||||
@@ -19,6 +19,11 @@ package org.sufficientlysecure.keychain.ui.util;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.res.Resources;
|
||||
import android.support.v4.app.Fragment;
|
||||
import android.support.v4.app.FragmentActivity;
|
||||
import android.support.v4.app.FragmentManager;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
|
||||
import com.nispok.snackbar.Snackbar;
|
||||
import com.nispok.snackbar.Snackbar.SnackbarDuration;
|
||||
@@ -61,11 +66,11 @@ public class Notify {
|
||||
break;
|
||||
}
|
||||
|
||||
SnackbarManager.show(bar);
|
||||
showSnackbar(activity, bar);
|
||||
|
||||
}
|
||||
|
||||
public static Showable createNotify (Activity activity, int resId, int duration, Style style) {
|
||||
public static Showable createNotify (final Activity activity, int resId, int duration, Style style) {
|
||||
final Snackbar bar = getSnackbar(activity)
|
||||
.text(resId);
|
||||
|
||||
@@ -90,7 +95,7 @@ public class Notify {
|
||||
return new Showable () {
|
||||
@Override
|
||||
public void show() {
|
||||
SnackbarManager.show(bar);
|
||||
showSnackbar(activity, bar);
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -104,7 +109,7 @@ public class Notify {
|
||||
return createNotify(activity, msg, duration, style, null, 0);
|
||||
}
|
||||
|
||||
public static Showable createNotify(Activity activity, String msg, int duration, Style style,
|
||||
public static Showable createNotify(final Activity activity, String msg, int duration, Style style,
|
||||
final ActionListener listener, int resIdAction) {
|
||||
|
||||
final Snackbar bar = getSnackbar(activity)
|
||||
@@ -141,7 +146,7 @@ public class Notify {
|
||||
return new Showable () {
|
||||
@Override
|
||||
public void show() {
|
||||
SnackbarManager.show(bar);
|
||||
showSnackbar(activity, bar);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -178,6 +183,26 @@ public class Notify {
|
||||
return bar;
|
||||
}
|
||||
|
||||
private static void showSnackbar(Activity activity, Snackbar snackbar) {
|
||||
if (activity instanceof FragmentActivity) {
|
||||
FragmentManager fragmentManager = ((FragmentActivity) activity).getSupportFragmentManager();
|
||||
|
||||
int count = fragmentManager.getBackStackEntryCount();
|
||||
Fragment fragment = fragmentManager.getFragments().get(count > 0 ? count - 1 : 0);
|
||||
|
||||
if (fragment != null) {
|
||||
View view = fragment.getView();
|
||||
|
||||
if (view != null) {
|
||||
SnackbarManager.show(snackbar, (ViewGroup) view);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SnackbarManager.show(snackbar);
|
||||
}
|
||||
|
||||
public interface Showable {
|
||||
public void show();
|
||||
|
||||
|
||||
@@ -58,9 +58,10 @@ public class EmailEditText extends AutoCompleteTextView {
|
||||
}
|
||||
|
||||
private void init() {
|
||||
this.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS);
|
||||
this.addTextChangedListener(textWatcher);
|
||||
removeFlag();
|
||||
setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_EMAIL_ADDRESS);
|
||||
reenableKeyboardSuggestions();
|
||||
|
||||
addTextChangedListener(textWatcher);
|
||||
initAdapter();
|
||||
}
|
||||
|
||||
@@ -104,7 +105,7 @@ public class EmailEditText extends AutoCompleteTextView {
|
||||
* Hack to re-enable keyboard auto correction in AutoCompleteTextView.
|
||||
* From http://stackoverflow.com/a/22512858
|
||||
*/
|
||||
private void removeFlag() {
|
||||
private void reenableKeyboardSuggestions() {
|
||||
int inputType = getInputType();
|
||||
inputType &= ~EditorInfo.TYPE_TEXT_FLAG_AUTO_COMPLETE;
|
||||
setRawInputType(inputType);
|
||||
|
||||
@@ -50,7 +50,7 @@ public class NameEditText extends AutoCompleteTextView {
|
||||
}
|
||||
|
||||
private void init() {
|
||||
removeFlag();
|
||||
reenableKeyboardSuggestions();
|
||||
initAdapter();
|
||||
}
|
||||
|
||||
@@ -62,10 +62,10 @@ public class NameEditText extends AutoCompleteTextView {
|
||||
}
|
||||
|
||||
/**
|
||||
* Hack to re-enable keyboard auto correction in AutoCompleteTextView.
|
||||
* Hack to re-enable keyboard suggestions in AutoCompleteTextView.
|
||||
* From http://stackoverflow.com/a/22512858
|
||||
*/
|
||||
private void removeFlag() {
|
||||
private void reenableKeyboardSuggestions() {
|
||||
int inputType = getInputType();
|
||||
inputType &= ~EditorInfo.TYPE_TEXT_FLAG_AUTO_COMPLETE;
|
||||
setRawInputType(inputType);
|
||||
|
||||
Reference in New Issue
Block a user