Introduced IDatabaseLoader
(kdb not yet working)
This commit is contained in:
		| @@ -19,6 +19,8 @@ using System; | ||||
| using System.IO; | ||||
| using System.Linq; | ||||
| using System.Threading.Tasks; | ||||
| using Android.App; | ||||
| using KeePassLib; | ||||
| using KeePassLib.Keys; | ||||
| using KeePassLib.Serialization; | ||||
|  | ||||
| @@ -50,10 +52,24 @@ namespace keepass2android | ||||
| 			try | ||||
| 			{ | ||||
| 				StatusLogger.UpdateMessage(UiStringKey.loading_database); | ||||
| 				MemoryStream memoryStream = _databaseData == null ? null : _databaseData.Result; | ||||
| 				_app.LoadDatabase(_ioc, memoryStream, _compositeKey, StatusLogger); | ||||
| 				SaveFileData(_ioc, _keyfileOrProvider); | ||||
| 				//get the stream data into a single stream variable (databaseStream) regardless whether its preloaded or not: | ||||
| 				MemoryStream preloadedMemoryStream = _databaseData == null ? null : _databaseData.Result; | ||||
| 				MemoryStream databaseStream;  | ||||
| 				if (preloadedMemoryStream != null) | ||||
| 					databaseStream = preloadedMemoryStream; | ||||
| 				else | ||||
| 				{ | ||||
| 					using (Stream s = _app.GetFileStorage(_ioc).OpenFileForRead(_ioc)) | ||||
| 					{ | ||||
| 						databaseStream = new MemoryStream(); | ||||
| 						s.CopyTo(databaseStream); | ||||
| 						databaseStream.Seek(0, SeekOrigin.Begin); | ||||
| 					} | ||||
| 				} | ||||
|  | ||||
| 				//ok, try to load the database. Let's start with Kdbx format and retry later if that is the wrong guess: | ||||
| 				IDatabaseLoader loader = new KdbxDatabaseLoader(KdbpFile.GetFormatToUse(_ioc));  | ||||
| 				TryLoad(databaseStream, loader); | ||||
| 			} | ||||
| 			catch (KeyFileException) | ||||
| 			{ | ||||
| @@ -73,11 +89,6 @@ namespace keepass2android | ||||
| 				Finish(false, _app.GetResourceString(UiStringKey.ErrorOcurred) + " " + message); | ||||
| 				return; | ||||
| 			} | ||||
| 			catch (OldFormatException ) | ||||
| 			{ | ||||
| 				Finish(false, "Cannot open Keepass 1.x database. As explained in the app description, Keepass2Android is for Keepass 2 only! Please use the desktop application to convert your database to the new file format!"); | ||||
| 				return; | ||||
| 			} | ||||
| 			catch (Exception e) | ||||
| 			{ | ||||
| 				Kp2aLog.Log("Exception: " + e); | ||||
| @@ -85,10 +96,48 @@ namespace keepass2android | ||||
| 				return; | ||||
| 			} | ||||
| 			 | ||||
| 			Kp2aLog.Log("LoadDB OK"); | ||||
| 			Finish(true); | ||||
| 			 | ||||
| 		} | ||||
| 		 | ||||
|  | ||||
| 		private void TryLoad(MemoryStream databaseStream, IDatabaseLoader loader) | ||||
| 		{ | ||||
| 			//create a copy of the stream so we can try again if we get an exception which indicates we should change parameters | ||||
| 			//This is not optimal in terms of (short-time) memory usage but is hard to avoid because the Keepass library closes streams also in case of errors. | ||||
| 			//Alternatives would involve increased traffic (if file is on remote) and slower loading times, so this seems to be the best choice. | ||||
| 			MemoryStream workingCopy = new MemoryStream(); | ||||
| 			databaseStream.CopyTo(workingCopy); | ||||
| 			workingCopy.Seek(0, SeekOrigin.Begin); | ||||
| 			//reset stream if we need to reuse it later: | ||||
| 			databaseStream.Seek(0, SeekOrigin.Begin); | ||||
| 			//now let's go: | ||||
| 			try | ||||
| 			{ | ||||
| 				_app.LoadDatabase(_ioc, workingCopy, _compositeKey, StatusLogger, loader); | ||||
| 				SaveFileData(_ioc, _keyfileOrProvider); | ||||
| 				Kp2aLog.Log("LoadDB OK"); | ||||
| 				Finish(true); | ||||
| 			} | ||||
| 			catch (OldFormatException) | ||||
| 			{ | ||||
| 				TryLoad(databaseStream, new KdbDatabaseLoader(Application.Context)); | ||||
| 			} | ||||
| 			catch (InvalidCompositeKeyException) | ||||
| 			{ | ||||
| 				KcpPassword passwordKey = (KcpPassword)_compositeKey.GetUserKey(typeof(KcpPassword)); | ||||
|  | ||||
| 				if ((passwordKey != null) && (passwordKey.Password.ReadString() == "") && (_compositeKey.UserKeyCount > 1)) | ||||
| 				{ | ||||
| 					//if we don't get a password, we don't know whether this means "empty password" or "no password" | ||||
| 					//retry without password: | ||||
| 					_compositeKey.RemoveUserKey(passwordKey); | ||||
| 					//retry: | ||||
| 					TryLoad(databaseStream, loader); | ||||
| 				} | ||||
| 				else throw; | ||||
| 			} | ||||
| 			 | ||||
| 		} | ||||
|  | ||||
| 		private void SaveFileData(IOConnectionInfo ioc, String keyfileOrProvider) { | ||||
|  | ||||
|             if (!_rememberKeyfile) | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Philipp Crocoll
					Philipp Crocoll