mirror of
https://github.com/bitwarden/android.git
synced 2024-12-24 09:58:27 +03:00
background thread full/incremental sync operations. pool sqlconnection. sqlconnection to FullMutex mode for multithread environment. try/catch decryption errors.
This commit is contained in:
parent
0be15d7a34
commit
29c7a0ccf0
4 changed files with 104 additions and 71 deletions
|
@ -1,22 +1,29 @@
|
||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using Bit.App.Abstractions;
|
using Bit.App.Abstractions;
|
||||||
|
using SQLite;
|
||||||
|
|
||||||
namespace Bit.Android.Services
|
namespace Bit.Android.Services
|
||||||
{
|
{
|
||||||
public class SqlService : ISqlService
|
public class SqlService : ISqlService
|
||||||
{
|
{
|
||||||
public SQLite.SQLiteConnection GetConnection()
|
private SQLiteConnection _connection;
|
||||||
|
|
||||||
|
public SQLiteConnection GetConnection()
|
||||||
{
|
{
|
||||||
|
if(_connection != null)
|
||||||
|
{
|
||||||
|
return _connection;
|
||||||
|
}
|
||||||
|
|
||||||
var sqliteFilename = "bitwarden.db3";
|
var sqliteFilename = "bitwarden.db3";
|
||||||
var documentsPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal); // Documents folder
|
var documentsPath = Environment.GetFolderPath(Environment.SpecialFolder.Personal); // Documents folder
|
||||||
var path = Path.Combine(documentsPath, sqliteFilename);
|
var path = Path.Combine(documentsPath, sqliteFilename);
|
||||||
|
|
||||||
Console.WriteLine(path);
|
Console.WriteLine(path);
|
||||||
var conn = new SQLite.SQLiteConnection(path);
|
|
||||||
|
|
||||||
// Return the database connection
|
_connection = new SQLiteConnection(path,
|
||||||
return conn;
|
SQLiteOpenFlags.ReadWrite | SQLiteOpenFlags.Create | SQLiteOpenFlags.FullMutex | SQLiteOpenFlags.SharedCache);
|
||||||
|
return _connection;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
117
src/App/App.cs
117
src/App/App.cs
|
@ -57,35 +57,7 @@ namespace Bit.App
|
||||||
MessagingCenter.Subscribe<Application, bool>(Current, "Resumed", async (sender, args) =>
|
MessagingCenter.Subscribe<Application, bool>(Current, "Resumed", async (sender, args) =>
|
||||||
{
|
{
|
||||||
await CheckLockAsync(args);
|
await CheckLockAsync(args);
|
||||||
if(_connectivity.IsConnected)
|
await Task.Run(() => IncrementalSyncAsync()).ConfigureAwait(false);
|
||||||
{
|
|
||||||
var attempt = 0;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await _syncService.IncrementalSyncAsync();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
catch(WebException)
|
|
||||||
{
|
|
||||||
Debug.WriteLine("Failed to sync.");
|
|
||||||
if(attempt >= 1)
|
|
||||||
{
|
|
||||||
await _userDialogs.AlertAsync("Unable to automatically sync.");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
await Task.Delay(1000);
|
|
||||||
}
|
|
||||||
attempt++;
|
|
||||||
}
|
|
||||||
} while(attempt <= 1);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Debug.WriteLine("Not connected.");
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
MessagingCenter.Subscribe<Application, bool>(Current, "Lock", async (sender, args) =>
|
MessagingCenter.Subscribe<Application, bool>(Current, "Lock", async (sender, args) =>
|
||||||
|
@ -99,30 +71,7 @@ namespace Bit.App
|
||||||
// Handle when your app starts
|
// Handle when your app starts
|
||||||
await CheckLockAsync(false);
|
await CheckLockAsync(false);
|
||||||
_databaseService.CreateTables();
|
_databaseService.CreateTables();
|
||||||
if(_connectivity.IsConnected)
|
await Task.Run(() => FullSyncAsync()).ConfigureAwait(false);
|
||||||
{
|
|
||||||
var attempt = 0;
|
|
||||||
do
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await _syncService.FullSyncAsync();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
catch(WebException)
|
|
||||||
{
|
|
||||||
if(attempt >= 1)
|
|
||||||
{
|
|
||||||
await _userDialogs.AlertAsync("Unable to automatically sync. Manual sync required.");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
await Task.Delay(1000);
|
|
||||||
}
|
|
||||||
attempt++;
|
|
||||||
}
|
|
||||||
} while(attempt <= 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
Debug.WriteLine("OnStart");
|
Debug.WriteLine("OnStart");
|
||||||
}
|
}
|
||||||
|
@ -155,6 +104,68 @@ namespace Bit.App
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private async Task IncrementalSyncAsync()
|
||||||
|
{
|
||||||
|
if(_connectivity.IsConnected)
|
||||||
|
{
|
||||||
|
var attempt = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await _syncService.IncrementalSyncAsync();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
catch(WebException)
|
||||||
|
{
|
||||||
|
Debug.WriteLine("Failed to incremental sync.");
|
||||||
|
if(attempt >= 1)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await Task.Delay(1000);
|
||||||
|
}
|
||||||
|
attempt++;
|
||||||
|
}
|
||||||
|
} while(attempt <= 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Debug.WriteLine("Not connected.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task FullSyncAsync()
|
||||||
|
{
|
||||||
|
if(_connectivity.IsConnected)
|
||||||
|
{
|
||||||
|
var attempt = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await _syncService.FullSyncAsync();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
catch(WebException)
|
||||||
|
{
|
||||||
|
Debug.WriteLine("Failed to full sync.");
|
||||||
|
if(attempt >= 1)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await Task.Delay(1000);
|
||||||
|
}
|
||||||
|
attempt++;
|
||||||
|
}
|
||||||
|
} while(attempt <= 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private async Task CheckLockAsync(bool forceLock)
|
private async Task CheckLockAsync(bool forceLock)
|
||||||
{
|
{
|
||||||
// Only lock if they are logged in
|
// Only lock if they are logged in
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
using System;
|
using System;
|
||||||
|
using System.Diagnostics;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Bit.App.Abstractions;
|
using Bit.App.Abstractions;
|
||||||
using Bit.App.Models;
|
using Bit.App.Models;
|
||||||
|
using Org.BouncyCastle.Crypto;
|
||||||
using Org.BouncyCastle.Crypto.Digests;
|
using Org.BouncyCastle.Crypto.Digests;
|
||||||
using Org.BouncyCastle.Crypto.Engines;
|
using Org.BouncyCastle.Crypto.Engines;
|
||||||
using Org.BouncyCastle.Crypto.Generators;
|
using Org.BouncyCastle.Crypto.Generators;
|
||||||
|
@ -113,14 +115,20 @@ namespace Bit.App.Services
|
||||||
throw new ArgumentNullException(nameof(encyptedValue));
|
throw new ArgumentNullException(nameof(encyptedValue));
|
||||||
}
|
}
|
||||||
|
|
||||||
var keyParamWithIV = new ParametersWithIV(_keyParameter, encyptedValue.InitializationVectorBytes, 0, InitializationVectorSize);
|
try
|
||||||
|
{
|
||||||
_cipher.Init(false, keyParamWithIV);
|
var keyParamWithIV = new ParametersWithIV(_keyParameter, encyptedValue.InitializationVectorBytes, 0, InitializationVectorSize);
|
||||||
byte[] comparisonBytes = new byte[_cipher.GetOutputSize(encyptedValue.CipherTextBytes.Length)];
|
_cipher.Init(false, keyParamWithIV);
|
||||||
var length = _cipher.ProcessBytes(encyptedValue.CipherTextBytes, comparisonBytes, 0);
|
byte[] comparisonBytes = new byte[_cipher.GetOutputSize(encyptedValue.CipherTextBytes.Length)];
|
||||||
_cipher.DoFinal(comparisonBytes, length);
|
var length = _cipher.ProcessBytes(encyptedValue.CipherTextBytes, comparisonBytes, 0);
|
||||||
|
_cipher.DoFinal(comparisonBytes, length);
|
||||||
return Encoding.UTF8.GetString(comparisonBytes, 0, comparisonBytes.Length).TrimEnd('\0');
|
return Encoding.UTF8.GetString(comparisonBytes, 0, comparisonBytes.Length).TrimEnd('\0');
|
||||||
|
}
|
||||||
|
catch(Exception e)
|
||||||
|
{
|
||||||
|
Debug.WriteLine("Could not decrypt '{0}'. {1}", encyptedValue, e.Message);
|
||||||
|
return "[error: cannot decrypt]";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public byte[] MakeKeyFromPassword(string password, string salt)
|
public byte[] MakeKeyFromPassword(string password, string salt)
|
||||||
|
|
|
@ -2,24 +2,31 @@
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using Bit.App.Abstractions;
|
using Bit.App.Abstractions;
|
||||||
using Foundation;
|
using Foundation;
|
||||||
|
using SQLite;
|
||||||
|
|
||||||
namespace Bit.iOS.Core.Services
|
namespace Bit.iOS.Core.Services
|
||||||
{
|
{
|
||||||
public class SqlService : ISqlService
|
public class SqlService : ISqlService
|
||||||
{
|
{
|
||||||
public SQLite.SQLiteConnection GetConnection()
|
private SQLiteConnection _connection;
|
||||||
|
|
||||||
|
public SQLiteConnection GetConnection()
|
||||||
{
|
{
|
||||||
|
if(_connection != null)
|
||||||
|
{
|
||||||
|
return _connection;
|
||||||
|
}
|
||||||
|
|
||||||
var sqliteFilename = "bitwarden.db3";
|
var sqliteFilename = "bitwarden.db3";
|
||||||
var fileManager = new NSFileManager();
|
var fileManager = new NSFileManager();
|
||||||
var appGroupContainer = fileManager.GetContainerUrl("group.com.8bit.bitwarden");
|
var appGroupContainer = fileManager.GetContainerUrl("group.com.8bit.bitwarden");
|
||||||
var libraryPath = Path.Combine(appGroupContainer.Path, "Library"); // Library folder
|
var libraryPath = Path.Combine(appGroupContainer.Path, "Library"); // Library folder
|
||||||
var path = Path.Combine(libraryPath, sqliteFilename);
|
var path = Path.Combine(libraryPath, sqliteFilename);
|
||||||
|
|
||||||
Console.WriteLine(path);
|
Console.WriteLine(path);
|
||||||
var conn = new SQLite.SQLiteConnection(path);
|
|
||||||
|
|
||||||
// Return the database connection
|
_connection = new SQLiteConnection(path,
|
||||||
return conn;
|
SQLiteOpenFlags.ReadWrite | SQLiteOpenFlags.Create | SQLiteOpenFlags.FullMutex | SQLiteOpenFlags.SharedCache);
|
||||||
|
return _connection;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue