diff --git a/.gitignore b/.gitignore index c8a63025..ef284c85 100644 --- a/.gitignore +++ b/.gitignore @@ -26,3 +26,5 @@ /src/java/KP2ASoftKeyboard/projectzip /src/java/KP2ASoftKeyboard/createProjectZip.bat Thumbs.db + +/src/monodroid-unittesting/*.suo diff --git a/src/KeePass.sln b/src/KeePass.sln index 0b73d48e..e2c3baef 100644 --- a/src/KeePass.sln +++ b/src/KeePass.sln @@ -1,6 +1,6 @@  -Microsoft Visual Studio Solution File, Format Version 11.00 -# Visual Studio 2010 +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 2012 Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KeePassLib2Android", "KeePassLib2Android\KeePassLib2Android.csproj", "{545B4A6B-8BBA-4FBE-92FC-4AC060122A54}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "keepass2android", "keepass2android\keepass2android.csproj", "{A6CF8A86-37C1-4197-80FE-519DE2C842F5}" @@ -9,6 +9,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "kp2akeytransform", "kp2akey EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Kp2aKeyboardBinding", "Kp2aKeyboardBinding\Kp2aKeyboardBinding.csproj", "{A8779D4D-7C49-4C2F-82BD-2CDC448391DA}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Kp2aBusinessLogic", "Kp2aBusinessLogic\Kp2aBusinessLogic.csproj", "{53A9CB7F-6553-4BC0-B56B-9410BB2E59AA}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MonoDroidUnitTesting", "monodroid-unittesting\MonoDroidUnitTesting\MonoDroidUnitTesting.csproj", "{A5F8FB02-00E0-4335-91EF-AEAA2C2F3C48}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Kp2aUnitTests", "Kp2aUnitTests\Kp2aUnitTests.csproj", "{46B769B8-2C58-4138-9CC0-70E3AE3C9A3A}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -20,6 +26,9 @@ Global Release|Win32 = Release|Win32 Release|x64 = Release|x64 ReleaseNoNet|Any CPU = ReleaseNoNet|Any CPU + ReleaseNoNet|Mixed Platforms = ReleaseNoNet|Mixed Platforms + ReleaseNoNet|Win32 = ReleaseNoNet|Win32 + ReleaseNoNet|x64 = ReleaseNoNet|x64 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {545B4A6B-8BBA-4FBE-92FC-4AC060122A54}.Debug|Any CPU.ActiveCfg = Debug|Any CPU @@ -40,6 +49,34 @@ Global {545B4A6B-8BBA-4FBE-92FC-4AC060122A54}.Release|x64.Build.0 = Release|Any CPU {545B4A6B-8BBA-4FBE-92FC-4AC060122A54}.ReleaseNoNet|Any CPU.ActiveCfg = ReleaseNoNet|Any CPU {545B4A6B-8BBA-4FBE-92FC-4AC060122A54}.ReleaseNoNet|Any CPU.Build.0 = ReleaseNoNet|Any CPU + {545B4A6B-8BBA-4FBE-92FC-4AC060122A54}.ReleaseNoNet|Mixed Platforms.ActiveCfg = ReleaseNoNet|Any CPU + {545B4A6B-8BBA-4FBE-92FC-4AC060122A54}.ReleaseNoNet|Mixed Platforms.Build.0 = ReleaseNoNet|Any CPU + {545B4A6B-8BBA-4FBE-92FC-4AC060122A54}.ReleaseNoNet|Win32.ActiveCfg = ReleaseNoNet|Any CPU + {545B4A6B-8BBA-4FBE-92FC-4AC060122A54}.ReleaseNoNet|x64.ActiveCfg = ReleaseNoNet|Any CPU + {A6CF8A86-37C1-4197-80FE-519DE2C842F5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A6CF8A86-37C1-4197-80FE-519DE2C842F5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A6CF8A86-37C1-4197-80FE-519DE2C842F5}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {A6CF8A86-37C1-4197-80FE-519DE2C842F5}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {A6CF8A86-37C1-4197-80FE-519DE2C842F5}.Debug|Mixed Platforms.Deploy.0 = Debug|Any CPU + {A6CF8A86-37C1-4197-80FE-519DE2C842F5}.Debug|Win32.ActiveCfg = Debug|Any CPU + {A6CF8A86-37C1-4197-80FE-519DE2C842F5}.Debug|Win32.Build.0 = Debug|Any CPU + {A6CF8A86-37C1-4197-80FE-519DE2C842F5}.Debug|x64.ActiveCfg = Debug|Any CPU + {A6CF8A86-37C1-4197-80FE-519DE2C842F5}.Debug|x64.Build.0 = Debug|Any CPU + {A6CF8A86-37C1-4197-80FE-519DE2C842F5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A6CF8A86-37C1-4197-80FE-519DE2C842F5}.Release|Any CPU.Build.0 = Release|Any CPU + {A6CF8A86-37C1-4197-80FE-519DE2C842F5}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {A6CF8A86-37C1-4197-80FE-519DE2C842F5}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {A6CF8A86-37C1-4197-80FE-519DE2C842F5}.Release|Win32.ActiveCfg = Release|Any CPU + {A6CF8A86-37C1-4197-80FE-519DE2C842F5}.Release|Win32.Build.0 = Release|Any CPU + {A6CF8A86-37C1-4197-80FE-519DE2C842F5}.Release|x64.ActiveCfg = Release|Any CPU + {A6CF8A86-37C1-4197-80FE-519DE2C842F5}.Release|x64.Build.0 = Release|Any CPU + {A6CF8A86-37C1-4197-80FE-519DE2C842F5}.ReleaseNoNet|Any CPU.ActiveCfg = ReleaseNoNet|Any CPU + {A6CF8A86-37C1-4197-80FE-519DE2C842F5}.ReleaseNoNet|Any CPU.Build.0 = ReleaseNoNet|Any CPU + {A6CF8A86-37C1-4197-80FE-519DE2C842F5}.ReleaseNoNet|Mixed Platforms.ActiveCfg = ReleaseNoNet|Any CPU + {A6CF8A86-37C1-4197-80FE-519DE2C842F5}.ReleaseNoNet|Mixed Platforms.Build.0 = ReleaseNoNet|Any CPU + {A6CF8A86-37C1-4197-80FE-519DE2C842F5}.ReleaseNoNet|Mixed Platforms.Deploy.0 = ReleaseNoNet|Any CPU + {A6CF8A86-37C1-4197-80FE-519DE2C842F5}.ReleaseNoNet|Win32.ActiveCfg = ReleaseNoNet|Any CPU + {A6CF8A86-37C1-4197-80FE-519DE2C842F5}.ReleaseNoNet|x64.ActiveCfg = ReleaseNoNet|Any CPU {A57B3ACE-5634-469A-88C4-858BB409F356}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {A57B3ACE-5634-469A-88C4-858BB409F356}.Debug|Any CPU.Build.0 = Debug|Any CPU {A57B3ACE-5634-469A-88C4-858BB409F356}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU @@ -58,24 +95,10 @@ Global {A57B3ACE-5634-469A-88C4-858BB409F356}.Release|x64.Build.0 = Release|Any CPU {A57B3ACE-5634-469A-88C4-858BB409F356}.ReleaseNoNet|Any CPU.ActiveCfg = Debug|Any CPU {A57B3ACE-5634-469A-88C4-858BB409F356}.ReleaseNoNet|Any CPU.Build.0 = Debug|Any CPU - {A6CF8A86-37C1-4197-80FE-519DE2C842F5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {A6CF8A86-37C1-4197-80FE-519DE2C842F5}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A6CF8A86-37C1-4197-80FE-519DE2C842F5}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU - {A6CF8A86-37C1-4197-80FE-519DE2C842F5}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU - {A6CF8A86-37C1-4197-80FE-519DE2C842F5}.Debug|Win32.ActiveCfg = Debug|Any CPU - {A6CF8A86-37C1-4197-80FE-519DE2C842F5}.Debug|Win32.Build.0 = Debug|Any CPU - {A6CF8A86-37C1-4197-80FE-519DE2C842F5}.Debug|x64.ActiveCfg = Debug|Any CPU - {A6CF8A86-37C1-4197-80FE-519DE2C842F5}.Debug|x64.Build.0 = Debug|Any CPU - {A6CF8A86-37C1-4197-80FE-519DE2C842F5}.Release|Any CPU.ActiveCfg = Release|Any CPU - {A6CF8A86-37C1-4197-80FE-519DE2C842F5}.Release|Any CPU.Build.0 = Release|Any CPU - {A6CF8A86-37C1-4197-80FE-519DE2C842F5}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU - {A6CF8A86-37C1-4197-80FE-519DE2C842F5}.Release|Mixed Platforms.Build.0 = Release|Any CPU - {A6CF8A86-37C1-4197-80FE-519DE2C842F5}.Release|Win32.ActiveCfg = Release|Any CPU - {A6CF8A86-37C1-4197-80FE-519DE2C842F5}.Release|Win32.Build.0 = Release|Any CPU - {A6CF8A86-37C1-4197-80FE-519DE2C842F5}.Release|x64.ActiveCfg = Release|Any CPU - {A6CF8A86-37C1-4197-80FE-519DE2C842F5}.Release|x64.Build.0 = Release|Any CPU - {A6CF8A86-37C1-4197-80FE-519DE2C842F5}.ReleaseNoNet|Any CPU.ActiveCfg = ReleaseNoNet|Any CPU - {A6CF8A86-37C1-4197-80FE-519DE2C842F5}.ReleaseNoNet|Any CPU.Build.0 = ReleaseNoNet|Any CPU + {A57B3ACE-5634-469A-88C4-858BB409F356}.ReleaseNoNet|Mixed Platforms.ActiveCfg = Release|Any CPU + {A57B3ACE-5634-469A-88C4-858BB409F356}.ReleaseNoNet|Mixed Platforms.Build.0 = Release|Any CPU + {A57B3ACE-5634-469A-88C4-858BB409F356}.ReleaseNoNet|Win32.ActiveCfg = Release|Any CPU + {A57B3ACE-5634-469A-88C4-858BB409F356}.ReleaseNoNet|x64.ActiveCfg = Release|Any CPU {A8779D4D-7C49-4C2F-82BD-2CDC448391DA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {A8779D4D-7C49-4C2F-82BD-2CDC448391DA}.Debug|Any CPU.Build.0 = Debug|Any CPU {A8779D4D-7C49-4C2F-82BD-2CDC448391DA}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU @@ -94,7 +117,73 @@ Global {A8779D4D-7C49-4C2F-82BD-2CDC448391DA}.Release|x64.Build.0 = Release|Any CPU {A8779D4D-7C49-4C2F-82BD-2CDC448391DA}.ReleaseNoNet|Any CPU.ActiveCfg = Debug|Any CPU {A8779D4D-7C49-4C2F-82BD-2CDC448391DA}.ReleaseNoNet|Any CPU.Build.0 = Debug|Any CPU - + {A8779D4D-7C49-4C2F-82BD-2CDC448391DA}.ReleaseNoNet|Mixed Platforms.ActiveCfg = Release|Any CPU + {A8779D4D-7C49-4C2F-82BD-2CDC448391DA}.ReleaseNoNet|Mixed Platforms.Build.0 = Release|Any CPU + {A8779D4D-7C49-4C2F-82BD-2CDC448391DA}.ReleaseNoNet|Win32.ActiveCfg = Release|Any CPU + {A8779D4D-7C49-4C2F-82BD-2CDC448391DA}.ReleaseNoNet|x64.ActiveCfg = Release|Any CPU + {53A9CB7F-6553-4BC0-B56B-9410BB2E59AA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {53A9CB7F-6553-4BC0-B56B-9410BB2E59AA}.Debug|Any CPU.Build.0 = Debug|Any CPU + {53A9CB7F-6553-4BC0-B56B-9410BB2E59AA}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {53A9CB7F-6553-4BC0-B56B-9410BB2E59AA}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {53A9CB7F-6553-4BC0-B56B-9410BB2E59AA}.Debug|Win32.ActiveCfg = Debug|Any CPU + {53A9CB7F-6553-4BC0-B56B-9410BB2E59AA}.Debug|x64.ActiveCfg = Debug|Any CPU + {53A9CB7F-6553-4BC0-B56B-9410BB2E59AA}.Release|Any CPU.ActiveCfg = Release|Any CPU + {53A9CB7F-6553-4BC0-B56B-9410BB2E59AA}.Release|Any CPU.Build.0 = Release|Any CPU + {53A9CB7F-6553-4BC0-B56B-9410BB2E59AA}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {53A9CB7F-6553-4BC0-B56B-9410BB2E59AA}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {53A9CB7F-6553-4BC0-B56B-9410BB2E59AA}.Release|Win32.ActiveCfg = Release|Any CPU + {53A9CB7F-6553-4BC0-B56B-9410BB2E59AA}.Release|x64.ActiveCfg = Release|Any CPU + {53A9CB7F-6553-4BC0-B56B-9410BB2E59AA}.ReleaseNoNet|Any CPU.ActiveCfg = Release|Any CPU + {53A9CB7F-6553-4BC0-B56B-9410BB2E59AA}.ReleaseNoNet|Any CPU.Build.0 = Release|Any CPU + {53A9CB7F-6553-4BC0-B56B-9410BB2E59AA}.ReleaseNoNet|Mixed Platforms.ActiveCfg = Release|Any CPU + {53A9CB7F-6553-4BC0-B56B-9410BB2E59AA}.ReleaseNoNet|Mixed Platforms.Build.0 = Release|Any CPU + {53A9CB7F-6553-4BC0-B56B-9410BB2E59AA}.ReleaseNoNet|Win32.ActiveCfg = Release|Any CPU + {53A9CB7F-6553-4BC0-B56B-9410BB2E59AA}.ReleaseNoNet|x64.ActiveCfg = Release|Any CPU + {A5F8FB02-00E0-4335-91EF-AEAA2C2F3C48}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {A5F8FB02-00E0-4335-91EF-AEAA2C2F3C48}.Debug|Any CPU.Build.0 = Debug|Any CPU + {A5F8FB02-00E0-4335-91EF-AEAA2C2F3C48}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {A5F8FB02-00E0-4335-91EF-AEAA2C2F3C48}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {A5F8FB02-00E0-4335-91EF-AEAA2C2F3C48}.Debug|Win32.ActiveCfg = Debug|Any CPU + {A5F8FB02-00E0-4335-91EF-AEAA2C2F3C48}.Debug|x64.ActiveCfg = Debug|Any CPU + {A5F8FB02-00E0-4335-91EF-AEAA2C2F3C48}.Release|Any CPU.ActiveCfg = Release|Any CPU + {A5F8FB02-00E0-4335-91EF-AEAA2C2F3C48}.Release|Any CPU.Build.0 = Release|Any CPU + {A5F8FB02-00E0-4335-91EF-AEAA2C2F3C48}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {A5F8FB02-00E0-4335-91EF-AEAA2C2F3C48}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {A5F8FB02-00E0-4335-91EF-AEAA2C2F3C48}.Release|Win32.ActiveCfg = Release|Any CPU + {A5F8FB02-00E0-4335-91EF-AEAA2C2F3C48}.Release|x64.ActiveCfg = Release|Any CPU + {A5F8FB02-00E0-4335-91EF-AEAA2C2F3C48}.ReleaseNoNet|Any CPU.ActiveCfg = Release|Any CPU + {A5F8FB02-00E0-4335-91EF-AEAA2C2F3C48}.ReleaseNoNet|Any CPU.Build.0 = Release|Any CPU + {A5F8FB02-00E0-4335-91EF-AEAA2C2F3C48}.ReleaseNoNet|Mixed Platforms.ActiveCfg = Release|Any CPU + {A5F8FB02-00E0-4335-91EF-AEAA2C2F3C48}.ReleaseNoNet|Mixed Platforms.Build.0 = Release|Any CPU + {A5F8FB02-00E0-4335-91EF-AEAA2C2F3C48}.ReleaseNoNet|Win32.ActiveCfg = Release|Any CPU + {A5F8FB02-00E0-4335-91EF-AEAA2C2F3C48}.ReleaseNoNet|x64.ActiveCfg = Release|Any CPU + {46B769B8-2C58-4138-9CC0-70E3AE3C9A3A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {46B769B8-2C58-4138-9CC0-70E3AE3C9A3A}.Debug|Any CPU.Build.0 = Debug|Any CPU + {46B769B8-2C58-4138-9CC0-70E3AE3C9A3A}.Debug|Any CPU.Deploy.0 = Debug|Any CPU + {46B769B8-2C58-4138-9CC0-70E3AE3C9A3A}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU + {46B769B8-2C58-4138-9CC0-70E3AE3C9A3A}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU + {46B769B8-2C58-4138-9CC0-70E3AE3C9A3A}.Debug|Mixed Platforms.Deploy.0 = Debug|Any CPU + {46B769B8-2C58-4138-9CC0-70E3AE3C9A3A}.Debug|Win32.ActiveCfg = Debug|Any CPU + {46B769B8-2C58-4138-9CC0-70E3AE3C9A3A}.Debug|x64.ActiveCfg = Debug|Any CPU + {46B769B8-2C58-4138-9CC0-70E3AE3C9A3A}.Release|Any CPU.ActiveCfg = Release|Any CPU + {46B769B8-2C58-4138-9CC0-70E3AE3C9A3A}.Release|Any CPU.Build.0 = Release|Any CPU + {46B769B8-2C58-4138-9CC0-70E3AE3C9A3A}.Release|Any CPU.Deploy.0 = Release|Any CPU + {46B769B8-2C58-4138-9CC0-70E3AE3C9A3A}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU + {46B769B8-2C58-4138-9CC0-70E3AE3C9A3A}.Release|Mixed Platforms.Build.0 = Release|Any CPU + {46B769B8-2C58-4138-9CC0-70E3AE3C9A3A}.Release|Mixed Platforms.Deploy.0 = Release|Any CPU + {46B769B8-2C58-4138-9CC0-70E3AE3C9A3A}.Release|Win32.ActiveCfg = Release|Any CPU + {46B769B8-2C58-4138-9CC0-70E3AE3C9A3A}.Release|x64.ActiveCfg = Release|Any CPU + {46B769B8-2C58-4138-9CC0-70E3AE3C9A3A}.ReleaseNoNet|Any CPU.ActiveCfg = Release|Any CPU + {46B769B8-2C58-4138-9CC0-70E3AE3C9A3A}.ReleaseNoNet|Any CPU.Build.0 = Release|Any CPU + {46B769B8-2C58-4138-9CC0-70E3AE3C9A3A}.ReleaseNoNet|Any CPU.Deploy.0 = Release|Any CPU + {46B769B8-2C58-4138-9CC0-70E3AE3C9A3A}.ReleaseNoNet|Mixed Platforms.ActiveCfg = Release|Any CPU + {46B769B8-2C58-4138-9CC0-70E3AE3C9A3A}.ReleaseNoNet|Mixed Platforms.Build.0 = Release|Any CPU + {46B769B8-2C58-4138-9CC0-70E3AE3C9A3A}.ReleaseNoNet|Mixed Platforms.Deploy.0 = Release|Any CPU + {46B769B8-2C58-4138-9CC0-70E3AE3C9A3A}.ReleaseNoNet|Win32.ActiveCfg = Release|Any CPU + {46B769B8-2C58-4138-9CC0-70E3AE3C9A3A}.ReleaseNoNet|x64.ActiveCfg = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE EndGlobalSection GlobalSection(MonoDevelopProperties) = preSolution StartupItem = keepass2android\keepass2android.csproj @@ -102,7 +191,7 @@ Global $0.DotNetNamingPolicy = $1 $1.DirectoryNamespaceAssociation = None $1.ResourceNamePolicy = FileFormatDefault - $0.TextStylePolicy = $2 + $0.TextStylePolicy = $5 $2.FileWidth = 120 $2.TabsToSpaces = False $2.inheritsSet = VisualStudio @@ -127,13 +216,11 @@ Global $3.inheritsSet = Mono $3.inheritsScope = text/x-csharp $3.scope = text/x-csharp - $0.TextStylePolicy = $4 $4.FileWidth = 120 $4.TabsToSpaces = False $4.inheritsSet = VisualStudio $4.inheritsScope = text/plain $4.scope = text/plain - $0.TextStylePolicy = $5 $5.inheritsSet = null $5.scope = application/xml $0.XmlFormattingPolicy = $6 @@ -144,7 +231,4 @@ Global $7.Text = @/*\nThis file is part of Keepass2Android, Copyright 2013 Philipp Crocoll.\n\n Keepass2Android is free software: you can redistribute it and/or modify\n it under the terms of the GNU General Public License as published by\n the Free Software Foundation, either version 2 of the License, or\n (at your option) any later version.\n\n Keepass2Android is distributed in the hope that it will be useful,\n but WITHOUT ANY WARRANTY; without even the implied warranty of\n MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n GNU General Public License for more details.\n\n You should have received a copy of the GNU General Public License\n along with Keepass2Android. If not, see .\n */\n $7.IncludeInNewFiles = True EndGlobalSection - GlobalSection(SolutionProperties) = preSolution - HideSolutionNode = FALSE - EndGlobalSection EndGlobal diff --git a/src/Kp2aBusinessLogic/IDrawableFactory.cs b/src/Kp2aBusinessLogic/IDrawableFactory.cs new file mode 100644 index 00000000..fdf5733f --- /dev/null +++ b/src/Kp2aBusinessLogic/IDrawableFactory.cs @@ -0,0 +1,17 @@ +using Android.Widget; +using Android.Content.Res; +using KeePassLib; +using Android.Graphics.Drawables; + +namespace keepass2android +{ + public interface IDrawableFactory + { + void AssignDrawableTo (ImageView iv, Resources res, PwDatabase db, PwIcon icon, PwUuid customIconId); + + Drawable GetIconDrawable(Resources res, PwDatabase db, PwIcon icon, PwUuid customIconId); + + + void Clear(); + } +} \ No newline at end of file diff --git a/src/Kp2aBusinessLogic/IKp2aApp.cs b/src/Kp2aBusinessLogic/IKp2aApp.cs new file mode 100644 index 00000000..23cd5962 --- /dev/null +++ b/src/Kp2aBusinessLogic/IKp2aApp.cs @@ -0,0 +1,53 @@ +using System; +using Android.Content; +using KeePassLib.Serialization; + +namespace keepass2android +{ + /// + /// Interface through which Activities and the logic layer can access some app specific functionalities and Application static data + /// + /// This also contains methods which are UI specific and should be replacable for testing. + public interface IKp2aApp + { + + /// + /// Set the flag that the database needs to be locked. + /// + void SetShutdown(); + + /// + /// Returns the current database + /// + Database GetDb(); + + /// + /// Tell the app that the file from ioc was opened with keyfile. + /// + void StoreOpenedFileAsRecent(IOConnectionInfo ioc, string keyfile); + + /// + /// Creates a new database and returns it + /// + Database CreateNewDatabase(); + + /// + /// Returns the user-displayable string identified by stringKey + /// + string GetResourceString(UiStringKey stringKey); + + /// + /// Returns the value from the preferences corresponding to key + /// + bool GetBooleanPreference(PreferenceKey key); + + /// + /// Asks the user the question "messageKey" with the options Yes/No/Cancel, calls the handler corresponding to the answer. + /// + void AskYesNoCancel(UiStringKey titleKey, UiStringKey messageKey, + EventHandler yesHandler, + EventHandler noHandler, + EventHandler cancelHandler, + Context ctx); + } +} \ No newline at end of file diff --git a/src/keepass2android/KeyFileException.cs b/src/Kp2aBusinessLogic/KeyFileException.cs similarity index 91% rename from src/keepass2android/KeyFileException.cs rename to src/Kp2aBusinessLogic/KeyFileException.cs index fe8190f1..1eb4d824 100644 --- a/src/keepass2android/KeyFileException.cs +++ b/src/Kp2aBusinessLogic/KeyFileException.cs @@ -16,20 +16,12 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file */ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -using Android.App; -using Android.Content; -using Android.OS; -using Android.Runtime; -using Android.Views; -using Android.Widget; namespace keepass2android { - + /// + /// Thrown when there is an error adding the keyfie to the user key + /// [Serializable] public class KeyFileException : Exception { diff --git a/src/Kp2aBusinessLogic/Kp2aBusinessLogic.csproj b/src/Kp2aBusinessLogic/Kp2aBusinessLogic.csproj new file mode 100644 index 00000000..7d35fea3 --- /dev/null +++ b/src/Kp2aBusinessLogic/Kp2aBusinessLogic.csproj @@ -0,0 +1,86 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {53A9CB7F-6553-4BC0-B56B-9410BB2E59AA} + {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Library + Properties + keepass2android + Kp2aBusinessLogic + 512 + Resources\Resource.Designer.cs + Off + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {545b4a6b-8bba-4fbe-92fc-4ac060122a54} + KeePassLib2Android + + + + + \ No newline at end of file diff --git a/src/Kp2aBusinessLogic/PreferenceKey.cs b/src/Kp2aBusinessLogic/PreferenceKey.cs new file mode 100644 index 00000000..6e62362a --- /dev/null +++ b/src/Kp2aBusinessLogic/PreferenceKey.cs @@ -0,0 +1,11 @@ +namespace keepass2android +{ + /// + /// Keys which can be used to get a preference setting + /// + public enum PreferenceKey + { + remember_keyfile, + UseFileTransactions + } +} \ No newline at end of file diff --git a/src/keepass2android/ProgressTask.cs b/src/Kp2aBusinessLogic/ProgressTask.cs similarity index 55% rename from src/keepass2android/ProgressTask.cs rename to src/Kp2aBusinessLogic/ProgressTask.cs index e6f20b1e..878b722c 100644 --- a/src/keepass2android/ProgressTask.cs +++ b/src/Kp2aBusinessLogic/ProgressTask.cs @@ -15,68 +15,62 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file along with Keepass2Android. If not, see . */ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - using Android.App; using Android.Content; using Android.OS; -using Android.Runtime; -using Android.Views; -using Android.Widget; using Java.Lang; namespace keepass2android { + /// + /// Class to run a task while a progress dialog is shown + /// public class ProgressTask { - private Context mCtx; - private Handler mHandler; - private RunnableOnFinish mTask; - private ProgressDialog mPd; + private readonly Handler _handler; + private readonly RunnableOnFinish _task; + private readonly ProgressDialog _progressDialog; + private readonly IKp2aApp _app; - public ProgressTask(Context ctx, RunnableOnFinish task, int messageId) { - mCtx = ctx; - mTask = task; - mHandler = new Handler(); + public ProgressTask(IKp2aApp app, Context ctx, RunnableOnFinish task, UiStringKey messageKey) { + _task = task; + _handler = new Handler(); + _app = app; // Show process dialog - mPd = new ProgressDialog(mCtx); - mPd.SetTitle(ctx.GetText(Resource.String.progress_title)); - mPd.SetMessage(ctx.GetText(messageId)); + _progressDialog = new ProgressDialog(ctx); + _progressDialog.SetTitle(_app.GetResourceString(UiStringKey.progress_title)); + _progressDialog.SetMessage(_app.GetResourceString(messageKey)); // Set code to run when this is finished - mTask.setStatus(new UpdateStatus(ctx, mHandler, mPd)); - mTask.mFinish = new AfterTask(task.mFinish, mHandler, mPd); + _task.SetStatus(new UpdateStatus(_app, _handler, _progressDialog)); + _task.OnFinishToRun = new AfterTask(task.OnFinishToRun, _handler, _progressDialog); } - public void run() { + public void Run() { // Show process dialog - mPd.Show(); + _progressDialog.Show(); // Start Thread to Run task - Thread t = new Thread(mTask.run); + Thread t = new Thread(_task.Run); t.Start(); } private class AfterTask : OnFinish { - - ProgressDialog mPd; + readonly ProgressDialog _progressDialog; public AfterTask (OnFinish finish, Handler handler, ProgressDialog pd): base(finish, handler) { - mPd = pd; + _progressDialog = pd; } - public override void run() { - base.run(); + public override void Run() { + base.Run(); // Remove the progress dialog - mHandler.Post(delegate() {mPd.Dismiss();}); + Handler.Post(delegate {_progressDialog.Dismiss();}); } diff --git a/src/Kp2aBusinessLogic/Properties/AssemblyInfo.cs b/src/Kp2aBusinessLogic/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..b65267bb --- /dev/null +++ b/src/Kp2aBusinessLogic/Properties/AssemblyInfo.cs @@ -0,0 +1,34 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using Android.App; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Kp2aBusinessLogic")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Kp2aBusinessLogic")] +[assembly: AssemblyCopyright("Copyright © 2013")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] +[assembly: ComVisible(false)] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] + +// Add some common permissions, these can be removed if not needed +[assembly: UsesPermission(Android.Manifest.Permission.Internet)] +[assembly: UsesPermission(Android.Manifest.Permission.WriteExternalStorage)] diff --git a/src/keepass2android/PwGroupEqualityFromIdComparer.cs b/src/Kp2aBusinessLogic/PwGroupEqualityFromIdComparer.cs similarity index 86% rename from src/keepass2android/PwGroupEqualityFromIdComparer.cs rename to src/Kp2aBusinessLogic/PwGroupEqualityFromIdComparer.cs index 6b86efc4..066e00cf 100644 --- a/src/keepass2android/PwGroupEqualityFromIdComparer.cs +++ b/src/Kp2aBusinessLogic/PwGroupEqualityFromIdComparer.cs @@ -15,21 +15,14 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. along with Keepass2Android. If not, see . */ -using System; using System.Collections.Generic; -using System.Linq; -using System.Text; - -using Android.App; -using Android.Content; -using Android.OS; -using Android.Runtime; -using Android.Views; -using Android.Widget; using KeePassLib; namespace keepass2android { + /// + /// EqualityComparer implementation to compare PwGroups based on their Id + /// class PwGroupEqualityFromIdComparer: IEqualityComparer { #region IEqualityComparer implementation diff --git a/src/keepass2android/PwUuidEqualityComparer.cs b/src/Kp2aBusinessLogic/PwUuidEqualityComparer.cs similarity index 81% rename from src/keepass2android/PwUuidEqualityComparer.cs rename to src/Kp2aBusinessLogic/PwUuidEqualityComparer.cs index f769ff03..c0aa5419 100644 --- a/src/keepass2android/PwUuidEqualityComparer.cs +++ b/src/Kp2aBusinessLogic/PwUuidEqualityComparer.cs @@ -15,23 +15,15 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. along with Keepass2Android. If not, see . */ -using System; using System.Collections.Generic; -using System.Linq; -using System.Text; - -using Android.App; -using Android.Content; -using Android.OS; -using Android.Runtime; -using Android.Views; -using Android.Widget; - using KeePassLib; namespace keepass2android { - class PwUuidEqualityComparer: IEqualityComparer + /// + /// EqualityComparer for PwUuid based on their value (instead of reference) + /// + public class PwUuidEqualityComparer: IEqualityComparer { #region IEqualityComparer implementation public bool Equals (PwUuid x, PwUuid y) diff --git a/src/Kp2aBusinessLogic/Resources/Resource.Designer.cs b/src/Kp2aBusinessLogic/Resources/Resource.Designer.cs new file mode 100644 index 00000000..e69de29b diff --git a/src/keepass2android/search/SearchDbHelper.cs b/src/Kp2aBusinessLogic/SearchDbHelper.cs similarity index 61% rename from src/keepass2android/search/SearchDbHelper.cs rename to src/Kp2aBusinessLogic/SearchDbHelper.cs index f1888d24..3706a450 100644 --- a/src/keepass2android/search/SearchDbHelper.cs +++ b/src/Kp2aBusinessLogic/SearchDbHelper.cs @@ -15,44 +15,34 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file along with Keepass2Android. If not, see . */ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -using Android.App; -using Android.Content; -using Android.OS; -using Android.Runtime; -using Android.Views; -using Android.Widget; using KeePassLib; -using Android.Preferences; using System.Text.RegularExpressions; using KeePassLib.Collections; using KeePassLib.Interfaces; using KeePassLib.Utility; -using Android.Util; namespace keepass2android { + /// + /// Helper class providing methods to search a given database for specific things + /// public class SearchDbHelper { + private readonly IKp2aApp _app; - private readonly Context mCtx; - public SearchDbHelper(Context ctx) { - mCtx = ctx; + public SearchDbHelper(IKp2aApp app) { + _app = app; } - public PwGroup searchForText (Database database, string str) + public PwGroup SearchForText (Database database, string str) { - SearchParameters sp = new SearchParameters(); - sp.SearchString = str; + SearchParameters sp = new SearchParameters {SearchString = str}; - return search(database, sp, null); + return Search(database, sp, null); } - public PwGroup search(Database database, SearchParameters sp, IDictionary resultContexts) + public PwGroup Search(Database database, SearchParameters sp, IDictionary resultContexts) { if(sp.RegularExpression) // Validate regular expression @@ -60,14 +50,13 @@ namespace keepass2android new Regex(sp.SearchString); } - string strGroupName = mCtx.GetString(Resource.String.search_results) + " (\"" + sp.SearchString + "\")"; - PwGroup pgResults = new PwGroup(true, true, strGroupName, PwIcon.EMailSearch); - pgResults.IsVirtual = true; - + string strGroupName = _app.GetResourceString(UiStringKey.search_results) + " (\"" + sp.SearchString + "\")"; + PwGroup pgResults = new PwGroup(true, true, strGroupName, PwIcon.EMailSearch) {IsVirtual = true}; + PwObjectList listResults = pgResults.Entries; - database.root.SearchEntries(sp, listResults, resultContexts, new NullStatusLogger()); + database.Root.SearchEntries(sp, listResults, resultContexts, new NullStatusLogger()); return pgResults; @@ -76,7 +65,7 @@ namespace keepass2android } - public PwGroup searchForExactUrl (Database database, string url) + public PwGroup SearchForExactUrl (Database database, string url) { SearchParameters sp = SearchParameters.None; sp.SearchInUrls = true; @@ -87,36 +76,34 @@ namespace keepass2android new Regex(sp.SearchString); } - string strGroupName = mCtx.GetString(Resource.String.search_results) + " (\"" + sp.SearchString + "\")"; - PwGroup pgResults = new PwGroup(true, true, strGroupName, PwIcon.EMailSearch); - pgResults.IsVirtual = true; - + string strGroupName = _app.GetResourceString(UiStringKey.search_results) + " (\"" + sp.SearchString + "\")"; + PwGroup pgResults = new PwGroup(true, true, strGroupName, PwIcon.EMailSearch) {IsVirtual = true}; + PwObjectList listResults = pgResults.Entries; - database.root.SearchEntries(sp, listResults, new NullStatusLogger()); + database.Root.SearchEntries(sp, listResults, new NullStatusLogger()); return pgResults; } - private String extractHost(String url) + private static String ExtractHost(String url) { return UrlUtil.GetHost(url.Trim()); } - public PwGroup searchForHost(Database database, String url, bool allowSubdomains) + public PwGroup SearchForHost(Database database, String url, bool allowSubdomains) { - String host = extractHost(url); - string strGroupName = mCtx.GetString(Resource.String.search_results) + " (\"" + host + "\")"; - PwGroup pgResults = new PwGroup(true, true, strGroupName, PwIcon.EMailSearch); - pgResults.IsVirtual = true; + String host = ExtractHost(url); + string strGroupName = _app.GetResourceString(UiStringKey.search_results) + " (\"" + host + "\")"; + PwGroup pgResults = new PwGroup(true, true, strGroupName, PwIcon.EMailSearch) {IsVirtual = true}; if (String.IsNullOrWhiteSpace(host)) return pgResults; - foreach (PwEntry entry in database.entries.Values) + foreach (PwEntry entry in database.Entries.Values) { - String otherHost = extractHost(entry.Strings.ReadSafe(PwDefs.UrlField)); + String otherHost = ExtractHost(entry.Strings.ReadSafe(PwDefs.UrlField)); if ((allowSubdomains) && (otherHost.StartsWith("www."))) otherHost = otherHost.Substring(4); //remove "www." if (String.IsNullOrWhiteSpace(otherHost)) diff --git a/src/Kp2aBusinessLogic/UiStringKey.cs b/src/Kp2aBusinessLogic/UiStringKey.cs new file mode 100644 index 00000000..fd6982c0 --- /dev/null +++ b/src/Kp2aBusinessLogic/UiStringKey.cs @@ -0,0 +1,22 @@ +namespace keepass2android +{ + /// + /// Keys to identify user-displayable strings. + /// + /// Do not rename the keys here unless you rename the corresponding keys in the resource file of KP2A. + /// The keys are resolved by reflection to the static Resource class. This kind of duplication is necessary + /// in order to use the Resource mechanism of Android but still decouple the logic layer from the UI. + public enum UiStringKey + { + AskDeletePermanentlyGroup, + progress_title, + AskDeletePermanentlyEntry, + search_results, + AskDeletePermanently_title, + saving_database, + keyfile_does_not_exist, + RecycleBin, + progress_create, + loading_database + } +} \ No newline at end of file diff --git a/src/keepass2android/UpdateStatus.cs b/src/Kp2aBusinessLogic/UpdateStatus.cs similarity index 63% rename from src/keepass2android/UpdateStatus.cs rename to src/Kp2aBusinessLogic/UpdateStatus.cs index 2fe27848..66c98f23 100644 --- a/src/keepass2android/UpdateStatus.cs +++ b/src/Kp2aBusinessLogic/UpdateStatus.cs @@ -16,45 +16,40 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file */ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - using Android.App; -using Android.Content; using Android.OS; -using Android.Runtime; -using Android.Views; -using Android.Widget; using KeePassLib.Interfaces; namespace keepass2android { + /// + /// StatusLogger implementation which shows the progress in a progress dialog + /// public class UpdateStatus: IStatusLogger { - private ProgressDialog mPD; - private Context mCtx; - private Handler mHandler; + private readonly ProgressDialog _progressDialog; + readonly IKp2aApp _app; + private readonly Handler _handler; public UpdateStatus() { } - public UpdateStatus(Context ctx, Handler handler, ProgressDialog pd) { - mCtx = ctx; - mPD = pd; - mHandler = handler; + public UpdateStatus(IKp2aApp app, Handler handler, ProgressDialog pd) { + _app = app; + _progressDialog = pd; + _handler = handler; } - public void updateMessage(int resId) { - if ( mCtx != null && mPD != null && mHandler != null ) { - mHandler.Post( () => {mPD.SetMessage(mCtx.GetString(resId));}); + public void UpdateMessage(UiStringKey stringKey) { + if ( _app != null && _progressDialog != null && _handler != null ) { + _handler.Post( () => {_progressDialog.SetMessage(_app.GetResourceString(stringKey));}); } } - public void updateMessage (String message) + public void UpdateMessage (String message) { - if ( mCtx != null && mPD != null && mHandler != null ) { - mHandler.Post(() => {mPD.SetMessage(message); } ); + if ( _app!= null && _progressDialog != null && _handler != null ) { + _handler.Post(() => {_progressDialog.SetMessage(message); } ); } } @@ -77,7 +72,7 @@ namespace keepass2android public bool SetText (string strNewText, LogStatusType lsType) { - updateMessage(strNewText); + UpdateMessage(strNewText); return true; } diff --git a/src/Kp2aBusinessLogic/database/Database.cs b/src/Kp2aBusinessLogic/database/Database.cs new file mode 100644 index 00000000..f22926b8 --- /dev/null +++ b/src/Kp2aBusinessLogic/database/Database.cs @@ -0,0 +1,218 @@ +/* +This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file is based on Keepassdroid, Copyright Brian Pellin. + + Keepass2Android is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + Keepass2Android is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Keepass2Android. If not, see . + */ + +using System; +using System.Collections.Generic; +using Android.Content; +using KeePassLib; +using KeePassLib.Serialization; + +namespace keepass2android +{ + + public class Database { + + + public Dictionary Groups = new Dictionary(new PwUuidEqualityComparer()); + public Dictionary Entries = new Dictionary(new PwUuidEqualityComparer()); + public HashSet Dirty = new HashSet(new PwGroupEqualityFromIdComparer()); + public PwGroup Root; + public PwDatabase KpDatabase; + public IOConnectionInfo Ioc; + public DateTime LastChangeDate; + public SearchDbHelper SearchHelper; + + public IDrawableFactory DrawableFactory; + + readonly IKp2aApp _app; + + public Database(IDrawableFactory drawableFactory, IKp2aApp app) + { + DrawableFactory = drawableFactory; + _app = app; + } + + private bool _loaded; + + private bool _reloadRequested; + + public bool ReloadRequested + { + get { return _reloadRequested; } + set { _reloadRequested = value; } + } + + public bool Loaded { + get { return _loaded;} + set { _loaded = value; } + } + + public bool Open + { + get { return Loaded && (!Locked); } + } + + bool _locked; + public bool Locked + { + get + { + return _locked; + } + set + { + _locked = value; + } + } + + public bool DidOpenFileChange() + { + if ((Loaded == false) || (Ioc.IsLocalFile() == false)) + { + return false; + } + return System.IO.File.GetLastWriteTimeUtc(Ioc.Path) > LastChangeDate; + } + + + public void LoadData(IKp2aApp app, IOConnectionInfo iocInfo, String password, String keyfile, UpdateStatus status) + { + Ioc = iocInfo; + + PwDatabase pwDatabase = new PwDatabase(); + + KeePassLib.Keys.CompositeKey key = new KeePassLib.Keys.CompositeKey(); + key.AddUserKey(new KeePassLib.Keys.KcpPassword(password)); + if (!String.IsNullOrEmpty(keyfile)) + { + + try + { + key.AddUserKey(new KeePassLib.Keys.KcpKeyFile(keyfile)); + } catch (Exception) + { + throw new KeyFileException(); + } + } + + pwDatabase.Open(iocInfo, key, status); + + if (iocInfo.IsLocalFile()) + { + LastChangeDate = System.IO.File.GetLastWriteTimeUtc(iocInfo.Path); + } else + { + LastChangeDate = DateTime.MinValue; + } + + Root = pwDatabase.RootGroup; + PopulateGlobals(Root); + + + Loaded = true; + KpDatabase = pwDatabase; + SearchHelper = new SearchDbHelper(app); + } + + public bool QuickUnlockEnabled { get; set; } + + //KeyLength of QuickUnlock at time of loading the database. + //This is important to not allow an attacker to set the length to 1 when QuickUnlock is started already. + public int QuickUnlockKeyLength + { + get; + set; + } + + public PwGroup SearchForText(String str) { + PwGroup group = SearchHelper.SearchForText(this, str); + + return group; + + } + + public PwGroup Search(SearchParameters searchParams) + { + return SearchHelper.Search(this, searchParams); + } + + + public PwGroup SearchForExactUrl(String url) { + PwGroup group = SearchHelper.SearchForExactUrl(this, url); + + return group; + + } + + public PwGroup SearchForHost(String url, bool allowSubdomains) { + PwGroup group = SearchHelper.SearchForHost(this, url, allowSubdomains); + + return group; + + } + + + public void SaveData(Context ctx) { + + KpDatabase.UseFileTransactions = _app.GetBooleanPreference(PreferenceKey.UseFileTransactions); + KpDatabase.Save(null); + + } + + private void PopulateGlobals (PwGroup currentGroup) + { + + var childGroups = currentGroup.Groups; + var childEntries = currentGroup.Entries; + + foreach (PwEntry e in childEntries) { + Entries [e.Uuid] = e; + } + foreach (PwGroup g in childGroups) { + Groups[g.Uuid] = g; + PopulateGlobals(g); + } + } + + public void Clear() { + Groups.Clear(); + Entries.Clear(); + Dirty.Clear(); + DrawableFactory.Clear(); + + Root = null; + KpDatabase = null; + Ioc = null; + _loaded = false; + _locked = false; + _reloadRequested = false; + } + + public void MarkAllGroupsAsDirty() { + foreach ( PwGroup group in Groups.Values ) { + Dirty.Add(group); + } + + + } + + + } + + +} + diff --git a/src/keepass2android/database/edit/ActionOnFinish.cs b/src/Kp2aBusinessLogic/database/edit/ActionOnFinish.cs similarity index 66% rename from src/keepass2android/database/edit/ActionOnFinish.cs rename to src/Kp2aBusinessLogic/database/edit/ActionOnFinish.cs index a0c4c95f..f9446ebf 100644 --- a/src/keepass2android/database/edit/ActionOnFinish.cs +++ b/src/Kp2aBusinessLogic/database/edit/ActionOnFinish.cs @@ -16,16 +16,7 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. */ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -using Android.App; -using Android.Content; using Android.OS; -using Android.Runtime; -using Android.Views; -using Android.Widget; namespace keepass2android { @@ -33,34 +24,34 @@ namespace keepass2android { public delegate void ActionToPerformOnFinsh(bool success, String message); - ActionToPerformOnFinsh actionToPerform; + readonly ActionToPerformOnFinsh _actionToPerform; public ActionOnFinish(ActionToPerformOnFinsh actionToPerform) : base(null, null) { - this.actionToPerform = actionToPerform; + _actionToPerform = actionToPerform; } public ActionOnFinish(ActionToPerformOnFinsh actionToPerform, OnFinish finish) : base(finish) { - this.actionToPerform = actionToPerform; + _actionToPerform = actionToPerform; } public ActionOnFinish(ActionToPerformOnFinsh actionToPerform, Handler handler) : base(handler) { - this.actionToPerform = actionToPerform; + _actionToPerform = actionToPerform; } - public override void run() + public override void Run() { - if (this.mMessage == null) - this.mMessage = ""; - if (this.mHandler != null) + if (Message == null) + Message = ""; + if (Handler != null) { - this.mHandler.Post(() => {actionToPerform(this.mSuccess, this.mMessage);}); + Handler.Post(() => {_actionToPerform(Success, Message);}); } else - actionToPerform(this.mSuccess, this.mMessage); - base.run(); + _actionToPerform(Success, Message); + base.Run(); } } } diff --git a/src/keepass2android/database/edit/AddEntry.cs b/src/Kp2aBusinessLogic/database/edit/AddEntry.cs similarity index 60% rename from src/keepass2android/database/edit/AddEntry.cs rename to src/Kp2aBusinessLogic/database/edit/AddEntry.cs index de7bead6..1de447c1 100644 --- a/src/keepass2android/database/edit/AddEntry.cs +++ b/src/Kp2aBusinessLogic/database/edit/AddEntry.cs @@ -15,79 +15,69 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file along with Keepass2Android. If not, see . */ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -using Android.App; using Android.Content; -using Android.OS; -using Android.Runtime; -using Android.Views; -using Android.Widget; using KeePassLib; namespace keepass2android { public class AddEntry : RunnableOnFinish { - protected Database mDb; - private PwEntry mEntry; - private PwGroup mParentGroup; - private Context mCtx; + protected Database Db; + private readonly PwEntry _entry; + private readonly PwGroup _parentGroup; + private readonly Context _ctx; - public static AddEntry getInstance(Context ctx, Database db, PwEntry entry, PwGroup parentGroup, OnFinish finish) { + public static AddEntry GetInstance(Context ctx, Database db, PwEntry entry, PwGroup parentGroup, OnFinish finish) { return new AddEntry(ctx, db, entry, parentGroup, finish); } protected AddEntry(Context ctx, Database db, PwEntry entry, PwGroup parentGroup, OnFinish finish):base(finish) { - mCtx = ctx; - mParentGroup = parentGroup; - mDb = db; - mEntry = entry; + _ctx = ctx; + _parentGroup = parentGroup; + Db = db; + _entry = entry; - mFinish = new AfterAdd(db, entry, mFinish); + OnFinishToRun = new AfterAdd(db, entry, OnFinishToRun); } - public override void run() { - mParentGroup.AddEntry(mEntry, true); + public override void Run() { + _parentGroup.AddEntry(_entry, true); // Commit to disk - SaveDB save = new SaveDB(mCtx, mDb, mFinish); - save.run(); + SaveDb save = new SaveDb(_ctx, Db, OnFinishToRun); + save.Run(); } private class AfterAdd : OnFinish { - protected Database mDb; - private PwEntry mEntry; + private readonly Database _db; + private readonly PwEntry _entry; public AfterAdd(Database db, PwEntry entry, OnFinish finish):base(finish) { - mDb = db; - mEntry = entry; + _db = db; + _entry = entry; } - public override void run() { - if ( mSuccess ) { + public override void Run() { + if ( Success ) { - PwGroup parent = mEntry.ParentGroup; + PwGroup parent = _entry.ParentGroup; // Mark parent group dirty - mDb.dirty.Add(parent); + _db.Dirty.Add(parent); // Add entry to global - mDb.entries[mEntry.Uuid] = mEntry; + _db.Entries[_entry.Uuid] = _entry; } else { //TODO test fail - mEntry.ParentGroup.Entries.Remove(mEntry); + _entry.ParentGroup.Entries.Remove(_entry); } - base.run(); + base.Run(); } } diff --git a/src/keepass2android/database/edit/AddGroup.cs b/src/Kp2aBusinessLogic/database/edit/AddGroup.cs similarity index 58% rename from src/keepass2android/database/edit/AddGroup.cs rename to src/Kp2aBusinessLogic/database/edit/AddGroup.cs index 55f89b0b..b972dd97 100644 --- a/src/keepass2android/database/edit/AddGroup.cs +++ b/src/Kp2aBusinessLogic/database/edit/AddGroup.cs @@ -16,82 +16,71 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file */ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -using Android.App; using Android.Content; -using Android.OS; -using Android.Runtime; -using Android.Views; -using Android.Widget; using KeePassLib; namespace keepass2android { public class AddGroup : RunnableOnFinish { - internal Database mDb; - private String mName; - private int mIconID; - internal PwGroup mGroup; - internal PwGroup mParent; - protected bool mDontSave; - Context mCtx; + internal Database Db; + private readonly String _name; + private readonly int _iconId; + internal PwGroup Group; + internal PwGroup Parent; + protected bool DontSave; + readonly Context _ctx; - public static AddGroup getInstance(Context ctx, Database db, String name, int iconid, PwGroup parent, OnFinish finish, bool dontSave) { + public static AddGroup GetInstance(Context ctx, Database db, String name, int iconid, PwGroup parent, OnFinish finish, bool dontSave) { return new AddGroup(ctx, db, name, iconid, parent, finish, dontSave); } private AddGroup(Context ctx, Database db, String name, int iconid, PwGroup parent, OnFinish finish, bool dontSave): base(finish) { - mCtx = ctx; - mDb = db; - mName = name; - mIconID = iconid; - mParent = parent; - mDontSave = dontSave; + _ctx = ctx; + Db = db; + _name = name; + _iconId = iconid; + Parent = parent; + DontSave = dontSave; - mFinish = new AfterAdd(this, mFinish); + OnFinishToRun = new AfterAdd(this, OnFinishToRun); } - public override void run() { - PwDatabase pm = mDb.pm; + public override void Run() { // Generate new group - mGroup = new PwGroup(true, true, mName, (PwIcon)mIconID); - mParent.AddGroup(mGroup, true); + Group = new PwGroup(true, true, _name, (PwIcon)_iconId); + Parent.AddGroup(Group, true); // Commit to disk - SaveDB save = new SaveDB(mCtx, mDb, mFinish, mDontSave); - save.run(); + SaveDb save = new SaveDb(_ctx, Db, OnFinishToRun, DontSave); + save.Run(); } private class AfterAdd : OnFinish { - - AddGroup addGroup; + readonly AddGroup _addGroup; public AfterAdd(AddGroup addGroup,OnFinish finish): base(finish) { - this.addGroup = addGroup; + _addGroup = addGroup; } - public override void run() { + public override void Run() { - if ( mSuccess ) { + if ( Success ) { // Mark parent group dirty - addGroup.mDb.dirty.Add(addGroup.mParent); + _addGroup.Db.Dirty.Add(_addGroup.Parent); // Add group to global list - addGroup.mDb.groups[addGroup.mGroup.Uuid] = addGroup.mGroup; + _addGroup.Db.Groups[_addGroup.Group.Uuid] = _addGroup.Group; } else { - addGroup.mParent.Groups.Remove(addGroup.mGroup); + _addGroup.Parent.Groups.Remove(_addGroup.Group); } - base.run(); + base.Run(); } } diff --git a/src/Kp2aBusinessLogic/database/edit/CreateDB.cs b/src/Kp2aBusinessLogic/database/edit/CreateDB.cs new file mode 100644 index 00000000..72b9a3cb --- /dev/null +++ b/src/Kp2aBusinessLogic/database/edit/CreateDB.cs @@ -0,0 +1,78 @@ +/* +This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file is based on Keepassdroid, Copyright Brian Pellin. + + Keepass2Android is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + Keepass2Android is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Keepass2Android. If not, see . + */ + +using Android.Content; +using KeePassLib.Serialization; +using KeePassLib.Keys; + +namespace keepass2android +{ + + public class CreateDb : RunnableOnFinish { + + private const int DefaultEncryptionRounds = 1000; + + private readonly IOConnectionInfo _ioc; + private readonly bool _dontSave; + private readonly Context _ctx; + private readonly IKp2aApp _app; + + public CreateDb(IKp2aApp app, Context ctx, IOConnectionInfo ioc, OnFinish finish, bool dontSave): base(finish) { + _ctx = ctx; + _ioc = ioc; + _dontSave = dontSave; + _app = app; + } + + + public override void Run() { + Database db = _app.CreateNewDatabase(); + + db.KpDatabase = new KeePassLib.PwDatabase(); + //Key will be changed/created immediately after creation: + CompositeKey tempKey = new CompositeKey(); + db.KpDatabase.New(_ioc, tempKey); + + + db.KpDatabase.KeyEncryptionRounds = DefaultEncryptionRounds; + db.KpDatabase.Name = "Keepass2Android Password Database"; + + + // Set Database state + db.Root = db.KpDatabase.RootGroup; + db.Ioc = _ioc; + db.Loaded = true; + db.SearchHelper = new SearchDbHelper(_app); + + // Add a couple default groups + AddGroup internet = AddGroup.GetInstance(_ctx, db, "Internet", 1, db.KpDatabase.RootGroup, null, true); + internet.Run(); + AddGroup email = AddGroup.GetInstance(_ctx, db, "eMail", 19, db.KpDatabase.RootGroup, null, true); + email.Run(); + + // Commit changes + SaveDb save = new SaveDb(_ctx, db, OnFinishToRun, _dontSave); + OnFinishToRun = null; + save.Run(); + + + } + + } + +} + diff --git a/src/keepass2android/database/edit/DeleteEntry.cs b/src/Kp2aBusinessLogic/database/edit/DeleteEntry.cs similarity index 60% rename from src/keepass2android/database/edit/DeleteEntry.cs rename to src/Kp2aBusinessLogic/database/edit/DeleteEntry.cs index e6fc2e11..97a468e4 100644 --- a/src/keepass2android/database/edit/DeleteEntry.cs +++ b/src/Kp2aBusinessLogic/database/edit/DeleteEntry.cs @@ -16,28 +16,19 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file */ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -using Android.App; using Android.Content; -using Android.OS; -using Android.Runtime; -using Android.Views; -using Android.Widget; using KeePassLib; namespace keepass2android { public class DeleteEntry : DeleteRunnable { - - private PwEntry mEntry; - public DeleteEntry(Context ctx, Database db, PwEntry entry, OnFinish finish):base(finish) { - mCtx = ctx; - mDb = db; - mEntry = entry; + private readonly PwEntry _entry; + + public DeleteEntry(Context ctx, IKp2aApp app, PwEntry entry, OnFinish finish):base(finish, app) { + Ctx = ctx; + Db = app.GetDb(); + _entry = entry; } @@ -45,27 +36,27 @@ namespace keepass2android { get { - return CanRecycleGroup(mEntry.ParentGroup); + return CanRecycleGroup(_entry.ParentGroup); } } - protected override int QuestionsResourceId + protected override UiStringKey QuestionsResourceId { get { - return Resource.String.AskDeletePermanentlyEntry; + return UiStringKey.AskDeletePermanentlyEntry; } } - public override void run() { + public override void Run() { - PwDatabase pd = mDb.pm; + PwDatabase pd = Db.KpDatabase; PwGroup pgRecycleBin = pd.RootGroup.FindGroup(pd.RecycleBinUuid, true); bool bUpdateGroupList = false; DateTime dtNow = DateTime.Now; - PwEntry pe = mEntry; + PwEntry pe = _entry; PwGroup pgParent = pe.ParentGroup; if(pgParent != null) { @@ -77,19 +68,19 @@ namespace keepass2android PwDeletedObject pdo = new PwDeletedObject(pe.Uuid, dtNow); pd.DeletedObjects.Add(pdo); - mFinish = new ActionOnFinish( (success, message) => - { - if ( success ) { - // Mark parent dirty - if ( pgParent != null ) { - mDb.dirty.Add(pgParent); + OnFinishToRun = new ActionOnFinish((success, message) => + { + if (success) + { + // Mark parent dirty + Db.Dirty.Add(pgParent); } - } else { - // Let's not bother recovering from a failure to save a deleted entry. It is too much work. - App.setShutdown(); - } - - }, this.mFinish); + else + { + // Let's not bother recovering from a failure to save a deleted entry. It is too much work. + App.SetShutdown(); + } + }, OnFinishToRun); } else // Recycle { @@ -98,27 +89,25 @@ namespace keepass2android pgRecycleBin.AddEntry(pe, true, true); pe.Touch(false); - mFinish = new ActionOnFinish( (success, message) => + OnFinishToRun = new ActionOnFinish( (success, message) => { if ( success ) { // Mark previous parent dirty - if ( pgParent != null ) { - mDb.dirty.Add(pgParent); - } + Db.Dirty.Add(pgParent); // Mark new parent dirty - mDb.dirty.Add(pgRecycleBin); + Db.Dirty.Add(pgRecycleBin); } else { // Let's not bother recovering from a failure to save a deleted entry. It is too much work. - App.setShutdown(); + App.SetShutdown(); } - }, this.mFinish); + }, OnFinishToRun); } } // Commit database - SaveDB save = new SaveDB(mCtx, mDb, mFinish, false); - save.run(); + SaveDb save = new SaveDb(Ctx, Db, OnFinishToRun, false); + save.Run(); } diff --git a/src/keepass2android/database/edit/DeleteGroup.cs b/src/Kp2aBusinessLogic/database/edit/DeleteGroup.cs similarity index 57% rename from src/keepass2android/database/edit/DeleteGroup.cs rename to src/Kp2aBusinessLogic/database/edit/DeleteGroup.cs index b8135319..8c7bd71a 100644 --- a/src/keepass2android/database/edit/DeleteGroup.cs +++ b/src/Kp2aBusinessLogic/database/edit/DeleteGroup.cs @@ -16,16 +16,7 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file */ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -using Android.App; using Android.Content; -using Android.OS; -using Android.Runtime; -using Android.Views; -using Android.Widget; using KeePassLib; namespace keepass2android @@ -33,55 +24,58 @@ namespace keepass2android public class DeleteGroup : DeleteRunnable { - private PwGroup mGroup; - private GroupBaseActivity mAct; - protected bool mDontSave; + private PwGroup _group; + protected bool DontSave; - public DeleteGroup(Context ctx, Database db, PwGroup group, GroupBaseActivity act, OnFinish finish):base(finish) { - setMembers(ctx, db, group, act, false); + public DeleteGroup(Context ctx, IKp2aApp app, PwGroup group, OnFinish finish) + : base(finish, app) + { + SetMembers(ctx, app, group, false); } - - public DeleteGroup(Context ctx, Database db, PwGroup group, GroupBaseActivity act, OnFinish finish, bool dontSave):base(finish) { - setMembers(ctx, db, group, act, dontSave); + /* + public DeleteGroup(Context ctx, Database db, PwGroup group, Activity act, OnFinish finish, bool dontSave) + : base(finish) + { + SetMembers(ctx, db, group, act, dontSave); } - + public DeleteGroup(Context ctx, Database db, PwGroup group, OnFinish finish, bool dontSave):base(finish) { - setMembers(ctx, db, group, null, dontSave); + SetMembers(ctx, db, group, null, dontSave); } - - private void setMembers(Context ctx, Database db, PwGroup group, GroupBaseActivity act, bool dontSave) { - base.setMembers(ctx, db); - - mGroup = group; - mAct = act; - mDontSave = dontSave; + */ + private void SetMembers(Context ctx, IKp2aApp app, PwGroup group, bool dontSave) + { + base.SetMembers(ctx, app.GetDb()); + _group = group; + DontSave = dontSave; + } public override bool CanRecycle { get { - return CanRecycleGroup(mGroup); + return CanRecycleGroup(_group); } } - protected override int QuestionsResourceId + protected override UiStringKey QuestionsResourceId { get { - return Resource.String.AskDeletePermanentlyGroup; + return UiStringKey.AskDeletePermanentlyGroup; } } - public override void run() { + public override void Run() { //from KP Desktop - PwGroup pg = mGroup; + PwGroup pg = _group; PwGroup pgParent = pg.ParentGroup; if(pgParent == null) return; // Can't remove virtual or root group - PwDatabase pd = mDb.pm; + PwDatabase pd = Db.KpDatabase; PwGroup pgRecycleBin = pd.RootGroup.FindGroup(pd.RecycleBinUuid, true); pgParent.Groups.Remove(pg); @@ -92,7 +86,7 @@ namespace keepass2android PwDeletedObject pdo = new PwDeletedObject(pg.Uuid, DateTime.Now); pd.DeletedObjects.Add(pdo); - mFinish = new AfterDeletePermanently(mFinish, mDb, mGroup); + OnFinishToRun = new AfterDeletePermanently(OnFinishToRun, App, _group); } else // Recycle { @@ -101,59 +95,59 @@ namespace keepass2android pgRecycleBin.AddGroup(pg, true, true); pg.Touch(false); - mFinish = new ActionOnFinish((success, message) => + OnFinishToRun = new ActionOnFinish((success, message) => { if ( success ) { // Mark new parent (Recycle bin) dirty - PwGroup parent = mGroup.ParentGroup; + PwGroup parent = _group.ParentGroup; if ( parent != null ) { - mDb.dirty.Add(parent); + Db.Dirty.Add(parent); } //Mark old parent dirty: - mDb.dirty.Add(pgParent); + Db.Dirty.Add(pgParent); } else { // Let's not bother recovering from a failure to save a deleted group. It is too much work. - App.setShutdown(); + App.SetShutdown(); } - }, this.mFinish); + }, OnFinishToRun); } // Save - SaveDB save = new SaveDB(mCtx, mDb, mFinish, mDontSave); - save.run(); + SaveDb save = new SaveDb(Ctx, Db, OnFinishToRun, DontSave); + save.Run(); } private class AfterDeletePermanently : OnFinish { - Database mDb; + readonly IKp2aApp _app; - PwGroup mGroup; + readonly PwGroup _group; - public AfterDeletePermanently(OnFinish finish, Database db, PwGroup group):base(finish) { - this.mDb = db; - this.mGroup = group; + public AfterDeletePermanently(OnFinish finish, IKp2aApp app, PwGroup group):base(finish) { + _app = app; + _group = group; } - public override void run() { - if ( mSuccess ) { + public override void Run() { + if ( Success ) { // Remove from group global - mDb.groups.Remove(mGroup.Uuid); + _app.GetDb().Groups.Remove(_group.Uuid); // Remove group from the dirty global (if it is present), not a big deal if this fails (doesn't throw) - mDb.dirty.Remove(mGroup); + _app.GetDb().Dirty.Remove(_group); // Mark parent dirty - PwGroup parent = mGroup.ParentGroup; + PwGroup parent = _group.ParentGroup; if ( parent != null ) { - mDb.dirty.Add(parent); + _app.GetDb().Dirty.Add(parent); } } else { // Let's not bother recovering from a failure to save a deleted group. It is too much work. - App.setShutdown(); + _app.SetShutdown(); } - base.run(); + base.Run(); } diff --git a/src/Kp2aBusinessLogic/database/edit/DeleteRunnable.cs b/src/Kp2aBusinessLogic/database/edit/DeleteRunnable.cs new file mode 100644 index 00000000..3b07a551 --- /dev/null +++ b/src/Kp2aBusinessLogic/database/edit/DeleteRunnable.cs @@ -0,0 +1,134 @@ +using Android.Content; +using KeePassLib; + +namespace keepass2android +{ + public abstract class DeleteRunnable : RunnableOnFinish + { + protected DeleteRunnable(OnFinish finish, IKp2aApp app):base(finish) + { + App = app; + } + + protected IKp2aApp App; + + protected Database Db; + + protected Context Ctx; + + protected void SetMembers(Context ctx, Database db) + { + Ctx = ctx; + Db = db; + } + + + private bool _deletePermanently = true; + + public bool DeletePermanently + { + get + { + return _deletePermanently; + } + set + { + _deletePermanently = value; + } + } + + public abstract bool CanRecycle + { + get; + } + + protected bool CanRecycleGroup(PwGroup pgParent) + { + bool bShiftPressed = false; + PwDatabase pd = Db.KpDatabase; + PwGroup pgRecycleBin = pd.RootGroup.FindGroup(pd.RecycleBinUuid, true); + bool bPermanent = false; + if (pgParent != null) + { + if (pd.RecycleBinEnabled == false) + bPermanent = true; + else if (bShiftPressed) + bPermanent = true; + else if (pgRecycleBin == null) + { + } // Recycle + else if (pgParent == pgRecycleBin) + bPermanent = true; + else if (pgParent.IsContainedIn(pgRecycleBin)) + bPermanent = true; + } + return !bPermanent; + } + + + protected void EnsureRecycleBin(ref PwGroup pgRecycleBin, + ref bool bGroupListUpdateRequired) + { + if ((Db == null) || (Db.KpDatabase == null)) { return; } + + if(pgRecycleBin == Db.KpDatabase.RootGroup) + { + pgRecycleBin = null; + } + + if(pgRecycleBin == null) + { + pgRecycleBin = new PwGroup(true, true, App.GetResourceString(UiStringKey.RecycleBin), + PwIcon.TrashBin) + { + EnableAutoType = false, + EnableSearching = false, + IsExpanded = false + }; + + Db.KpDatabase.RootGroup.AddGroup(pgRecycleBin, true); + + Db.KpDatabase.RecycleBinUuid = pgRecycleBin.Uuid; + + bGroupListUpdateRequired = true; + } + else { System.Diagnostics.Debug.Assert(pgRecycleBin.Uuid.EqualsValue(Db.KpDatabase.RecycleBinUuid)); } + } + + protected abstract UiStringKey QuestionsResourceId + { + get; + } + + public void Start() + { + if (CanRecycle) + { + App.AskYesNoCancel(UiStringKey.AskDeletePermanently_title, + QuestionsResourceId, + (dlgSender, dlgEvt) => + { + DeletePermanently = true; + ProgressTask pt = new ProgressTask(App, Ctx, this, UiStringKey.saving_database); + pt.Run(); + }, + (dlgSender, dlgEvt) => { + DeletePermanently = false; + ProgressTask pt = new ProgressTask(App, Ctx, this, UiStringKey.saving_database); + pt.Run(); + }, + (dlgSender, dlgEvt) => {}, + Ctx); + + + + } else + { + ProgressTask pt = new ProgressTask(App, Ctx, this, UiStringKey.saving_database); + pt.Run(); + } + } + + } +} + diff --git a/src/keepass2android/database/edit/FileOnFinish.cs b/src/Kp2aBusinessLogic/database/edit/FileOnFinish.cs similarity index 67% rename from src/keepass2android/database/edit/FileOnFinish.cs rename to src/Kp2aBusinessLogic/database/edit/FileOnFinish.cs index aeecd7ab..58c40311 100644 --- a/src/keepass2android/database/edit/FileOnFinish.cs +++ b/src/Kp2aBusinessLogic/database/edit/FileOnFinish.cs @@ -16,34 +16,21 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file */ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -using Android.App; -using Android.Content; -using Android.OS; -using Android.Runtime; -using Android.Views; -using Android.Widget; namespace keepass2android { public abstract class FileOnFinish : OnFinish { - private String mFilename = ""; - - public FileOnFinish(FileOnFinish finish):base(finish) { + private String _filename = ""; + + protected FileOnFinish(FileOnFinish finish):base(finish) { } - - public void setFilename(String filename) { - mFilename = filename; + + public string Filename + { + get { return _filename; } + set { _filename = value; } } - - public String getFilename() { - return mFilename; - } - } } diff --git a/src/Kp2aBusinessLogic/database/edit/LoadDB.cs b/src/Kp2aBusinessLogic/database/edit/LoadDB.cs new file mode 100644 index 00000000..3dd8cfda --- /dev/null +++ b/src/Kp2aBusinessLogic/database/edit/LoadDB.cs @@ -0,0 +1,105 @@ +/* +This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file is based on Keepassdroid, Copyright Brian Pellin. + + Keepass2Android is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 2 of the License, or + (at your option) any later version. + + Keepass2Android is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Keepass2Android. If not, see . + */ + +using System; +using KeePassLib.Serialization; + +namespace keepass2android +{ + public class LoadDb : RunnableOnFinish { + private readonly IOConnectionInfo _ioc; + private readonly String _pass; + private readonly String _key; + private readonly IKp2aApp _app; + private readonly bool _rememberKeyfile; + + public LoadDb(IKp2aApp app, IOConnectionInfo ioc, String pass, String key, OnFinish finish): base(finish) + { + _app = app; + _ioc = ioc; + _pass = pass; + _key = key; + + + _rememberKeyfile = app.GetBooleanPreference(PreferenceKey.remember_keyfile); + } + + + public override void Run () + { + try { + _app.GetDb().LoadData (_app, _ioc, _pass, _key, Status); + + SaveFileData (_ioc, _key); + + } catch (KeyFileException) { + Finish(false, /*TODO Localize: use Keepass error text KPRes.KeyFileError (including "or invalid format")*/ _app.GetResourceString(UiStringKey.keyfile_does_not_exist)); + } + catch (Exception e) { + Finish(false, "An error occured: " + e.Message); + return; + } + /* catch (InvalidPasswordException e) { + finish(false, Ctx.GetString(Resource.String.InvalidPassword)); + return; + } catch (FileNotFoundException e) { + finish(false, Ctx.GetString(Resource.String.FileNotFound)); + return; + } catch (IOException e) { + finish(false, e.getMessage()); + return; + } catch (KeyFileEmptyException e) { + finish(false, Ctx.GetString(Resource.String.keyfile_is_empty)); + return; + } catch (InvalidAlgorithmException e) { + finish(false, Ctx.GetString(Resource.String.invalid_algorithm)); + return; + } catch (InvalidKeyFileException e) { + finish(false, Ctx.GetString(Resource.String.keyfile_does_not_exist)); + return; + } catch (InvalidDBSignatureException e) { + finish(false, Ctx.GetString(Resource.String.invalid_db_sig)); + return; + } catch (InvalidDBVersionException e) { + finish(false, Ctx.GetString(Resource.String.unsupported_db_version)); + return; + } catch (InvalidDBException e) { + finish(false, Ctx.GetString(Resource.String.error_invalid_db)); + return; + } catch (OutOfMemoryError e) { + finish(false, Ctx.GetString(Resource.String.error_out_of_memory)); + return; + } + */ + Finish(true); + } + + private void SaveFileData(IOConnectionInfo ioc, String key) { + + if (!_rememberKeyfile) + { + key = ""; + } + _app.StoreOpenedFileAsRecent(ioc, key); + } + + + + } + +} + diff --git a/src/keepass2android/database/edit/OnFinish.cs b/src/Kp2aBusinessLogic/database/edit/OnFinish.cs similarity index 52% rename from src/keepass2android/database/edit/OnFinish.cs rename to src/Kp2aBusinessLogic/database/edit/OnFinish.cs index 67e3094f..c89478f8 100644 --- a/src/keepass2android/database/edit/OnFinish.cs +++ b/src/Kp2aBusinessLogic/database/edit/OnFinish.cs @@ -16,72 +16,65 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file */ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -using Android.App; using Android.Content; using Android.OS; -using Android.Runtime; -using Android.Views; using Android.Widget; namespace keepass2android { public abstract class OnFinish { - protected bool mSuccess; - protected String mMessage; + protected bool Success; + protected String Message; - protected OnFinish mOnFinish; - protected Handler mHandler; - - public OnFinish() { + protected OnFinish BaseOnFinish; + protected Handler Handler; + + protected OnFinish() { + } + + protected OnFinish(Handler handler) { + BaseOnFinish = null; + Handler = handler; + } + + protected OnFinish(OnFinish finish, Handler handler) { + BaseOnFinish = finish; + Handler = handler; + } + + protected OnFinish(OnFinish finish) { + BaseOnFinish = finish; + Handler = null; } - public OnFinish(Handler handler) { - mOnFinish = null; - mHandler = handler; + public void SetResult(bool success, String message) { + Success = success; + Message = message; } - public OnFinish(OnFinish finish, Handler handler) { - mOnFinish = finish; - mHandler = handler; + public void SetResult(bool success) { + Success = success; } - public OnFinish(OnFinish finish) { - mOnFinish = finish; - mHandler = null; - } - - public void setResult(bool success, String message) { - mSuccess = success; - mMessage = message; - } - - public void setResult(bool success) { - mSuccess = success; - } - - public virtual void run() { - if ( mOnFinish != null ) { + public virtual void Run() { + if ( BaseOnFinish != null ) { // Pass on result on call finish - mOnFinish.setResult(mSuccess, mMessage); + BaseOnFinish.SetResult(Success, Message); - if ( mHandler != null ) { - mHandler.Post(mOnFinish.run); + if ( Handler != null ) { + Handler.Post(BaseOnFinish.Run); } else { - mOnFinish.run(); + BaseOnFinish.Run(); } } } - protected void displayMessage(Context ctx) { - displayMessage(ctx, mMessage); + protected void DisplayMessage(Context ctx) { + DisplayMessage(ctx, Message); } - public static void displayMessage(Context ctx, string message) + public static void DisplayMessage(Context ctx, string message) { if ( !String.IsNullOrEmpty(message) ) { Toast.MakeText(ctx, message, ToastLength.Long).Show(); diff --git a/src/keepass2android/BitmapDrawableCompat.cs b/src/Kp2aBusinessLogic/database/edit/RunnableOnFinish.cs similarity index 57% rename from src/keepass2android/BitmapDrawableCompat.cs rename to src/Kp2aBusinessLogic/database/edit/RunnableOnFinish.cs index 41269b79..f899519c 100644 --- a/src/keepass2android/BitmapDrawableCompat.cs +++ b/src/Kp2aBusinessLogic/database/edit/RunnableOnFinish.cs @@ -14,32 +14,39 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file You should have received a copy of the GNU General Public License along with Keepass2Android. If not, see . */ - using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -using Android.App; -using Android.Content; -using Android.OS; -using Android.Runtime; -using Android.Views; -using Android.Widget; -using Android.Graphics.Drawables; -using Android.Content.Res; -using Android.Graphics; namespace keepass2android { - - public class BitmapDrawableCompat { - public static BitmapDrawable getBitmapDrawable(Resources res, Bitmap bitmap) { - return new BitmapDrawable(res, bitmap); + public abstract class RunnableOnFinish { + + public OnFinish OnFinishToRun; + public UpdateStatus Status; + + protected RunnableOnFinish(OnFinish finish) { + OnFinishToRun = finish; } + protected void Finish(bool result, String message) { + if ( OnFinishToRun != null ) { + OnFinishToRun.SetResult(result, message); + OnFinishToRun.Run(); + } + } + + protected void Finish(bool result) { + if ( OnFinishToRun != null ) { + OnFinishToRun.SetResult(result); + OnFinishToRun.Run(); + } + } + + public void SetStatus(UpdateStatus status) { + Status = status; + } + + abstract public void Run(); } - } diff --git a/src/keepass2android/database/edit/SaveDB.cs b/src/Kp2aBusinessLogic/database/edit/SaveDB.cs similarity index 60% rename from src/keepass2android/database/edit/SaveDB.cs rename to src/Kp2aBusinessLogic/database/edit/SaveDB.cs index 5e355b69..c98fe438 100644 --- a/src/keepass2android/database/edit/SaveDB.cs +++ b/src/Kp2aBusinessLogic/database/edit/SaveDB.cs @@ -15,46 +15,37 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file along with Keepass2Android. If not, see . */ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -using Android.App; using Android.Content; -using Android.OS; -using Android.Runtime; -using Android.Views; -using Android.Widget; namespace keepass2android { - public class SaveDB : RunnableOnFinish { - private Database mDb; - private bool mDontSave; - private Context mCtx; + public class SaveDb : RunnableOnFinish { + private readonly Database _db; + private readonly bool _dontSave; + private readonly Context _ctx; - public SaveDB(Context ctx, Database db, OnFinish finish, bool dontSave): base(finish) { - mCtx = ctx; - mDb = db; - mDontSave = dontSave; + public SaveDb(Context ctx, Database db, OnFinish finish, bool dontSave): base(finish) { + _ctx = ctx; + _db = db; + _dontSave = dontSave; } - public SaveDB(Context ctx, Database db, OnFinish finish):base(finish) { - mCtx = ctx; - mDb = db; - mDontSave = false; + public SaveDb(Context ctx, Database db, OnFinish finish):base(finish) { + _ctx = ctx; + _db = db; + _dontSave = false; } - public override void run () + public override void Run () { - if (! mDontSave) { + if (! _dontSave) { try { - mDb.SaveData (mCtx); - if (mDb.mIoc.IsLocalFile()) - mDb.mLastChangeDate = System.IO.File.GetLastWriteTimeUtc(mDb.mIoc.Path); + _db.SaveData (_ctx); + if (_db.Ioc.IsLocalFile()) + _db.LastChangeDate = System.IO.File.GetLastWriteTimeUtc(_db.Ioc.Path); } catch (Exception e) { /* TODO KPDesktop: * catch(Exception exSave) @@ -63,12 +54,12 @@ namespace keepass2android bSuccess = false; } */ - finish (false, e.Message); + Finish (false, e.Message); return; } } - finish(true); + Finish(true); } } diff --git a/src/keepass2android/database/edit/SetPassword.cs b/src/Kp2aBusinessLogic/database/edit/SetPassword.cs similarity index 57% rename from src/keepass2android/database/edit/SetPassword.cs rename to src/Kp2aBusinessLogic/database/edit/SetPassword.cs index 2192b123..ca238321 100644 --- a/src/keepass2android/database/edit/SetPassword.cs +++ b/src/Kp2aBusinessLogic/database/edit/SetPassword.cs @@ -15,16 +15,7 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file along with Keepass2Android. If not, see . */ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -using Android.App; using Android.Content; -using Android.OS; -using Android.Runtime; -using Android.Views; -using Android.Widget; using KeePassLib; using KeePassLib.Keys; @@ -32,40 +23,40 @@ namespace keepass2android { public class SetPassword : RunnableOnFinish { - private String mPassword; - private String mKeyfile; - private Database mDb; - private bool mDontSave; - private Context mCtx; + private readonly String _password; + private readonly String _keyfile; + private readonly Database _db; + private readonly bool _dontSave; + private readonly Context _ctx; public SetPassword(Context ctx, Database db, String password, String keyfile, OnFinish finish): base(finish) { - mCtx = ctx; - mDb = db; - mPassword = password; - mKeyfile = keyfile; - mDontSave = false; + _ctx = ctx; + _db = db; + _password = password; + _keyfile = keyfile; + _dontSave = false; } public SetPassword(Context ctx, Database db, String password, String keyfile, OnFinish finish, bool dontSave): base(finish) { - mCtx = ctx; - mDb = db; - mPassword = password; - mKeyfile = keyfile; - mDontSave = dontSave; + _ctx = ctx; + _db = db; + _password = password; + _keyfile = keyfile; + _dontSave = dontSave; } - public override void run () + public override void Run () { - PwDatabase pm = mDb.pm; + PwDatabase pm = _db.KpDatabase; CompositeKey newKey = new CompositeKey (); - if (String.IsNullOrEmpty (mPassword) == false) { - newKey.AddUserKey (new KcpPassword (mPassword)); + if (String.IsNullOrEmpty (_password) == false) { + newKey.AddUserKey (new KcpPassword (_password)); } - if (String.IsNullOrEmpty (mKeyfile) == false) { + if (String.IsNullOrEmpty (_keyfile) == false) { try { - newKey.AddUserKey (new KcpKeyFile (mKeyfile)); - } catch (Exception exKF) { + newKey.AddUserKey (new KcpKeyFile (_keyfile)); + } catch (Exception) { //TODO MessageService.ShowWarning (strKeyFile, KPRes.KeyFileError, exKF); return; } @@ -78,29 +69,29 @@ namespace keepass2android pm.MasterKey = newKey; // Save Database - mFinish = new AfterSave(previousKey, previousMasterKeyChanged, pm, mFinish); - SaveDB save = new SaveDB(mCtx, mDb, mFinish, mDontSave); - save.run(); + OnFinishToRun = new AfterSave(previousKey, previousMasterKeyChanged, pm, OnFinishToRun); + SaveDb save = new SaveDb(_ctx, _db, OnFinishToRun, _dontSave); + save.Run(); } private class AfterSave : OnFinish { - private CompositeKey mBackup; - private DateTime mPreviousKeyChanged; - private PwDatabase mDb; + private readonly CompositeKey _backup; + private readonly DateTime _previousKeyChanged; + private readonly PwDatabase _db; public AfterSave(CompositeKey backup, DateTime previousKeyChanged, PwDatabase db, OnFinish finish): base(finish) { - mPreviousKeyChanged = previousKeyChanged; - mBackup = backup; - mDb = db; + _previousKeyChanged = previousKeyChanged; + _backup = backup; + _db = db; } - public override void run() { - if ( ! mSuccess ) { - mDb.MasterKey = mBackup; - mDb.MasterKeyChanged = mPreviousKeyChanged; + public override void Run() { + if ( ! Success ) { + _db.MasterKey = _backup; + _db.MasterKeyChanged = _previousKeyChanged; } - base.run(); + base.Run(); } } diff --git a/src/keepass2android/database/edit/UpdateEntry.cs b/src/Kp2aBusinessLogic/database/edit/UpdateEntry.cs similarity index 56% rename from src/keepass2android/database/edit/UpdateEntry.cs rename to src/Kp2aBusinessLogic/database/edit/UpdateEntry.cs index 2ecc4e3e..40f7bf4a 100644 --- a/src/keepass2android/database/edit/UpdateEntry.cs +++ b/src/Kp2aBusinessLogic/database/edit/UpdateEntry.cs @@ -15,81 +15,67 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file along with Keepass2Android. If not, see . */ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; - -using Android.App; using Android.Content; -using Android.OS; -using Android.Runtime; -using Android.Views; -using Android.Widget; using KeePassLib; namespace keepass2android { public class UpdateEntry : RunnableOnFinish { - private Database mDb; - private PwEntry mOldE; - private PwEntry mNewE; - private Context mCtx; + private readonly Database _db; + private readonly Context _ctx; public UpdateEntry(Context ctx, Database db, PwEntry oldE, PwEntry newE, OnFinish finish):base(finish) { - mCtx = ctx; - mDb = db; - mOldE = oldE; - mNewE = newE; + _ctx = ctx; + _db = db; - mFinish = new AfterUpdate(oldE, newE, db, finish); + OnFinishToRun = new AfterUpdate(oldE, newE, db, finish); } - public override void run() { + public override void Run() { // Commit to disk - SaveDB save = new SaveDB(mCtx, mDb, mFinish); - save.run(); + SaveDb save = new SaveDb(_ctx, _db, OnFinishToRun); + save.Run(); } private class AfterUpdate : OnFinish { - private PwEntry mBackup; - private PwEntry mUpdatedEntry; - private Database mDb; + private readonly PwEntry _backup; + private readonly PwEntry _updatedEntry; + private readonly Database _db; public AfterUpdate(PwEntry backup, PwEntry updatedEntry, Database db, OnFinish finish):base(finish) { - mBackup = backup; - mUpdatedEntry = updatedEntry; - mDb = db; + _backup = backup; + _updatedEntry = updatedEntry; + _db = db; } - public override void run() { - if ( mSuccess ) { + public override void Run() { + if ( Success ) { // Mark group dirty if title, icon or Expiry stuff changes - if ( ! mBackup.Strings.ReadSafe (PwDefs.TitleField).Equals(mUpdatedEntry.Strings.ReadSafe (PwDefs.TitleField)) - || ! mBackup.IconId.Equals(mUpdatedEntry.IconId) - || ! mBackup.CustomIconUuid.EqualsValue(mUpdatedEntry.CustomIconUuid) - || mBackup.Expires != mUpdatedEntry.Expires - || (mBackup.Expires && (! mBackup.ExpiryTime.Equals(mUpdatedEntry.ExpiryTime))) + if ( ! _backup.Strings.ReadSafe (PwDefs.TitleField).Equals(_updatedEntry.Strings.ReadSafe (PwDefs.TitleField)) + || ! _backup.IconId.Equals(_updatedEntry.IconId) + || ! _backup.CustomIconUuid.EqualsValue(_updatedEntry.CustomIconUuid) + || _backup.Expires != _updatedEntry.Expires + || (_backup.Expires && (! _backup.ExpiryTime.Equals(_updatedEntry.ExpiryTime))) ) { - PwGroup parent = mUpdatedEntry.ParentGroup; + PwGroup parent = _updatedEntry.ParentGroup; if ( parent != null ) { // Mark parent group dirty - mDb.dirty.Add(parent); + _db.Dirty.Add(parent); } } } else { // If we fail to save, back out changes to global structure //TODO test fail - mUpdatedEntry.AssignProperties(mBackup, false, true, false); + _updatedEntry.AssignProperties(_backup, false, true, false); } - base.run(); + base.Run(); } } diff --git a/src/Kp2aUnitTests/Kp2aUnitTests.csproj b/src/Kp2aUnitTests/Kp2aUnitTests.csproj new file mode 100644 index 00000000..87ccfb1b --- /dev/null +++ b/src/Kp2aUnitTests/Kp2aUnitTests.csproj @@ -0,0 +1,90 @@ + + + + Debug + AnyCPU + 8.0.30703 + 2.0 + {46B769B8-2C58-4138-9CC0-70E3AE3C9A3A} + {EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + Library + Properties + Kp2aUnitTests + Kp2aUnitTests + 512 + true + Resources\Resource.Designer.cs + Off + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + True + None + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + False + SdkOnly + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + {545B4A6B-8BBA-4FBE-92FC-4AC060122A54} + KeePassLib2Android + + + {53A9CB7F-6553-4BC0-B56B-9410BB2E59AA} + Kp2aBusinessLogic + + + {a5f8fb02-00e0-4335-91ef-aeaa2c2f3c48} + MonoDroidUnitTesting + + + + + \ No newline at end of file diff --git a/src/Kp2aUnitTests/MainActivity.cs b/src/Kp2aUnitTests/MainActivity.cs new file mode 100644 index 00000000..718670d8 --- /dev/null +++ b/src/Kp2aUnitTests/MainActivity.cs @@ -0,0 +1,27 @@ +using System; + +using Android.App; +using Android.Content; +using Android.Runtime; +using Android.Views; +using Android.Widget; +using Android.OS; +using MonoDroidUnitTesting; +using System.Reflection; + +namespace Kp2aUnitTests +{ + [Activity(Label = "MonoDroidUnit", MainLauncher = true, Icon = "@drawable/icon")] + public class MainActivity : GuiTestRunnerActivity + { + protected override TestRunner CreateTestRunner() + { + TestRunner runner = new TestRunner(); + // Run all tests from this assembly + runner.AddTests(Assembly.GetExecutingAssembly()); + return runner; + } + } + +} + diff --git a/src/Kp2aUnitTests/Properties/AssemblyInfo.cs b/src/Kp2aUnitTests/Properties/AssemblyInfo.cs new file mode 100644 index 00000000..10d04ed0 --- /dev/null +++ b/src/Kp2aUnitTests/Properties/AssemblyInfo.cs @@ -0,0 +1,34 @@ +using System.Reflection; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; +using Android.App; + +// General Information about an assembly is controlled through the following +// set of attributes. Change these attribute values to modify the information +// associated with an assembly. +[assembly: AssemblyTitle("Kp2aUnitTests")] +[assembly: AssemblyDescription("")] +[assembly: AssemblyConfiguration("")] +[assembly: AssemblyCompany("")] +[assembly: AssemblyProduct("Kp2aUnitTests")] +[assembly: AssemblyCopyright("Copyright © 2013")] +[assembly: AssemblyTrademark("")] +[assembly: AssemblyCulture("")] +[assembly: ComVisible(false)] + +// Version information for an assembly consists of the following four values: +// +// Major Version +// Minor Version +// Build Number +// Revision +// +// You can specify all the values or you can default the Build and Revision Numbers +// by using the '*' as shown below: +// [assembly: AssemblyVersion("1.0.*")] +[assembly: AssemblyVersion("1.0.0.0")] +[assembly: AssemblyFileVersion("1.0.0.0")] + +// Add some common permissions, these can be removed if not needed +[assembly: UsesPermission(Android.Manifest.Permission.Internet)] +[assembly: UsesPermission(Android.Manifest.Permission.WriteExternalStorage)] diff --git a/src/Kp2aUnitTests/Resources/AboutResources.txt b/src/Kp2aUnitTests/Resources/AboutResources.txt new file mode 100644 index 00000000..194ae28a --- /dev/null +++ b/src/Kp2aUnitTests/Resources/AboutResources.txt @@ -0,0 +1,50 @@ +Images, layout descriptions, binary blobs and string dictionaries can be included +in your application as resource files. Various Android APIs are designed to +operate on the resource IDs instead of dealing with images, strings or binary blobs +directly. + +For example, a sample Android app that contains a user interface layout (main.xml), +an internationalization string table (strings.xml) and some icons (drawable-XXX/icon.png) +would keep its resources in the "Resources" directory of the application: + +Resources/ + drawable-hdpi/ + icon.png + + drawable-ldpi/ + icon.png + + drawable-mdpi/ + icon.png + + layout/ + main.xml + + values/ + strings.xml + +In order to get the build system to recognize Android resources, set the build action to +"AndroidResource". The native Android APIs do not operate directly with filenames, but +instead operate on resource IDs. When you compile an Android application that uses resources, +the build system will package the resources for distribution and generate a class called +"Resource" that contains the tokens for each one of the resources included. For example, +for the above Resources layout, this is what the Resource class would expose: + +public class Resource { + public class drawable { + public const int icon = 0x123; + } + + public class layout { + public const int main = 0x456; + } + + public class strings { + public const int first_string = 0xabc; + public const int second_string = 0xbcd; + } +} + +You would then use R.drawable.icon to reference the drawable/icon.png file, or Resource.layout.main +to reference the layout/main.xml file, or Resource.strings.first_string to reference the first +string in the dictionary file values/strings.xml. \ No newline at end of file diff --git a/src/Kp2aUnitTests/Resources/Drawable/Icon.png b/src/Kp2aUnitTests/Resources/Drawable/Icon.png new file mode 100644 index 00000000..8074c4c5 Binary files /dev/null and b/src/Kp2aUnitTests/Resources/Drawable/Icon.png differ diff --git a/src/Kp2aUnitTests/Resources/Layout/Main.axml b/src/Kp2aUnitTests/Resources/Layout/Main.axml new file mode 100644 index 00000000..98be1643 --- /dev/null +++ b/src/Kp2aUnitTests/Resources/Layout/Main.axml @@ -0,0 +1,13 @@ + + +