Improved Certificate Handling (fixed problem with Certificate validation)
This commit is contained in:
		@@ -20,7 +20,7 @@
 | 
			
		||||
    <DebugType>full</DebugType>
 | 
			
		||||
    <Optimize>False</Optimize>
 | 
			
		||||
    <OutputPath>bin\Debug</OutputPath>
 | 
			
		||||
    <DefineConstants>DEBUG;EXCLUDE_TWOFISH;EXCLUDE_KEYBOARD;EXCLUDE_KEYTRANSFORM;INCLUDE_FILECHOOSER;INCLUDE_JAVAFILESTORAGE</DefineConstants>
 | 
			
		||||
    <DefineConstants>DEBUG;EXCLUDE_TWOFISH;EXCLUDE_KEYBOARD;EXCLUDE_KEYTRANSFORM;EXCLUDE_FILECHOOSER;EXCLUDE_JAVAFILESTORAGE</DefineConstants>
 | 
			
		||||
    <ErrorReport>prompt</ErrorReport>
 | 
			
		||||
    <WarningLevel>4</WarningLevel>
 | 
			
		||||
    <ConsolePause>False</ConsolePause>
 | 
			
		||||
 
 | 
			
		||||
@@ -317,7 +317,7 @@ namespace KeePassLib.Serialization
 | 
			
		||||
				if ((ex.Response is HttpWebResponse) && (((HttpWebResponse)ex.Response).StatusCode == HttpStatusCode.Unauthorized))
 | 
			
		||||
					return CreateWebClient(ioc, true).OpenRead(new Uri(ioc.Path));
 | 
			
		||||
				else
 | 
			
		||||
					throw ex;
 | 
			
		||||
					throw;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
		}
 | 
			
		||||
@@ -369,7 +369,7 @@ namespace KeePassLib.Serialization
 | 
			
		||||
					if ((ex.Response is HttpWebResponse) && (((HttpWebResponse) ex.Response).StatusCode == HttpStatusCode.Unauthorized))
 | 
			
		||||
						uploadData(IOConnection.CreateWebClient(ioc, true));
 | 
			
		||||
					else
 | 
			
		||||
						throw ex;
 | 
			
		||||
						throw;
 | 
			
		||||
				}
 | 
			
		||||
				
 | 
			
		||||
			}
 | 
			
		||||
 
 | 
			
		||||
@@ -78,5 +78,11 @@ namespace keepass2android
 | 
			
		||||
		IFileStorage GetFileStorage(IOConnectionInfo iocInfo);
 | 
			
		||||
 | 
			
		||||
		void TriggerReload(Context context);
 | 
			
		||||
 | 
			
		||||
		/// <summary>
 | 
			
		||||
		/// Handles a failed certificate validation. Returns true if the users wants to continue, false otherwise.
 | 
			
		||||
		/// see http://msdn.microsoft.com/en-us/library/system.net.icertificatepolicy(v=vs.110).aspx
 | 
			
		||||
		/// </summary>
 | 
			
		||||
		bool OnServerCertificateError(int certificateProblem);
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -3,8 +3,10 @@ using System.Collections.Generic;
 | 
			
		||||
using System.Globalization;
 | 
			
		||||
using System.IO;
 | 
			
		||||
using System.Net;
 | 
			
		||||
using System.Net.Security;
 | 
			
		||||
using Android.Content;
 | 
			
		||||
using Android.OS;
 | 
			
		||||
using Java.Security.Cert;
 | 
			
		||||
using KeePassLib.Serialization;
 | 
			
		||||
using KeePassLib.Utility;
 | 
			
		||||
 | 
			
		||||
@@ -12,6 +14,56 @@ namespace keepass2android.Io
 | 
			
		||||
{
 | 
			
		||||
	public class BuiltInFileStorage: IFileStorage
 | 
			
		||||
	{
 | 
			
		||||
		public enum CertificateProblem :long
 | 
			
		||||
		{
 | 
			
		||||
			CertEXPIRED = 0x800B0101,
 | 
			
		||||
			CertVALIDITYPERIODNESTING = 0x800B0102,
 | 
			
		||||
			CertROLE = 0x800B0103,
 | 
			
		||||
			CertPATHLENCONST = 0x800B0104,
 | 
			
		||||
			CertCRITICAL = 0x800B0105,
 | 
			
		||||
			CertPURPOSE = 0x800B0106,
 | 
			
		||||
			CertISSUERCHAINING = 0x800B0107,
 | 
			
		||||
			CertMALFORMED = 0x800B0108,
 | 
			
		||||
			CertUNTRUSTEDROOT = 0x800B0109,
 | 
			
		||||
			CertCHAINING = 0x800B010A,
 | 
			
		||||
			CertREVOKED = 0x800B010C,
 | 
			
		||||
			CertUNTRUSTEDTESTROOT = 0x800B010D,
 | 
			
		||||
			CertREVOCATION_FAILURE = 0x800B010E,
 | 
			
		||||
			CertCN_NO_MATCH = 0x800B010F,
 | 
			
		||||
			CertWRONG_USAGE = 0x800B0110,
 | 
			
		||||
			CertUNTRUSTEDCA = 0x800B0112
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		private readonly IKp2aApp _app;
 | 
			
		||||
 | 
			
		||||
		class CertificatePolicity: ICertificatePolicy 
 | 
			
		||||
		{
 | 
			
		||||
			private readonly IKp2aApp _app;
 | 
			
		||||
 | 
			
		||||
			public CertificatePolicity(IKp2aApp app)
 | 
			
		||||
			{
 | 
			
		||||
				_app = app;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			public bool CheckValidationResult(ServicePoint srvPoint, System.Security.Cryptography.X509Certificates.X509Certificate certificate, WebRequest request,
 | 
			
		||||
			                                  int certificateProblem)
 | 
			
		||||
			{
 | 
			
		||||
				if (certificateProblem == 0) //ok
 | 
			
		||||
					return true;
 | 
			
		||||
				return _app.OnServerCertificateError(certificateProblem);
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		public BuiltInFileStorage(IKp2aApp app)
 | 
			
		||||
		{
 | 
			
		||||
			_app = app;
 | 
			
		||||
			//use the obsolute CertificatePolicy because the ServerCertificateValidationCallback isn't called in Mono for Android (?)
 | 
			
		||||
			ServicePointManager.CertificatePolicy = new CertificatePolicity(app);
 | 
			
		||||
			
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public IEnumerable<string> SupportedProtocols 
 | 
			
		||||
		{ 
 | 
			
		||||
			get 
 | 
			
		||||
@@ -67,27 +119,52 @@ namespace keepass2android.Io
 | 
			
		||||
				return IOConnection.OpenRead(ioc);
 | 
			
		||||
			}
 | 
			
		||||
			catch (WebException ex)
 | 
			
		||||
			{
 | 
			
		||||
				ConvertException(ioc, ex);
 | 
			
		||||
				throw;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private void ConvertException(IOConnectionInfo ioc, WebException ex)
 | 
			
		||||
		{
 | 
			
		||||
			if ((ex.Response is HttpWebResponse) && (((HttpWebResponse) ex.Response).StatusCode == HttpStatusCode.NotFound))
 | 
			
		||||
			{
 | 
			
		||||
				throw new FileNotFoundException(ex.Message, ioc.Path, ex);
 | 
			
		||||
			}
 | 
			
		||||
				throw;
 | 
			
		||||
			if (ex.Status == WebExceptionStatus.TrustFailure)
 | 
			
		||||
			{
 | 
			
		||||
				throw new Exception(_app.GetResourceString(UiStringKey.CertificateFailure), ex);
 | 
			
		||||
			}
 | 
			
		||||
			var inner1 = ex.InnerException as IOException;
 | 
			
		||||
			if (inner1 != null)
 | 
			
		||||
			{
 | 
			
		||||
				var inner2 = inner1.InnerException;
 | 
			
		||||
				if (inner2 != null)
 | 
			
		||||
				{
 | 
			
		||||
					if (inner2.Message.Contains("Invalid certificate received from server."))
 | 
			
		||||
					{
 | 
			
		||||
						throw new Exception(_app.GetResourceString(UiStringKey.CertificateFailure), ex);
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
				 
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public IWriteTransaction OpenWriteTransaction(IOConnectionInfo ioc, bool useFileTransaction)
 | 
			
		||||
		{
 | 
			
		||||
			return new BuiltInFileTransaction(ioc, useFileTransaction);
 | 
			
		||||
			return new BuiltInFileTransaction(ioc, useFileTransaction, this);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public class BuiltInFileTransaction : IWriteTransaction
 | 
			
		||||
		{
 | 
			
		||||
			private readonly IOConnectionInfo _ioc;
 | 
			
		||||
			private readonly BuiltInFileStorage _fileStorage;
 | 
			
		||||
			private readonly FileTransactionEx _transaction;
 | 
			
		||||
 | 
			
		||||
			public BuiltInFileTransaction(IOConnectionInfo ioc, bool useFileTransaction)
 | 
			
		||||
			public BuiltInFileTransaction(IOConnectionInfo ioc, bool useFileTransaction, BuiltInFileStorage fileStorage)
 | 
			
		||||
			{
 | 
			
		||||
				_ioc = ioc;
 | 
			
		||||
				_fileStorage = fileStorage;
 | 
			
		||||
				_transaction = new FileTransactionEx(ioc, useFileTransaction);
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
@@ -97,14 +174,32 @@ namespace keepass2android.Io
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			public Stream OpenFile()
 | 
			
		||||
			{
 | 
			
		||||
				try
 | 
			
		||||
				{
 | 
			
		||||
					return _transaction.OpenWrite();
 | 
			
		||||
				}
 | 
			
		||||
				catch (WebException ex)
 | 
			
		||||
				{
 | 
			
		||||
					_fileStorage.ConvertException(_ioc, ex);
 | 
			
		||||
					throw;
 | 
			
		||||
				}
 | 
			
		||||
				
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			public void CommitWrite()
 | 
			
		||||
			{
 | 
			
		||||
				try
 | 
			
		||||
				{
 | 
			
		||||
					_transaction.CommitWrite();
 | 
			
		||||
				}
 | 
			
		||||
				catch (WebException ex)
 | 
			
		||||
				{
 | 
			
		||||
					_fileStorage.ConvertException(_ioc, ex);
 | 
			
		||||
					throw;
 | 
			
		||||
				}
 | 
			
		||||
				
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public string GetFilenameWithoutPathAndExt(IOConnectionInfo ioc)
 | 
			
		||||
 
 | 
			
		||||
@@ -20,7 +20,7 @@
 | 
			
		||||
    <DebugType>full</DebugType>
 | 
			
		||||
    <Optimize>false</Optimize>
 | 
			
		||||
    <OutputPath>bin\Debug\</OutputPath>
 | 
			
		||||
    <DefineConstants>TRACE;DEBUG;EXCLUDE_TWOFISH;EXCLUDE_KEYBOARD;EXCLUDE_KEYTRANSFORM;INCLUDE_FILECHOOSER;INCLUDE_JAVAFILESTORAGE</DefineConstants>
 | 
			
		||||
    <DefineConstants>TRACE;DEBUG;EXCLUDE_TWOFISH;EXCLUDE_KEYBOARD;EXCLUDE_KEYTRANSFORM;EXCLUDE_FILECHOOSER;EXCLUDE_JAVAFILESTORAGE</DefineConstants>
 | 
			
		||||
    <ErrorReport>prompt</ErrorReport>
 | 
			
		||||
    <WarningLevel>4</WarningLevel>
 | 
			
		||||
  </PropertyGroup>
 | 
			
		||||
@@ -44,6 +44,7 @@
 | 
			
		||||
  </PropertyGroup>
 | 
			
		||||
  <ItemGroup>
 | 
			
		||||
    <Reference Include="Mono.Android" />
 | 
			
		||||
    <Reference Include="Mono.Security" />
 | 
			
		||||
    <Reference Include="mscorlib" />
 | 
			
		||||
    <Reference Include="System" />
 | 
			
		||||
    <Reference Include="System.Core" />
 | 
			
		||||
 
 | 
			
		||||
@@ -46,6 +46,7 @@ namespace keepass2android
 | 
			
		||||
		CannotMoveGroupHere,
 | 
			
		||||
		ErrorOcurred,
 | 
			
		||||
		SynchronizingOtpAuxFile,
 | 
			
		||||
		SavingOtpAuxFile
 | 
			
		||||
		SavingOtpAuxFile,
 | 
			
		||||
		CertificateFailure
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
@@ -18,9 +18,9 @@ namespace Kp2aUnitTests
 | 
			
		||||
        {
 | 
			
		||||
            TestRunner runner = new TestRunner();
 | 
			
		||||
            // Run all tests from this assembly
 | 
			
		||||
            runner.AddTests(Assembly.GetExecutingAssembly());
 | 
			
		||||
            //runner.AddTests(Assembly.GetExecutingAssembly());
 | 
			
		||||
			//runner.AddTests(new List<Type> { typeof(TestSynchronizeCachedDatabase)});
 | 
			
		||||
			//runner.AddTests(typeof(TestSaveDbCached).GetMethod("TestLoadEditSaveWhenModified"));
 | 
			
		||||
			runner.AddTests(typeof(TestLoadDb).GetMethod("LoadErrorWithCertificateTrustFailure"));
 | 
			
		||||
			
 | 
			
		||||
			//runner.AddTests(new List<Type> { typeof(TestSaveDb) });
 | 
			
		||||
			//runner.AddTests(new List<Type> { typeof(TestCachingFileStorage) });
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										2
									
								
								src/Kp2aUnitTests/Resources/Resource.Designer.cs
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										2
									
								
								src/Kp2aUnitTests/Resources/Resource.Designer.cs
									
									
									
										generated
									
									
									
								
							@@ -2,7 +2,7 @@
 | 
			
		||||
//------------------------------------------------------------------------------
 | 
			
		||||
// <auto-generated>
 | 
			
		||||
//     Dieser Code wurde von einem Tool generiert.
 | 
			
		||||
//     Laufzeitversion:4.0.30319.18051
 | 
			
		||||
//     Laufzeitversion:4.0.30319.34003
 | 
			
		||||
//
 | 
			
		||||
//     Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn
 | 
			
		||||
//     der Code erneut generiert wird.
 | 
			
		||||
 
 | 
			
		||||
@@ -66,7 +66,7 @@ namespace Kp2aUnitTests
 | 
			
		||||
			var app = CreateTestKp2aApp();
 | 
			
		||||
			app.CreateNewDatabase();
 | 
			
		||||
			bool loadSuccesful = false;
 | 
			
		||||
			LoadDb task = new LoadDb(app, new IOConnectionInfo() { Path = filename }, null, password, keyfile, new ActionOnFinish((success, message) =>
 | 
			
		||||
			LoadDb task = new LoadDb(app, new IOConnectionInfo() { Path = filename }, null, CreateKey(password, keyfile), keyfile, new ActionOnFinish((success, message) =>
 | 
			
		||||
				{
 | 
			
		||||
					if (!success)
 | 
			
		||||
						Kp2aLog.Log(message);
 | 
			
		||||
@@ -80,7 +80,20 @@ namespace Kp2aUnitTests
 | 
			
		||||
			Assert.IsTrue(loadSuccesful);
 | 
			
		||||
			return app;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		protected static CompositeKey CreateKey(string password, string keyfile)
 | 
			
		||||
		{
 | 
			
		||||
			CompositeKey key = new CompositeKey();
 | 
			
		||||
			key.AddUserKey(new KcpPassword(password));
 | 
			
		||||
			if (!String.IsNullOrEmpty(keyfile))
 | 
			
		||||
				key.AddUserKey(new KcpKeyFile(keyfile));
 | 
			
		||||
			return key;
 | 
			
		||||
		}
 | 
			
		||||
		protected static CompositeKey CreateKey(string password)
 | 
			
		||||
		{
 | 
			
		||||
			CompositeKey key = new CompositeKey();
 | 
			
		||||
			key.AddUserKey(new KcpPassword(password));
 | 
			
		||||
			return key;
 | 
			
		||||
		}
 | 
			
		||||
		protected virtual TestKp2aApp CreateTestKp2aApp()
 | 
			
		||||
		{
 | 
			
		||||
			TestKp2aApp app = new TestKp2aApp();
 | 
			
		||||
 
 | 
			
		||||
@@ -14,6 +14,12 @@ namespace Kp2aUnitTests
 | 
			
		||||
	[TestClass]
 | 
			
		||||
	class TestCachingFileStorage: TestBase
 | 
			
		||||
	{
 | 
			
		||||
		[TestInitialize]
 | 
			
		||||
		public void InitTests()
 | 
			
		||||
		{
 | 
			
		||||
			TestFileStorage.Offline = false;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private TestFileStorage _testFileStorage;
 | 
			
		||||
		private CachingFileStorage _fileStorage;
 | 
			
		||||
		private static readonly string CachingTestFile = DefaultDirectory + "cachingTestFile.txt";
 | 
			
		||||
@@ -37,7 +43,7 @@ namespace Kp2aUnitTests
 | 
			
		||||
			Assert.AreEqual(MemoryStreamToString(fileContents), _defaultCacheFileContents);
 | 
			
		||||
 | 
			
		||||
			//let the base file storage go offline:
 | 
			
		||||
			_testFileStorage.Offline = true;
 | 
			
		||||
			TestFileStorage.Offline = true;
 | 
			
		||||
 | 
			
		||||
			//now try to read the file again:
 | 
			
		||||
			MemoryStream fileContents2 = ReadToMemoryStream(_fileStorage, CachingTestFile);
 | 
			
		||||
@@ -98,7 +104,7 @@ namespace Kp2aUnitTests
 | 
			
		||||
			_testCacheSupervisor.AssertSingleCall(TestCacheSupervisor.UpdatedCachedFileOnLoadId);
 | 
			
		||||
 | 
			
		||||
			//let the base file storage go offline:
 | 
			
		||||
			_testFileStorage.Offline = true;
 | 
			
		||||
			TestFileStorage.Offline = true;
 | 
			
		||||
 | 
			
		||||
			//write something to the cache:
 | 
			
		||||
			string newContent = "new content";
 | 
			
		||||
@@ -116,7 +122,7 @@ namespace Kp2aUnitTests
 | 
			
		||||
			Assert.AreEqual(MemoryStreamToString(fileContents2), newContent);
 | 
			
		||||
 | 
			
		||||
			//now go online and read again. This should trigger a sync and the modified data must be returned
 | 
			
		||||
			_testFileStorage.Offline = false;
 | 
			
		||||
			TestFileStorage.Offline = false;
 | 
			
		||||
			MemoryStream fileContents3 = ReadToMemoryStream(_fileStorage, CachingTestFile);
 | 
			
		||||
			Assert.AreEqual(MemoryStreamToString(fileContents3), newContent);
 | 
			
		||||
 | 
			
		||||
@@ -141,7 +147,7 @@ namespace Kp2aUnitTests
 | 
			
		||||
			_testCacheSupervisor.AssertSingleCall(TestCacheSupervisor.UpdatedCachedFileOnLoadId);
 | 
			
		||||
 | 
			
		||||
			//let the base file storage go offline:
 | 
			
		||||
			_testFileStorage.Offline = true;
 | 
			
		||||
			TestFileStorage.Offline = true;
 | 
			
		||||
 | 
			
		||||
			//write something to the cache:
 | 
			
		||||
			string newLocalContent = "new local content";
 | 
			
		||||
@@ -153,7 +159,7 @@ namespace Kp2aUnitTests
 | 
			
		||||
			File.WriteAllText(CachingTestFile, "new remote content");
 | 
			
		||||
 | 
			
		||||
			//go online again:
 | 
			
		||||
			_testFileStorage.Offline = false;
 | 
			
		||||
			TestFileStorage.Offline = false;
 | 
			
		||||
 | 
			
		||||
			//now try to read the file again:
 | 
			
		||||
			MemoryStream fileContents2 = ReadToMemoryStream(_fileStorage, CachingTestFile);
 | 
			
		||||
@@ -231,7 +237,7 @@ namespace Kp2aUnitTests
 | 
			
		||||
 | 
			
		||||
		private void SetupFileStorage()
 | 
			
		||||
		{
 | 
			
		||||
			_testFileStorage = new TestFileStorage();
 | 
			
		||||
			_testFileStorage = new TestFileStorage(new TestKp2aApp());
 | 
			
		||||
			_testCacheSupervisor = new TestCacheSupervisor();
 | 
			
		||||
			//_fileStorage = new CachingFileStorage(_testFileStorage, Application.Context.CacheDir.Path, _testCacheSupervisor);
 | 
			
		||||
			_fileStorage = new CachingFileStorage(_testFileStorage, "/mnt/sdcard/kp2atest_cache", _testCacheSupervisor);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,16 +1,23 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.IO;
 | 
			
		||||
using Android.Content;
 | 
			
		||||
using Android.OS;
 | 
			
		||||
using KeePassLib.Serialization;
 | 
			
		||||
using keepass2android;
 | 
			
		||||
using keepass2android.Io;
 | 
			
		||||
 | 
			
		||||
namespace Kp2aUnitTests
 | 
			
		||||
{
 | 
			
		||||
	internal class TestFileStorage: IFileStorage
 | 
			
		||||
	{
 | 
			
		||||
		private BuiltInFileStorage _builtIn = new BuiltInFileStorage();
 | 
			
		||||
		public TestFileStorage(IKp2aApp app)
 | 
			
		||||
		{
 | 
			
		||||
			_builtIn = new BuiltInFileStorage(app);
 | 
			
		||||
		}
 | 
			
		||||
		private BuiltInFileStorage _builtIn;
 | 
			
		||||
 | 
			
		||||
		public bool Offline { get; set; }
 | 
			
		||||
		public static bool Offline { get; set; }
 | 
			
		||||
 | 
			
		||||
		public IEnumerable<string> SupportedProtocols { get { yield return "test"; } }
 | 
			
		||||
 | 
			
		||||
@@ -96,6 +103,11 @@ namespace Kp2aUnitTests
 | 
			
		||||
			return _builtIn.RequiresCredentials(ioc);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public void CreateDirectory(IOConnectionInfo ioc, string newDirName)
 | 
			
		||||
		{
 | 
			
		||||
			throw new NotImplementedException();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public void CreateDirectory(IOConnectionInfo ioc)
 | 
			
		||||
		{
 | 
			
		||||
			throw new NotImplementedException();
 | 
			
		||||
@@ -110,5 +122,66 @@ namespace Kp2aUnitTests
 | 
			
		||||
		{
 | 
			
		||||
			throw new NotImplementedException();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public bool RequiresSetup(IOConnectionInfo ioConnection)
 | 
			
		||||
		{
 | 
			
		||||
			return false;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public string IocToPath(IOConnectionInfo ioc)
 | 
			
		||||
		{
 | 
			
		||||
			return ioc.Path;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public void StartSelectFile(IFileStorageSetupInitiatorActivity activity, bool isForSave, int requestCode, string protocolId)
 | 
			
		||||
		{
 | 
			
		||||
			throw new NotImplementedException();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public void PrepareFileUsage(IFileStorageSetupInitiatorActivity activity, IOConnectionInfo ioc, int requestCode,
 | 
			
		||||
		                             bool alwaysReturnSuccess)
 | 
			
		||||
		{
 | 
			
		||||
			throw new NotImplementedException();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public void OnCreate(IFileStorageSetupActivity activity, Bundle savedInstanceState)
 | 
			
		||||
		{
 | 
			
		||||
			throw new NotImplementedException();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public void OnResume(IFileStorageSetupActivity activity)
 | 
			
		||||
		{
 | 
			
		||||
			throw new NotImplementedException();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public void OnStart(IFileStorageSetupActivity activity)
 | 
			
		||||
		{
 | 
			
		||||
			throw new NotImplementedException();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public void OnActivityResult(IFileStorageSetupActivity activity, int requestCode, int resultCode, Intent data)
 | 
			
		||||
		{
 | 
			
		||||
			throw new NotImplementedException();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public string GetDisplayName(IOConnectionInfo ioc)
 | 
			
		||||
		{
 | 
			
		||||
			return ioc.Path;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public string CreateFilePath(string parent, string newFilename)
 | 
			
		||||
		{
 | 
			
		||||
			throw new NotImplementedException();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public IOConnectionInfo GetParentPath(IOConnectionInfo ioc)
 | 
			
		||||
		{
 | 
			
		||||
			throw new NotImplementedException();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public IOConnectionInfo GetFilePath(IOConnectionInfo folderPath, string filename)
 | 
			
		||||
		{
 | 
			
		||||
			throw new NotImplementedException();
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
@@ -1,9 +1,11 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.IO;
 | 
			
		||||
using System.Net.Security;
 | 
			
		||||
using Android.App;
 | 
			
		||||
using Android.Content;
 | 
			
		||||
using Android.OS;
 | 
			
		||||
using KeePassLib.Keys;
 | 
			
		||||
using KeePassLib.Serialization;
 | 
			
		||||
using keepass2android;
 | 
			
		||||
using keepass2android.Io;
 | 
			
		||||
@@ -30,18 +32,27 @@ namespace Kp2aUnitTests
 | 
			
		||||
			
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public virtual TestFileStorage TestFileStorage
 | 
			
		||||
		{
 | 
			
		||||
			get
 | 
			
		||||
			{
 | 
			
		||||
				if (_testFileStorage != null)
 | 
			
		||||
					return _testFileStorage;
 | 
			
		||||
				return (TestFileStorage) FileStorage;
 | 
			
		||||
			}
 | 
			
		||||
			set { _testFileStorage = value; }
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public void LockDatabase(bool allowQuickUnlock = true)
 | 
			
		||||
		{
 | 
			
		||||
			throw new NotImplementedException();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public void LoadDatabase(IOConnectionInfo ioConnectionInfo, MemoryStream memoryStream, string password, string keyFile,
 | 
			
		||||
		public void LoadDatabase(IOConnectionInfo ioConnectionInfo, MemoryStream memoryStream, CompositeKey compKey,
 | 
			
		||||
		                         ProgressDialogStatusLogger statusLogger)
 | 
			
		||||
		{
 | 
			
		||||
			_db.LoadData(this, ioConnectionInfo, memoryStream, password, statusLogger);
 | 
			
		||||
			
 | 
			
		||||
			_db.LoadData(this, ioConnectionInfo, memoryStream, compKey, statusLogger);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public Database GetDb()
 | 
			
		||||
		{
 | 
			
		||||
			return _db;
 | 
			
		||||
@@ -128,10 +139,11 @@ namespace Kp2aUnitTests
 | 
			
		||||
 | 
			
		||||
		
 | 
			
		||||
		public bool TriggerReloadCalled;
 | 
			
		||||
		private TestFileStorage _testFileStorage;
 | 
			
		||||
 | 
			
		||||
		public TestKp2aApp()
 | 
			
		||||
		{
 | 
			
		||||
			FileStorage = new BuiltInFileStorage();
 | 
			
		||||
			FileStorage = new BuiltInFileStorage(this);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public void TriggerReload(Context ctx)
 | 
			
		||||
@@ -139,6 +151,16 @@ namespace Kp2aUnitTests
 | 
			
		||||
			TriggerReloadCalled = true;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public bool OnServerCertificateError(int sslPolicyErrors)
 | 
			
		||||
		{
 | 
			
		||||
			ServerCertificateErrorCalled = true;
 | 
			
		||||
			return ServerCertificateErrorResponse;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public bool ServerCertificateErrorResponse { get; set; }
 | 
			
		||||
 | 
			
		||||
		protected bool ServerCertificateErrorCalled { get; set; }
 | 
			
		||||
 | 
			
		||||
		public void SetYesNoCancelResult(YesNoCancelResult yesNoCancelResult)
 | 
			
		||||
		{
 | 
			
		||||
			_yesNoCancelResult = yesNoCancelResult;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,9 +1,7 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.IO;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Threading;
 | 
			
		||||
using Android.App;
 | 
			
		||||
using Android.OS;
 | 
			
		||||
using KeePassLib.Serialization;
 | 
			
		||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
 | 
			
		||||
using keepass2android;
 | 
			
		||||
@@ -21,8 +19,10 @@ namespace Kp2aUnitTests
 | 
			
		||||
			IKp2aApp app = new TestKp2aApp();
 | 
			
		||||
			app.CreateNewDatabase();
 | 
			
		||||
			bool loadSuccesful = false;
 | 
			
		||||
			LoadDb task = new LoadDb(app, new IOConnectionInfo() { Path = TestDbDirectory+filenameWithoutDir }, null,
 | 
			
		||||
				password, keyfile, new ActionOnFinish((success, message) =>
 | 
			
		||||
			var key = CreateKey(password, keyfile);
 | 
			
		||||
 | 
			
		||||
			LoadDb task = new LoadDb(app, new IOConnectionInfo { Path = TestDbDirectory+filenameWithoutDir }, null,
 | 
			
		||||
				key, keyfile, new ActionOnFinish((success, message) =>
 | 
			
		||||
					{
 | 
			
		||||
						if (!success)
 | 
			
		||||
							Android.Util.Log.Debug("KP2ATest", "error loading db: " + message);
 | 
			
		||||
@@ -41,6 +41,8 @@ namespace Kp2aUnitTests
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		[TestMethod]
 | 
			
		||||
		public void TestLoadWithPasswordOnly()
 | 
			
		||||
		{
 | 
			
		||||
@@ -74,11 +76,12 @@ namespace Kp2aUnitTests
 | 
			
		||||
		public void LoadFromRemoteWithDomain()
 | 
			
		||||
		{
 | 
			
		||||
			var ioc = RemoteDomainIoc; //note: this property is defined in "TestLoadDbCredentials.cs" which is deliberately excluded from Git because the credentials are not public!
 | 
			
		||||
			IKp2aApp app = new TestKp2aApp();
 | 
			
		||||
			var app = new TestKp2aApp();
 | 
			
		||||
			app.ServerCertificateErrorResponse = true; //accept invalid cert
 | 
			
		||||
			app.CreateNewDatabase();
 | 
			
		||||
			
 | 
			
		||||
			bool loadSuccesful = false;
 | 
			
		||||
			LoadDb task = new LoadDb(app, ioc, null, "a", null, new ActionOnFinish((success, message) =>
 | 
			
		||||
			LoadDb task = new LoadDb(app, ioc, null, CreateKey("a"), null, new ActionOnFinish((success, message) =>
 | 
			
		||||
				{
 | 
			
		||||
					if (!success)
 | 
			
		||||
						Android.Util.Log.Debug("KP2ATest", "error loading db: " + message);
 | 
			
		||||
@@ -95,14 +98,69 @@ namespace Kp2aUnitTests
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		[TestMethod]
 | 
			
		||||
		public void LoadFromRemote1and1()
 | 
			
		||||
		public void LoadErrorWithCertificateTrustFailure()
 | 
			
		||||
		{
 | 
			
		||||
			var ioc = RemoteCertFailureIoc; //note: this property is defined in "TestLoadDbCredentials.cs" which is deliberately excluded from Git because the credentials are not public!
 | 
			
		||||
			var app = new TestKp2aApp();
 | 
			
		||||
			app.ServerCertificateErrorResponse = false;
 | 
			
		||||
			app.CreateNewDatabase();
 | 
			
		||||
 | 
			
		||||
			bool loadSuccesful = false;
 | 
			
		||||
			string theMessage = "";
 | 
			
		||||
			LoadDb task = new LoadDb(app, ioc, null, CreateKey("test"), null, new ActionOnFinish((success, message) =>
 | 
			
		||||
			{
 | 
			
		||||
				if (!success)
 | 
			
		||||
					Android.Util.Log.Debug("KP2ATest", "error loading db: " + message);
 | 
			
		||||
				loadSuccesful = success;
 | 
			
		||||
				theMessage = message;
 | 
			
		||||
			})
 | 
			
		||||
				);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
			ProgressTask pt = new ProgressTask(app, Application.Context, task);
 | 
			
		||||
			Android.Util.Log.Debug("KP2ATest", "Running ProgressTask");
 | 
			
		||||
			pt.Run();
 | 
			
		||||
			pt.JoinWorkerThread();
 | 
			
		||||
			Android.Util.Log.Debug("KP2ATest", "PT.run finished");
 | 
			
		||||
			Assert.IsFalse(loadSuccesful, "database should not be loaded because invalid certificates are not accepted");
 | 
			
		||||
			Assert.AreEqual(theMessage, UiStringKey.ErrorOcurred +" "+UiStringKey.CertificateFailure);
 | 
			
		||||
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		[TestMethod]
 | 
			
		||||
		public void LoadWithAcceptedCertificateTrustFailure()
 | 
			
		||||
		{
 | 
			
		||||
			var ioc = RemoteCertFailureIoc; //note: this property is defined in "TestLoadDbCredentials.cs" which is deliberately excluded from Git because the credentials are not public!
 | 
			
		||||
			var app = new TestKp2aApp();
 | 
			
		||||
			app.ServerCertificateErrorResponse = true;
 | 
			
		||||
			app.CreateNewDatabase();
 | 
			
		||||
 | 
			
		||||
			bool loadSuccesful = false;
 | 
			
		||||
			LoadDb task = new LoadDb(app, ioc, null, CreateKey("test"), null, new ActionOnFinish((success, message) =>
 | 
			
		||||
			{
 | 
			
		||||
				if (!success)
 | 
			
		||||
					Android.Util.Log.Debug("KP2ATest", "error loading db: " + message);
 | 
			
		||||
				loadSuccesful = success;
 | 
			
		||||
			})
 | 
			
		||||
				);
 | 
			
		||||
			ProgressTask pt = new ProgressTask(app, Application.Context, task);
 | 
			
		||||
			Android.Util.Log.Debug("KP2ATest", "Running ProgressTask");
 | 
			
		||||
			pt.Run();
 | 
			
		||||
			pt.JoinWorkerThread();
 | 
			
		||||
			Android.Util.Log.Debug("KP2ATest", "PT.run finished");
 | 
			
		||||
			Assert.IsTrue(loadSuccesful, "database should be loaded because invalid certificates are accepted");
 | 
			
		||||
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		[TestMethod]
 | 
			
		||||
		public void LoadFromRemote1And1()
 | 
			
		||||
		{
 | 
			
		||||
			var ioc = RemoteIoc1and1; //note: this property is defined in "TestLoadDbCredentials.cs" which is deliberately excluded from Git because the credentials are not public!
 | 
			
		||||
			IKp2aApp app = new TestKp2aApp();
 | 
			
		||||
			app.CreateNewDatabase();
 | 
			
		||||
			
 | 
			
		||||
			bool loadSuccesful = false;
 | 
			
		||||
			LoadDb task = new LoadDb(app, ioc, null, "test", null, new ActionOnFinish((success, message) =>
 | 
			
		||||
			LoadDb task = new LoadDb(app, ioc, null, CreateKey("test"), null, new ActionOnFinish((success, message) =>
 | 
			
		||||
				{
 | 
			
		||||
					if (!success)
 | 
			
		||||
						Android.Util.Log.Debug("KP2ATest", "error loading db: " + message);
 | 
			
		||||
@@ -120,7 +178,7 @@ namespace Kp2aUnitTests
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		[TestMethod]
 | 
			
		||||
		public void LoadFromRemote1and1NonExisting()
 | 
			
		||||
		public void LoadFromRemote1And1NonExisting()
 | 
			
		||||
		{
 | 
			
		||||
			var ioc = RemoteIoc1and1NonExisting; //note: this property is defined in "TestLoadDbCredentials.cs" which is deliberately excluded from Git because the credentials are not public!
 | 
			
		||||
			IKp2aApp app = new TestKp2aApp();
 | 
			
		||||
@@ -128,7 +186,7 @@ namespace Kp2aUnitTests
 | 
			
		||||
 | 
			
		||||
			bool loadSuccesful = false;
 | 
			
		||||
			bool gotError = false;
 | 
			
		||||
			LoadDb task = new LoadDb(app, ioc, null, "test", null, new ActionOnFinish((success, message) =>
 | 
			
		||||
			LoadDb task = new LoadDb(app, ioc, null, CreateKey("test"), null, new ActionOnFinish((success, message) =>
 | 
			
		||||
			{
 | 
			
		||||
				if (!success)
 | 
			
		||||
				{
 | 
			
		||||
@@ -148,7 +206,7 @@ namespace Kp2aUnitTests
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		[TestMethod]
 | 
			
		||||
		public void LoadFromRemote1and1WrongCredentials()
 | 
			
		||||
		public void LoadFromRemote1And1WrongCredentials()
 | 
			
		||||
		{
 | 
			
		||||
			var ioc = RemoteIoc1and1WrongCredentials; //note: this property is defined in "TestLoadDbCredentials.cs" which is deliberately excluded from Git because the credentials are not public!
 | 
			
		||||
			IKp2aApp app = new TestKp2aApp();
 | 
			
		||||
@@ -156,7 +214,7 @@ namespace Kp2aUnitTests
 | 
			
		||||
 | 
			
		||||
			bool loadSuccesful = false;
 | 
			
		||||
			bool gotError = false;
 | 
			
		||||
			LoadDb task = new LoadDb(app, ioc, null, "test", null, new ActionOnFinish((success, message) =>
 | 
			
		||||
			LoadDb task = new LoadDb(app, ioc, null, CreateKey("test"), null, new ActionOnFinish((success, message) =>
 | 
			
		||||
			{
 | 
			
		||||
				if (!success)
 | 
			
		||||
				{
 | 
			
		||||
@@ -179,7 +237,7 @@ namespace Kp2aUnitTests
 | 
			
		||||
		[TestMethod]
 | 
			
		||||
		public void FileNotFoundExceptionWithWebDav()
 | 
			
		||||
		{
 | 
			
		||||
			var fileStorage = new BuiltInFileStorage();
 | 
			
		||||
			var fileStorage = new BuiltInFileStorage(new TestKp2aApp());
 | 
			
		||||
			
 | 
			
		||||
			//should work:
 | 
			
		||||
			using (var stream = fileStorage.OpenFileForRead(RemoteIoc1and1))
 | 
			
		||||
 
 | 
			
		||||
@@ -22,12 +22,12 @@ namespace Kp2aUnitTests
 | 
			
		||||
	class TestSaveDbCached: TestBase
 | 
			
		||||
	{
 | 
			
		||||
		private TestCacheSupervisor _testCacheSupervisor = new TestCacheSupervisor();
 | 
			
		||||
		private TestFileStorage _testFileStorage = new TestFileStorage();
 | 
			
		||||
		
 | 
			
		||||
 | 
			
		||||
		protected override TestKp2aApp CreateTestKp2aApp()
 | 
			
		||||
		{
 | 
			
		||||
			TestKp2aApp app = base.CreateTestKp2aApp();
 | 
			
		||||
			app.FileStorage = new CachingFileStorage(_testFileStorage, "/mnt/sdcard/kp2atest/cache/", _testCacheSupervisor);
 | 
			
		||||
			app.FileStorage = new CachingFileStorage(new TestFileStorage(app), "/mnt/sdcard/kp2atest/cache/", _testCacheSupervisor);
 | 
			
		||||
			return app;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -19,13 +19,20 @@ namespace Kp2aUnitTests
 | 
			
		||||
	[TestClass]
 | 
			
		||||
	internal class TestSynchronizeCachedDatabase : TestBase
 | 
			
		||||
	{
 | 
			
		||||
		[TestInitialize]
 | 
			
		||||
		public void InitTests()
 | 
			
		||||
		{
 | 
			
		||||
			TestFileStorage.Offline = false;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		private TestCacheSupervisor _testCacheSupervisor = new TestCacheSupervisor();
 | 
			
		||||
		private TestFileStorage _testFileStorage = new TestFileStorage();
 | 
			
		||||
 | 
			
		||||
		protected override TestKp2aApp CreateTestKp2aApp()
 | 
			
		||||
		{
 | 
			
		||||
			TestKp2aApp app = base.CreateTestKp2aApp();
 | 
			
		||||
			app.FileStorage = new CachingFileStorage(_testFileStorage, "/mnt/sdcard/kp2atest/cache/", _testCacheSupervisor);
 | 
			
		||||
			app.TestFileStorage = new TestFileStorage(app);
 | 
			
		||||
 | 
			
		||||
			app.FileStorage = new CachingFileStorage(app.TestFileStorage, "/mnt/sdcard/kp2atest/cache/", _testCacheSupervisor);
 | 
			
		||||
			return app;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
@@ -58,7 +65,7 @@ namespace Kp2aUnitTests
 | 
			
		||||
			Assert.AreEqual(resultMessage, app.GetResourceString(UiStringKey.FilesInSync));
 | 
			
		||||
 | 
			
		||||
			//go offline:
 | 
			
		||||
			_testFileStorage.Offline = true;
 | 
			
		||||
			TestFileStorage.Offline = true;
 | 
			
		||||
 | 
			
		||||
			//sync when offline (->error)
 | 
			
		||||
			Synchronize(app, out wasSuccessful, out resultMessage);
 | 
			
		||||
@@ -73,7 +80,7 @@ namespace Kp2aUnitTests
 | 
			
		||||
			_testCacheSupervisor.AssertSingleCall(TestCacheSupervisor.CouldntSaveToRemoteId);
 | 
			
		||||
 | 
			
		||||
			//go online again:
 | 
			
		||||
			_testFileStorage.Offline = false;
 | 
			
		||||
			TestFileStorage.Offline = false;
 | 
			
		||||
 | 
			
		||||
			//sync with local changes only (-> upload):
 | 
			
		||||
			Synchronize(app, out wasSuccessful, out resultMessage);
 | 
			
		||||
@@ -81,10 +88,10 @@ namespace Kp2aUnitTests
 | 
			
		||||
			Assert.AreEqual(resultMessage, app.GetResourceString(UiStringKey.SynchronizedDatabaseSuccessfully));
 | 
			
		||||
 | 
			
		||||
			//ensure both files are identical and up to date now:
 | 
			
		||||
			_testFileStorage.Offline = true;
 | 
			
		||||
			TestFileStorage.Offline = true;
 | 
			
		||||
			var appOfflineLoaded = LoadDatabase(DefaultFilename, DefaultPassword, DefaultKeyfile);
 | 
			
		||||
			_testCacheSupervisor.AssertSingleCall(TestCacheSupervisor.CouldntOpenFromRemoteId);
 | 
			
		||||
			_testFileStorage.Offline = false;
 | 
			
		||||
			TestFileStorage.Offline = false;
 | 
			
		||||
			var appRemoteLoaded = LoadDatabase(DefaultFilename, DefaultPassword, DefaultKeyfile);
 | 
			
		||||
			_testCacheSupervisor.AssertSingleCall(TestCacheSupervisor.LoadedFromRemoteInSyncId);
 | 
			
		||||
 | 
			
		||||
@@ -92,6 +99,8 @@ namespace Kp2aUnitTests
 | 
			
		||||
			AssertDatabasesAreEqual(app.GetDb().KpDatabase, appRemoteLoaded.GetDb().KpDatabase);
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		
 | 
			
		||||
 | 
			
		||||
		[TestMethod]
 | 
			
		||||
		public void TestSyncWhenRemoteDeleted()
 | 
			
		||||
		{
 | 
			
		||||
@@ -133,11 +142,11 @@ namespace Kp2aUnitTests
 | 
			
		||||
			_testCacheSupervisor.AssertSingleCall(TestCacheSupervisor.LoadedFromRemoteInSyncId);
 | 
			
		||||
 | 
			
		||||
			var app2 = LoadDatabase(DefaultFilename, DefaultPassword, DefaultKeyfile);
 | 
			
		||||
			app2.FileStorage = _testFileStorage; //give app2 direct access to the remote file
 | 
			
		||||
			app2.FileStorage = app.TestFileStorage; //give app2 direct access to the remote file
 | 
			
		||||
			_testCacheSupervisor.AssertSingleCall(TestCacheSupervisor.LoadedFromRemoteInSyncId);
 | 
			
		||||
 | 
			
		||||
			//go offline:
 | 
			
		||||
			_testFileStorage.Offline = true;
 | 
			
		||||
			TestFileStorage.Offline = true;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
			string resultMessage;
 | 
			
		||||
@@ -153,7 +162,7 @@ namespace Kp2aUnitTests
 | 
			
		||||
			_testCacheSupervisor.AssertSingleCall(TestCacheSupervisor.CouldntSaveToRemoteId);
 | 
			
		||||
 | 
			
		||||
			//go online again:
 | 
			
		||||
			_testFileStorage.Offline = false;
 | 
			
		||||
			TestFileStorage.Offline = false;
 | 
			
		||||
			
 | 
			
		||||
			//...and remote only for "app2":
 | 
			
		||||
			SaveDatabase(app2);
 | 
			
		||||
 
 | 
			
		||||
@@ -1,5 +1,5 @@
 | 
			
		||||
<?xml version="1.0" encoding="utf-8"?>
 | 
			
		||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="30" android:versionName="0.9.2" package="keepass2android.keepass2android" android:installLocation="auto">
 | 
			
		||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="31" android:versionName="0.9.2-r2" package="keepass2android.keepass2android" android:installLocation="auto">
 | 
			
		||||
	<uses-sdk android:minSdkVersion="8" android:targetSdkVersion="14" />
 | 
			
		||||
	<permission android:description="@string/permission_desc" android:icon="@drawable/ic_launcher" android:label="KP2A internal file browsing" android:name="keepass2android.keepass2android.permission.KP2aInternalFileBrowsing" android:protectionLevel="signature" />
 | 
			
		||||
	<application android:label="keepass2android" android:icon="@drawable/ic_launcher">
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										1634
									
								
								src/keepass2android/Resources/Resource.designer.cs
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										1634
									
								
								src/keepass2android/Resources/Resource.designer.cs
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -89,6 +89,7 @@
 | 
			
		||||
	<string name="UseFileTransactions_key">UseFileTransactions</string>
 | 
			
		||||
	<string name="LockWhenScreenOff_key">LockWhenScreenOff</string>
 | 
			
		||||
	<string name="UseOfflineCache_key">UseOfflineCache</string>
 | 
			
		||||
	<string name="AcceptAllServerCertificates_key">AcceptAllServerCertificates</string>
 | 
			
		||||
	<string name="CheckForFileChangesOnSave_key">CheckForFileChangesOnSave</string>
 | 
			
		||||
 | 
			
		||||
	<string name="MarketURL">market://details?id=</string>
 | 
			
		||||
@@ -122,6 +123,13 @@
 | 
			
		||||
    	<item>28</item>
 | 
			
		||||
    </string-array>
 | 
			
		||||
 | 
			
		||||
	<string name="AcceptAllServerCertificates_default">WARN</string>
 | 
			
		||||
	<string-array name="AcceptAllServerCertificates_values">
 | 
			
		||||
		<item>IGNORE</item>
 | 
			
		||||
		<item>WARN</item>
 | 
			
		||||
		<item>ERROR</item>
 | 
			
		||||
	</string-array>
 | 
			
		||||
 | 
			
		||||
	<string name="ShowUnlockedNotification_key">ShowUnlockedNotification</string>
 | 
			
		||||
	<bool name="ShowUnlockedNotification_default">true</bool>
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -239,6 +239,11 @@
 | 
			
		||||
  <string name="LockWhenScreenOff_summary">Lock the database when screen is switched off.</string>
 | 
			
		||||
	<string name="UseOfflineCache_title">Database caching</string>
 | 
			
		||||
	<string name="UseOfflineCache_summary">Keep a copy of remote database files in the application cache directory. This allows to use remote databases even when offline.</string>
 | 
			
		||||
 | 
			
		||||
	<string name="AcceptAllServerCertificates_title">SSL certificates</string>
 | 
			
		||||
	<string name="AcceptAllServerCertificates_summary">Define the behavior when certificate validation fails. Note: you can install certificates on your device if validation fails!</string>
 | 
			
		||||
	
 | 
			
		||||
	
 | 
			
		||||
	<string name="ClearOfflineCache_title">Clear cache?</string>
 | 
			
		||||
	<string name="ClearOfflineCache_question">This will delete all cached database files. Any changes you made while being offline which have not yet been synchronized will be lost! Continue?</string>
 | 
			
		||||
  <string name="CheckForFileChangesOnSave_title">Check for modifications</string>
 | 
			
		||||
@@ -373,15 +378,19 @@
 | 
			
		||||
 | 
			
		||||
	<string name="loading">Loading…</string>
 | 
			
		||||
 | 
			
		||||
	<string name="CertificateWarning">Warning: Server certificate validation failed: %1$s. Install appropriate root certificate on your device or see settings!</string>
 | 
			
		||||
	<string name="CertificateFailure">Error: Server certificate validation failed! Install appropriate root certificate on your device or see settings!</string>
 | 
			
		||||
	
 | 
			
		||||
	<string name="ChangeLog_title">Change log</string>
 | 
			
		||||
 | 
			
		||||
	<string name="ChangeLog_0_9_2">
 | 
			
		||||
		<b>Version 0.9.2b (preview)</b>\n
 | 
			
		||||
		<b>Version 0.9.2</b>\n
 | 
			
		||||
		* Added OTP support (compatible with OtpKeyProv plugin)\n
 | 
			
		||||
		* Integrated NFC support for OTPs from YubiKey NEO \n
 | 
			
		||||
		* Several UI improvements\n
 | 
			
		||||
		* Integrated Keepass 2.24 library\n
 | 
			
		||||
		* Added option to kill the app process (see settings)\n
 | 
			
		||||
		* Improved SSL certificate validation\n
 | 
			
		||||
		* Bug fixes\n
 | 
			
		||||
	</string>
 | 
			
		||||
 | 
			
		||||
@@ -501,4 +510,10 @@ Initial public release
 | 
			
		||||
		<item>Password + OTP</item>
 | 
			
		||||
		<item>Password + OTP secret (recovery mode)</item>
 | 
			
		||||
	</string-array>
 | 
			
		||||
	<string-array name="AcceptAllServerCertificates_options">
 | 
			
		||||
		<item>Ignore certificate validation failures</item>
 | 
			
		||||
		<item>Warn when validation fails</item>
 | 
			
		||||
		<item>Do not accept invalid certificates</item>
 | 
			
		||||
	</string-array>
 | 
			
		||||
 | 
			
		||||
</resources>
 | 
			
		||||
 
 | 
			
		||||
@@ -204,6 +204,16 @@
 | 
			
		||||
				  android:defaultValue="true"
 | 
			
		||||
				  android:title="@string/UseOfflineCache_title"
 | 
			
		||||
				  android:key="@string/UseOfflineCache_key" />
 | 
			
		||||
			<ListPreference
 | 
			
		||||
			  android:key="@string/AcceptAllServerCertificates_key"
 | 
			
		||||
			  android:title="@string/AcceptAllServerCertificates_title"
 | 
			
		||||
			  android:summary="@string/AcceptAllServerCertificates_summary"
 | 
			
		||||
			  android:entries="@array/AcceptAllServerCertificates_options"
 | 
			
		||||
			  android:entryValues="@array/AcceptAllServerCertificates_values"
 | 
			
		||||
			  android:dialogTitle="@string/AcceptAllServerCertificates_title"
 | 
			
		||||
			  android:defaultValue="@string/AcceptAllServerCertificates_default"/>
 | 
			
		||||
			
 | 
			
		||||
		
 | 
			
		||||
			<CheckBoxPreference
 | 
			
		||||
				android:enabled="true"
 | 
			
		||||
				  android:persistent="true"
 | 
			
		||||
 
 | 
			
		||||
@@ -353,7 +353,7 @@ namespace keepass2android
 | 
			
		||||
		public IFileStorage GetFileStorage(IOConnectionInfo iocInfo)
 | 
			
		||||
		{
 | 
			
		||||
			if (iocInfo.IsLocalFile())
 | 
			
		||||
				return new BuiltInFileStorage();
 | 
			
		||||
				return new BuiltInFileStorage(this);
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
				IFileStorage innerFileStorage = GetCloudFileStorage(iocInfo);
 | 
			
		||||
@@ -399,7 +399,7 @@ namespace keepass2android
 | 
			
		||||
							new GoogleDriveFileStorage(Application.Context, this),
 | 
			
		||||
							new SkyDriveFileStorage(Application.Context, this),
 | 
			
		||||
#endif
 | 
			
		||||
							new BuiltInFileStorage()
 | 
			
		||||
							new BuiltInFileStorage(this)
 | 
			
		||||
						};
 | 
			
		||||
				}
 | 
			
		||||
				return _fileStorages;
 | 
			
		||||
@@ -416,6 +416,61 @@ namespace keepass2android
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		
 | 
			
		||||
 | 
			
		||||
		private String GetProblemMessage(BuiltInFileStorage.CertificateProblem problem)
 | 
			
		||||
		{
 | 
			
		||||
			String problemMessage;
 | 
			
		||||
			const BuiltInFileStorage.CertificateProblem problemList = new BuiltInFileStorage.CertificateProblem();
 | 
			
		||||
			string problemCodeName = Enum.GetName(typeof(BuiltInFileStorage.CertificateProblem), problem);
 | 
			
		||||
				
 | 
			
		||||
			if (problemCodeName != null)
 | 
			
		||||
				problemMessage = problemCodeName;
 | 
			
		||||
			else
 | 
			
		||||
				problemMessage = "Unknown Certificate Problem";
 | 
			
		||||
			return problemMessage;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		enum ValidationMode
 | 
			
		||||
		{
 | 
			
		||||
			Ignore, Warn, Error
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public bool OnServerCertificateError(int certificateProblem)
 | 
			
		||||
		{
 | 
			
		||||
			var prefs = PreferenceManager.GetDefaultSharedPreferences(Application.Context);
 | 
			
		||||
 | 
			
		||||
			ValidationMode validationMode = ValidationMode.Warn;
 | 
			
		||||
			
 | 
			
		||||
			string strValMode = prefs.GetString(Application.Context.Resources.GetString(Resource.String.AcceptAllServerCertificates_key),
 | 
			
		||||
												 Application.Context.Resources.GetString(Resource.String.AcceptAllServerCertificates_default));
 | 
			
		||||
 | 
			
		||||
			if (strValMode == "IGNORE")
 | 
			
		||||
				validationMode = ValidationMode.Ignore;
 | 
			
		||||
			else if (strValMode == "ERROR")
 | 
			
		||||
				validationMode = ValidationMode.Error;
 | 
			
		||||
			;
 | 
			
		||||
 | 
			
		||||
			switch (validationMode)
 | 
			
		||||
			{
 | 
			
		||||
				case ValidationMode.Ignore:
 | 
			
		||||
					return true;
 | 
			
		||||
				case ValidationMode.Warn:
 | 
			
		||||
					ShowToast(Application.Context.GetString(Resource.String.CertificateWarning,
 | 
			
		||||
				                                        new Java.Lang.Object[]
 | 
			
		||||
					                                        {
 | 
			
		||||
						                                        GetProblemMessage(
 | 
			
		||||
							                                        (BuiltInFileStorage.CertificateProblem)
 | 
			
		||||
							                                        (System.UInt32) certificateProblem)
 | 
			
		||||
					                                        }));
 | 
			
		||||
					return true;
 | 
			
		||||
				case ValidationMode.Error:
 | 
			
		||||
					return false;
 | 
			
		||||
				default:
 | 
			
		||||
					throw new ArgumentOutOfRangeException();
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		internal void OnTerminate()
 | 
			
		||||
        {
 | 
			
		||||
            if (_db != null)
 | 
			
		||||
@@ -492,7 +547,7 @@ namespace keepass2android
 | 
			
		||||
 | 
			
		||||
		public void ClearOfflineCache()
 | 
			
		||||
		{
 | 
			
		||||
			new CachingFileStorage(new BuiltInFileStorage(), Application.Context.CacheDir.Path, this).ClearCache();
 | 
			
		||||
			new CachingFileStorage(new BuiltInFileStorage(this), Application.Context.CacheDir.Path, this).ClearCache();
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		public IFileStorage GetFileStorage(string protocolId)
 | 
			
		||||
@@ -508,7 +563,7 @@ namespace keepass2android
 | 
			
		||||
		{
 | 
			
		||||
 | 
			
		||||
			if (iocInfo.IsLocalFile())
 | 
			
		||||
				return new BuiltInFileStorage();
 | 
			
		||||
				return new BuiltInFileStorage(this);
 | 
			
		||||
			else
 | 
			
		||||
			{
 | 
			
		||||
				IFileStorage innerFileStorage = GetCloudFileStorage(iocInfo);
 | 
			
		||||
 
 | 
			
		||||
@@ -29,7 +29,7 @@
 | 
			
		||||
    <DebugType>full</DebugType>
 | 
			
		||||
    <Optimize>False</Optimize>
 | 
			
		||||
    <OutputPath>bin\Debug</OutputPath>
 | 
			
		||||
    <DefineConstants>DEBUG;EXCLUDE_TWOFISH;INCLUDE_KEYBOARD;EXCLUDE_KEYTRANSFORM;INCLUDE_FILECHOOSER;INCLUDE_JAVAFILESTORAGE</DefineConstants>
 | 
			
		||||
    <DefineConstants>DEBUG;EXCLUDE_TWOFISH;EXCLUDE_KEYBOARD;EXCLUDE_KEYTRANSFORM;EXCLUDE_FILECHOOSER;EXCLUDE_JAVAFILESTORAGE</DefineConstants>
 | 
			
		||||
    <ErrorReport>prompt</ErrorReport>
 | 
			
		||||
    <WarningLevel>4</WarningLevel>
 | 
			
		||||
    <ConsolePause>False</ConsolePause>
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user