bitwarden-mobile/src/App/Platforms/Android/Autofill/FilledItem.cs

228 lines
8.5 KiB
C#

using Android.Service.Autofill;
using Android.Views.Autofill;
using System.Linq;
using Bit.Core.Enums;
using Android.Views;
using Bit.Core.Models.View;
using Resource = Bit.Core.Resource;
namespace Bit.Droid.Autofill
{
public class FilledItem
{
private string _password;
private string _cardName;
private string _cardNumber;
private string _cardExpMonth;
private string _cardExpYear;
private string _cardCode;
private string _idPhone;
private string _idEmail;
private string _idUsername;
private string _idAddress;
private string _idPostalCode;
public FilledItem(CipherView cipher)
{
Id = cipher.Id;
Name = cipher.Name;
Type = cipher.Type;
Subtitle = cipher.SubTitle;
switch (Type)
{
case CipherType.Login:
Icon = Resource.Drawable.login;
_password = cipher.Login.Password;
break;
case CipherType.Card:
_cardNumber = cipher.Card.Number;
Icon = Resource.Drawable.card;
_cardName = cipher.Card.CardholderName;
_cardCode = cipher.Card.Code;
_cardExpMonth = cipher.Card.ExpMonth;
_cardExpYear = cipher.Card.ExpYear;
break;
case CipherType.Identity:
Icon = Resource.Drawable.id;
_idPhone = cipher.Identity.Phone;
_idEmail = cipher.Identity.Email;
_idUsername = cipher.Identity.Username;
_idAddress = cipher.Identity.FullAddress;
_idPostalCode = cipher.Identity.PostalCode;
break;
default:
Icon = Resource.Drawable.login;
break;
}
}
public string Id { get; set; }
public string Name { get; set; }
public string Subtitle { get; set; } = string.Empty;
public int Icon { get; set; } = Resource.Drawable.login;
public CipherType Type { get; set; }
public bool ApplyToFields(FieldCollection fieldCollection, Dataset.Builder datasetBuilder)
{
if (!fieldCollection?.Fields.Any() ?? true)
{
return false;
}
var setValues = false;
if (Type == CipherType.Login)
{
if (fieldCollection.PasswordFields.Any() && !string.IsNullOrWhiteSpace(_password))
{
foreach (var f in fieldCollection.PasswordFields)
{
var val = ApplyValue(f, _password);
if (val != null)
{
setValues = true;
datasetBuilder.SetValue(f.AutofillId, val);
}
}
}
if (fieldCollection.UsernameFields.Any() && !string.IsNullOrWhiteSpace(Subtitle))
{
foreach (var f in fieldCollection.UsernameFields)
{
var val = ApplyValue(f, Subtitle);
if (val != null)
{
setValues = true;
datasetBuilder.SetValue(f.AutofillId, val);
}
}
}
}
else if (Type == CipherType.Card)
{
if (ApplyValue(datasetBuilder, fieldCollection, Android.Views.View.AutofillHintCreditCardNumber,
_cardNumber))
{
setValues = true;
}
if (ApplyValue(datasetBuilder, fieldCollection, Android.Views.View.AutofillHintCreditCardSecurityCode,
_cardCode))
{
setValues = true;
}
if (ApplyValue(datasetBuilder, fieldCollection,
Android.Views.View.AutofillHintCreditCardExpirationMonth, _cardExpMonth, true))
{
setValues = true;
}
if (ApplyValue(datasetBuilder, fieldCollection, Android.Views.View.AutofillHintCreditCardExpirationYear,
_cardExpYear))
{
setValues = true;
}
if (ApplyValue(datasetBuilder, fieldCollection, Android.Views.View.AutofillHintName, _cardName))
{
setValues = true;
}
}
else if (Type == CipherType.Identity)
{
if (ApplyValue(datasetBuilder, fieldCollection, Android.Views.View.AutofillHintPhone, _idPhone))
{
setValues = true;
}
if (ApplyValue(datasetBuilder, fieldCollection, Android.Views.View.AutofillHintEmailAddress, _idEmail))
{
setValues = true;
}
if (ApplyValue(datasetBuilder, fieldCollection, Android.Views.View.AutofillHintUsername,
_idUsername))
{
setValues = true;
}
if (ApplyValue(datasetBuilder, fieldCollection, Android.Views.View.AutofillHintPostalAddress,
_idAddress))
{
setValues = true;
}
if (ApplyValue(datasetBuilder, fieldCollection, Android.Views.View.AutofillHintPostalCode,
_idPostalCode))
{
setValues = true;
}
if (ApplyValue(datasetBuilder, fieldCollection, Android.Views.View.AutofillHintName, Subtitle))
{
setValues = true;
}
}
return setValues;
}
private static bool ApplyValue(Dataset.Builder builder, FieldCollection fieldCollection,
string hint, string value, bool monthValue = false)
{
bool setValues = false;
if (fieldCollection.HintToFieldsMap.ContainsKey(hint) && !string.IsNullOrWhiteSpace(value))
{
foreach (var f in fieldCollection.HintToFieldsMap[hint])
{
var val = ApplyValue(f, value, monthValue);
if (val != null)
{
setValues = true;
builder.SetValue(f.AutofillId, val);
}
}
}
return setValues;
}
private static AutofillValue ApplyValue(Field field, string value, bool monthValue = false)
{
switch (field.AutofillType)
{
case AutofillType.Date:
if (long.TryParse(value, out long dateValue))
{
return AutofillValue.ForDate(dateValue);
}
break;
case AutofillType.List:
if (field.AutofillOptions != null)
{
if (monthValue && int.TryParse(value, out int monthIndex))
{
if (field.AutofillOptions.Count == 13)
{
return AutofillValue.ForList(monthIndex);
}
else if (field.AutofillOptions.Count >= monthIndex)
{
return AutofillValue.ForList(monthIndex - 1);
}
}
for (var i = 0; i < field.AutofillOptions.Count; i++)
{
if (field.AutofillOptions[i].Equals(value))
{
return AutofillValue.ForList(i);
}
}
}
break;
case AutofillType.Text:
return AutofillValue.ForText(value);
case AutofillType.Toggle:
if (bool.TryParse(value, out bool toggleValue))
{
return AutofillValue.ForToggle(toggleValue);
}
break;
default:
break;
}
return null;
}
}
}