625 lines
24 KiB
C#
625 lines
24 KiB
C#
/*
|
|
This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file is based on Keepassdroid, Copyright Brian Pellin.
|
|
|
|
Keepass2Android 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.
|
|
|
|
Keepass2Android 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 Keepass2Android. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
using System;
|
|
using System.Collections.Generic;
|
|
using System.Globalization;
|
|
using System.Linq;
|
|
using Android.App;
|
|
using Android.App.Admin;
|
|
using Android.Content;
|
|
using Android.Content.PM;
|
|
using Android.Graphics;
|
|
using Android.OS;
|
|
using Android.Preferences;
|
|
using Android.Views;
|
|
using Android.Widget;
|
|
using Google.Android.Material.Dialog;
|
|
using Java.Util;
|
|
using keepass2android;
|
|
using KeePassLib.Cryptography;
|
|
using Newtonsoft.Json;
|
|
using OtpKeyProv;
|
|
|
|
namespace keepass2android
|
|
{
|
|
[Activity(Label = "@string/app_name", Theme = "@style/Kp2aTheme_ActionBar", WindowSoftInputMode = SoftInput.StateHidden, ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.Keyboard | ConfigChanges.KeyboardHidden)]
|
|
public class GeneratePasswordActivity :
|
|
#if DEBUG
|
|
LifecycleAwareActivity
|
|
#else
|
|
LockCloseActivity
|
|
#endif
|
|
|
|
{
|
|
private readonly int[] _buttonLengthButtonIds = new[] {Resource.Id.btn_length6,
|
|
Resource.Id.btn_length8,
|
|
Resource.Id.btn_length12,
|
|
Resource.Id.btn_length16,
|
|
Resource.Id.btn_length24,
|
|
Resource.Id.btn_length32};
|
|
|
|
private readonly int[] _checkboxIds = new[] {Resource.Id.cb_uppercase,
|
|
Resource.Id.cb_lowercase,
|
|
Resource.Id.cb_digits,
|
|
Resource.Id.cb_minus,
|
|
Resource.Id.cb_underline,
|
|
Resource.Id.cb_space,
|
|
Resource.Id.cb_specials,
|
|
Resource.Id.cb_specials_extended,
|
|
Resource.Id.cb_brackets,
|
|
Resource.Id.cb_at_least_one_from_each_group,
|
|
Resource.Id.cb_exclude_lookalike
|
|
};
|
|
|
|
PasswordFont _passwordFont = new PasswordFont();
|
|
|
|
|
|
private ActivityDesign _design;
|
|
public GeneratePasswordActivity()
|
|
{
|
|
_design = new ActivityDesign(this);
|
|
}
|
|
|
|
public static void Launch(Activity act) {
|
|
Intent i = new Intent(act, typeof(GeneratePasswordActivity));
|
|
|
|
act.StartActivityForResult(i, 0);
|
|
}
|
|
|
|
public static void LaunchWithoutLockCheck(Activity act)
|
|
{
|
|
Intent i = new Intent(act, typeof(GeneratePasswordActivity));
|
|
|
|
#if DEBUG
|
|
#else
|
|
i.PutExtra(NoLockCheck, true);
|
|
#endif
|
|
|
|
act.StartActivityForResult(i, 0);
|
|
}
|
|
|
|
private PasswordProfiles _profiles;
|
|
|
|
private bool _updateDisabled = false;
|
|
|
|
class PasswordProfiles
|
|
{
|
|
public List<KeyValuePair<string, PasswordGenerator.CombinedKeyOptions>> Profiles { get; set; }
|
|
|
|
public PasswordGenerator.CombinedKeyOptions LastUsedSettings { get; set; }
|
|
|
|
public int? TryFindLastUsedProfileIndex()
|
|
{
|
|
for (int i=0;i<Profiles.Count;i++)
|
|
{
|
|
var kvp = Profiles[i];
|
|
if (kvp.Value.Equals(LastUsedSettings))
|
|
return i;
|
|
}
|
|
|
|
return null;
|
|
}
|
|
|
|
public void Add(string key, PasswordGenerator.CombinedKeyOptions options)
|
|
{
|
|
for (var index = 0; index < Profiles.Count; index++)
|
|
{
|
|
var kvp = Profiles[index];
|
|
if (kvp.Key == key)
|
|
{
|
|
Profiles[index] = new KeyValuePair<string, PasswordGenerator.CombinedKeyOptions>(key, options);
|
|
return;
|
|
}
|
|
}
|
|
|
|
Profiles.Add(new KeyValuePair<string, PasswordGenerator.CombinedKeyOptions>(key, options));
|
|
}
|
|
|
|
public void Remove(in int profileIndex)
|
|
{
|
|
Profiles.RemoveAt(profileIndex);
|
|
}
|
|
}
|
|
|
|
protected override void OnCreate(Bundle savedInstanceState) {
|
|
_design.ApplyTheme();
|
|
base.OnCreate(savedInstanceState);
|
|
|
|
SetContentView(Resource.Layout.generate_password);
|
|
SetResult(KeePass.ExitNormal);
|
|
|
|
|
|
var prefs = GetPreferences(FileCreationMode.Private);
|
|
|
|
|
|
|
|
string jsonOptions = prefs.GetString("password_generator_profiles", null);
|
|
if (jsonOptions != null)
|
|
{
|
|
try
|
|
{
|
|
_profiles = JsonConvert.DeserializeObject<PasswordProfiles>(jsonOptions);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Kp2aLog.LogUnexpectedError(e);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
PasswordGenerator.CombinedKeyOptions options = new PasswordGenerator.CombinedKeyOptions()
|
|
{
|
|
PasswordGenerationOptions = new PasswordGenerator.PasswordGenerationOptions()
|
|
{
|
|
Length = prefs.GetInt("length", 12),
|
|
UpperCase = prefs.GetBoolean("cb_uppercase", true),
|
|
LowerCase = prefs.GetBoolean("cb_lowercase", true),
|
|
Digits = prefs.GetBoolean("cb_digits", true),
|
|
Minus = prefs.GetBoolean("cb_minus", false),
|
|
Underline = prefs.GetBoolean("cb_underline", false),
|
|
Space = prefs.GetBoolean("cb_space", false),
|
|
Specials = prefs.GetBoolean("cb_specials", false),
|
|
SpecialsExtended = false,
|
|
Brackets = prefs.GetBoolean("cb_brackets", false)
|
|
}
|
|
};
|
|
_profiles = new PasswordProfiles()
|
|
{
|
|
LastUsedSettings = options,
|
|
Profiles = GetDefaultProfiles()
|
|
};
|
|
|
|
}
|
|
|
|
_profiles ??= new PasswordProfiles();
|
|
_profiles.LastUsedSettings ??= new PasswordGenerator.CombinedKeyOptions()
|
|
{
|
|
PasswordGenerationOptions = new PasswordGenerator.PasswordGenerationOptions()
|
|
{Length = 7, UpperCase = true, LowerCase = true, Digits = true}
|
|
};
|
|
_profiles.Profiles ??= new List<KeyValuePair<string, PasswordGenerator.CombinedKeyOptions>>();
|
|
|
|
_updateDisabled = true;
|
|
PopulateFieldsFromOptions(_profiles.LastUsedSettings);
|
|
_updateDisabled = false;
|
|
|
|
|
|
var profileSpinner = UpdateProfileSpinner();
|
|
|
|
profileSpinner.ItemSelected += (sender, args) =>
|
|
{
|
|
if (profileSpinner.SelectedItemPosition > 0)
|
|
{
|
|
_profiles.LastUsedSettings = _profiles.Profiles[profileSpinner.SelectedItemPosition - 1].Value;
|
|
_updateDisabled = true;
|
|
PopulateFieldsFromOptions(_profiles.LastUsedSettings);
|
|
_updateDisabled = false;
|
|
UpdatePassword();
|
|
}
|
|
};
|
|
|
|
foreach (int id in _buttonLengthButtonIds) {
|
|
Button button = (Button) FindViewById(id);
|
|
button.Click += (sender, e) =>
|
|
{
|
|
Button b = (Button) sender;
|
|
|
|
EditText editText = (EditText) FindViewById(Resource.Id.length);
|
|
editText.Text = b.Text;
|
|
};
|
|
}
|
|
|
|
FindViewById<EditText>(Resource.Id.length).TextChanged += (sender, args) => UpdatePassword();
|
|
FindViewById<EditText>(Resource.Id.wordcount).TextChanged += (sender, args) => UpdatePassword();
|
|
FindViewById<EditText>(Resource.Id.wordseparator).TextChanged += (sender, args) => UpdatePassword();
|
|
|
|
foreach (int id in _checkboxIds)
|
|
{
|
|
FindViewById<CheckBox>(id).CheckedChange += (sender, args) => UpdatePassword();
|
|
}
|
|
|
|
var mode_spinner = FindViewById<Spinner>(Resource.Id.spinner_password_generator_mode);
|
|
mode_spinner.ItemSelected += (sender, args) =>
|
|
{
|
|
FindViewById(Resource.Id.passphraseOptions).Visibility =
|
|
mode_spinner.SelectedItemPosition == 0 ? ViewStates.Gone : ViewStates.Visible;
|
|
FindViewById(Resource.Id.passwordOptions).Visibility =
|
|
mode_spinner.SelectedItemPosition == 1 ? ViewStates.Gone : ViewStates.Visible;
|
|
|
|
UpdatePassword();
|
|
};
|
|
|
|
FindViewById<Spinner>(Resource.Id.spinner_password_generator_case_mode).ItemSelected += (sender, args) =>
|
|
{
|
|
UpdatePassword();
|
|
};
|
|
|
|
Button genPassButton = (Button) FindViewById(Resource.Id.generate_password_button);
|
|
genPassButton.Click += (sender, e) => { UpdatePassword(); };
|
|
|
|
|
|
|
|
View acceptButton = FindViewById(Resource.Id.accept_button);
|
|
acceptButton.Click += (sender, e) => {
|
|
EditText password = (EditText) FindViewById(Resource.Id.password_edit);
|
|
|
|
Intent intent = new Intent();
|
|
intent.PutExtra("keepass2android.password.generated_password", password.Text);
|
|
|
|
SetResult(KeePass.ResultOkPasswordGenerator, intent);
|
|
|
|
Finish();
|
|
};
|
|
|
|
|
|
View cancelButton = FindViewById(Resource.Id.cancel_button);
|
|
cancelButton.Click += (sender, e) =>
|
|
{
|
|
SetResult(Result.Canceled);
|
|
|
|
Finish();
|
|
};
|
|
|
|
FindViewById(Resource.Id.btn_password_generator_profile_save)
|
|
.Click += (sender, args) =>
|
|
{
|
|
var editText = new EditText(this);
|
|
new MaterialAlertDialogBuilder(this)
|
|
.SetMessage(Resource.String.save_password_generation_profile_text)
|
|
.SetView(editText)
|
|
.SetPositiveButton(Android.Resource.String.Ok, (o, eventArgs) =>
|
|
{
|
|
_profiles.Add(editText.Text, GetOptions());
|
|
UpdateProfileSpinner();
|
|
})
|
|
.Show();
|
|
};
|
|
|
|
FindViewById(Resource.Id.btn_password_generator_profile_delete)
|
|
.Click += (sender, args) =>
|
|
{
|
|
if (profileSpinner.SelectedItemPosition > 0)
|
|
{
|
|
_profiles.Remove(profileSpinner.SelectedItemPosition-1);
|
|
UpdateProfileSpinner();
|
|
}
|
|
};
|
|
|
|
|
|
EditText txtPasswordToSet = (EditText) FindViewById(Resource.Id.password_edit);
|
|
|
|
_passwordFont.ApplyTo(txtPasswordToSet);
|
|
|
|
UpdatePassword();
|
|
|
|
SupportActionBar.SetDisplayHomeAsUpEnabled(true);
|
|
SupportActionBar.SetHomeButtonEnabled(true);
|
|
|
|
}
|
|
|
|
private Spinner UpdateProfileSpinner()
|
|
{
|
|
string[] profileNames = new List<string> {GetString(Resource.String.custom_settings)}
|
|
.Concat(_profiles.Profiles.Select(p => p.Key))
|
|
.ToArray();
|
|
ArrayAdapter<String> profileArrayAdapter = new ArrayAdapter<String>(this,
|
|
Android.Resource.Layout.SimpleSpinnerDropDownItem,
|
|
profileNames);
|
|
var profileSpinner = FindViewById<Spinner>(Resource.Id.spinner_password_generator_profile);
|
|
profileSpinner.Adapter = profileArrayAdapter;
|
|
|
|
UpdateProfileSpinnerSelection();
|
|
return profileSpinner;
|
|
}
|
|
|
|
private static List<KeyValuePair<string, PasswordGenerator.CombinedKeyOptions>> GetDefaultProfiles()
|
|
{
|
|
return new List<KeyValuePair<string, PasswordGenerator.CombinedKeyOptions>>()
|
|
{
|
|
new KeyValuePair<string, PasswordGenerator.CombinedKeyOptions>(
|
|
"Simple12", new PasswordGenerator.CombinedKeyOptions()
|
|
{
|
|
PasswordGenerationOptions
|
|
= new PasswordGenerator.PasswordGenerationOptions()
|
|
{
|
|
Length = 12, AtLeastOneFromEachGroup = true, ExcludeLookAlike = true,
|
|
Digits = true, LowerCase = true, UpperCase = true
|
|
}
|
|
|
|
}
|
|
),
|
|
new KeyValuePair<string, PasswordGenerator.CombinedKeyOptions>(
|
|
"Special12", new PasswordGenerator.CombinedKeyOptions()
|
|
{
|
|
PasswordGenerationOptions
|
|
= new PasswordGenerator.PasswordGenerationOptions()
|
|
{
|
|
Length = 12, AtLeastOneFromEachGroup = true, ExcludeLookAlike = true,
|
|
Digits = true, LowerCase = true, UpperCase = true,Specials = true,Brackets = true
|
|
}
|
|
|
|
}
|
|
),
|
|
new KeyValuePair<string, PasswordGenerator.CombinedKeyOptions>(
|
|
"Password64", new PasswordGenerator.CombinedKeyOptions()
|
|
{
|
|
PasswordGenerationOptions
|
|
= new PasswordGenerator.PasswordGenerationOptions()
|
|
{
|
|
Length = 64, AtLeastOneFromEachGroup = true,
|
|
Digits = true, LowerCase = true, UpperCase = true, ExcludeLookAlike = false,Specials = true,Brackets = true, Minus = true, Space = true, SpecialsExtended = true,Underline = true
|
|
}
|
|
|
|
}
|
|
),
|
|
new KeyValuePair<string, PasswordGenerator.CombinedKeyOptions>(
|
|
|
|
"Passphrase7", new PasswordGenerator.CombinedKeyOptions()
|
|
{
|
|
PassphraseGenerationOptions
|
|
= new PasswordGenerator.PassphraseGenerationOptions()
|
|
{
|
|
WordCount = 7,
|
|
CaseMode = PasswordGenerator.PassphraseGenerationOptions.PassphraseCaseMode.Lowercase,
|
|
Separator = " "
|
|
}
|
|
}
|
|
),
|
|
new KeyValuePair<string, PasswordGenerator.CombinedKeyOptions>(
|
|
"Passphrase5Plus", new PasswordGenerator.CombinedKeyOptions()
|
|
{
|
|
PassphraseGenerationOptions
|
|
= new PasswordGenerator.PassphraseGenerationOptions()
|
|
{
|
|
WordCount = 5,
|
|
CaseMode = PasswordGenerator.PassphraseGenerationOptions.PassphraseCaseMode.PascalCase,
|
|
Separator = " "
|
|
},
|
|
PasswordGenerationOptions = new PasswordGenerator.PasswordGenerationOptions()
|
|
{
|
|
Length = 2,
|
|
AtLeastOneFromEachGroup = true,
|
|
ExcludeLookAlike = true,
|
|
Digits = true,
|
|
Specials = true
|
|
}
|
|
}
|
|
)
|
|
|
|
};
|
|
}
|
|
|
|
private void PopulateFieldsFromOptions(PasswordGenerator.CombinedKeyOptions combinedOptions)
|
|
{
|
|
PasswordGenerator.PasswordGenerationOptions passwordOptions = combinedOptions.PasswordGenerationOptions;
|
|
if (passwordOptions != null)
|
|
{
|
|
((CheckBox)FindViewById(Resource.Id.cb_uppercase)).Checked = passwordOptions.UpperCase;
|
|
((CheckBox)FindViewById(Resource.Id.cb_lowercase)).Checked = passwordOptions.LowerCase;
|
|
((CheckBox)FindViewById(Resource.Id.cb_digits)).Checked = passwordOptions.Digits;
|
|
((CheckBox)FindViewById(Resource.Id.cb_minus)).Checked = passwordOptions.Minus;
|
|
((CheckBox)FindViewById(Resource.Id.cb_underline)).Checked = passwordOptions.Underline;
|
|
((CheckBox)FindViewById(Resource.Id.cb_space)).Checked = passwordOptions.Space;
|
|
((CheckBox)FindViewById(Resource.Id.cb_specials)).Checked = passwordOptions.Specials;
|
|
((CheckBox)FindViewById(Resource.Id.cb_specials_extended)).Checked = passwordOptions.SpecialsExtended;
|
|
((CheckBox)FindViewById(Resource.Id.cb_brackets)).Checked = passwordOptions.Brackets;
|
|
((CheckBox)FindViewById(Resource.Id.cb_exclude_lookalike)).Checked = passwordOptions.ExcludeLookAlike;
|
|
((CheckBox)FindViewById(Resource.Id.cb_at_least_one_from_each_group)).Checked = passwordOptions.AtLeastOneFromEachGroup;
|
|
|
|
((EditText)FindViewById(Resource.Id.length)).Text = passwordOptions.Length.ToString(CultureInfo.InvariantCulture);
|
|
|
|
FindViewById(Resource.Id.passwordOptions).Visibility = ViewStates.Visible;
|
|
}
|
|
else
|
|
{
|
|
FindViewById(Resource.Id.passwordOptions).Visibility = ViewStates.Gone;
|
|
}
|
|
|
|
var passphraseOptions = combinedOptions.PassphraseGenerationOptions;
|
|
|
|
if (passphraseOptions != null)
|
|
{
|
|
FindViewById<EditText>(Resource.Id.wordcount).Text = passphraseOptions.WordCount.ToString(CultureInfo.InvariantCulture);
|
|
FindViewById<EditText>(Resource.Id.wordseparator).Text = passphraseOptions.Separator;
|
|
FindViewById<Spinner>(Resource.Id.spinner_password_generator_case_mode)
|
|
.SetSelection((int)passphraseOptions.CaseMode);
|
|
|
|
FindViewById(Resource.Id.passphraseOptions).Visibility = ViewStates.Visible;
|
|
}
|
|
else
|
|
{
|
|
FindViewById(Resource.Id.passphraseOptions).Visibility = ViewStates.Gone;
|
|
}
|
|
|
|
|
|
int mode;
|
|
if (combinedOptions.PasswordGenerationOptions != null &&
|
|
combinedOptions.PassphraseGenerationOptions != null)
|
|
mode = 2;
|
|
else if (combinedOptions.PasswordGenerationOptions == null &&
|
|
combinedOptions.PassphraseGenerationOptions != null)
|
|
mode = 1;
|
|
else mode = 0;
|
|
|
|
FindViewById<Spinner>(Resource.Id.spinner_password_generator_mode)
|
|
.SetSelection(mode);
|
|
|
|
}
|
|
|
|
private void UpdatePassword()
|
|
{
|
|
if (_updateDisabled)
|
|
return;
|
|
|
|
String password = "";
|
|
uint passwordBits = 0;
|
|
|
|
Task.Run(() =>
|
|
{
|
|
password = GeneratePassword();
|
|
passwordBits = QualityEstimation.EstimatePasswordBits(password.ToCharArray());
|
|
RunOnUiThread(() =>
|
|
{
|
|
EditText txtPassword = (EditText)FindViewById(Resource.Id.password_edit);
|
|
txtPassword.Text = password;
|
|
|
|
var progressBar = FindViewById<ProgressBar>(Resource.Id.pb_password_strength);
|
|
|
|
progressBar.Progress = (int)passwordBits;
|
|
progressBar.Max = 128;
|
|
|
|
Color color = new Color(196, 63, 49);
|
|
if (passwordBits > 40)
|
|
{
|
|
color = new Color(219, 152, 55);
|
|
}
|
|
|
|
if (passwordBits > 64)
|
|
{
|
|
color = new Color(96, 138, 38);
|
|
}
|
|
|
|
if (passwordBits > 100)
|
|
{
|
|
color = new Color(31, 128, 31);
|
|
}
|
|
|
|
progressBar.ProgressDrawable.SetColorFilter(new PorterDuffColorFilter(color,
|
|
PorterDuff.Mode.SrcIn));
|
|
|
|
FindViewById<TextView>(Resource.Id.tv_password_strength).Text = " " + passwordBits + " bits";
|
|
|
|
|
|
|
|
UpdateProfileSpinnerSelection();
|
|
});
|
|
});
|
|
|
|
}
|
|
|
|
private void UpdateProfileSpinnerSelection()
|
|
{
|
|
int? lastUsedIndex = _profiles.TryFindLastUsedProfileIndex();
|
|
FindViewById<Spinner>(Resource.Id.spinner_password_generator_profile)
|
|
.SetSelection(lastUsedIndex != null ? lastUsedIndex.Value + 1 : 0);
|
|
}
|
|
|
|
public String GeneratePassword() {
|
|
String password = "";
|
|
|
|
try
|
|
{
|
|
PasswordGenerator generator = new PasswordGenerator(this);
|
|
|
|
var options = GetOptions();
|
|
|
|
try
|
|
{
|
|
password = generator.GeneratePassword(options);
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
throw new ArgumentException(GetString(Resource.String.error_pass_gen_type));
|
|
}
|
|
|
|
_profiles.LastUsedSettings = options;
|
|
|
|
SaveProfiles();
|
|
}
|
|
catch (Exception e)
|
|
{
|
|
Toast.MakeText(this, e.Message, ToastLength.Long).Show();
|
|
}
|
|
|
|
return password;
|
|
}
|
|
|
|
private void SaveProfiles()
|
|
{
|
|
var prefs = GetPreferences(FileCreationMode.Private);
|
|
prefs.Edit()
|
|
.PutString("password_generator_profiles", JsonConvert.SerializeObject(_profiles))
|
|
.Commit();
|
|
}
|
|
|
|
private PasswordGenerator.CombinedKeyOptions GetOptions()
|
|
{
|
|
PasswordGenerator.CombinedKeyOptions options = new PasswordGenerator.CombinedKeyOptions();
|
|
if (FindViewById(Resource.Id.passphraseOptions).Visibility == ViewStates.Visible)
|
|
{
|
|
int wordCount;
|
|
if (!int.TryParse(((EditText)FindViewById(Resource.Id.wordcount)).Text, out wordCount))
|
|
{
|
|
throw new Exception(GetString(Resource.String.error_wrong_length));
|
|
}
|
|
|
|
options.PassphraseGenerationOptions =
|
|
new PasswordGenerator.PassphraseGenerationOptions()
|
|
{
|
|
WordCount = wordCount,
|
|
Separator = FindViewById<EditText>(Resource.Id.wordseparator).Text,
|
|
CaseMode = (PasswordGenerator.PassphraseGenerationOptions.PassphraseCaseMode)FindViewById<Spinner>(Resource.Id.spinner_password_generator_case_mode).SelectedItemPosition
|
|
};
|
|
}
|
|
|
|
if (FindViewById(Resource.Id.passwordOptions).Visibility == ViewStates.Visible)
|
|
{
|
|
int length;
|
|
if (!int.TryParse(((EditText) FindViewById(Resource.Id.length)).Text, out length))
|
|
{
|
|
throw new Exception(GetString(Resource.String.error_wrong_length));
|
|
}
|
|
|
|
options.PasswordGenerationOptions =
|
|
new PasswordGenerator.PasswordGenerationOptions()
|
|
{
|
|
Length = length,
|
|
UpperCase = ((CheckBox) FindViewById(Resource.Id.cb_uppercase)).Checked,
|
|
LowerCase = ((CheckBox) FindViewById(Resource.Id.cb_lowercase)).Checked,
|
|
Digits = ((CheckBox) FindViewById(Resource.Id.cb_digits)).Checked,
|
|
Minus = ((CheckBox) FindViewById(Resource.Id.cb_minus)).Checked,
|
|
Underline = ((CheckBox) FindViewById(Resource.Id.cb_underline)).Checked,
|
|
Space = ((CheckBox) FindViewById(Resource.Id.cb_space)).Checked,
|
|
Specials = ((CheckBox) FindViewById(Resource.Id.cb_specials)).Checked,
|
|
SpecialsExtended = ((CheckBox) FindViewById(Resource.Id.cb_specials_extended)).Checked,
|
|
Brackets = ((CheckBox) FindViewById(Resource.Id.cb_brackets)).Checked,
|
|
ExcludeLookAlike = ((CheckBox) FindViewById(Resource.Id.cb_exclude_lookalike)).Checked,
|
|
AtLeastOneFromEachGroup = ((CheckBox) FindViewById(Resource.Id.cb_at_least_one_from_each_group))
|
|
.Checked
|
|
};
|
|
}
|
|
|
|
return options;
|
|
}
|
|
|
|
|
|
public override bool OnOptionsItemSelected(IMenuItem item)
|
|
{
|
|
switch (item.ItemId)
|
|
{
|
|
case Android.Resource.Id.Home:
|
|
OnBackPressed();
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
|
|
}
|
|
|