diff --git a/app/src/main/java/com/zeapo/pwdstore/PasswordGeneratorDialogFragment.java b/app/src/main/java/com/zeapo/pwdstore/PasswordGeneratorDialogFragment.java index f161b927..698ec495 100644 --- a/app/src/main/java/com/zeapo/pwdstore/PasswordGeneratorDialogFragment.java +++ b/app/src/main/java/com/zeapo/pwdstore/PasswordGeneratorDialogFragment.java @@ -13,9 +13,13 @@ import android.widget.Button; import android.widget.CheckBox; import android.widget.EditText; import android.widget.TextView; +import android.widget.Toast; + import androidx.appcompat.app.AlertDialog; import androidx.fragment.app.DialogFragment; + import com.zeapo.pwdstore.pwgen.PasswordGenerator; + import org.jetbrains.annotations.NotNull; import java.util.ArrayList; @@ -53,6 +57,9 @@ public class PasswordGeneratorDialogFragment extends DialogFragment { checkBox = view.findViewById(R.id.uppercase); checkBox.setChecked(!prefs.getBoolean("A", false)); + checkBox = view.findViewById(R.id.lowercase); + checkBox.setChecked(!prefs.getBoolean("L", false)); + checkBox = view.findViewById(R.id.ambiguous); checkBox.setChecked(!prefs.getBoolean("B", false)); @@ -79,12 +86,22 @@ public class PasswordGeneratorDialogFragment extends DialogFragment { final AlertDialog ad = builder.setTitle(this.getResources().getString(R.string.pwgen_title)).create(); ad.setOnShowListener(dialog -> { setPreferences(); - passwordText.setText(PasswordGenerator.INSTANCE.generate(getActivity().getApplicationContext()).get(0)); + try { + passwordText.setText(PasswordGenerator.INSTANCE.generate(getActivity().getApplicationContext()).get(0)); + } catch (PasswordGenerator.PasswordGeneratorExeption e) { + Toast.makeText(getActivity(), e.getMessage(), Toast.LENGTH_SHORT).show(); + passwordText.setText(""); + } Button b = ad.getButton(AlertDialog.BUTTON_NEUTRAL); b.setOnClickListener(v -> { setPreferences(); - passwordText.setText(PasswordGenerator.INSTANCE.generate(callingActivity.getApplicationContext()).get(0)); + try { + passwordText.setText(PasswordGenerator.INSTANCE.generate(callingActivity.getApplicationContext()).get(0)); + } catch (PasswordGenerator.PasswordGeneratorExeption e) { + Toast.makeText(getActivity(), e.getMessage(), Toast.LENGTH_SHORT).show(); + passwordText.setText(""); + } }); }); return ad; @@ -107,6 +124,10 @@ public class PasswordGeneratorDialogFragment extends DialogFragment { if (!((CheckBox) getDialog().findViewById(R.id.pronounceable)).isChecked()) { preferences.add("s"); } + if (!((CheckBox) getDialog().findViewById(R.id.lowercase)).isChecked()) { + preferences.add("L"); + } + EditText editText = getDialog().findViewById(R.id.lengthNumber); try { int length = Integer.valueOf(editText.getText().toString()); diff --git a/app/src/main/java/com/zeapo/pwdstore/pwgen/PasswordGenerator.kt b/app/src/main/java/com/zeapo/pwdstore/pwgen/PasswordGenerator.kt index 3a7dcc27..6132d2dc 100644 --- a/app/src/main/java/com/zeapo/pwdstore/pwgen/PasswordGenerator.kt +++ b/app/src/main/java/com/zeapo/pwdstore/pwgen/PasswordGenerator.kt @@ -1,15 +1,19 @@ package com.zeapo.pwdstore.pwgen import android.content.Context +import com.zeapo.pwdstore.R import java.util.ArrayList + + object PasswordGenerator { internal const val DIGITS = 0x0001 internal const val UPPERS = 0x0002 internal const val SYMBOLS = 0x0004 internal const val AMBIGUOUS = 0x0008 internal const val NO_VOWELS = 0x0010 + internal const val LOWERS = 0x0020 internal const val DIGITS_STR = "0123456789" internal const val UPPERS_STR = "ABCDEFGHIJKLMNOPQRSTUVWXYZ" @@ -19,7 +23,7 @@ object PasswordGenerator { internal const val VOWELS_STR = "01aeiouyAEIOUY" // No a, c, n, h, H, C, 1, N - private const val pwOptions = "0ABsvy" + private const val pwOptions = "0ABsvyL" /** * Sets password generation preferences. @@ -35,6 +39,7 @@ object PasswordGenerator { * sgenerate completely random passwords * vdon't include vowels * yinclude at least one symbol + * Ldon't include lowercase letters * * @param numArgv numerical options for password generation: length of * generated passwords followed by number of passwords to @@ -76,17 +81,19 @@ object PasswordGenerator { * preferences file 'PasswordGenerator' * @return list of generated passwords */ + @Throws(PasswordGenerator.PasswordGeneratorExeption::class) fun generate(ctx: Context): ArrayList { val prefs = ctx.getSharedPreferences("PasswordGenerator", Context.MODE_PRIVATE) var phonemes = true - var pwgenFlags = DIGITS or UPPERS + var pwgenFlags = DIGITS or UPPERS or LOWERS for (option in pwOptions.toCharArray()) { if (prefs.getBoolean(option.toString(), false)) { when (option) { '0' -> pwgenFlags = pwgenFlags and DIGITS.inv() 'A' -> pwgenFlags = pwgenFlags and UPPERS.inv() + 'L' -> pwgenFlags = pwgenFlags and LOWERS.inv() 'B' -> pwgenFlags = pwgenFlags or AMBIGUOUS 's' -> phonemes = false 'y' -> pwgenFlags = pwgenFlags or SYMBOLS @@ -99,15 +106,27 @@ object PasswordGenerator { } val length = prefs.getInt("length", 8) - if (length < 5) { + var numCategories = 0 + var categories = pwgenFlags and AMBIGUOUS.inv() + + while (categories != 0) { + if (categories and 1 == 1) + numCategories++ + categories = categories shr 1 + } + if (numCategories == 0) { + throw PasswordGeneratorExeption(ctx.resources.getString(R.string.pwgen_no_chars_error)) + } + if (length < numCategories) { + throw PasswordGeneratorExeption(ctx.resources.getString(R.string.pwgen_length_too_short_error)) + } + if ((pwgenFlags and UPPERS) == 0 && (pwgenFlags and LOWERS) == 0) { // Only digits and/or symbols + phonemes = false + pwgenFlags = pwgenFlags and AMBIGUOUS.inv() + } else if (length < 5) { phonemes = false } - if (length <= 2) { - pwgenFlags = pwgenFlags and UPPERS.inv() - } - if (length <= 1) { - pwgenFlags = pwgenFlags and DIGITS.inv() - } + val passwords = ArrayList() val num = prefs.getInt("num", 1) @@ -120,5 +139,7 @@ object PasswordGenerator { } return passwords } + + public class PasswordGeneratorExeption(string: String) : Exception(string) } diff --git a/app/src/main/java/com/zeapo/pwdstore/pwgen/Phonemes.kt b/app/src/main/java/com/zeapo/pwdstore/pwgen/Phonemes.kt index 4ec204bc..24d1edef 100644 --- a/app/src/main/java/com/zeapo/pwdstore/pwgen/Phonemes.kt +++ b/app/src/main/java/com/zeapo/pwdstore/pwgen/Phonemes.kt @@ -65,6 +65,7 @@ internal object Phonemes { * 1include at least one uppercase letter * 2include at least one symbol * 3don't include ambiguous characters + * 5include at least one lowercase letter * * @return the generated password */ @@ -119,7 +120,8 @@ internal object Phonemes { // Handle UPPERS if (pwFlags and PasswordGenerator.UPPERS > 0) { - if ((first || flags and CONSONANT > 0) && RandomNumberGenerator.number(10) < 2) { + if ((pwFlags and PasswordGenerator.LOWERS == 0) || + (first || flags and CONSONANT > 0) && RandomNumberGenerator.number(10) < 2) { val index = password.length - length password = password.substring(0, index) + str.toUpperCase() featureFlags = featureFlags and PasswordGenerator.UPPERS.inv() @@ -131,6 +133,17 @@ internal object Phonemes { for (ambiguous in PasswordGenerator.AMBIGUOUS_STR.toCharArray()) { if (password.contains(ambiguous.toString())) { password = password.substring(0, curSize) + + // Still have upper letters + if ((pwFlags and PasswordGenerator.UPPERS) > 0) { + featureFlags = featureFlags or PasswordGenerator.UPPERS + for (upper in PasswordGenerator.UPPERS_STR.toCharArray()) { + if (password.contains(upper.toString())) { + featureFlags = featureFlags and PasswordGenerator.UPPERS.inv() + break + } + } + } break } } diff --git a/app/src/main/java/com/zeapo/pwdstore/pwgen/RandomPasswordGenerator.kt b/app/src/main/java/com/zeapo/pwdstore/pwgen/RandomPasswordGenerator.kt index 632fa579..5e565c0e 100644 --- a/app/src/main/java/com/zeapo/pwdstore/pwgen/RandomPasswordGenerator.kt +++ b/app/src/main/java/com/zeapo/pwdstore/pwgen/RandomPasswordGenerator.kt @@ -15,6 +15,7 @@ internal object RandomPasswordGenerator { * 2include at least one symbol * 3don't include ambiguous characters * 4don't include vowels + * 5include at least one lowercase * * @return the generated password */ @@ -33,7 +34,9 @@ internal object RandomPasswordGenerator { if (pwFlags and PasswordGenerator.UPPERS > 0) { bank += PasswordGenerator.UPPERS_STR } - bank += PasswordGenerator.LOWERS_STR + if (pwFlags and PasswordGenerator.LOWERS > 0) { + bank += PasswordGenerator.LOWERS_STR + } if (pwFlags and PasswordGenerator.SYMBOLS > 0) { bank += PasswordGenerator.SYMBOLS_STR } @@ -65,8 +68,11 @@ internal object RandomPasswordGenerator { if (PasswordGenerator.SYMBOLS_STR.contains(`val`)) { featureFlags = featureFlags and PasswordGenerator.SYMBOLS.inv() } + if (PasswordGenerator.LOWERS_STR.contains(`val`)) { + featureFlags = featureFlags and PasswordGenerator.LOWERS.inv() + } } - } while (featureFlags and (PasswordGenerator.UPPERS or PasswordGenerator.DIGITS or PasswordGenerator.SYMBOLS) > 0) + } while (featureFlags and (PasswordGenerator.UPPERS or PasswordGenerator.DIGITS or PasswordGenerator.SYMBOLS or PasswordGenerator.LOWERS) > 0) return password } } diff --git a/app/src/main/res/layout/fragment_pwgen.xml b/app/src/main/res/layout/fragment_pwgen.xml index b5293920..eab23f7c 100644 --- a/app/src/main/res/layout/fragment_pwgen.xml +++ b/app/src/main/res/layout/fragment_pwgen.xml @@ -62,10 +62,10 @@ android:text="@string/pwgen_uppercase" /> + android:text="@string/pwgen_lowercase" /> @@ -97,6 +97,12 @@ android:layout_height="wrap_content" android:text="@string/pwgen_pronounceable" /> + + diff --git a/app/src/main/res/values-es/strings.xml b/app/src/main/res/values-es/strings.xml index 392be07f..84d1f7b9 100644 --- a/app/src/main/res/values-es/strings.xml +++ b/app/src/main/res/values-es/strings.xml @@ -166,8 +166,11 @@ Números Símbolos Mayúsculas + Minúsculas Caracteres ambiguos Pronunciable + No se han incluído caracteres + Longitud demasiado corta para el criterio seleccionado Longitud diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 0b1afda1..ba0fed4c 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -180,8 +180,11 @@ Numerals Symbols Uppercase + Lowercase Ambiguous Pronounceable + No characters included + Length too short for selected criteria Length