diff --git a/src/Android/Resources/Resource.Designer.cs b/src/Android/Resources/Resource.Designer.cs index 3ffd358ea..c937e355e 100644 --- a/src/Android/Resources/Resource.Designer.cs +++ b/src/Android/Resources/Resource.Designer.cs @@ -6475,17 +6475,17 @@ namespace Bit.Android // aapt resource value: 0x7f090051 public const int ApplicationName = 2131296337; - // aapt resource value: 0x7f0900ab - public const int AutoFillServiceDescription = 2131296427; + // aapt resource value: 0x7f0900b2 + public const int AutoFillServiceDescription = 2131296434; - // aapt resource value: 0x7f0900aa - public const int AutoFillServiceSummary = 2131296426; + // aapt resource value: 0x7f0900b1 + public const int AutoFillServiceSummary = 2131296433; // aapt resource value: 0x7f090050 public const int Hello = 2131296336; - // aapt resource value: 0x7f0900ac - public const int MyVault = 2131296428; + // aapt resource value: 0x7f0900b3 + public const int MyVault = 2131296435; // aapt resource value: 0x7f090027 public const int abc_action_bar_home_description = 2131296295; @@ -6640,6 +6640,27 @@ namespace Bit.Android // aapt resource value: 0x7f09000f public const int common_signin_button_text_long = 2131296271; + // aapt resource value: 0x7f0900ac + public const int default_web_client_id = 2131296428; + + // aapt resource value: 0x7f0900ad + public const int firebase_database_url = 2131296429; + + // aapt resource value: 0x7f0900aa + public const int gcm_defaultSenderId = 2131296426; + + // aapt resource value: 0x7f0900ae + public const int google_api_key = 2131296430; + + // aapt resource value: 0x7f0900ab + public const int google_app_id = 2131296427; + + // aapt resource value: 0x7f0900af + public const int google_crash_reporting_api_key = 2131296431; + + // aapt resource value: 0x7f0900b0 + public const int google_storage_bucket = 2131296432; + // aapt resource value: 0x7f090052 public const int hockeyapp_crash_dialog_app_name_fallback = 2131296338; diff --git a/src/App/Controls/FormEntryCell.cs b/src/App/Controls/FormEntryCell.cs index 9193e887d..eecaab319 100644 --- a/src/App/Controls/FormEntryCell.cs +++ b/src/App/Controls/FormEntryCell.cs @@ -1,6 +1,7 @@ using Bit.App.Abstractions; using FFImageLoading.Forms; using System; +using System.Collections.Generic; using Xamarin.Forms; using XLabs.Ioc; @@ -150,6 +151,7 @@ namespace Bit.App.Controls } } } + public Dictionary MetaData { get; set; } public void InitEvents() { diff --git a/src/App/Pages/Vault/VaultAddCipherPage.cs b/src/App/Pages/Vault/VaultAddCipherPage.cs index 169a5feb9..fbec59733 100644 --- a/src/App/Pages/Vault/VaultAddCipherPage.cs +++ b/src/App/Pages/Vault/VaultAddCipherPage.cs @@ -452,7 +452,7 @@ namespace Bit.App.Pages TextColor = Colors.Primary }; UrisSection.Add(AddUriCell); - UrisSection.Insert(0, Helpers.MakeUriCell(string.Empty, UrisSection)); + UrisSection.Insert(0, Helpers.MakeUriCell(string.Empty, null, UrisSection, this)); } else if(_type == CipherType.Card) { @@ -833,7 +833,7 @@ namespace Bit.App.Pages private void AddUriCell_Tapped(object sender, EventArgs e) { - var cell = Helpers.MakeUriCell(string.Empty, UrisSection); + var cell = Helpers.MakeUriCell(string.Empty, null, UrisSection, this); if(cell != null) { UrisSection.Insert(UrisSection.Count - 1, cell); diff --git a/src/App/Pages/Vault/VaultEditCipherPage.cs b/src/App/Pages/Vault/VaultEditCipherPage.cs index 203de6904..9aa2c8f93 100644 --- a/src/App/Pages/Vault/VaultEditCipherPage.cs +++ b/src/App/Pages/Vault/VaultEditCipherPage.cs @@ -223,7 +223,8 @@ namespace Bit.App.Pages foreach(var uri in Cipher.Login.Uris) { var value = uri.Uri?.Decrypt(Cipher.OrganizationId); - UrisSection.Insert(UrisSection.Count - 1, Helpers.MakeUriCell(value, UrisSection)); + UrisSection.Insert(UrisSection.Count - 1, + Helpers.MakeUriCell(value, uri.Match, UrisSection, this)); } } } @@ -930,7 +931,7 @@ namespace Bit.App.Pages private void AddUriCell_Tapped(object sender, EventArgs e) { - var cell = Helpers.MakeUriCell(string.Empty, UrisSection); + var cell = Helpers.MakeUriCell(string.Empty, null, UrisSection, this); if(cell != null) { UrisSection.Insert(UrisSection.Count - 1, cell); diff --git a/src/App/Resources/AppResources.Designer.cs b/src/App/Resources/AppResources.Designer.cs index 76552a8f1..8cfc4b752 100644 --- a/src/App/Resources/AppResources.Designer.cs +++ b/src/App/Resources/AppResources.Designer.cs @@ -420,6 +420,15 @@ namespace Bit.App.Resources { } } + /// + /// Looks up a localized string similar to Base Domain. + /// + public static string BaseDomain { + get { + return ResourceManager.GetString("BaseDomain", resourceCulture); + } + } + /// /// Looks up a localized string similar to Beta. /// @@ -924,6 +933,15 @@ namespace Bit.App.Resources { } } + /// + /// Looks up a localized string similar to Default. + /// + public static string Default { + get { + return ResourceManager.GetString("Default", resourceCulture); + } + } + /// /// Looks up a localized string similar to Delete. /// @@ -1158,6 +1176,15 @@ namespace Bit.App.Resources { } } + /// + /// Looks up a localized string similar to Exact. + /// + public static string Exact { + get { + return ResourceManager.GetString("Exact", resourceCulture); + } + } + /// /// Looks up a localized string similar to Re-enable App Extension. /// @@ -1554,6 +1581,15 @@ namespace Bit.App.Resources { } } + /// + /// Looks up a localized string similar to Host. + /// + public static string Host { + get { + return ResourceManager.GetString("Host", resourceCulture); + } + } + /// /// Looks up a localized string similar to Icons. /// @@ -2472,6 +2508,15 @@ namespace Bit.App.Resources { } } + /// + /// Looks up a localized string similar to Regular expression. + /// + public static string RegEx { + get { + return ResourceManager.GetString("RegEx", resourceCulture); + } + } + /// /// Looks up a localized string similar to Remember me. /// @@ -2706,6 +2751,15 @@ namespace Bit.App.Resources { } } + /// + /// Looks up a localized string similar to Starts with. + /// + public static string StartsWith { + get { + return ResourceManager.GetString("StartsWith", resourceCulture); + } + } + /// /// Looks up a localized string similar to State / Province. /// @@ -2949,6 +3003,15 @@ namespace Bit.App.Resources { } } + /// + /// Looks up a localized string similar to URI Match Detection. + /// + public static string URIMatchDetection { + get { + return ResourceManager.GetString("URIMatchDetection", resourceCulture); + } + } + /// /// Looks up a localized string similar to URI {0}. /// diff --git a/src/App/Resources/AppResources.resx b/src/App/Resources/AppResources.resx index 480c38a30..f5c8e8a77 100644 --- a/src/App/Resources/AppResources.resx +++ b/src/App/Resources/AppResources.resx @@ -1256,4 +1256,27 @@ URI {0} Label for a uri/url with position. i.e. URI 1, URI 2, etc + + Base Domain + + + Default + + + Exact + + + Host + A URL's host value. For example, the host of https://sub.domain.com:443 is 'sub.domain.com:443'. + + + Regular expression + A programming term, also known as 'RegEx'. + + + Starts with + + + URI Match Detection + \ No newline at end of file diff --git a/src/App/Utilities/Helpers.cs b/src/App/Utilities/Helpers.cs index 0cb3d4d37..67b25a729 100644 --- a/src/App/Utilities/Helpers.cs +++ b/src/App/Utilities/Helpers.cs @@ -18,6 +18,15 @@ namespace Bit.App.Utilities public static class Helpers { public static readonly DateTime Epoc = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); + public static IDictionary UriMatchOptionsMap = new Dictionary + { + [UriMatchType.Domain] = AppResources.BaseDomain, + [UriMatchType.Host] = AppResources.Host, + [UriMatchType.StartsWith] = AppResources.StartsWith, + [UriMatchType.RegularExpression] = AppResources.RegEx, + [UriMatchType.Exact] = AppResources.Exact, + [UriMatchType.Never] = AppResources.Never + }; public static long EpocUtcNow() { @@ -374,13 +383,14 @@ namespace Bit.App.Utilities } } - public static FormEntryCell MakeUriCell(string value, TableSection urisSection) + public static FormEntryCell MakeUriCell(string value, UriMatchType? match, TableSection urisSection, Page page) { var label = string.Format(AppResources.URIPosition, urisSection.Count); var cell = new FormEntryCell(label, entryKeyboard: Keyboard.Url); cell.Entry.Text = value; cell.Entry.DisableAutocapitalize = true; cell.Entry.Autocorrect = false; + cell.MetaData = new Dictionary { ["match"] = match }; var deleteAction = new MenuItem { Text = AppResources.Remove, IsDestructive = true }; deleteAction.Clicked += (sender, e) => @@ -407,7 +417,28 @@ namespace Bit.App.Utilities var optionsAction = new MenuItem { Text = AppResources.Options }; optionsAction.Clicked += async (sender, e) => { + var options = UriMatchOptionsMap.Select(v => v.Value).ToList(); + options.Insert(0, AppResources.Default); + var exactingMatchVal = cell.MetaData["match"] as UriMatchType?; + var matchIndex = exactingMatchVal.HasValue ? + Array.IndexOf(UriMatchOptionsMap.Keys.ToArray(), exactingMatchVal) + 1 : 0; + options[matchIndex] = $"✓ {options[matchIndex]}"; + + var optionsArr = options.ToArray(); + var val = await page.DisplayActionSheet(AppResources.URIMatchDetection, AppResources.Cancel, + null, options.ToArray()); + + UriMatchType? selectedVal = null; + if(val == AppResources.Cancel) + { + selectedVal = exactingMatchVal; + } + else if(val != AppResources.Default) + { + selectedVal = UriMatchOptionsMap.ElementAt(Array.IndexOf(optionsArr, val) - 1).Key; + } + cell.MetaData["match"] = selectedVal; }; cell.ContextActions.Add(optionsAction); @@ -424,10 +455,11 @@ namespace Bit.App.Utilities { if(cell is FormEntryCell entryCell && !string.IsNullOrWhiteSpace(entryCell.Entry.Text)) { + var match = entryCell?.MetaData["match"] as UriMatchType?; uris.Add(new LoginUri { Uri = entryCell.Entry.Text.Encrypt(cipher.OrganizationId), - Match = null + Match = match }); } }