Handle user input on key creation more generously

Allow empty name and do not regex-check email
fixes #1825
This commit is contained in:
fiaxh 2016-04-15 01:21:15 +02:00
parent 88ba5688d8
commit 249b8d7d78
7 changed files with 67 additions and 85 deletions

View file

@ -78,18 +78,20 @@ public abstract class KeyRing {
}
/**
* Returns a composed user id. Returns null if name is null!
* Returns a composed user id. Returns null if name, email and comment are empty.
*/
public static String createUserId(UserId userId) {
String userIdString = userId.name; // consider name a required value
if (userIdString != null && !TextUtils.isEmpty(userId.comment)) {
userIdString += " (" + userId.comment + ")";
StringBuilder userIdBuilder = new StringBuilder();
if (!TextUtils.isEmpty(userId.name)) {
userIdBuilder.append(userId.comment);
}
if (userIdString != null && !TextUtils.isEmpty(userId.email)) {
userIdString += " <" + userId.email + ">";
if (!TextUtils.isEmpty(userId.comment)) {
userIdBuilder.append(" (" + userId.comment + ")");
}
return userIdString;
if (!TextUtils.isEmpty(userId.email)) {
userIdBuilder.append(" <" + userId.email + ">");
}
return userIdBuilder.length() == 0 ? null : userIdBuilder.toString();
}
public static class UserId implements Serializable {

View file

@ -44,7 +44,6 @@ 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 {
private CreateKeyActivity mCreateKeyActivity;
@ -52,10 +51,6 @@ public class CreateKeyEmailFragment extends Fragment {
private ArrayList<EmailAdapter.ViewModel> mAdditionalEmailModels = new ArrayList<>();
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
*/
@ -76,16 +71,15 @@ public class CreateKeyEmailFragment extends Fragment {
* @return true if EditText is not empty
*/
private boolean isMainEmailValid(EditText editText) {
boolean output = true;
if (!checkEmail(editText.getText().toString(), false)) {
if (editText.getText().length() == 0) {
editText.setError(getString(R.string.create_key_empty));
editText.requestFocus();
output = false;
} else {
editText.setError(null);
return false;
} else if (!checkEmail(editText.getText().toString(), false)){
return false;
}
return output;
editText.setError(null);
return true;
}
@Override
@ -146,10 +140,9 @@ public class CreateKeyEmailFragment extends Fragment {
* @return
*/
private boolean checkEmail(String email, boolean additionalEmail) {
// check for email format or if the user did any input
if (!isEmailFormatValid(email)) {
if (email.isEmpty()) {
Notify.create(getActivity(),
getString(R.string.create_key_email_invalid_email),
getString(R.string.create_key_email_empty_email),
Notify.LENGTH_LONG, Notify.Style.ERROR).show(CreateKeyEmailFragment.this);
return false;
}
@ -166,18 +159,6 @@ public class CreateKeyEmailFragment extends Fragment {
return true;
}
/**
* Checks the email format
* Uses the default Android Email Pattern
*
* @param email
* @return
*/
private boolean isEmailFormatValid(String email) {
// check for email format or if the user did any input
return !(email.length() == 0 || !EMAIL_PATTERN.matcher(email).matches());
}
/**
* Checks for duplicated emails inside the additional email adapter.
*

View file

@ -57,6 +57,7 @@ import org.sufficientlysecure.keychain.util.Preferences;
import java.util.Date;
import java.util.Iterator;
import java.util.regex.Pattern;
public class CreateKeyFinalFragment extends Fragment {
@ -81,6 +82,10 @@ public class CreateKeyFinalFragment extends Fragment {
private OperationResult mQueuedFinishResult;
private EditKeyResult mQueuedDisplayResult;
// 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]+$");
public static CreateKeyFinalFragment newInstance() {
CreateKeyFinalFragment frag = new CreateKeyFinalFragment();
frag.setRetainInstance(true);
@ -106,7 +111,11 @@ public class CreateKeyFinalFragment extends Fragment {
CreateKeyActivity createKeyActivity = (CreateKeyActivity) getActivity();
// set values
mNameEdit.setText(createKeyActivity.mName);
if (createKeyActivity.mName != null) {
mNameEdit.setText(createKeyActivity.mName);
} else {
mNameEdit.setText(getString(R.string.user_id_no_name));
}
if (createKeyActivity.mAdditionalEmails != null && createKeyActivity.mAdditionalEmails.size() > 0) {
String emailText = createKeyActivity.mEmail + ", ";
Iterator<?> it = createKeyActivity.mAdditionalEmails.iterator();
@ -122,6 +131,8 @@ public class CreateKeyFinalFragment extends Fragment {
mEmailEdit.setText(createKeyActivity.mEmail);
}
checkEmailValidity();
mCreateButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
@ -309,6 +320,31 @@ public class CreateKeyFinalFragment extends Fragment {
return saveKeyringParcel;
}
private void checkEmailValidity() {
CreateKeyActivity createKeyActivity = (CreateKeyActivity) getActivity();
boolean emailsValid = true;
if (!EMAIL_PATTERN.matcher(createKeyActivity.mEmail).matches()) {
emailsValid = false;
}
if (createKeyActivity.mAdditionalEmails != null && createKeyActivity.mAdditionalEmails.size() > 0) {
for (Iterator<?> it = createKeyActivity.mAdditionalEmails.iterator(); it.hasNext(); ) {
if (!EMAIL_PATTERN.matcher(it.next().toString()).matches()) {
emailsValid = false;
}
}
}
if (!emailsValid) {
mEmailEdit.setError(getString(R.string.create_key_final_email_valid_warning));
mEmailEdit.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
mNameEdit.requestFocus(); // Workaround to remove focus from email
}
});
}
}
private void createKey() {
CreateKeyActivity activity = (CreateKeyActivity) getActivity();
if (activity == null) {

View file

@ -18,13 +18,11 @@
package org.sufficientlysecure.keychain.ui;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.EditText;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.ui.CreateKeyActivity.FragAction;
@ -50,27 +48,6 @@ public class CreateKeyNameFragment extends Fragment {
return frag;
}
/**
* 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) {
boolean output = true;
if (editText.getText().length() == 0) {
editText.setError(context.getString(R.string.create_key_empty));
editText.requestFocus();
output = false;
} else {
editText.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);
@ -109,13 +86,11 @@ public class CreateKeyNameFragment extends Fragment {
}
private void nextClicked() {
if (isEditTextNotEmpty(getActivity(), mNameEdit)) {
// save state
mCreateKeyActivity.mName = mNameEdit.getText().toString();
// save state
mCreateKeyActivity.mName = mNameEdit.getText().length() == 0 ? null : mNameEdit.getText().toString();
CreateKeyEmailFragment frag = CreateKeyEmailFragment.newInstance();
mCreateKeyActivity.loadFragment(frag, FragAction.TO_RIGHT);
}
CreateKeyEmailFragment frag = CreateKeyEmailFragment.newInstance();
mCreateKeyActivity.loadFragment(frag, FragAction.TO_RIGHT);
}
}

View file

@ -23,15 +23,11 @@ import android.text.Editable;
import android.text.InputType;
import android.text.TextWatcher;
import android.util.AttributeSet;
import android.util.Patterns;
import android.view.inputmethod.EditorInfo;
import android.widget.ArrayAdapter;
import org.sufficientlysecure.keychain.R;
import org.sufficientlysecure.keychain.util.ContactHelper;
import java.util.regex.Matcher;
public class EmailEditText extends AppCompatAutoCompleteTextView {
public EmailEditText(Context context) {
@ -70,20 +66,7 @@ public class EmailEditText extends AppCompatAutoCompleteTextView {
@Override
public void afterTextChanged(Editable editable) {
String email = editable.toString();
if (email.length() > 0) {
Matcher emailMatcher = Patterns.EMAIL_ADDRESS.matcher(email);
if (emailMatcher.matches()) {
EmailEditText.this.setCompoundDrawablesWithIntrinsicBounds(0, 0,
R.drawable.ic_stat_retyped_ok, 0);
} else {
EmailEditText.this.setCompoundDrawablesWithIntrinsicBounds(0, 0,
R.drawable.ic_stat_retyped_bad, 0);
}
} else {
// remove drawable if email is empty
EmailEditText.this.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
}
}
};

View file

@ -39,7 +39,9 @@
android:layout_height="wrap_content"
android:layout_marginBottom="8dp"
android:layout_marginLeft="8dp"
android:textAppearance="?android:attr/textAppearanceMedium" />
android:textAppearance="?android:attr/textAppearanceMedium"
android:focusable="true"
android:focusableInTouchMode="true" />
<TextView
android:layout_width="match_parent"
@ -54,6 +56,8 @@
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textAppearance="?android:attr/textAppearanceMedium"
android:focusable="true"
android:focusableInTouchMode="true"
android:layout_marginBottom="8dp"
android:layout_marginLeft="8dp" />

View file

@ -768,6 +768,7 @@
<string name="create_key_passphrases_not_equal">"Passwords do not match"</string>
<string name="create_key_final_text">"You entered the following identity:"</string>
<string name="create_key_final_robot_text">"Creating a key may take a while, have a cup of coffee in the meantime…"</string>
<string name="create_key_final_email_valid_warning">"Many applications work better when provided with keys only containing valid email addresses"</string>
<string name="create_key_rsa">"(3 subkeys, RSA, 4096 bit)"</string>
<string name="create_key_custom">"(custom key configuration)"</string>
<string name="create_key_name_text">"Choose a name associated with this key. This can be a full name, e.g., 'John Doe', or a nickname, e.g., 'Johnny'."</string>
@ -778,7 +779,7 @@
<string name="create_key_add_email">"Add email address"</string>
<string name="create_key_add_email_text">"Additional email addresses are also associated to this key and can be used for secure communication."</string>
<string name="create_key_email_already_exists_text">"Email address has already been added"</string>
<string name="create_key_email_invalid_email">"Email address format is invalid"</string>
<string name="create_key_email_empty_email">"Email address can not be empty"</string>
<string name="create_key_yubi_key_pin_text">"Please choose a PIN with 6 numbers."</string>
<string name="create_key_yubi_key_admin_pin_text">"Please write down the Admin PIN and store it in a safe place (required when you used a wrong PIN 3 times)."</string>
<string name="create_key_yubi_key_pin">"PIN"</string>