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 {
*
s | generate completely random passwords |
* v | don't include vowels |
* y | include at least one symbol |
+ * L | don'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 {
* 1 | include at least one uppercase letter |
* 2 | include at least one symbol |
* 3 | don't include ambiguous characters |
+ * 5 | include 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 {
* 2 | include at least one symbol |
* 3 | don't include ambiguous characters |
* 4 | don't include vowels |
+ * 5 | include 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