mirror of
https://github.com/bitwarden/mobile
synced 2025-12-25 20:53:25 +00:00
reset for v2
This commit is contained in:
@@ -1,14 +0,0 @@
|
||||
using System;
|
||||
using Bit.App.Abstractions;
|
||||
using Foundation;
|
||||
|
||||
namespace Bit.iOS.Core.Services
|
||||
{
|
||||
public class AppInfoService : IAppInfoService
|
||||
{
|
||||
public string Build => NSBundle.MainBundle.InfoDictionary["CFBundleVersion"].ToString();
|
||||
public string Version => NSBundle.MainBundle.InfoDictionary["CFBundleShortVersionString"].ToString();
|
||||
public bool AutofillAccessibilityServiceEnabled => false;
|
||||
public bool AutofillServiceEnabled => false;
|
||||
}
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
using Bit.App.Abstractions;
|
||||
using Foundation;
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Bit.iOS.Core.Services
|
||||
{
|
||||
public class CommonCryptoKeyDerivationService : IKeyDerivationService
|
||||
{
|
||||
private const uint PBKDFAlgorithm = 2; // PBKDF2
|
||||
private const uint PseudoRandomAlgorithm = 3; // SHA256
|
||||
private const uint KeyLength = 32; // 256 bit
|
||||
|
||||
public byte[] DeriveKey(byte[] password, byte[] salt, uint rounds)
|
||||
{
|
||||
var passwordData = NSData.FromArray(password);
|
||||
var saltData = NSData.FromArray(salt);
|
||||
|
||||
var keyData = new NSMutableData();
|
||||
keyData.Length = KeyLength;
|
||||
var result = CCKeyCerivationPBKDF(PBKDFAlgorithm, passwordData.Bytes, passwordData.Length, saltData.Bytes,
|
||||
saltData.Length, PseudoRandomAlgorithm, rounds, keyData.MutableBytes, keyData.Length);
|
||||
|
||||
byte[] keyBytes = new byte[keyData.Length];
|
||||
Marshal.Copy(keyData.Bytes, keyBytes, 0, Convert.ToInt32(keyData.Length));
|
||||
return keyBytes;
|
||||
}
|
||||
|
||||
// ref: http://opensource.apple.com//source/CommonCrypto/CommonCrypto-55010/CommonCrypto/CommonKeyDerivation.h
|
||||
[DllImport(ObjCRuntime.Constants.libSystemLibrary, EntryPoint = "CCKeyDerivationPBKDF")]
|
||||
private extern static int CCKeyCerivationPBKDF(uint algorithm, IntPtr password, nuint passwordLen,
|
||||
IntPtr salt, nuint saltLen, uint prf, nuint rounds, IntPtr derivedKey, nuint derivedKeyLength);
|
||||
}
|
||||
}
|
||||
@@ -1,59 +0,0 @@
|
||||
using Bit.App.Abstractions;
|
||||
using Foundation;
|
||||
using LocalAuthentication;
|
||||
using UIKit;
|
||||
|
||||
namespace Bit.iOS.Core.Services
|
||||
{
|
||||
public class DeviceInfoService : IDeviceInfoService
|
||||
{
|
||||
public DeviceInfoService()
|
||||
: this(false)
|
||||
{ }
|
||||
|
||||
public DeviceInfoService(bool isExtension)
|
||||
{
|
||||
IsExtension = isExtension;
|
||||
}
|
||||
|
||||
public string Type => Xamarin.Forms.Device.iOS;
|
||||
public string Model => UIDevice.CurrentDevice.Model;
|
||||
public int Version
|
||||
{
|
||||
get
|
||||
{
|
||||
var versionParts = UIDevice.CurrentDevice.SystemVersion.Split('.');
|
||||
if(versionParts.Length > 0 && int.TryParse(versionParts[0], out int version))
|
||||
{
|
||||
return version;
|
||||
}
|
||||
|
||||
// unable to determine version
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
public float Scale => (float)UIScreen.MainScreen.Scale;
|
||||
public bool NfcEnabled => CoreNFC.NFCNdefReaderSession.ReadingAvailable;
|
||||
public bool HasCamera => true;
|
||||
public bool AutofillServiceSupported => false;
|
||||
public bool HasFaceIdSupport
|
||||
{
|
||||
get
|
||||
{
|
||||
if(Version < 11)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var context = new LAContext();
|
||||
if(!context.CanEvaluatePolicy(LAPolicy.DeviceOwnerAuthenticationWithBiometrics, out NSError e))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return context.BiometryType == LABiometryType.FaceId;
|
||||
}
|
||||
}
|
||||
public bool IsExtension { get; private set; }
|
||||
}
|
||||
}
|
||||
@@ -1,47 +0,0 @@
|
||||
using System;
|
||||
using Bit.App.Abstractions;
|
||||
using Plugin.Settings.Abstractions;
|
||||
|
||||
namespace Bit.iOS.Core.Services
|
||||
{
|
||||
public class GoogleAnalyticsService : IGoogleAnalyticsService
|
||||
{
|
||||
public GoogleAnalyticsService(
|
||||
IAppIdService appIdService,
|
||||
ISettings settings)
|
||||
{}
|
||||
|
||||
public void TrackAppEvent(string eventName, string label = null)
|
||||
{
|
||||
}
|
||||
|
||||
public void TrackExtensionEvent(string eventName, string label = null)
|
||||
{
|
||||
}
|
||||
|
||||
public void TrackAutofillExtensionEvent(string eventName, string label = null)
|
||||
{
|
||||
}
|
||||
|
||||
public void TrackEvent(string category, string eventName, string label = null)
|
||||
{
|
||||
}
|
||||
|
||||
public void TrackException(string message, bool fatal)
|
||||
{
|
||||
}
|
||||
|
||||
public void TrackPage(string pageName)
|
||||
{
|
||||
}
|
||||
|
||||
public void Dispatch(Action completionHandler = null)
|
||||
{
|
||||
completionHandler?.Invoke();
|
||||
}
|
||||
|
||||
public void SetAppOptOut(bool optOut)
|
||||
{
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
using System;
|
||||
using Bit.App;
|
||||
using Bit.App.Abstractions;
|
||||
|
||||
namespace Bit.iOS.Core.Services
|
||||
{
|
||||
public class HttpService : IHttpService
|
||||
{
|
||||
public ApiHttpClient ApiClient => new ApiHttpClient();
|
||||
public IdentityHttpClient IdentityClient => new IdentityHttpClient();
|
||||
}
|
||||
}
|
||||
@@ -1,92 +0,0 @@
|
||||
using System;
|
||||
using System.Runtime.CompilerServices;
|
||||
using Bit.App.Abstractions;
|
||||
using Foundation;
|
||||
using Security;
|
||||
|
||||
namespace Bit.iOS.Core.Services
|
||||
{
|
||||
public class KeyChainStorageService : ISecureStorageService
|
||||
{
|
||||
public void Store(string key, byte[] dataBytes)
|
||||
{
|
||||
using(var data = NSData.FromArray(dataBytes))
|
||||
using(var newRecord = GetKeyRecord(key, data))
|
||||
{
|
||||
Delete(key);
|
||||
CheckError(SecKeyChain.Add(newRecord));
|
||||
}
|
||||
}
|
||||
|
||||
public byte[] Retrieve(string key)
|
||||
{
|
||||
SecStatusCode resultCode;
|
||||
|
||||
using(var existingRecord = GetKeyRecord(key))
|
||||
using(var record = SecKeyChain.QueryAsRecord(existingRecord, out resultCode))
|
||||
{
|
||||
if(resultCode == SecStatusCode.ItemNotFound)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
CheckError(resultCode);
|
||||
return record.Generic.ToArray();
|
||||
}
|
||||
}
|
||||
|
||||
public void Delete(string key)
|
||||
{
|
||||
using(var record = GetExistingRecord(key))
|
||||
{
|
||||
if(record != null)
|
||||
{
|
||||
CheckError(SecKeyChain.Remove(record));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public bool Contains(string key)
|
||||
{
|
||||
using(var existingRecord = GetExistingRecord(key))
|
||||
{
|
||||
return existingRecord != null;
|
||||
}
|
||||
}
|
||||
|
||||
private static void CheckError(SecStatusCode resultCode, [CallerMemberName] string caller = null)
|
||||
{
|
||||
if(resultCode != SecStatusCode.Success)
|
||||
{
|
||||
throw new Exception(string.Format("Failed to execute {0}. Result code: {1}", caller, resultCode));
|
||||
}
|
||||
}
|
||||
|
||||
private static SecRecord GetKeyRecord(string key, NSData data = null)
|
||||
{
|
||||
var record = new SecRecord(SecKind.GenericPassword)
|
||||
{
|
||||
Service = "com.8bit.bitwarden",
|
||||
Account = key,
|
||||
AccessGroup = "LTZ2PFU5D6.com.8bit.bitwarden"
|
||||
};
|
||||
|
||||
if(data != null)
|
||||
{
|
||||
record.Generic = data;
|
||||
}
|
||||
|
||||
return record;
|
||||
}
|
||||
|
||||
private static SecRecord GetExistingRecord(string key)
|
||||
{
|
||||
var existingRecord = GetKeyRecord(key);
|
||||
|
||||
SecStatusCode resultCode;
|
||||
SecKeyChain.QueryAsRecord(existingRecord, out resultCode);
|
||||
|
||||
return resultCode == SecStatusCode.Success ? existingRecord : null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,111 +0,0 @@
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.Threading;
|
||||
using Foundation;
|
||||
using Bit.App.Abstractions;
|
||||
using Bit.App.Models;
|
||||
|
||||
namespace Bit.iOS.Core.Services
|
||||
{
|
||||
public class LocalizeService : ILocalizeService
|
||||
{
|
||||
public void SetLocale(CultureInfo ci)
|
||||
{
|
||||
Thread.CurrentThread.CurrentCulture = ci;
|
||||
Thread.CurrentThread.CurrentUICulture = ci;
|
||||
Console.WriteLine("CurrentCulture set: " + ci.Name);
|
||||
}
|
||||
|
||||
public CultureInfo GetCurrentCultureInfo()
|
||||
{
|
||||
var netLanguage = "en";
|
||||
if(NSLocale.PreferredLanguages.Length > 0)
|
||||
{
|
||||
var pref = NSLocale.PreferredLanguages[0];
|
||||
|
||||
netLanguage = iOSToDotnetLanguage(pref);
|
||||
}
|
||||
|
||||
// this gets called a lot - try/catch can be expensive so consider caching or something
|
||||
CultureInfo ci = null;
|
||||
try
|
||||
{
|
||||
ci = new CultureInfo(netLanguage);
|
||||
}
|
||||
catch(CultureNotFoundException e1)
|
||||
{
|
||||
// iOS locale not valid .NET culture (eg. "en-ES" : English in Spain)
|
||||
// fallback to first characters, in this case "en"
|
||||
try
|
||||
{
|
||||
var fallback = ToDotnetFallbackLanguage(new PlatformCulture(netLanguage));
|
||||
Console.WriteLine(netLanguage + " failed, trying " + fallback + " (" + e1.Message + ")");
|
||||
ci = new CultureInfo(fallback);
|
||||
}
|
||||
catch(CultureNotFoundException e2)
|
||||
{
|
||||
// iOS language not valid .NET culture, falling back to English
|
||||
Console.WriteLine(netLanguage + " couldn't be set, using 'en' (" + e2.Message + ")");
|
||||
ci = new CultureInfo("en");
|
||||
}
|
||||
}
|
||||
|
||||
return ci;
|
||||
}
|
||||
|
||||
private string iOSToDotnetLanguage(string iOSLanguage)
|
||||
{
|
||||
Console.WriteLine("iOS Language:" + iOSLanguage);
|
||||
var netLanguage = iOSLanguage;
|
||||
|
||||
if(iOSLanguage.StartsWith("zh-Hant") || iOSLanguage.StartsWith("zh-HK"))
|
||||
{
|
||||
netLanguage = "zh-Hant";
|
||||
}
|
||||
else if(iOSLanguage.StartsWith("zh"))
|
||||
{
|
||||
netLanguage = "zh-Hans";
|
||||
}
|
||||
else
|
||||
{
|
||||
//certain languages need to be converted to CultureInfo equivalent
|
||||
switch(iOSLanguage)
|
||||
{
|
||||
case "ms-MY": // "Malaysian (Malaysia)" not supported .NET culture
|
||||
case "ms-SG": // "Malaysian (Singapore)" not supported .NET culture
|
||||
netLanguage = "ms"; // closest supported
|
||||
break;
|
||||
case "gsw-CH": // "Schwiizertüütsch (Swiss German)" not supported .NET culture
|
||||
netLanguage = "de-CH"; // closest supported
|
||||
break;
|
||||
// add more application-specific cases here (if required)
|
||||
// ONLY use cultures that have been tested and known to work
|
||||
}
|
||||
}
|
||||
|
||||
Console.WriteLine(".NET Language/Locale:" + netLanguage);
|
||||
return netLanguage;
|
||||
}
|
||||
|
||||
private string ToDotnetFallbackLanguage(PlatformCulture platCulture)
|
||||
{
|
||||
Console.WriteLine(".NET Fallback Language:" + platCulture.LanguageCode);
|
||||
var netLanguage = platCulture.LanguageCode; // use the first part of the identifier (two chars, usually);
|
||||
|
||||
switch(platCulture.LanguageCode)
|
||||
{
|
||||
case "pt":
|
||||
netLanguage = "pt-PT"; // fallback to Portuguese (Portugal)
|
||||
break;
|
||||
case "gsw":
|
||||
netLanguage = "de-CH"; // equivalent to German (Switzerland) for this app
|
||||
break;
|
||||
// add more application-specific cases here (if required)
|
||||
// ONLY use cultures that have been tested and known to work
|
||||
}
|
||||
|
||||
Console.WriteLine(".NET Fallback Language/Locale:" + netLanguage + " (application-specific)");
|
||||
return netLanguage;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,13 +0,0 @@
|
||||
using System;
|
||||
using Bit.App.Abstractions;
|
||||
|
||||
namespace Bit.iOS.Core.Services
|
||||
{
|
||||
public class LogService : ILogService
|
||||
{
|
||||
public void WriteLine(string message)
|
||||
{
|
||||
Console.WriteLine(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,101 +0,0 @@
|
||||
using System;
|
||||
using Bit.App.Abstractions;
|
||||
using System.Threading.Tasks;
|
||||
using Bit.App.Models.Page;
|
||||
using Xamarin.Forms;
|
||||
|
||||
namespace Bit.iOS.Core.Services
|
||||
{
|
||||
public class NoopDeviceActionService : IDeviceActionService
|
||||
{
|
||||
public void Autofill(VaultListPageModel.Cipher cipher)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
public void Background()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
public bool CanOpenFile(string fileName)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public void ClearCache()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
public void CloseAutofill()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
public void CopyToClipboard(string text)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
public void DismissKeyboard()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
public Task<string> DisplayAlertAsync(string title, string message, string cancel, params string[] buttons)
|
||||
{
|
||||
return Task.FromResult<string>(null);
|
||||
}
|
||||
|
||||
public Task<string> DisplayPromptAync(string title = null, string description = null, string text = null)
|
||||
{
|
||||
return Task.FromResult<string>(null);
|
||||
}
|
||||
|
||||
public Task HideLoadingAsync()
|
||||
{
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task LaunchAppAsync(string appName, Page page)
|
||||
{
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public void OpenAccessibilitySettings()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
public void OpenAutofillSettings()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
public bool OpenFile(byte[] fileData, string id, string fileName)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
public void RateApp()
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
|
||||
public Task SelectFileAsync()
|
||||
{
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public Task ShowLoadingAsync(string text)
|
||||
{
|
||||
return Task.FromResult(0);
|
||||
}
|
||||
|
||||
public void Toast(string text, bool longDuration = false)
|
||||
{
|
||||
// do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,495 +0,0 @@
|
||||
using System;
|
||||
using Foundation;
|
||||
#if __IOS__
|
||||
using UIKit;
|
||||
#endif
|
||||
using Plugin.Settings.Abstractions;
|
||||
|
||||
namespace Bit.iOS.Core.Services
|
||||
{
|
||||
/// <summary>
|
||||
/// Main implementation for ISettings
|
||||
/// </summary>
|
||||
[Preserve(AllMembers = true)]
|
||||
public class Settings : ISettings
|
||||
{
|
||||
private readonly object locker = new object();
|
||||
private readonly string _defaultsName;
|
||||
|
||||
public Settings(string defaultsName)
|
||||
{
|
||||
_defaultsName = defaultsName;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the current value or the default that you specify.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Vaue of t (bool, int, float, long, string)</typeparam>
|
||||
/// <param name="key">Key for settings</param>
|
||||
/// <param name="defaultValue">default value if not set</param>
|
||||
/// <param name="fileName">Name of file for settings to be stored and retrieved </param>
|
||||
/// <returns>Value or default</returns>
|
||||
T GetValueOrDefaultInternal<T>(string key, T defaultValue = default(T), string fileName = null)
|
||||
{
|
||||
lock(locker)
|
||||
{
|
||||
var defaults = GetUserDefaults(fileName);
|
||||
|
||||
if(defaults[key] == null)
|
||||
return defaultValue;
|
||||
|
||||
Type typeOf = typeof(T);
|
||||
if(typeOf.IsGenericType && typeOf.GetGenericTypeDefinition() == typeof(Nullable<>))
|
||||
{
|
||||
typeOf = Nullable.GetUnderlyingType(typeOf);
|
||||
}
|
||||
object value = null;
|
||||
var typeCode = Type.GetTypeCode(typeOf);
|
||||
switch(typeCode)
|
||||
{
|
||||
case TypeCode.Decimal:
|
||||
var savedDecimal = defaults.StringForKey(key);
|
||||
value = Convert.ToDecimal(savedDecimal, System.Globalization.CultureInfo.InvariantCulture);
|
||||
break;
|
||||
case TypeCode.Boolean:
|
||||
value = defaults.BoolForKey(key);
|
||||
break;
|
||||
case TypeCode.Int64:
|
||||
var savedInt64 = defaults.StringForKey(key);
|
||||
value = Convert.ToInt64(savedInt64, System.Globalization.CultureInfo.InvariantCulture);
|
||||
break;
|
||||
case TypeCode.Double:
|
||||
value = defaults.DoubleForKey(key);
|
||||
break;
|
||||
case TypeCode.String:
|
||||
value = defaults.StringForKey(key);
|
||||
break;
|
||||
case TypeCode.Int32:
|
||||
value = (Int32)defaults.IntForKey(key);
|
||||
break;
|
||||
case TypeCode.Single:
|
||||
value = defaults.FloatForKey(key);
|
||||
break;
|
||||
|
||||
case TypeCode.DateTime:
|
||||
var savedTime = defaults.StringForKey(key);
|
||||
if(string.IsNullOrWhiteSpace(savedTime))
|
||||
{
|
||||
value = defaultValue;
|
||||
}
|
||||
else
|
||||
{
|
||||
var ticks = Convert.ToInt64(savedTime, System.Globalization.CultureInfo.InvariantCulture);
|
||||
if(ticks >= 0)
|
||||
{
|
||||
//Old value, stored before update to UTC values
|
||||
value = new DateTime(ticks);
|
||||
}
|
||||
else
|
||||
{
|
||||
//New value, UTC
|
||||
value = new DateTime(-ticks, DateTimeKind.Utc);
|
||||
}
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
||||
if(defaultValue is Guid)
|
||||
{
|
||||
var outGuid = Guid.Empty;
|
||||
var savedGuid = defaults.StringForKey(key);
|
||||
if(string.IsNullOrWhiteSpace(savedGuid))
|
||||
{
|
||||
value = outGuid;
|
||||
}
|
||||
else
|
||||
{
|
||||
Guid.TryParse(savedGuid, out outGuid);
|
||||
value = outGuid;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException($"Value of type {typeCode} is not supported.");
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
return null != value ? (T)value : defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Adds or updates a value
|
||||
/// </summary>
|
||||
/// <param name="key">key to update</param>
|
||||
/// <param name="value">value to set</param>
|
||||
/// <param name="fileName">Name of file for settings to be stored and retrieved </param>
|
||||
/// <returns>True if added or update and you need to save</returns>
|
||||
bool AddOrUpdateValueInternal<T>(string key, T value, string fileName = null)
|
||||
{
|
||||
if(value == null)
|
||||
{
|
||||
Remove(key, fileName);
|
||||
return true;
|
||||
}
|
||||
|
||||
Type typeOf = typeof(T);
|
||||
if(typeOf.IsGenericType && typeOf.GetGenericTypeDefinition() == typeof(Nullable<>))
|
||||
{
|
||||
typeOf = Nullable.GetUnderlyingType(typeOf);
|
||||
}
|
||||
var typeCode = Type.GetTypeCode(typeOf);
|
||||
return AddOrUpdateValueCore(key, value, typeCode, fileName);
|
||||
}
|
||||
|
||||
bool AddOrUpdateValueCore(string key, object value, TypeCode typeCode, string fileName)
|
||||
{
|
||||
lock(locker)
|
||||
{
|
||||
var defaults = GetUserDefaults(fileName);
|
||||
switch(typeCode)
|
||||
{
|
||||
case TypeCode.Decimal:
|
||||
defaults.SetString(Convert.ToString(value, System.Globalization.CultureInfo.InvariantCulture), key);
|
||||
break;
|
||||
case TypeCode.Boolean:
|
||||
defaults.SetBool(Convert.ToBoolean(value), key);
|
||||
break;
|
||||
case TypeCode.Int64:
|
||||
defaults.SetString(Convert.ToString(value, System.Globalization.CultureInfo.InvariantCulture), key);
|
||||
break;
|
||||
case TypeCode.Double:
|
||||
defaults.SetDouble(Convert.ToDouble(value, System.Globalization.CultureInfo.InvariantCulture), key);
|
||||
break;
|
||||
case TypeCode.String:
|
||||
defaults.SetString(Convert.ToString(value), key);
|
||||
break;
|
||||
case TypeCode.Int32:
|
||||
defaults.SetInt(Convert.ToInt32(value, System.Globalization.CultureInfo.InvariantCulture), key);
|
||||
break;
|
||||
case TypeCode.Single:
|
||||
defaults.SetFloat(Convert.ToSingle(value, System.Globalization.CultureInfo.InvariantCulture), key);
|
||||
break;
|
||||
case TypeCode.DateTime:
|
||||
defaults.SetString(Convert.ToString(-(Convert.ToDateTime(value)).ToUniversalTime().Ticks), key);
|
||||
break;
|
||||
default:
|
||||
if(value is Guid)
|
||||
{
|
||||
if(value == null)
|
||||
value = Guid.Empty;
|
||||
|
||||
defaults.SetString(((Guid)value).ToString(), key);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException($"Value of type {typeCode} is not supported.");
|
||||
}
|
||||
break;
|
||||
}
|
||||
try
|
||||
{
|
||||
defaults.Synchronize();
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
Console.WriteLine("Unable to save: " + key, " Message: " + ex.Message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Removes a desired key from the settings
|
||||
/// </summary>
|
||||
/// <param name="key">Key for setting</param>
|
||||
/// <param name="fileName">Name of file for settings to be stored and retrieved </param>
|
||||
public void Remove(string key, string fileName = null)
|
||||
{
|
||||
lock(locker)
|
||||
{
|
||||
var defaults = GetUserDefaults(fileName);
|
||||
try
|
||||
{
|
||||
if(defaults[key] != null)
|
||||
{
|
||||
defaults.RemoveObject(key);
|
||||
defaults.Synchronize();
|
||||
}
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
Console.WriteLine("Unable to remove: " + key, " Message: " + ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Clear all keys from settings
|
||||
/// </summary>
|
||||
/// <param name="fileName">Name of file for settings to be stored and retrieved </param>
|
||||
public void Clear(string fileName = null)
|
||||
{
|
||||
lock(locker)
|
||||
{
|
||||
var defaults = GetUserDefaults(fileName);
|
||||
try
|
||||
{
|
||||
var items = defaults.ToDictionary();
|
||||
|
||||
foreach(var item in items.Keys)
|
||||
{
|
||||
if(item is NSString nsString)
|
||||
defaults.RemoveObject(nsString);
|
||||
}
|
||||
defaults.Synchronize();
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
Console.WriteLine("Unable to clear all defaults. Message: " + ex.Message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Checks to see if the key has been added.
|
||||
/// </summary>
|
||||
/// <param name="key">Key to check</param>
|
||||
/// <param name="fileName">Name of file for settings to be stored and retrieved </param>
|
||||
/// <returns>True if contains key, else false</returns>
|
||||
public bool Contains(string key, string fileName = null)
|
||||
{
|
||||
lock(locker)
|
||||
{
|
||||
var defaults = GetUserDefaults(fileName);
|
||||
try
|
||||
{
|
||||
var setting = defaults[key];
|
||||
return setting != null;
|
||||
}
|
||||
catch(Exception ex)
|
||||
{
|
||||
Console.WriteLine("Unable to clear all defaults. Message: " + ex.Message);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
NSUserDefaults GetUserDefaults(string fileName = null)
|
||||
{
|
||||
if(string.IsNullOrWhiteSpace(fileName) && !string.IsNullOrWhiteSpace(_defaultsName))
|
||||
{
|
||||
return new NSUserDefaults(_defaultsName, NSUserDefaultsType.SuiteName);
|
||||
}
|
||||
|
||||
return string.IsNullOrWhiteSpace(fileName) ?
|
||||
NSUserDefaults.StandardUserDefaults :
|
||||
new NSUserDefaults(fileName, NSUserDefaultsType.SuiteName);
|
||||
}
|
||||
|
||||
|
||||
|
||||
#region GetValueOrDefault
|
||||
/// <summary>
|
||||
/// Gets the current value or the default that you specify.
|
||||
/// </summary>
|
||||
/// <param name="key">Key for settings</param>
|
||||
/// <param name="defaultValue">default value if not set</param>
|
||||
/// <param name="fileName">Name of file for settings to be stored and retrieved </param>
|
||||
/// <returns>Value or default</returns>
|
||||
public decimal GetValueOrDefault(string key, decimal defaultValue, string fileName = null) =>
|
||||
GetValueOrDefaultInternal(key, defaultValue, fileName);
|
||||
/// <summary>
|
||||
/// Gets the current value or the default that you specify.
|
||||
/// </summary>
|
||||
/// <param name="key">Key for settings</param>
|
||||
/// <param name="defaultValue">default value if not set</param>
|
||||
/// <param name="fileName">Name of file for settings to be stored and retrieved </param>
|
||||
/// <returns>Value or default</returns>
|
||||
public bool GetValueOrDefault(string key, bool defaultValue, string fileName = null) =>
|
||||
GetValueOrDefaultInternal(key, defaultValue, fileName);
|
||||
/// <summary>
|
||||
/// Gets the current value or the default that you specify.
|
||||
/// </summary>
|
||||
/// <param name="key">Key for settings</param>
|
||||
/// <param name="defaultValue">default value if not set</param>
|
||||
/// <param name="fileName">Name of file for settings to be stored and retrieved </param>
|
||||
/// <returns>Value or default</returns>
|
||||
public long GetValueOrDefault(string key, long defaultValue, string fileName = null) =>
|
||||
GetValueOrDefaultInternal(key, defaultValue, fileName);
|
||||
/// <summary>
|
||||
/// Gets the current value or the default that you specify.
|
||||
/// </summary>
|
||||
/// <param name="key">Key for settings</param>
|
||||
/// <param name="defaultValue">default value if not set</param>
|
||||
/// <param name="fileName">Name of file for settings to be stored and retrieved </param>
|
||||
/// <returns>Value or default</returns>
|
||||
public string GetValueOrDefault(string key, string defaultValue, string fileName = null) =>
|
||||
GetValueOrDefaultInternal(key, defaultValue, fileName);
|
||||
/// <summary>
|
||||
/// Gets the current value or the default that you specify.
|
||||
/// </summary>
|
||||
/// <param name="key">Key for settings</param>
|
||||
/// <param name="defaultValue">default value if not set</param>
|
||||
/// <param name="fileName">Name of file for settings to be stored and retrieved </param>
|
||||
/// <returns>Value or default</returns>
|
||||
public int GetValueOrDefault(string key, int defaultValue, string fileName = null) =>
|
||||
GetValueOrDefaultInternal(key, defaultValue, fileName);
|
||||
/// <summary>
|
||||
/// Gets the current value or the default that you specify.
|
||||
/// </summary>
|
||||
/// <param name="key">Key for settings</param>
|
||||
/// <param name="defaultValue">default value if not set</param>
|
||||
/// <param name="fileName">Name of file for settings to be stored and retrieved </param>
|
||||
/// <returns>Value or default</returns>
|
||||
public float GetValueOrDefault(string key, float defaultValue, string fileName = null) =>
|
||||
GetValueOrDefaultInternal(key, defaultValue, fileName);
|
||||
/// <summary>
|
||||
/// Gets the current value or the default that you specify.
|
||||
/// </summary>
|
||||
/// <param name="key">Key for settings</param>
|
||||
/// <param name="defaultValue">default value if not set</param>
|
||||
/// <param name="fileName">Name of file for settings to be stored and retrieved </param>
|
||||
/// <returns>Value or default</returns>
|
||||
public DateTime GetValueOrDefault(string key, DateTime defaultValue, string fileName = null) =>
|
||||
GetValueOrDefaultInternal(key, defaultValue, fileName);
|
||||
/// <summary>
|
||||
/// Gets the current value or the default that you specify.
|
||||
/// </summary>
|
||||
/// <param name="key">Key for settings</param>
|
||||
/// <param name="defaultValue">default value if not set</param>
|
||||
/// <param name="fileName">Name of file for settings to be stored and retrieved </param>
|
||||
/// <returns>Value or default</returns>
|
||||
public Guid GetValueOrDefault(string key, Guid defaultValue, string fileName = null) =>
|
||||
GetValueOrDefaultInternal(key, defaultValue, fileName);
|
||||
/// <summary>
|
||||
/// Gets the current value or the default that you specify.
|
||||
/// </summary>
|
||||
/// <param name="key">Key for settings</param>
|
||||
/// <param name="defaultValue">default value if not set</param>
|
||||
/// <param name="fileName">Name of file for settings to be stored and retrieved </param>
|
||||
/// <returns>Value or default</returns>
|
||||
public double GetValueOrDefault(string key, double defaultValue, string fileName = null) =>
|
||||
GetValueOrDefaultInternal(key, defaultValue, fileName);
|
||||
#endregion
|
||||
|
||||
#region AddOrUpdateValue
|
||||
/// <summary>
|
||||
/// Adds or updates the value
|
||||
/// </summary>
|
||||
/// <param name="key">Key for settting</param>
|
||||
/// <param name="value">Value to set</param>
|
||||
/// <param name="fileName">Name of file for settings to be stored and retrieved </param>
|
||||
/// <returns>True of was added or updated and you need to save it.</returns>
|
||||
public bool AddOrUpdateValue(string key, decimal value, string fileName = null) =>
|
||||
AddOrUpdateValueInternal(key, value, fileName);
|
||||
/// <summary>
|
||||
/// Adds or updates the value
|
||||
/// </summary>
|
||||
/// <param name="key">Key for settting</param>
|
||||
/// <param name="value">Value to set</param>
|
||||
/// <param name="fileName">Name of file for settings to be stored and retrieved </param>
|
||||
/// <returns>True of was added or updated and you need to save it.</returns>
|
||||
public bool AddOrUpdateValue(string key, bool value, string fileName = null) =>
|
||||
AddOrUpdateValueInternal(key, value, fileName);
|
||||
/// <summary>
|
||||
/// Adds or updates the value
|
||||
/// </summary>
|
||||
/// <param name="key">Key for settting</param>
|
||||
/// <param name="value">Value to set</param>
|
||||
/// <param name="fileName">Name of file for settings to be stored and retrieved </param>
|
||||
/// <returns>True of was added or updated and you need to save it.</returns>
|
||||
public bool AddOrUpdateValue(string key, long value, string fileName = null) =>
|
||||
AddOrUpdateValueInternal(key, value, fileName);
|
||||
/// <summary>
|
||||
/// Adds or updates the value
|
||||
/// </summary>
|
||||
/// <param name="key">Key for settting</param>
|
||||
/// <param name="value">Value to set</param>
|
||||
/// <param name="fileName">Name of file for settings to be stored and retrieved </param>
|
||||
/// <returns>True of was added or updated and you need to save it.</returns>
|
||||
public bool AddOrUpdateValue(string key, string value, string fileName = null) =>
|
||||
AddOrUpdateValueInternal(key, value, fileName);
|
||||
/// <summary>
|
||||
/// Adds or updates the value
|
||||
/// </summary>
|
||||
/// <param name="key">Key for settting</param>
|
||||
/// <param name="value">Value to set</param>
|
||||
/// <param name="fileName">Name of file for settings to be stored and retrieved </param>
|
||||
/// <returns>True of was added or updated and you need to save it.</returns>
|
||||
public bool AddOrUpdateValue(string key, int value, string fileName = null) =>
|
||||
AddOrUpdateValueInternal(key, value, fileName);
|
||||
/// <summary>
|
||||
/// Adds or updates the value
|
||||
/// </summary>
|
||||
/// <param name="key">Key for settting</param>
|
||||
/// <param name="value">Value to set</param>
|
||||
/// <param name="fileName">Name of file for settings to be stored and retrieved </param>
|
||||
/// <returns>True of was added or updated and you need to save it.</returns>
|
||||
public bool AddOrUpdateValue(string key, float value, string fileName = null) =>
|
||||
AddOrUpdateValueInternal(key, value, fileName);
|
||||
/// <summary>
|
||||
/// Adds or updates the value
|
||||
/// </summary>
|
||||
/// <param name="key">Key for settting</param>
|
||||
/// <param name="value">Value to set</param>
|
||||
/// <param name="fileName">Name of file for settings to be stored and retrieved </param>
|
||||
/// <returns>True of was added or updated and you need to save it.</returns>
|
||||
public bool AddOrUpdateValue(string key, DateTime value, string fileName = null) =>
|
||||
AddOrUpdateValueInternal(key, value, fileName);
|
||||
/// <summary>
|
||||
/// Adds or updates the value
|
||||
/// </summary>
|
||||
/// <param name="key">Key for settting</param>
|
||||
/// <param name="value">Value to set</param>
|
||||
/// <param name="fileName">Name of file for settings to be stored and retrieved </param>
|
||||
/// <returns>True of was added or updated and you need to save it.</returns>
|
||||
public bool AddOrUpdateValue(string key, Guid value, string fileName = null) =>
|
||||
AddOrUpdateValueInternal(key, value, fileName);
|
||||
/// <summary>
|
||||
/// Adds or updates the value
|
||||
/// </summary>
|
||||
/// <param name="key">Key for settting</param>
|
||||
/// <param name="value">Value to set</param>
|
||||
/// <param name="fileName">Name of file for settings to be stored and retrieved </param>
|
||||
/// <returns>True of was added or updated and you need to save it.</returns>
|
||||
public bool AddOrUpdateValue(string key, double value, string fileName = null) =>
|
||||
AddOrUpdateValueInternal(key, value, fileName);
|
||||
|
||||
#endregion
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Attempts to open the app settings page.
|
||||
/// </summary>
|
||||
/// <returns>true if success, else false and not supported</returns>
|
||||
public bool OpenAppSettings()
|
||||
{
|
||||
#if __IOS__
|
||||
//Opening settings only open in iOS 8+
|
||||
if(!UIDevice.CurrentDevice.CheckSystemVersion(8, 0))
|
||||
return false;
|
||||
|
||||
try
|
||||
{
|
||||
UIApplication.SharedApplication.OpenUrl(new NSUrl(UIApplication.OpenSettingsUrlString));
|
||||
return true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return false;
|
||||
}
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,32 +0,0 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using Bit.App.Abstractions;
|
||||
using Foundation;
|
||||
using SQLite;
|
||||
|
||||
namespace Bit.iOS.Core.Services
|
||||
{
|
||||
public class SqlService : ISqlService
|
||||
{
|
||||
private SQLiteConnection _connection;
|
||||
|
||||
public SQLiteConnection GetConnection()
|
||||
{
|
||||
if(_connection != null)
|
||||
{
|
||||
return _connection;
|
||||
}
|
||||
|
||||
var sqliteFilename = "bitwarden.db3";
|
||||
var fileManager = new NSFileManager();
|
||||
var appGroupContainer = fileManager.GetContainerUrl("group.com.8bit.bitwarden");
|
||||
var libraryPath = Path.Combine(appGroupContainer.Path, "Library"); // Library folder
|
||||
var path = Path.Combine(libraryPath, sqliteFilename);
|
||||
Console.WriteLine(path);
|
||||
|
||||
_connection = new SQLiteConnection(path,
|
||||
SQLiteOpenFlags.ReadWrite | SQLiteOpenFlags.Create | SQLiteOpenFlags.FullMutex | SQLiteOpenFlags.SharedCache);
|
||||
return _connection;
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user