2020-02-14 22:10:58 +01:00
|
|
|
|
using System;
|
|
|
|
|
using Bit.App.Abstractions;
|
|
|
|
|
using Bit.App.Resources;
|
|
|
|
|
using Bit.Core.Abstractions;
|
|
|
|
|
using Bit.Core.Utilities;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Text;
|
|
|
|
|
using System.Threading.Tasks;
|
2020-04-02 16:30:21 +02:00
|
|
|
|
#if !FDROID
|
|
|
|
|
using Microsoft.AppCenter.Crashes;
|
|
|
|
|
#endif
|
2020-02-14 22:10:58 +01:00
|
|
|
|
using Xamarin.Forms;
|
|
|
|
|
|
|
|
|
|
namespace Bit.App.Pages
|
|
|
|
|
{
|
|
|
|
|
public class ExportVaultPageViewModel : BaseViewModel
|
|
|
|
|
{
|
|
|
|
|
private readonly IDeviceActionService _deviceActionService;
|
|
|
|
|
private readonly IPlatformUtilsService _platformUtilsService;
|
|
|
|
|
private readonly II18nService _i18nService;
|
|
|
|
|
private readonly ICryptoService _cryptoService;
|
|
|
|
|
private readonly IExportService _exportService;
|
|
|
|
|
|
|
|
|
|
private int _fileFormatSelectedIndex;
|
|
|
|
|
private bool _showPassword;
|
|
|
|
|
private string _masterPassword;
|
|
|
|
|
private byte[] _exportResult;
|
|
|
|
|
private string _defaultFilename;
|
|
|
|
|
|
|
|
|
|
public ExportVaultPageViewModel()
|
|
|
|
|
{
|
|
|
|
|
_deviceActionService = ServiceContainer.Resolve<IDeviceActionService>("deviceActionService");
|
|
|
|
|
_platformUtilsService = ServiceContainer.Resolve<IPlatformUtilsService>("platformUtilsService");
|
|
|
|
|
_i18nService = ServiceContainer.Resolve<II18nService>("i18nService");
|
|
|
|
|
_cryptoService = ServiceContainer.Resolve<ICryptoService>("cryptoService");
|
|
|
|
|
_exportService = ServiceContainer.Resolve<IExportService>("exportService");
|
|
|
|
|
|
|
|
|
|
PageTitle = AppResources.ExportVault;
|
|
|
|
|
TogglePasswordCommand = new Command(TogglePassword);
|
|
|
|
|
ExportVaultCommand = new Command(async () => await ExportVaultAsync());
|
|
|
|
|
|
|
|
|
|
FileFormatOptions = new List<KeyValuePair<string, string>>
|
|
|
|
|
{
|
|
|
|
|
new KeyValuePair<string, string>("json", ".json"),
|
|
|
|
|
new KeyValuePair<string, string>("csv", ".csv")
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public async Task InitAsync()
|
|
|
|
|
{
|
|
|
|
|
FileFormatSelectedIndex = FileFormatOptions.FindIndex(k => k.Key == "json");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public List<KeyValuePair<string, string>> FileFormatOptions { get; set; }
|
|
|
|
|
|
|
|
|
|
public int FileFormatSelectedIndex
|
|
|
|
|
{
|
|
|
|
|
get => _fileFormatSelectedIndex;
|
|
|
|
|
set { SetProperty(ref _fileFormatSelectedIndex, value); }
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public bool ShowPassword
|
|
|
|
|
{
|
|
|
|
|
get => _showPassword;
|
|
|
|
|
set => SetProperty(ref _showPassword, value,
|
|
|
|
|
additionalPropertyNames: new string[] {nameof(ShowPasswordIcon)});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public string MasterPassword
|
|
|
|
|
{
|
|
|
|
|
get => _masterPassword;
|
|
|
|
|
set => SetProperty(ref _masterPassword, value);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Command TogglePasswordCommand { get; }
|
|
|
|
|
|
|
|
|
|
public string ShowPasswordIcon => ShowPassword ? "" : "";
|
|
|
|
|
|
|
|
|
|
public void TogglePassword()
|
|
|
|
|
{
|
|
|
|
|
ShowPassword = !ShowPassword;
|
|
|
|
|
(Page as ExportVaultPage).MasterPasswordEntry.Focus();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public Command ExportVaultCommand { get; }
|
|
|
|
|
|
|
|
|
|
public async Task ExportVaultAsync()
|
|
|
|
|
{
|
2020-03-28 14:16:28 +01:00
|
|
|
|
if (string.IsNullOrEmpty(_masterPassword))
|
2020-02-14 22:10:58 +01:00
|
|
|
|
{
|
|
|
|
|
await _platformUtilsService.ShowDialogAsync(_i18nService.T("InvalidMasterPassword"));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
var keyHash = await _cryptoService.HashPasswordAsync(_masterPassword, null);
|
|
|
|
|
MasterPassword = string.Empty;
|
|
|
|
|
|
|
|
|
|
var storedKeyHash = await _cryptoService.GetKeyHashAsync();
|
2020-03-28 14:16:28 +01:00
|
|
|
|
if (storedKeyHash != null && keyHash != null && storedKeyHash == keyHash)
|
2020-02-14 22:10:58 +01:00
|
|
|
|
{
|
|
|
|
|
try
|
|
|
|
|
{
|
2020-05-29 18:38:26 +02:00
|
|
|
|
var data = await _exportService.GetExport(FileFormatOptions[FileFormatSelectedIndex].Key);
|
2020-02-14 22:10:58 +01:00
|
|
|
|
var fileFormat = FileFormatOptions[FileFormatSelectedIndex].Key;
|
|
|
|
|
_defaultFilename = _exportService.GetFileName(null, fileFormat);
|
2020-05-29 18:38:26 +02:00
|
|
|
|
_exportResult = Encoding.ASCII.GetBytes(data);
|
2020-02-14 22:10:58 +01:00
|
|
|
|
|
2020-03-28 14:16:28 +01:00
|
|
|
|
if (!_deviceActionService.SaveFile(_exportResult, null, _defaultFilename, null))
|
2020-02-14 22:10:58 +01:00
|
|
|
|
{
|
|
|
|
|
ClearResult();
|
|
|
|
|
await _platformUtilsService.ShowDialogAsync(_i18nService.T("ExportVaultFailure"));
|
|
|
|
|
}
|
|
|
|
|
}
|
2020-03-28 14:16:28 +01:00
|
|
|
|
catch (Exception ex)
|
2020-02-14 22:10:58 +01:00
|
|
|
|
{
|
|
|
|
|
ClearResult();
|
2020-03-13 16:02:49 +01:00
|
|
|
|
await _platformUtilsService.ShowDialogAsync(_i18nService.T("ExportVaultFailure"));
|
2020-02-14 22:10:58 +01:00
|
|
|
|
System.Diagnostics.Debug.WriteLine(">>> {0}: {1}", ex.GetType(), ex.StackTrace);
|
2020-04-02 16:30:21 +02:00
|
|
|
|
#if !FDROID
|
|
|
|
|
Crashes.TrackError(ex);
|
|
|
|
|
#endif
|
2020-02-14 22:10:58 +01:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
await _platformUtilsService.ShowDialogAsync(_i18nService.T("InvalidMasterPassword"));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public async void SaveFileSelected(string contentUri, string filename)
|
|
|
|
|
{
|
2020-03-28 14:16:28 +01:00
|
|
|
|
if (_deviceActionService.SaveFile(_exportResult, null, filename ?? _defaultFilename, contentUri))
|
2020-02-14 22:10:58 +01:00
|
|
|
|
{
|
|
|
|
|
ClearResult();
|
|
|
|
|
_platformUtilsService.ShowToast("success", null, _i18nService.T("ExportVaultSuccess"));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
ClearResult();
|
|
|
|
|
await _platformUtilsService.ShowDialogAsync(_i18nService.T("ExportVaultFailure"));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void ClearResult()
|
|
|
|
|
{
|
|
|
|
|
_defaultFilename = null;
|
|
|
|
|
_exportResult = null;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|