Merge remote-tracking branch 'upstream/master'

Conflicts:
	src/Kp2aBusinessLogic/SearchDbHelper.cs
	src/keepass2android/Database.cs
	src/keepass2android/EntryActivity.cs
	src/keepass2android/EntryEditActivity.cs
	src/keepass2android/icons/DrawableFactory.cs
	src/keepass2android/search/SearchResults.cs
This commit is contained in:
AlexVallat 2013-06-19 20:31:18 +01:00
commit f442a04520
150 changed files with 7940 additions and 4139 deletions

2
.gitignore vendored
View File

@ -26,3 +26,5 @@
/src/java/KP2ASoftKeyboard/projectzip
/src/java/KP2ASoftKeyboard/createProjectZip.bat
Thumbs.db
/src/monodroid-unittesting/*.suo

View File

@ -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 <http://www.gnu.org/licenses/>.\n */\n
$7.IncludeInNewFiles = True
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

View File

@ -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();
}
}

View File

@ -0,0 +1,53 @@
using System;
using Android.Content;
using KeePassLib.Serialization;
namespace keepass2android
{
/// <summary>
/// Interface through which Activities and the logic layer can access some app specific functionalities and Application static data
/// </summary>
/// This also contains methods which are UI specific and should be replacable for testing.
public interface IKp2aApp
{
/// <summary>
/// Set the flag that the database needs to be locked.
/// </summary>
void SetShutdown();
/// <summary>
/// Returns the current database
/// </summary>
Database GetDb();
/// <summary>
/// Tell the app that the file from ioc was opened with keyfile.
/// </summary>
void StoreOpenedFileAsRecent(IOConnectionInfo ioc, string keyfile);
/// <summary>
/// Creates a new database and returns it
/// </summary>
Database CreateNewDatabase();
/// <summary>
/// Returns the user-displayable string identified by stringKey
/// </summary>
string GetResourceString(UiStringKey stringKey);
/// <summary>
/// Returns the value from the preferences corresponding to key
/// </summary>
bool GetBooleanPreference(PreferenceKey key);
/// <summary>
/// Asks the user the question "messageKey" with the options Yes/No/Cancel, calls the handler corresponding to the answer.
/// </summary>
void AskYesNoCancel(UiStringKey titleKey, UiStringKey messageKey,
EventHandler<DialogClickEventArgs> yesHandler,
EventHandler<DialogClickEventArgs> noHandler,
EventHandler<DialogClickEventArgs> cancelHandler,
Context ctx);
}
}

View File

@ -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
{
/// <summary>
/// Thrown when there is an error adding the keyfie to the user key
/// </summary>
[Serializable]
public class KeyFileException : Exception
{

View File

@ -0,0 +1,86 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{53A9CB7F-6553-4BC0-B56B-9410BB2E59AA}</ProjectGuid>
<ProjectTypeGuids>{EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>keepass2android</RootNamespace>
<AssemblyName>Kp2aBusinessLogic</AssemblyName>
<FileAlignment>512</FileAlignment>
<AndroidResgenFile>Resources\Resource.Designer.cs</AndroidResgenFile>
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<ItemGroup>
<Reference Include="Mono.Android" />
<Reference Include="mscorlib" />
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="PreferenceKey.cs" />
<Compile Include="UiStringKey.cs" />
<Compile Include="database\Database.cs" />
<Compile Include="database\edit\ActionOnFinish.cs" />
<Compile Include="database\edit\AddEntry.cs" />
<Compile Include="database\edit\AddGroup.cs" />
<Compile Include="database\edit\CreateDb.cs" />
<Compile Include="database\edit\DeleteEntry.cs" />
<Compile Include="database\edit\DeleteGroup.cs" />
<Compile Include="database\edit\DeleteRunnable.cs" />
<Compile Include="database\edit\FileOnFinish.cs" />
<Compile Include="database\edit\LoadDb.cs" />
<Compile Include="database\edit\OnFinish.cs" />
<Compile Include="database\edit\RunnableOnFinish.cs" />
<Compile Include="database\edit\SaveDb.cs" />
<Compile Include="database\edit\SetPassword.cs" />
<Compile Include="database\edit\UpdateEntry.cs" />
<Compile Include="IKp2aApp.cs" />
<Compile Include="IDrawableFactory.cs" />
<Compile Include="KeyFileException.cs" />
<Compile Include="ProgressTask.cs" />
<Compile Include="PwGroupEqualityFromIdComparer.cs" />
<Compile Include="PwUuidEqualityComparer.cs" />
<Compile Include="Resources\Resource.Designer.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="SearchDbHelper.cs" />
<Compile Include="UpdateStatus.cs" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\KeePassLib2Android\KeePassLib2Android.csproj">
<Project>{545b4a6b-8bba-4fbe-92fc-4ac060122a54}</Project>
<Name>KeePassLib2Android</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@ -0,0 +1,11 @@
namespace keepass2android
{
/// <summary>
/// Keys which can be used to get a preference setting
/// </summary>
public enum PreferenceKey
{
remember_keyfile,
UseFileTransactions
}
}

View File

@ -15,68 +15,62 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file
along with Keepass2Android. If not, see <http://www.gnu.org/licenses/>.
*/
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
{
/// <summary>
/// Class to run a task while a progress dialog is shown
/// </summary>
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();});
}

View File

@ -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)]

View File

@ -15,21 +15,14 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll.
along with Keepass2Android. If not, see <http://www.gnu.org/licenses/>.
*/
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
{
/// <summary>
/// EqualityComparer implementation to compare PwGroups based on their Id
/// </summary>
class PwGroupEqualityFromIdComparer: IEqualityComparer<PwGroup>
{
#region IEqualityComparer implementation

View File

@ -15,23 +15,15 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll.
along with Keepass2Android. If not, see <http://www.gnu.org/licenses/>.
*/
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<PwUuid>
/// <summary>
/// EqualityComparer for PwUuid based on their value (instead of reference)
/// </summary>
public class PwUuidEqualityComparer: IEqualityComparer<PwUuid>
{
#region IEqualityComparer implementation
public bool Equals (PwUuid x, PwUuid y)

View File

View File

@ -15,44 +15,34 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file
along with Keepass2Android. If not, see <http://www.gnu.org/licenses/>.
*/
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
{
/// <summary>
/// Helper class providing methods to search a given database for specific things
/// </summary>
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<PwUuid, String> resultContexts)
public PwGroup Search(Database database, SearchParameters sp, IDictionary<PwUuid, String> 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<PwEntry> 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<PwEntry> 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))

View File

@ -0,0 +1,22 @@
namespace keepass2android
{
/// <summary>
/// Keys to identify user-displayable strings.
/// </summary>
/// 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
}
}

View File

@ -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
{
/// <summary>
/// StatusLogger implementation which shows the progress in a progress dialog
/// </summary>
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;
}

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using Android.Content;
using KeePassLib;
using KeePassLib.Serialization;
namespace keepass2android
{
public class Database {
public Dictionary<PwUuid, PwGroup> Groups = new Dictionary<PwUuid, PwGroup>(new PwUuidEqualityComparer());
public Dictionary<PwUuid, PwEntry> Entries = new Dictionary<PwUuid, PwEntry>(new PwUuidEqualityComparer());
public HashSet<PwGroup> Dirty = new HashSet<PwGroup>(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);
}
}
}
}

View File

@ -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();
}
}
}

View File

@ -15,79 +15,69 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file
along with Keepass2Android. If not, see <http://www.gnu.org/licenses/>.
*/
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();
}
}

View File

@ -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();
}
}

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
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();
}
}
}

View File

@ -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;
private readonly PwEntry _entry;
public DeleteEntry(Context ctx, Database db, PwEntry entry, OnFinish finish):base(finish) {
mCtx = ctx;
mDb = db;
mEntry = 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) =>
OnFinishToRun = new ActionOnFinish((success, message) =>
{
if (success)
{
if ( success ) {
// Mark parent dirty
if ( pgParent != null ) {
mDb.dirty.Add(pgParent);
Db.Dirty.Add(pgParent);
}
} else {
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);
}
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();
}

View File

@ -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,28 +24,31 @@ 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, IKp2aApp app, PwGroup group, bool dontSave)
{
base.SetMembers(ctx, app.GetDb());
private void setMembers(Context ctx, Database db, PwGroup group, GroupBaseActivity act, bool dontSave) {
base.setMembers(ctx, db);
mGroup = group;
mAct = act;
mDontSave = dontSave;
_group = group;
DontSave = dontSave;
}
@ -62,26 +56,26 @@ namespace keepass2android
{
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();
}

View File

@ -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();
}
}
}
}

View File

@ -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 = "";
private String _filename = "";
public FileOnFinish(FileOnFinish finish):base(finish) {
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;
}
}
}

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
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);
}
}
}

View File

@ -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;
protected OnFinish BaseOnFinish;
protected Handler Handler;
public OnFinish() {
protected OnFinish() {
}
public OnFinish(Handler handler) {
mOnFinish = null;
mHandler = handler;
protected OnFinish(Handler handler) {
BaseOnFinish = null;
Handler = handler;
}
public OnFinish(OnFinish finish, Handler handler) {
mOnFinish = finish;
mHandler = handler;
protected OnFinish(OnFinish finish, Handler handler) {
BaseOnFinish = finish;
Handler = handler;
}
public OnFinish(OnFinish finish) {
mOnFinish = finish;
mHandler = null;
protected OnFinish(OnFinish finish) {
BaseOnFinish = finish;
Handler = null;
}
public void setResult(bool success, String message) {
mSuccess = success;
mMessage = message;
public void SetResult(bool success, String message) {
Success = success;
Message = message;
}
public void setResult(bool success) {
mSuccess = success;
public void SetResult(bool success) {
Success = 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();

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
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 abstract class RunnableOnFinish {
public static BitmapDrawable getBitmapDrawable(Resources res, Bitmap bitmap) {
return new BitmapDrawable(res, bitmap);
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();
}
}

View File

@ -15,46 +15,37 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file
along with Keepass2Android. If not, see <http://www.gnu.org/licenses/>.
*/
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);
}
}

View File

@ -15,16 +15,7 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file
along with Keepass2Android. If not, see <http://www.gnu.org/licenses/>.
*/
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();
}
}

View File

@ -15,81 +15,67 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file
along with Keepass2Android. If not, see <http://www.gnu.org/licenses/>.
*/
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();
}
}

View File

@ -0,0 +1,90 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProductVersion>8.0.30703</ProductVersion>
<SchemaVersion>2.0</SchemaVersion>
<ProjectGuid>{46B769B8-2C58-4138-9CC0-70E3AE3C9A3A}</ProjectGuid>
<ProjectTypeGuids>{EFBA0AD7-5A72-4C68-AF49-83D382785DCF};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
<OutputType>Library</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>Kp2aUnitTests</RootNamespace>
<AssemblyName>Kp2aUnitTests</AssemblyName>
<FileAlignment>512</FileAlignment>
<AndroidApplication>true</AndroidApplication>
<AndroidResgenFile>Resources\Resource.Designer.cs</AndroidResgenFile>
<GenerateSerializationAssemblies>Off</GenerateSerializationAssemblies>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AndroidUseSharedRuntime>True</AndroidUseSharedRuntime>
<AndroidLinkMode>None</AndroidLinkMode>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
<AndroidUseSharedRuntime>False</AndroidUseSharedRuntime>
<AndroidLinkMode>SdkOnly</AndroidLinkMode>
</PropertyGroup>
<ItemGroup>
<Reference Include="Mono.Android" />
<Reference Include="mscorlib" />
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="TestDrawableFactory.cs" />
<Compile Include="TestCreateDb.cs" />
<Compile Include="MainActivity.cs" />
<Compile Include="Resources\Resource.Designer.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="Resources\AboutResources.txt" />
<None Include="Assets\AboutAssets.txt" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\Layout\Main.axml" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\Values\Strings.xml" />
</ItemGroup>
<ItemGroup>
<AndroidResource Include="Resources\Drawable\Icon.png" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\KeePassLib2Android\KeePassLib2Android.csproj">
<Project>{545B4A6B-8BBA-4FBE-92FC-4AC060122A54}</Project>
<Name>KeePassLib2Android</Name>
</ProjectReference>
<ProjectReference Include="..\Kp2aBusinessLogic\Kp2aBusinessLogic.csproj">
<Project>{53A9CB7F-6553-4BC0-B56B-9410BB2E59AA}</Project>
<Name>Kp2aBusinessLogic</Name>
</ProjectReference>
<ProjectReference Include="..\monodroid-unittesting\MonoDroidUnitTesting\MonoDroidUnitTesting.csproj">
<Project>{a5f8fb02-00e0-4335-91ef-aeaa2c2f3c48}</Project>
<Name>MonoDroidUnitTesting</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@ -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;
}
}
}

View File

@ -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)]

View File

@ -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.

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.0 KiB

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<Button
android:id="@+id/MyButton"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/Hello"
/>
</LinearLayout>

View File

@ -0,0 +1,116 @@
#pragma warning disable 1591
//------------------------------------------------------------------------------
// <auto-generated>
// Dieser Code wurde von einem Tool generiert.
// Laufzeitversion:4.0.30319.18046
//
// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn
// der Code erneut generiert wird.
// </auto-generated>
//------------------------------------------------------------------------------
[assembly: global::Android.Runtime.ResourceDesignerAttribute("Kp2aUnitTests.Resource", IsApplication=true)]
namespace Kp2aUnitTests
{
[System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Android.Build.Tasks", "1.0.0.0")]
public partial class Resource
{
static Resource()
{
global::Android.Runtime.ResourceIdManager.UpdateIdValues();
}
public static void UpdateIdValues()
{
KeePassLib2Android.Resource.String.library_name = Kp2aUnitTests.Resource.String.library_name;
}
public partial class Attribute
{
static Attribute()
{
global::Android.Runtime.ResourceIdManager.UpdateIdValues();
}
private Attribute()
{
}
}
public partial class Drawable
{
// aapt resource value: 0x7f020000
public const int Icon = 2130837504;
static Drawable()
{
global::Android.Runtime.ResourceIdManager.UpdateIdValues();
}
private Drawable()
{
}
}
public partial class Id
{
// aapt resource value: 0x7f050000
public const int MyButton = 2131034112;
static Id()
{
global::Android.Runtime.ResourceIdManager.UpdateIdValues();
}
private Id()
{
}
}
public partial class Layout
{
// aapt resource value: 0x7f030000
public const int Main = 2130903040;
static Layout()
{
global::Android.Runtime.ResourceIdManager.UpdateIdValues();
}
private Layout()
{
}
}
public partial class String
{
// aapt resource value: 0x7f040001
public const int ApplicationName = 2130968577;
// aapt resource value: 0x7f040000
public const int Hello = 2130968576;
// aapt resource value: 0x7f040002
public const int library_name = 2130968578;
static String()
{
global::Android.Runtime.ResourceIdManager.UpdateIdValues();
}
private String()
{
}
}
}
}
#pragma warning restore 1591

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="Hello">Hello World, Click Me!</string>
<string name="ApplicationName">Kp2aUnitTests</string>
</resources>

View File

@ -0,0 +1,51 @@
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using Java.IO;
using KeePassLib;
using KeePassLib.Keys;
using KeePassLib.Serialization;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using keepass2android;
namespace Kp2aUnitTests
{
[TestClass]
class TestCreateDb
{
[TestMethod]
public void CreateAndSaveLocal()
{
IKp2aApp app = new TestKp2aApp();
IOConnectionInfo ioc = new IOConnectionInfo {Path = "/mnt/sdcard/kp2atest/savetest.kdbx"};
File outputDir = new File("/mnt/sdcard/kp2atest/");
outputDir.Mkdirs();
File targetFile = new File(ioc.Path);
if (targetFile.Exists())
targetFile.Delete();
bool createSuccesful = false;
//create the task:
CreateDb createDb = new CreateDb(app, Application.Context, ioc, new ActionOnFinish((success, message) =>
{ createSuccesful = success; if (!success)
Assert.Fail(message);
}), false);
//run it:
createDb.Run();
//check expectations:
Assert.IsTrue(createSuccesful);
Assert.IsNotNull(app.GetDb());
Assert.IsNotNull(app.GetDb().KpDatabase);
//the create task should create two groups:
Assert.AreEqual(2, app.GetDb().KpDatabase.RootGroup.Groups.Count());
//ensure the the database can be loaded from file:
PwDatabase loadedDb = new PwDatabase();
loadedDb.Open(ioc, new CompositeKey(), null);
}
}
}

View File

@ -0,0 +1,27 @@
using System;
using Android.Content.Res;
using Android.Graphics.Drawables;
using Android.Widget;
using KeePassLib;
using keepass2android;
namespace Kp2aUnitTests
{
internal class TestDrawableFactory : IDrawableFactory
{
public void AssignDrawableTo(ImageView iv, Resources res, PwDatabase db, PwIcon icon, PwUuid customIconId)
{
}
public Drawable GetIconDrawable(Resources res, PwDatabase db, PwIcon icon, PwUuid customIconId)
{
return res.GetDrawable(Resource.Drawable.Icon);
}
public void Clear()
{
}
}
}

View File

@ -0,0 +1,54 @@
using System;
using Android.Content;
using KeePassLib.Serialization;
using keepass2android;
namespace Kp2aUnitTests
{
/// <summary>
/// Very simple implementation of the Kp2aApp interface to be used in tests
/// </summary>
internal class TestKp2aApp : IKp2aApp
{
private Database _db;
public void SetShutdown()
{
}
public Database GetDb()
{
return _db;
}
public void StoreOpenedFileAsRecent(IOConnectionInfo ioc, string keyfile)
{
}
public Database CreateNewDatabase()
{
TestDrawableFactory testDrawableFactory = new TestDrawableFactory();
_db = new Database(testDrawableFactory, new TestKp2aApp());
return _db;
}
public string GetResourceString(UiStringKey stringKey)
{
return stringKey.ToString();
}
public bool GetBooleanPreference(PreferenceKey key)
{
return true;
}
public void AskYesNoCancel(UiStringKey titleKey, UiStringKey messageKey, EventHandler<DialogClickEventArgs> yesHandler, EventHandler<DialogClickEventArgs> noHandler,
EventHandler<DialogClickEventArgs> cancelHandler, Context ctx)
{
yesHandler(null, null);
}
}
}

View File

@ -16,15 +16,9 @@ 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 Android.Content.PM;
@ -41,15 +35,15 @@ namespace keepass2android
SetContentView(Resource.Layout.about);
SetTitle(Resource.String.app_name);
setVersion();
SetVersion();
Button okButton = (Button) FindViewById(Resource.Id.about_button);
okButton.Click += (object sender, EventArgs e) => {
okButton.Click += (sender, e) => {
Dismiss();
};
}
private void setVersion() {
private void SetVersion() {
Context ctx = Context;
String version;

View File

@ -14,7 +14,8 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll.
You should have received a copy of the GNU General Public License
along with Keepass2Android. If not, see <http://www.gnu.org/licenses/>.
*/
using Android.App;

View File

@ -1,27 +1,21 @@
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.Util;
using Java.IO;
using Android.Net;
namespace keepass2android
{
[ContentProvider(new string[]{"keepass2android."+AppNames.PackagePart+".provider"})]
/// <summary>
/// Makes attachments of PwEntries accessible when they are stored in the app cache
/// </summary>
[ContentProvider(new[]{"keepass2android."+AppNames.PackagePart+".provider"})]
public class AttachmentContentProvider : ContentProvider {
private const String CLASS_NAME = "AttachmentContentProvider";
private const String ClassName = "AttachmentContentProvider";
// The authority is the symbolic name for the provider class
public const String AUTHORITY = "keepass2android."+AppNames.PackagePart+".provider";
public const String Authority = "keepass2android."+AppNames.PackagePart+".provider";
public override bool OnCreate() {
@ -31,12 +25,12 @@ namespace keepass2android
public override ParcelFileDescriptor OpenFile(Android.Net.Uri uri, String mode)
{
String LOG_TAG = CLASS_NAME + " - openFile";
const string logTag = ClassName + " - openFile";
Log.Verbose(LOG_TAG,
Log.Verbose(logTag,
"Called with uri: '" + uri + "'." + uri.LastPathSegment);
if (uri.ToString().StartsWith("content://" + AUTHORITY))
if (uri.ToString().StartsWith("content://" + Authority))
{
// The desired file name is specified by the last segment of the
// path
@ -54,13 +48,10 @@ namespace keepass2android
return pfd;
}
else
{
Log.Verbose(LOG_TAG, "Unsupported uri: '" + uri + "'.");
Log.Verbose(logTag, "Unsupported uri: '" + uri + "'.");
throw new FileNotFoundException("Unsupported uri: "
+ uri.ToString());
}
}
// //////////////////////////////////////////////////////////////
// Not supported / used / required for this example

View File

@ -15,36 +15,22 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file
along with Keepass2Android. If not, see <http://www.gnu.org/licenses/>.
*/
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 CancelDialog : Dialog {
private bool mCanceled = false;
public CancelDialog(Context context): base(context) {
}
public bool canceled() {
return mCanceled;
}
public bool Canceled { get; private set; }
public override void Cancel() {
base.Cancel();
mCanceled = true;
Canceled = true;
}
}

View File

@ -1,288 +0,0 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
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.Interfaces;
using KeePassLib.Serialization;
namespace keepass2android
{
public class Database {
public Dictionary<PwUuid, PwGroup> groups = new Dictionary<PwUuid, PwGroup>(new PwUuidEqualityComparer());
public Dictionary<PwUuid, PwEntry> entries = new Dictionary<PwUuid, PwEntry>(new PwUuidEqualityComparer());
public HashSet<PwGroup> dirty = new HashSet<PwGroup>(new PwGroupEqualityFromIdComparer());
public PwGroup root;
public PwDatabase pm;
public IOConnectionInfo mIoc;
public DateTime mLastChangeDate;
public SearchDbHelper searchHelper;
public DrawableFactory drawFactory = new DrawableFactory();
private bool loaded = false;
private bool mReloadRequested = false;
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) || (mIoc.IsLocalFile() == false))
{
return false;
}
return System.IO.File.GetLastWriteTimeUtc(mIoc.Path) > mLastChangeDate;
}
public void CheckForOpenFileChanged(Activity activity)
{
if (DidOpenFileChange())
{
if (mReloadRequested)
{
activity.SetResult(KeePass.EXIT_RELOAD_DB);
activity.Finish();
}
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.SetTitle(activity.GetString(Resource.String.AskReloadFile_title));
builder.SetMessage(activity.GetString(Resource.String.AskReloadFile));
builder.SetPositiveButton(activity.GetString(Android.Resource.String.Yes), new EventHandler<DialogClickEventArgs>((dlgSender, dlgEvt) =>
{
mReloadRequested = true;
activity.SetResult(KeePass.EXIT_RELOAD_DB);
activity.Finish();
}));
builder.SetNegativeButton(activity.GetString(Android.Resource.String.No), new EventHandler<DialogClickEventArgs>((dlgSender, dlgEvt) =>
{
}));
Dialog dialog = builder.Create();
dialog.Show();
}
}
public void LoadData(Context ctx, IOConnectionInfo iocInfo, String password, String keyfile, UpdateStatus status)
{
mIoc = iocInfo;
KeePassLib.PwDatabase pwDatabase = new KeePassLib.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())
{
mLastChangeDate = System.IO.File.GetLastWriteTimeUtc(iocInfo.Path);
} else
{
mLastChangeDate = DateTime.MinValue;
}
root = pwDatabase.RootGroup;
populateGlobals(root);
Loaded = true;
pm = pwDatabase;
searchHelper = new SearchDbHelper(ctx);
}
bool quickUnlockEnabled = false;
public bool QuickUnlockEnabled
{
get
{
return quickUnlockEnabled;
}
set
{
quickUnlockEnabled = value;
}
}
//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 Search(searchParams, null);
}
public PwGroup Search(SearchParameters searchParams, IDictionary<PwUuid, String> resultContexts)
{
return searchHelper.search(this, searchParams, resultContexts);
}
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) {
ISharedPreferences prefs = Android.Preferences.PreferenceManager.GetDefaultSharedPreferences(ctx);
pm.UseFileTransactions = prefs.GetBoolean(ctx.GetString(Resource.String.UseFileTransactions_key), true);
pm.Save(null);
}
class SaveStatusLogger: IStatusLogger
{
#region IStatusLogger implementation
public void StartLogging (string strOperation, bool bWriteOperationToLog)
{
}
public void EndLogging ()
{
}
public bool SetProgress (uint uPercent)
{
Android.Util.Log.Debug("DEBUG", "Progress: " + uPercent+"%");
return true;
}
public bool SetText (string strNewText, LogStatusType lsType)
{
Android.Util.Log.Debug("DEBUG", strNewText);
return true;
}
public bool ContinueWork ()
{
return true;
}
#endregion
}
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();
drawFactory.Clear();
root = null;
pm = null;
mIoc = null;
loaded = false;
locked = false;
mReloadRequested = false;
}
public void markAllGroupsAsDirty() {
foreach ( PwGroup group in groups.Values ) {
dirty.Add(group);
}
}
}
}

View File

@ -17,26 +17,20 @@ 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;
using Android.Text.Format;
using KeePassLib.Utility;
using Java.Util;
using Android.Preferences;
using Android.Text.Method;
using Android.Util;
using System.Globalization;
using Android.Content.PM;
using KeePassLib.Security;
using keepass2android.view;
using Android.Webkit;
using Android.Graphics;
using Java.IO;
@ -45,41 +39,39 @@ namespace keepass2android
{
[Activity (Label = "@string/app_name", ConfigurationChanges=ConfigChanges.Orientation|ConfigChanges.KeyboardHidden, Theme="@style/NoTitleBar")]
public class EntryActivity : LockCloseActivity {
public const String KEY_ENTRY = "entry";
public const String KEY_REFRESH_POS = "refresh_pos";
public const String KEY_CLOSE_AFTER_CREATE = "close_after_create";
public const String KeyEntry = "entry";
public const String KeyRefreshPos = "refresh_pos";
public const String KeyCloseAfterCreate = "close_after_create";
public static void Launch(Activity act, PwEntry pw, int pos, AppTask appTask) {
Intent i;
i = new Intent(act, typeof(EntryActivity));
Intent i = new Intent(act, typeof(EntryActivity));
i.PutExtra(KEY_ENTRY, pw.Uuid.ToHexString());
i.PutExtra(KEY_REFRESH_POS, pos);
i.PutExtra(KeyEntry, pw.Uuid.ToHexString());
i.PutExtra(KeyRefreshPos, pos);
appTask.ToIntent(i);
act.StartActivityForResult(i,0);
}
protected PwEntry mEntry;
protected PwEntry Entry;
private bool mShowPassword;
private int mPos;
private bool _showPassword;
private int _pos;
AppTask mAppTask;
AppTask _appTask;
protected void setEntryView() {
protected void SetEntryView() {
SetContentView(Resource.Layout.entry_view);
}
protected void setupEditButtons() {
protected void SetupEditButtons() {
View edit = FindViewById(Resource.Id.entry_edit);
edit.Click += (sender, e) => {
EntryEditActivity.Launch(this, mEntry,mAppTask);
EntryEditActivity.Launch(this, Entry,_appTask);
};
}
@ -91,17 +83,14 @@ namespace keepass2android
ISharedPreferencesEditor edit = prefs.Edit();
edit.PutLong(GetString(Resource.String.UsageCount_key), usageCount+1);
EditorCompat.apply(edit);
EditorCompat.Apply(edit);
mShowPassword = ! prefs.GetBoolean(GetString(Resource.String.maskpass_key), Resources.GetBoolean(Resource.Boolean.maskpass_default));
_showPassword = ! prefs.GetBoolean(GetString(Resource.String.maskpass_key), Resources.GetBoolean(Resource.Boolean.maskpass_default));
base.OnCreate(savedInstanceState);
setEntryView();
SetEntryView();
Context appCtx = ApplicationContext;
Database db = App.getDB();
Database db = App.Kp2a.GetDb();
// Likely the app has been killed exit the activity
if (! db.Loaded)
{
@ -109,77 +98,62 @@ namespace keepass2android
return;
}
SetResult(KeePass.EXIT_NORMAL);
SetResult(KeePass.ExitNormal);
Intent i = Intent;
PwUuid uuid = new PwUuid(MemUtil.HexStringToByteArray(i.GetStringExtra(KEY_ENTRY)));
mPos = i.GetIntExtra(KEY_REFRESH_POS, -1);
PwUuid uuid = new PwUuid(MemUtil.HexStringToByteArray(i.GetStringExtra(KeyEntry)));
_pos = i.GetIntExtra(KeyRefreshPos, -1);
mAppTask = AppTask.GetTaskInOnCreate(savedInstanceState, Intent);
_appTask = AppTask.GetTaskInOnCreate(savedInstanceState, Intent);
bool closeAfterCreate = mAppTask.CloseEntryActivityAfterCreate;
bool closeAfterCreate = _appTask.CloseEntryActivityAfterCreate;
mEntry = db.entries [uuid];
Entry = db.Entries [uuid];
// Refresh Menu contents in case onCreateMenuOptions was called before mEntry was set
ActivityCompat.invalidateOptionsMenu(this);
// Refresh Menu contents in case onCreateMenuOptions was called before _entry was set
ActivityCompat.InvalidateOptionsMenu(this);
// Update last access time.
mEntry.Touch(false);
Entry.Touch(false);
if (PwDefs.IsTanEntry(mEntry) && prefs.GetBoolean(GetString(Resource.String.TanExpiresOnUse_key), Resources.GetBoolean(Resource.Boolean.TanExpiresOnUse_default)) && ((mEntry.Expires == false) || mEntry.ExpiryTime > DateTime.Now))
if (PwDefs.IsTanEntry(Entry) && prefs.GetBoolean(GetString(Resource.String.TanExpiresOnUse_key), Resources.GetBoolean(Resource.Boolean.TanExpiresOnUse_default)) && ((Entry.Expires == false) || Entry.ExpiryTime > DateTime.Now))
{
PwEntry backupEntry = mEntry.CloneDeep();
mEntry.ExpiryTime = DateTime.Now;
mEntry.Expires = true;
mEntry.Touch(true);
requiresRefresh();
Handler handler = new Handler();
UpdateEntry update = new UpdateEntry(this, App.getDB(), backupEntry, mEntry, new AfterSave(handler));
ProgressTask pt = new ProgressTask(this, update, Resource.String.saving_database);
pt.run();
PwEntry backupEntry = Entry.CloneDeep();
Entry.ExpiryTime = DateTime.Now;
Entry.Expires = true;
Entry.Touch(true);
RequiresRefresh();
UpdateEntry update = new UpdateEntry(this, App.Kp2a.GetDb(), backupEntry, Entry, null);
ProgressTask pt = new ProgressTask(App.Kp2a, this, update, UiStringKey.saving_database);
pt.Run();
}
fillData(false);
FillData(false);
setupEditButtons();
SetupEditButtons();
Intent showNotIntent = new Intent(this, typeof(CopyToClipboardService));
Intent.SetAction(Intents.SHOW_NOTIFICATION);
showNotIntent.PutExtra(KEY_ENTRY, mEntry.Uuid.ToHexString());
showNotIntent.PutExtra(KEY_CLOSE_AFTER_CREATE, closeAfterCreate);
Intent.SetAction(Intents.ShowNotification);
showNotIntent.PutExtra(KeyEntry, Entry.Uuid.ToHexString());
showNotIntent.PutExtra(KeyCloseAfterCreate, closeAfterCreate);
StartService(showNotIntent);
Android.Util.Log.Debug("DEBUG", "Requesting copy to clipboard for Uuid=" + mEntry.Uuid.ToHexString());
Android.Util.Log.Debug("DEBUG", "Requesting copy to clipboard for Uuid=" + Entry.Uuid.ToHexString());
/*foreach (PwUuid key in App.getDB().entries.Keys)
/*foreach (PwUuid key in App.Kp2a.GetDb().entries.Keys)
{
Android.Util.Log.Debug("DEBUG",key.ToHexString() + " -> " + App.getDB().entries[key].Uuid.ToHexString());
Android.Util.Log.Debug("DEBUG",key.ToHexString() + " -> " + App.Kp2a.GetDb().entries[key].Uuid.ToHexString());
}*/
if (closeAfterCreate)
{
SetResult(KeePass.EXIT_CLOSE_AFTER_TASK_COMPLETE);
SetResult(KeePass.ExitCloseAfterTaskComplete);
Finish();
}
}
private class AfterSave : OnFinish {
public AfterSave(Handler handler):base(handler) {
}
public override void run() {
base.run();
}
};
private String getDateTime(System.DateTime dt) {
private String getDateTime(DateTime dt) {
return dt.ToString ("g", CultureInfo.CurrentUICulture);
}
@ -196,7 +170,7 @@ namespace keepass2android
return sb.ToString();
}
void populateExtraStrings(bool trimList)
void PopulateExtraStrings(bool trimList)
{
ViewGroup extraGroup = (ViewGroup)FindViewById(Resource.Id.extra_strings);
if (trimList)
@ -204,7 +178,7 @@ namespace keepass2android
extraGroup.RemoveAllViews();
}
bool hasExtraFields = false;
foreach (var view in from pair in mEntry.Strings where !PwDefs.IsStandardField(pair.Key) orderby pair.Key
foreach (var view in from pair in Entry.Strings where !PwDefs.IsStandardField(pair.Key) orderby pair.Key
select CreateEditSection(pair.Key, pair.Value.ReadString()))
{
//View view = new EntrySection(this, null, key, pair.Value.ReadString());
@ -216,9 +190,8 @@ namespace keepass2android
View CreateEditSection(string key, string value)
{
LinearLayout layout = new LinearLayout(this, null);
layout.Orientation = Orientation.Vertical;
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(LinearLayout.LayoutParams.FillParent, LinearLayout.LayoutParams.WrapContent);
LinearLayout layout = new LinearLayout(this, null) {Orientation = Orientation.Vertical};
LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.FillParent, ViewGroup.LayoutParams.WrapContent);
layoutParams.SetMargins(10,0,0,0);
layout.LayoutParameters = layoutParams;
View viewInflated = LayoutInflater.Inflate(Resource.Layout.entry_extrastring_title,null);
@ -232,15 +205,15 @@ namespace keepass2android
valueView.Text = value;
valueView.Typeface = Typeface.Monospace;
if ((int)Android.OS.Build.VERSION.SdkInt >= 11)
if ((int)Build.VERSION.SdkInt >= 11)
valueView.SetTextIsSelectable(true);
layout.AddView(valueView);
return layout;
}
Android.Net.Uri writeBinaryToFile(string key, bool writeToCacheDirectory)
Android.Net.Uri WriteBinaryToFile(string key, bool writeToCacheDirectory)
{
ProtectedBinary pb = mEntry.Binaries.Get(key);
ProtectedBinary pb = Entry.Binaries.Get(key);
System.Diagnostics.Debug.Assert(pb != null);
if (pb == null)
throw new ArgumentException();
@ -253,9 +226,9 @@ namespace keepass2android
string filepart = key;
if (writeToCacheDirectory)
filepart = filepart.Replace(" ", "");
var targetFile = new Java.IO.File(binaryDirectory, filepart);
var targetFile = new File(binaryDirectory, filepart);
Java.IO.File parent = targetFile.ParentFile;
File parent = targetFile.ParentFile;
if (parent == null || (parent.Exists() && ! parent.IsDirectory))
{
@ -296,29 +269,25 @@ namespace keepass2android
Toast.MakeText(this, GetString(Resource.String.SaveAttachment_doneMessage, new Java.Lang.Object[]{filename}), ToastLength.Short).Show();
if (writeToCacheDirectory)
{
return Android.Net.Uri.Parse("content://" + AttachmentContentProvider.AUTHORITY + "/"
return Android.Net.Uri.Parse("content://" + AttachmentContentProvider.Authority + "/"
+ filename);
}
else
{
return fileUri;
}
}
void openBinaryFile(Android.Net.Uri uri)
void OpenBinaryFile(Android.Net.Uri uri)
{
String theMIMEType = getMimeType(uri.Path);
if (theMIMEType != null)
String theMimeType = GetMimeType(uri.Path);
if (theMimeType != null)
{
Intent theIntent = new Intent(Intent.ActionView);
theIntent.AddFlags(ActivityFlags.NewTask | ActivityFlags.ExcludeFromRecents);
theIntent.SetDataAndType(uri, theMIMEType);
theIntent.SetDataAndType(uri, theMimeType);
try
{
StartActivity(theIntent);
}
catch (ActivityNotFoundException anfe)
catch (ActivityNotFoundException)
{
//ignore
Toast.MakeText(this, "Couldn't open file", ToastLength.Short).Show();
@ -326,21 +295,21 @@ namespace keepass2android
}
}
void populateBinaries(bool trimList)
void PopulateBinaries(bool trimList)
{
ViewGroup binariesGroup = (ViewGroup)FindViewById(Resource.Id.binaries);
if (trimList)
{
binariesGroup.RemoveAllViews();
}
foreach (KeyValuePair<string, ProtectedBinary> pair in mEntry.Binaries)
foreach (KeyValuePair<string, ProtectedBinary> pair in Entry.Binaries)
{
String key = pair.Key;
Button binaryButton = new Button(this);
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.FillParent, RelativeLayout.LayoutParams.WrapContent);
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.FillParent, ViewGroup.LayoutParams.WrapContent);
binaryButton.Text = key;
binaryButton.SetCompoundDrawablesWithIntrinsicBounds( Resources.GetDrawable(Android.Resource.Drawable.IcMenuSave),null, null, null);
binaryButton.Click += (object sender, EventArgs e) =>
binaryButton.Click += (sender, e) =>
{
Button btnSender = (Button)(sender);
@ -349,19 +318,19 @@ namespace keepass2android
builder.SetMessage(GetString(Resource.String.SaveAttachmentDialog_text));
builder.SetPositiveButton(GetString(Resource.String.SaveAttachmentDialog_save), new EventHandler<DialogClickEventArgs>((dlgSender, dlgEvt) =>
builder.SetPositiveButton(GetString(Resource.String.SaveAttachmentDialog_save), (dlgSender, dlgEvt) =>
{
writeBinaryToFile(btnSender.Text, false);
}));
WriteBinaryToFile(btnSender.Text, false);
});
builder.SetNegativeButton(GetString(Resource.String.SaveAttachmentDialog_open), new EventHandler<DialogClickEventArgs>((dlgSender, dlgEvt) =>
builder.SetNegativeButton(GetString(Resource.String.SaveAttachmentDialog_open), (dlgSender, dlgEvt) =>
{
Android.Net.Uri newUri = writeBinaryToFile(btnSender.Text, true);
Android.Net.Uri newUri = WriteBinaryToFile(btnSender.Text, true);
if (newUri != null)
{
openBinaryFile(newUri);
OpenBinaryFile(newUri);
}
}));
});
Dialog dialog = builder.Create();
dialog.Show();
@ -372,11 +341,11 @@ namespace keepass2android
}
FindViewById(Resource.Id.entry_binaries_label).Visibility = mEntry.Binaries.UCount > 0 ? ViewStates.Visible : ViewStates.Gone;
FindViewById(Resource.Id.entry_binaries_label).Visibility = Entry.Binaries.UCount > 0 ? ViewStates.Visible : ViewStates.Gone;
}
// url = file path or whatever suitable URL you want.
public static String getMimeType(String url)
public static String GetMimeType(String url)
{
String type = null;
String extension = MimeTypeMap.GetFileExtensionFromUrl(url);
@ -393,58 +362,58 @@ namespace keepass2android
OverridePendingTransition(Resource.Animation.anim_enter_back, Resource.Animation.anim_leave_back);
}
protected void fillData(bool trimList)
protected void FillData(bool trimList)
{
ImageView iv = (ImageView)FindViewById(Resource.Id.entry_icon);
if (iv != null)
{
App.getDB().drawFactory.assignDrawableTo(iv, Resources, App.getDB().pm, mEntry.IconId, mEntry.CustomIconUuid);
App.Kp2a.GetDb().DrawableFactory.AssignDrawableTo(iv, Resources, App.Kp2a.GetDb().KpDatabase, Entry.IconId, Entry.CustomIconUuid);
}
//populateText(Resource.Id.entry_title, mEntry.Strings.ReadSafe(PwDefs.TitleField));
//populateText(Resource.Id.entry_title, _entry.Strings.ReadSafe(PwDefs.TitleField));
var button = ((Button)FindViewById(Resource.Id.entry_title));
if (button != null)
{
button.Text = mEntry.Strings.ReadSafe(PwDefs.TitleField);
button.Click += (object sender, EventArgs e) => {
button.Text = Entry.Strings.ReadSafe(PwDefs.TitleField);
button.Click += (sender, e) => {
Finish(); };
}
if (Util.HasActionBar(this))
{
ActionBar.Title = mEntry.Strings.ReadSafe(PwDefs.TitleField);
ActionBar.Title = Entry.Strings.ReadSafe(PwDefs.TitleField);
ActionBar.SetDisplayHomeAsUpEnabled(true);
}
populateText(Resource.Id.entry_user_name, Resource.Id.entry_user_name_label, mEntry.Strings.ReadSafe(PwDefs.UserNameField));
PopulateText(Resource.Id.entry_user_name, Resource.Id.entry_user_name_label, Entry.Strings.ReadSafe(PwDefs.UserNameField));
populateText(Resource.Id.entry_url, Resource.Id.entry_url_label, mEntry.Strings.ReadSafe(PwDefs.UrlField));
populateText(Resource.Id.entry_password, Resource.Id.entry_password_label, mEntry.Strings.ReadSafe(PwDefs.PasswordField));
setPasswordStyle();
PopulateText(Resource.Id.entry_url, Resource.Id.entry_url_label, Entry.Strings.ReadSafe(PwDefs.UrlField));
PopulateText(Resource.Id.entry_password, Resource.Id.entry_password_label, Entry.Strings.ReadSafe(PwDefs.PasswordField));
SetPasswordStyle();
populateText(Resource.Id.entry_created, Resource.Id.entry_created_label, getDateTime(mEntry.CreationTime));
populateText(Resource.Id.entry_modified, Resource.Id.entry_modified_label, getDateTime(mEntry.LastModificationTime));
populateText(Resource.Id.entry_accessed, Resource.Id.entry_accessed_label, getDateTime(mEntry.LastAccessTime));
PopulateText(Resource.Id.entry_created, Resource.Id.entry_created_label, getDateTime(Entry.CreationTime));
PopulateText(Resource.Id.entry_modified, Resource.Id.entry_modified_label, getDateTime(Entry.LastModificationTime));
PopulateText(Resource.Id.entry_accessed, Resource.Id.entry_accessed_label, getDateTime(Entry.LastAccessTime));
if (mEntry.Expires)
if (Entry.Expires)
{
populateText(Resource.Id.entry_expires, Resource.Id.entry_expires_label, getDateTime(mEntry.ExpiryTime));
PopulateText(Resource.Id.entry_expires, Resource.Id.entry_expires_label, getDateTime(Entry.ExpiryTime));
} else
{
populateText(Resource.Id.entry_expires, Resource.Id.entry_expires_label, Resource.String.never);
PopulateText(Resource.Id.entry_expires, Resource.Id.entry_expires_label, Resource.String.never);
}
populateText(Resource.Id.entry_comment, Resource.Id.entry_comment_label, mEntry.Strings.ReadSafe(PwDefs.NotesField));
PopulateText(Resource.Id.entry_comment, Resource.Id.entry_comment_label, Entry.Strings.ReadSafe(PwDefs.NotesField));
populateText(Resource.Id.entry_tags, Resource.Id.entry_tags_label, concatTags(mEntry.Tags));
PopulateText(Resource.Id.entry_tags, Resource.Id.entry_tags_label, concatTags(Entry.Tags));
populateText(Resource.Id.entry_override_url, Resource.Id.entry_override_url_label, mEntry.OverrideUrl);
PopulateText(Resource.Id.entry_override_url, Resource.Id.entry_override_url_label, Entry.OverrideUrl);
populateExtraStrings(trimList);
PopulateExtraStrings(trimList);
populateBinaries(trimList);
PopulateBinaries(trimList);
}
private void populateText(int viewId, int headerViewId,int resId) {
private void PopulateText(int viewId, int headerViewId,int resId) {
View header = FindViewById(headerViewId);
TextView tv = (TextView)FindViewById(viewId);
@ -452,7 +421,7 @@ namespace keepass2android
tv.SetText (resId);
}
private void populateText(int viewId, int headerViewId, String text)
private void PopulateText(int viewId, int headerViewId, String text)
{
View header = FindViewById(headerViewId);
TextView tv = (TextView)FindViewById(viewId);
@ -468,19 +437,19 @@ namespace keepass2android
}
}
void requiresRefresh ()
void RequiresRefresh ()
{
Intent ret = new Intent ();
ret.PutExtra (KEY_REFRESH_POS, mPos);
SetResult (KeePass.EXIT_REFRESH, ret);
ret.PutExtra (KeyRefreshPos, _pos);
SetResult (KeePass.ExitRefresh, ret);
}
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data) {
base.OnActivityResult(requestCode, resultCode, data);
if ( resultCode == KeePass.EXIT_REFRESH || resultCode == KeePass.EXIT_REFRESH_TITLE ) {
fillData(true);
if ( resultCode == KeePass.EXIT_REFRESH_TITLE ) {
requiresRefresh ();
if ( resultCode == KeePass.ExitRefresh || resultCode == KeePass.ExitRefreshTitle ) {
FillData(true);
if ( resultCode == KeePass.ExitRefreshTitle ) {
RequiresRefresh ();
}
}
}
@ -492,7 +461,7 @@ namespace keepass2android
inflater.Inflate(Resource.Menu.entry, menu);
IMenuItem togglePassword = menu.FindItem(Resource.Id.menu_toggle_pass);
if ( mShowPassword ) {
if ( _showPassword ) {
togglePassword.SetTitle(Resource.String.menu_hide_password);
} else {
togglePassword.SetTitle(Resource.String.show_password);
@ -503,23 +472,23 @@ namespace keepass2android
//Disabled IMenuItem copyPass = menu.FindItem(Resource.Id.menu_copy_pass);
// In API >= 11 onCreateOptionsMenu may be called before onCreate completes
// so mEntry may not be set
if (mEntry == null) {
// so _entry may not be set
if (Entry == null) {
gotoUrl.SetVisible(false);
//Disabled copyUser.SetVisible(false);
//Disabled copyPass.SetVisible(false);
}
else {
String url = mEntry.Strings.ReadSafe (PwDefs.UrlField);
String url = Entry.Strings.ReadSafe (PwDefs.UrlField);
if (String.IsNullOrEmpty(url)) {
// disable button if url is not available
gotoUrl.SetVisible(false);
}
if ( String.IsNullOrEmpty(mEntry.Strings.ReadSafe(PwDefs.UserNameField ))) {
if ( String.IsNullOrEmpty(Entry.Strings.ReadSafe(PwDefs.UserNameField ))) {
// disable button if username is not available
//Disabled copyUser.SetVisible(false);
}
if ( String.IsNullOrEmpty(mEntry.Strings.ReadSafe(PwDefs.PasswordField ))) {
if ( String.IsNullOrEmpty(Entry.Strings.ReadSafe(PwDefs.PasswordField ))) {
// disable button if password is not available
//Disabled copyPass.SetVisible(false);
}
@ -527,10 +496,10 @@ namespace keepass2android
return true;
}
private void setPasswordStyle() {
private void SetPasswordStyle() {
TextView password = (TextView) FindViewById(Resource.Id.entry_password);
if ( mShowPassword ) {
if ( _showPassword ) {
password.TransformationMethod = null;
} else {
password.TransformationMethod = PasswordTransformationMethod.Instance;
@ -546,18 +515,18 @@ namespace keepass2android
try {
File dir = CacheDir;
if (dir != null && dir.IsDirectory) {
deleteDir(dir);
DeleteDir(dir);
}
} catch (Exception e) {
} catch (Exception) {
}
}
public static bool deleteDir(File dir) {
public static bool DeleteDir(File dir) {
if (dir != null && dir.IsDirectory) {
String[] children = dir.List();
for (int i = 0; i < children.Length; i++) {
bool success = deleteDir(new File(dir, children[i]));
bool success = DeleteDir(new File(dir, children[i]));
if (!success) {
return false;
}
@ -580,20 +549,19 @@ namespace keepass2android
return true;
case Resource.Id.menu_toggle_pass:
if ( mShowPassword ) {
if ( _showPassword ) {
item.SetTitle(Resource.String.show_password);
mShowPassword = false;
_showPassword = false;
} else {
item.SetTitle(Resource.String.menu_hide_password);
mShowPassword = true;
_showPassword = true;
}
setPasswordStyle();
SetPasswordStyle();
return true;
case Resource.Id.menu_goto_url:
String url;
url = mEntry.Strings.ReadSafe (PwDefs.UrlField);
string url = Entry.Strings.ReadSafe (PwDefs.UrlField);
// Default http:// if no protocol specified
if ( ! url.Contains("://") ) {
@ -608,11 +576,11 @@ namespace keepass2android
return true;
/* TODO: required?
case Resource.Id.menu_copy_user:
timeoutCopyToClipboard(mEntry.Strings.ReadSafe (PwDefs.UserNameField));
timeoutCopyToClipboard(_entry.Strings.ReadSafe (PwDefs.UserNameField));
return true;
case Resource.Id.menu_copy_pass:
timeoutCopyToClipboard(mEntry.Strings.ReadSafe (PwDefs.UserNameField));
timeoutCopyToClipboard(_entry.Strings.ReadSafe (PwDefs.UserNameField));
return true;
*/
case Resource.Id.menu_rate:
@ -630,8 +598,8 @@ namespace keepass2android
}
return true;
case Resource.Id.menu_lock:
App.setShutdown();
SetResult(KeePass.EXIT_LOCK);
App.Kp2a.SetShutdown();
SetResult(KeePass.ExitLock);
Finish();
return true;
case Resource.Id.menu_translate:

View File

@ -17,13 +17,9 @@ 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 Android.Preferences;
@ -32,7 +28,6 @@ using KeePassLib;
using Android.Text;
using KeePassLib.Security;
using Android.Content.PM;
using keepass2android.view;
using System.IO;
using System.Globalization;
@ -40,23 +35,23 @@ namespace keepass2android
{
[Activity (Label = "@string/app_name", ConfigurationChanges=ConfigChanges.Orientation|ConfigChanges.KeyboardHidden, Theme="@style/NoTitleBar")]
public class EntryEditActivity : LockCloseActivity {
public const String KEY_ENTRY = "entry";
public const String KEY_PARENT = "parent";
public const String KeyEntry = "entry";
public const String KeyParent = "parent";
public const int RESULT_OK_ICON_PICKER = (int)Result.FirstUser + 1000;
public const int RESULT_OK_PASSWORD_GENERATOR = RESULT_OK_ICON_PICKER + 1;
public const int ResultOkIconPicker = (int)Result.FirstUser + 1000;
public const int ResultOkPasswordGenerator = ResultOkIconPicker + 1;
const string Intent_ContinueWithEditing = "ContinueWithEditing";
const string IntentContinueWithEditing = "ContinueWithEditing";
EntryEditActivityState State
{
get { return App.entryEditActivityState; }
get { return App.Kp2a.EntryEditActivityState; }
}
public static void Launch(Activity act, PwEntry pw, AppTask appTask) {
Intent i = new Intent(act, typeof(EntryEditActivity));
i.PutExtra(KEY_ENTRY, pw.Uuid.ToHexString());
i.PutExtra(KeyEntry, pw.Uuid.ToHexString());
appTask.ToIntent(i);
@ -67,38 +62,36 @@ namespace keepass2android
Intent i = new Intent(act, typeof(EntryEditActivity));
PwGroup parent = pw;
i.PutExtra(KEY_PARENT, parent.Uuid.ToHexString());
i.PutExtra(KeyParent, parent.Uuid.ToHexString());
appTask.ToIntent(i);
act.StartActivityForResult(i, 0);
}
private ScrollView scroll;
bool _closeForReload;
bool mCloseForReload;
AppTask mAppTask;
AppTask _appTask;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
if (this.LastNonConfigurationInstance != null)
if (LastNonConfigurationInstance != null)
{
//bug in Mono for Android or whatever: after config change the extra fields are wrong
// -> reload:
reload();
Reload();
return;
}
mAppTask = AppTask.GetTaskInOnCreate(savedInstanceState, Intent);
_appTask = AppTask.GetTaskInOnCreate(savedInstanceState, Intent);
SetContentView(Resource.Layout.entry_edit);
mCloseForReload = false;
_closeForReload = false;
// Likely the app has been killed exit the activity
Database db = App.getDB();
Database db = App.Kp2a.GetDb();
if (! db.Open)
{
Finish();
@ -106,34 +99,34 @@ namespace keepass2android
}
if (Intent.GetBooleanExtra(Intent_ContinueWithEditing, false))
if (Intent.GetBooleanExtra(IntentContinueWithEditing, false))
{
//property "State" will return the state
} else
{
App.entryEditActivityState = new EntryEditActivityState();
App.Kp2a.EntryEditActivityState = new EntryEditActivityState();
ISharedPreferences prefs = PreferenceManager.GetDefaultSharedPreferences(this);
State.mShowPassword = ! prefs.GetBoolean(GetString(Resource.String.maskpass_key), Resources.GetBoolean(Resource.Boolean.maskpass_default));
State.ShowPassword = ! prefs.GetBoolean(GetString(Resource.String.maskpass_key), Resources.GetBoolean(Resource.Boolean.maskpass_default));
Intent i = Intent;
String uuidBytes = i.GetStringExtra(KEY_ENTRY);
String uuidBytes = i.GetStringExtra(KeyEntry);
PwUuid entryId = PwUuid.Zero;
if (uuidBytes != null)
entryId = new KeePassLib.PwUuid(MemUtil.HexStringToByteArray(uuidBytes));
entryId = new PwUuid(MemUtil.HexStringToByteArray(uuidBytes));
State.parentGroup = null;
State.ParentGroup = null;
if (entryId.EqualsValue(PwUuid.Zero))
{
String groupId = i.GetStringExtra(KEY_PARENT);
String groupId = i.GetStringExtra(KeyParent);
State.parentGroup = db.groups [new PwUuid(MemUtil.HexStringToByteArray(groupId))];
State.ParentGroup = db.Groups [new PwUuid(MemUtil.HexStringToByteArray(groupId))];
State.mEntryInDatabase = new PwEntry(true, true);
State.mEntryInDatabase.Strings.Set(PwDefs.UserNameField, new ProtectedString(
db.pm.MemoryProtection.ProtectUserName, db.pm.DefaultUserName));
State.EntryInDatabase = new PwEntry(true, true);
State.EntryInDatabase.Strings.Set(PwDefs.UserNameField, new ProtectedString(
db.KpDatabase.MemoryProtection.ProtectUserName, db.KpDatabase.DefaultUserName));
/*KPDesktop
* ProtectedString psAutoGen;
@ -149,12 +142,12 @@ namespace keepass2android
pwe.ExpiryTime = DateTime.Now.AddDays(nExpireDays);
}*/
if ((State.parentGroup.IconId != PwIcon.Folder) && (State.parentGroup.IconId != PwIcon.FolderOpen) &&
(State.parentGroup.IconId != PwIcon.FolderPackage))
if ((State.ParentGroup.IconId != PwIcon.Folder) && (State.ParentGroup.IconId != PwIcon.FolderOpen) &&
(State.ParentGroup.IconId != PwIcon.FolderPackage))
{
State.mEntryInDatabase.IconId = State.parentGroup.IconId; // Inherit icon from group
State.EntryInDatabase.IconId = State.ParentGroup.IconId; // Inherit icon from group
}
State.mEntryInDatabase.CustomIconUuid = State.parentGroup.CustomIconUuid;
State.EntryInDatabase.CustomIconUuid = State.ParentGroup.CustomIconUuid;
/*
* KPDesktop
@ -174,52 +167,52 @@ namespace keepass2android
}
}
}*/
mAppTask.PrepareNewEntry(State.mEntryInDatabase);
State.mIsNew = true;
State.mEntryModified = true;
_appTask.PrepareNewEntry(State.EntryInDatabase);
State.IsNew = true;
State.EntryModified = true;
} else
{
System.Diagnostics.Debug.Assert(entryId != null);
State.mEntryInDatabase = db.entries [entryId];
State.mIsNew = false;
State.EntryInDatabase = db.Entries [entryId];
State.IsNew = false;
}
State.mEntry = State.mEntryInDatabase.CloneDeep();
State.Entry = State.EntryInDatabase.CloneDeep();
}
if (!State.mEntryModified)
SetResult(KeePass.EXIT_NORMAL);
if (!State.EntryModified)
SetResult(KeePass.ExitNormal);
else
SetResult(KeePass.EXIT_REFRESH_TITLE);
SetResult(KeePass.ExitRefreshTitle);
fillData();
FillData();
View scrollView = FindViewById(Resource.Id.entry_scroll);
scrollView.ScrollBarStyle = ScrollbarStyles.InsideInset;
ImageButton iconButton = (ImageButton)FindViewById(Resource.Id.icon_button);
if (State.mSelectedIcon)
if (State.SelectedIcon)
{
//TODO: custom image
iconButton.SetImageResource(Icons.iconToResId(State.mSelectedIconID));
iconButton.SetImageResource(Icons.IconToResId(State.SelectedIconId));
}
iconButton.Click += (sender, evt) => {
UpdateEntryFromUi(State.mEntry);
UpdateEntryFromUi(State.Entry);
IconPickerActivity.Launch(this);
};
// Generate password button
Button generatePassword = (Button)FindViewById(Resource.Id.generate_button);
generatePassword.Click += (object sender, EventArgs e) => {
UpdateEntryFromUi(State.mEntry);
generatePassword.Click += (sender, e) => {
UpdateEntryFromUi(State.Entry);
GeneratePasswordActivity.Launch(this);
};
@ -241,14 +234,14 @@ namespace keepass2android
save = FindViewById(Resource.Id.entry_save);
}
save.Click += (object sender, EventArgs e) =>
save.Click += (sender, e) =>
{
SaveEntry();
};
// Respect mask password setting
if (State.mShowPassword) {
if (State.ShowPassword) {
EditText pass = (EditText) FindViewById(Resource.Id.entry_password);
EditText conf = (EditText) FindViewById(Resource.Id.entry_confpassword);
@ -256,11 +249,9 @@ namespace keepass2android
conf.InputType = InputTypes.ClassText | InputTypes.TextVariationVisiblePassword;
}
scroll = (ScrollView) FindViewById(Resource.Id.entry_scroll);
Button addButton = (Button) FindViewById(Resource.Id.add_advanced);
addButton.Visibility = ViewStates.Visible;
addButton.Click += (object sender, EventArgs e) =>
addButton.Click += (sender, e) =>
{
LinearLayout container = (LinearLayout) FindViewById(Resource.Id.advanced_container);
@ -268,7 +259,7 @@ namespace keepass2android
LinearLayout ees = CreateExtraStringView(pair);
container.AddView(ees);
State.mEntryModified = true;
State.EntryModified = true;
TextView keyView = (TextView) ees.FindViewById(Resource.Id.title);
keyView.RequestFocus();
@ -276,16 +267,16 @@ namespace keepass2android
};
((CheckBox)FindViewById(Resource.Id.entry_expires_checkbox)).CheckedChange += (object sender, CompoundButton.CheckedChangeEventArgs e) =>
((CheckBox)FindViewById(Resource.Id.entry_expires_checkbox)).CheckedChange += (sender, e) =>
{
State.mEntry.Expires = e.IsChecked;
State.Entry.Expires = e.IsChecked;
if (e.IsChecked)
{
if (State.mEntry.ExpiryTime < DateTime.Now)
State.mEntry.ExpiryTime = DateTime.Now;
if (State.Entry.ExpiryTime < DateTime.Now)
State.Entry.ExpiryTime = DateTime.Now;
}
updateExpires();
State.mEntryModified = true;
UpdateExpires();
State.EntryModified = true;
};
@ -293,33 +284,33 @@ namespace keepass2android
void SaveEntry()
{
Database db = App.getDB();
Database db = App.Kp2a.GetDb();
EntryEditActivity act = this;
if (!validateBeforeSaving())
if (!ValidateBeforeSaving())
return;
PwEntry initialEntry = State.mEntryInDatabase.CloneDeep();
PwEntry initialEntry = State.EntryInDatabase.CloneDeep();
PwEntry newEntry = State.mEntryInDatabase;
PwEntry newEntry = State.EntryInDatabase;
//Clone history and re-assign:
newEntry.History = newEntry.History.CloneDeep();
//Based on KeePass Desktop
bool bCreateBackup = (!State.mIsNew);
bool bCreateBackup = (!State.IsNew);
if(bCreateBackup) newEntry.CreateBackup(null);
if (State.mSelectedIcon == false) {
if (State.mIsNew) {
if (State.SelectedIcon == false) {
if (State.IsNew) {
newEntry.IconId = PwIcon.Key;
} else {
// Keep previous icon, if no new one was selected
}
}
else {
newEntry.IconId = State.mSelectedIconID;
newEntry.CustomIconUuid = State.mSelectedCustomIconID;
newEntry.IconId = State.SelectedIconId;
newEntry.CustomIconUuid = State.SelectedCustomIconId;
}
/* KPDesktop
if(m_cbCustomForegroundColor.Checked)
@ -332,11 +323,11 @@ namespace keepass2android
*/
UpdateEntryFromUi(newEntry);
newEntry.Binaries = State.mEntry.Binaries;
newEntry.Expires = State.mEntry.Expires;
newEntry.Binaries = State.Entry.Binaries;
newEntry.Expires = State.Entry.Expires;
if (newEntry.Expires)
{
newEntry.ExpiryTime = State.mEntry.ExpiryTime;
newEntry.ExpiryTime = State.Entry.ExpiryTime;
}
@ -358,19 +349,19 @@ namespace keepass2android
{
// If only history items have been modified (deleted) => undo
// backup, but without restoring the last mod time
PwCompareOptions cmpOptNH = (cmpOpt | PwCompareOptions.IgnoreHistory);
if(newEntry.EqualsEntry(initialEntry, cmpOptNH, MemProtCmpMode.CustomOnly))
PwCompareOptions cmpOptNh = (cmpOpt | PwCompareOptions.IgnoreHistory);
if(newEntry.EqualsEntry(initialEntry, cmpOptNh, MemProtCmpMode.CustomOnly))
bUndoBackup = true;
}
if(bUndoBackup) newEntry.History.RemoveAt(newEntry.History.UCount - 1);
newEntry.MaintainBackups(db.pm);
newEntry.MaintainBackups(db.KpDatabase);
//if ( newEntry.Strings.ReadSafe (PwDefs.TitleField).Equals(State.mEntry.Strings.ReadSafe (PwDefs.TitleField)) ) {
//if ( newEntry.Strings.ReadSafe (PwDefs.TitleField).Equals(State.Entry.Strings.ReadSafe (PwDefs.TitleField)) ) {
// SetResult(KeePass.EXIT_REFRESH);
//} else {
//it's safer to always update the title as we might add further information in the title like expiry etc.
SetResult(KeePass.EXIT_REFRESH_TITLE);
SetResult(KeePass.ExitRefreshTitle);
//}
RunnableOnFinish runnable;
@ -381,57 +372,57 @@ namespace keepass2android
Finish();
} else
{
OnFinish.displayMessage(this, message);
OnFinish.DisplayMessage(this, message);
}
});
ActionOnFinish afterAddEntry = new ActionOnFinish((success, message) =>
{
if (success)
mAppTask.AfterAddNewEntry(this, newEntry);
_appTask.AfterAddNewEntry(this, newEntry);
},closeOrShowError);
if ( State.mIsNew ) {
runnable = AddEntry.getInstance(this, App.getDB(), newEntry, State.parentGroup, afterAddEntry);
if ( State.IsNew ) {
runnable = AddEntry.GetInstance(this, App.Kp2a.GetDb(), newEntry, State.ParentGroup, afterAddEntry);
} else {
runnable = new UpdateEntry(this, App.getDB(), initialEntry, newEntry, closeOrShowError);
runnable = new UpdateEntry(this, App.Kp2a.GetDb(), initialEntry, newEntry, closeOrShowError);
}
ProgressTask pt = new ProgressTask(act, runnable, Resource.String.saving_database);
pt.run();
ProgressTask pt = new ProgressTask(App.Kp2a, act, runnable, UiStringKey.saving_database);
pt.Run();
}
void UpdateEntryFromUi(PwEntry entry)
{
Database db = App.getDB();
Database db = App.Kp2a.GetDb();
EntryEditActivity act = this;
entry.Strings.Set(PwDefs.TitleField, new ProtectedString(db.pm.MemoryProtection.ProtectTitle,
entry.Strings.Set(PwDefs.TitleField, new ProtectedString(db.KpDatabase.MemoryProtection.ProtectTitle,
Util.getEditText(act, Resource.Id.entry_title)));
entry.Strings.Set(PwDefs.UserNameField, new ProtectedString(db.pm.MemoryProtection.ProtectUserName,
entry.Strings.Set(PwDefs.UserNameField, new ProtectedString(db.KpDatabase.MemoryProtection.ProtectUserName,
Util.getEditText(act, Resource.Id.entry_user_name)));
String pass = Util.getEditText(act, Resource.Id.entry_password);
byte[] password = StrUtil.Utf8.GetBytes(pass);
entry.Strings.Set(PwDefs.PasswordField, new ProtectedString(db.pm.MemoryProtection.ProtectPassword,
entry.Strings.Set(PwDefs.PasswordField, new ProtectedString(db.KpDatabase.MemoryProtection.ProtectPassword,
password));
MemUtil.ZeroByteArray(password);
entry.Strings.Set(PwDefs.UrlField, new ProtectedString(db.pm.MemoryProtection.ProtectUrl,
entry.Strings.Set(PwDefs.UrlField, new ProtectedString(db.KpDatabase.MemoryProtection.ProtectUrl,
Util.getEditText(act, Resource.Id.entry_url)));
entry.Strings.Set(PwDefs.NotesField, new ProtectedString(db.pm.MemoryProtection.ProtectNotes,
entry.Strings.Set(PwDefs.NotesField, new ProtectedString(db.KpDatabase.MemoryProtection.ProtectNotes,
Util.getEditText(act, Resource.Id.entry_comment)));
// Validate expiry date
DateTime newExpiry = new DateTime();
if ((State.mEntry.Expires) && (!DateTime.TryParse( Util.getEditText(this,Resource.Id.entry_expires), out newExpiry)))
if ((State.Entry.Expires) && (!DateTime.TryParse( Util.getEditText(this,Resource.Id.entry_expires), out newExpiry)))
{
//ignore here
}
else
{
State.mEntry.ExpiryTime = newExpiry;
State.Entry.ExpiryTime = newExpiry;
}
// Delete all non standard strings
@ -456,7 +447,7 @@ namespace keepass2android
bool protect = true;
ProtectedString initialString = State.mEntryInDatabase.Strings.Get(key);
ProtectedString initialString = State.EntryInDatabase.Strings.Get(key);
if (initialString != null)
protect = initialString.IsProtected;
entry.Strings.Set(key, new ProtectedString(protect, value));
@ -484,39 +475,39 @@ namespace keepass2android
}
void addBinaryOrAsk(string filename)
void AddBinaryOrAsk(string filename)
{
string strItem = UrlUtil.GetFileName(filename);
if(State.mEntry.Binaries.Get(strItem) != null)
if(State.Entry.Binaries.Get(strItem) != null)
{
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.SetTitle(GetString(Resource.String.AskOverwriteBinary_title));
builder.SetMessage(GetString(Resource.String.AskOverwriteBinary));
builder.SetPositiveButton(GetString(Resource.String.AskOverwriteBinary_yes), new EventHandler<DialogClickEventArgs>((dlgSender, dlgEvt) =>
builder.SetPositiveButton(GetString(Resource.String.AskOverwriteBinary_yes), (dlgSender, dlgEvt) =>
{
addBinary(filename, true);
}));
AddBinary(filename, true);
});
builder.SetNegativeButton(GetString(Resource.String.AskOverwriteBinary_no), new EventHandler<DialogClickEventArgs>((dlgSender, dlgEvt) =>
builder.SetNegativeButton(GetString(Resource.String.AskOverwriteBinary_no), (dlgSender, dlgEvt) =>
{
addBinary(filename, false);
}));
AddBinary(filename, false);
});
builder.SetNeutralButton(GetString(Android.Resource.String.Cancel),
new EventHandler<DialogClickEventArgs>((dlgSender, dlgEvt) => {}));
(dlgSender, dlgEvt) => {});
Dialog dialog = builder.Create();
dialog.Show();
} else
addBinary(filename, true);
AddBinary(filename, true);
}
void addBinary(string filename, bool overwrite)
void AddBinary(string filename, bool overwrite)
{
string strItem = UrlUtil.GetFileName(filename);
@ -528,8 +519,8 @@ namespace keepass2android
int nTry = 0;
while(true)
{
string strNewName = strFileName + nTry.ToString() + strExtension;
if(State.mEntry.Binaries.Get(strNewName) == null)
string strNewName = strFileName + nTry.ToString(CultureInfo.InvariantCulture) + strExtension;
if(State.Entry.Binaries.Get(strNewName) == null)
{
strItem = strNewName;
break;
@ -541,29 +532,26 @@ namespace keepass2android
try
{
byte[] vBytes = File.ReadAllBytes(filename);
if(vBytes != null)
{
ProtectedBinary pb = new ProtectedBinary(false, vBytes);
State.mEntry.Binaries.Set(strItem, pb);
}
State.Entry.Binaries.Set(strItem, pb);
}
catch(Exception exAttach)
{
Toast.MakeText(this, GetString(Resource.String.AttachFailed)+" "+exAttach.Message, ToastLength.Long).Show();
}
State.mEntryModified = true;
populateBinaries();
State.EntryModified = true;
PopulateBinaries();
}
protected override void OnSaveInstanceState(Bundle outState)
{
base.OnSaveInstanceState(outState);
mAppTask.ToBundle(outState);
_appTask.ToBundle(outState);
}
public override void OnBackPressed()
{
if (State.mEntryModified == false)
if (State.EntryModified == false)
{
base.OnBackPressed();
} else
@ -573,16 +561,16 @@ namespace keepass2android
builder.SetMessage(GetString(Resource.String.AskDiscardChanges));
builder.SetPositiveButton(GetString(Android.Resource.String.Yes), new EventHandler<DialogClickEventArgs>((dlgSender, dlgEvt) =>
builder.SetPositiveButton(GetString(Android.Resource.String.Yes), (dlgSender, dlgEvt) =>
{
Finish();
}));
});
builder.SetNegativeButton(GetString(Android.Resource.String.No), new EventHandler<DialogClickEventArgs>((dlgSender, dlgEvt) =>
builder.SetNegativeButton(GetString(Android.Resource.String.No), (dlgSender, dlgEvt) =>
{
}));
});
Dialog dialog = builder.Create();
@ -591,15 +579,15 @@ namespace keepass2android
}
public void reload() {
public void Reload() {
//this reload ìs necessary to overcome a strange problem with the extra string fields which get lost
//somehow after re-creating the activity. Maybe a Mono for Android bug?
Intent intent = Intent;
intent.PutExtra(Intent_ContinueWithEditing, true);
intent.PutExtra(IntentContinueWithEditing, true);
OverridePendingTransition(0, 0);
intent.AddFlags(ActivityFlags.NoAnimation);
mCloseForReload = true;
SetResult(KeePass.EXIT_REFRESH_TITLE); //probably the entry will be modified -> let the EditActivity refresh to be safe
_closeForReload = true;
SetResult(KeePass.ExitRefreshTitle); //probably the entry will be modified -> let the EditActivity refresh to be safe
Finish();
OverridePendingTransition(0, 0);
@ -610,30 +598,30 @@ namespace keepass2android
{
switch ((int)resultCode)
{
case RESULT_OK_ICON_PICKER:
State.mSelectedIconID = (PwIcon) data.Extras.GetInt(IconPickerActivity.KEY_ICON_ID);
State.mSelectedCustomIconID = PwUuid.Zero;
String customIconIdString = data.Extras.GetString(IconPickerActivity.KEY_CUSTOM_ICON_ID);
case ResultOkIconPicker:
State.SelectedIconId = (PwIcon) data.Extras.GetInt(IconPickerActivity.KeyIconId);
State.SelectedCustomIconId = PwUuid.Zero;
String customIconIdString = data.Extras.GetString(IconPickerActivity.KeyCustomIconId);
if (!String.IsNullOrEmpty(customIconIdString))
State.mSelectedCustomIconID = new PwUuid(MemUtil.HexStringToByteArray(customIconIdString));
State.mSelectedIcon = true;
State.mEntryModified = true;
reload();
State.SelectedCustomIconId = new PwUuid(MemUtil.HexStringToByteArray(customIconIdString));
State.SelectedIcon = true;
State.EntryModified = true;
Reload();
break;
case RESULT_OK_PASSWORD_GENERATOR:
case ResultOkPasswordGenerator:
String generatedPassword = data.GetStringExtra("keepass2android.password.generated_password");
byte[] password = StrUtil.Utf8.GetBytes(generatedPassword);
State.mEntry.Strings.Set(PwDefs.PasswordField, new ProtectedString(App.getDB().pm.MemoryProtection.ProtectPassword,
State.Entry.Strings.Set(PwDefs.PasswordField, new ProtectedString(App.Kp2a.GetDb().KpDatabase.MemoryProtection.ProtectPassword,
password));
MemUtil.ZeroByteArray(password);
State.mEntryModified = true;
reload();
State.EntryModified = true;
Reload();
break;
case (int)Result.Ok:
if (requestCode == Intents.REQUEST_CODE_FILE_BROWSE_FOR_BINARY)
if (requestCode == Intents.RequestCodeFileBrowseForBinary)
{
string filename = Util.IntentToFilename(data);
if (filename != null) {
@ -642,39 +630,35 @@ namespace keepass2android
}
filename = Java.Net.URLDecoder.Decode(filename);
addBinaryOrAsk(filename);
AddBinaryOrAsk(filename);
}
}
reload();
Reload();
break;
case (int)Result.Canceled:
reload();
break;
default:
Reload();
break;
}
}
void populateBinaries()
void PopulateBinaries()
{
ViewGroup binariesGroup = (ViewGroup)FindViewById(Resource.Id.binaries);
binariesGroup.RemoveAllViews();
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.FillParent, RelativeLayout.LayoutParams.WrapContent);
foreach (KeyValuePair<string, ProtectedBinary> pair in State.mEntry.Binaries)
RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.FillParent, ViewGroup.LayoutParams.WrapContent);
foreach (KeyValuePair<string, ProtectedBinary> pair in State.Entry.Binaries)
{
String key = pair.Key;
Button binaryButton = new Button(this);
Button binaryButton = new Button(this) {Text = key};
binaryButton.Text = key;
binaryButton.SetCompoundDrawablesWithIntrinsicBounds( Resources.GetDrawable(Android.Resource.Drawable.IcMenuDelete),null, null, null);
binaryButton.Click += (object sender, EventArgs e) =>
binaryButton.Click += (sender, e) =>
{
State.mEntryModified = true;
Button btnSender = (Button)(sender);
State.mEntry.Binaries.Remove(key);
populateBinaries();
State.EntryModified = true;
State.Entry.Binaries.Remove(key);
PopulateBinaries();
};
binariesGroup.AddView(binaryButton,layoutParams);
@ -682,19 +666,18 @@ namespace keepass2android
}
Button addBinaryButton = new Button(this);
addBinaryButton.Text = GetString(Resource.String.add_binary);
Button addBinaryButton = new Button(this) {Text = GetString(Resource.String.add_binary)};
addBinaryButton.SetCompoundDrawablesWithIntrinsicBounds( Resources.GetDrawable(Android.Resource.Drawable.IcMenuAdd) , null, null, null);
addBinaryButton.Click += (object sender, EventArgs e) =>
addBinaryButton.Click += (sender, e) =>
{
Util.showBrowseDialog("/mnt/sdcard", this, Intents.REQUEST_CODE_FILE_BROWSE_FOR_BINARY, false);
Util.showBrowseDialog("/mnt/sdcard", this, Intents.RequestCodeFileBrowseForBinary, false);
};
binariesGroup.AddView(addBinaryButton,layoutParams);
var binariesLabel = FindViewById(Resource.Id.entry_binaries_label);
if (binariesLabel != null)
binariesLabel.Visibility = State.mEntry.Binaries.UCount > 0 ? ViewStates.Visible : ViewStates.Gone;
binariesLabel.Visibility = State.Entry.Binaries.UCount > 0 ? ViewStates.Visible : ViewStates.Gone;
}
public override bool OnCreateOptionsMenu(IMenu menu) {
base.OnCreateOptionsMenu(menu);
@ -704,7 +687,7 @@ namespace keepass2android
IMenuItem togglePassword = menu.FindItem(Resource.Id.menu_toggle_pass);
if ( State.mShowPassword ) {
if ( State.ShowPassword ) {
togglePassword.SetTitle(Resource.String.menu_hide_password);
} else {
togglePassword.SetTitle(Resource.String.show_password);
@ -725,14 +708,14 @@ namespace keepass2android
return true;
case Resource.Id.menu_toggle_pass:
if ( State.mShowPassword ) {
if ( State.ShowPassword ) {
item.SetTitle(Resource.String.show_password);
State.mShowPassword = false;
State.ShowPassword = false;
} else {
item.SetTitle(Resource.String.menu_hide_password);
State.mShowPassword = true;
State.ShowPassword = true;
}
setPasswordStyle();
SetPasswordStyle();
return true;
case Resource.Id.menu_cancel_edit:
Finish();
@ -766,11 +749,11 @@ namespace keepass2android
return base.OnOptionsItemSelected(item);
}
private void setPasswordStyle() {
private void SetPasswordStyle() {
TextView password = (TextView) FindViewById(Resource.Id.entry_password);
TextView confpassword = (TextView) FindViewById(Resource.Id.entry_confpassword);
if ( State.mShowPassword ) {
if ( State.ShowPassword ) {
password.InputType = InputTypes.ClassText | InputTypes.TextVariationVisiblePassword;
confpassword.InputType = InputTypes.ClassText | InputTypes.TextVariationVisiblePassword;
@ -780,23 +763,23 @@ namespace keepass2android
}
}
void updateExpires()
void UpdateExpires()
{
if (State.mEntry.Expires)
if (State.Entry.Expires)
{
populateText(Resource.Id.entry_expires, getDateTime(State.mEntry.ExpiryTime));
PopulateText(Resource.Id.entry_expires, getDateTime(State.Entry.ExpiryTime));
}
else
{
populateText(Resource.Id.entry_expires, GetString(Resource.String.never));
PopulateText(Resource.Id.entry_expires, GetString(Resource.String.never));
}
((CheckBox)FindViewById(Resource.Id.entry_expires_checkbox)).Checked = State.mEntry.Expires;
((EditText)FindViewById(Resource.Id.entry_expires)).Enabled = State.mEntry.Expires;
((CheckBox)FindViewById(Resource.Id.entry_expires_checkbox)).Checked = State.Entry.Expires;
FindViewById(Resource.Id.entry_expires).Enabled = State.Entry.Expires;
}
public override Java.Lang.Object OnRetainNonConfigurationInstance()
{
UpdateEntryFromUi(State.mEntry);
UpdateEntryFromUi(State.Entry);
return this;
}
@ -804,31 +787,31 @@ namespace keepass2android
{
LinearLayout ees = (LinearLayout)LayoutInflater.Inflate(Resource.Layout.entry_edit_section, null);
((TextView)ees.FindViewById(Resource.Id.title)).Text = pair.Key;
((TextView)ees.FindViewById(Resource.Id.title)).TextChanged += (sender, e) => State.mEntryModified = true;
((TextView)ees.FindViewById(Resource.Id.title)).TextChanged += (sender, e) => State.EntryModified = true;
((TextView)ees.FindViewById(Resource.Id.value)).Text = pair.Value.ReadString();
((TextView)ees.FindViewById(Resource.Id.value)).TextChanged += (sender, e) => State.mEntryModified = true;
ees.FindViewById(Resource.Id.delete).Click += (sender, e) => deleteAdvancedString((View)sender);
((TextView)ees.FindViewById(Resource.Id.value)).TextChanged += (sender, e) => State.EntryModified = true;
ees.FindViewById(Resource.Id.delete).Click += (sender, e) => DeleteAdvancedString((View)sender);
return ees;
}
private void fillData() {
private void FillData() {
ImageButton currIconButton = (ImageButton) FindViewById(Resource.Id.icon_button);
App.getDB().drawFactory.assignDrawableTo(currIconButton, Resources, App.getDB().pm, State.mEntry.IconId, State.mEntry.CustomIconUuid);
App.Kp2a.GetDb().DrawableFactory.AssignDrawableTo(currIconButton, Resources, App.Kp2a.GetDb().KpDatabase, State.Entry.IconId, State.Entry.CustomIconUuid);
populateText(Resource.Id.entry_title, State.mEntry.Strings.ReadSafe (PwDefs.TitleField));
populateText(Resource.Id.entry_user_name, State.mEntry.Strings.ReadSafe (PwDefs.UserNameField));
populateText(Resource.Id.entry_url, State.mEntry.Strings.ReadSafe (PwDefs.UrlField));
PopulateText(Resource.Id.entry_title, State.Entry.Strings.ReadSafe (PwDefs.TitleField));
PopulateText(Resource.Id.entry_user_name, State.Entry.Strings.ReadSafe (PwDefs.UserNameField));
PopulateText(Resource.Id.entry_url, State.Entry.Strings.ReadSafe (PwDefs.UrlField));
String password = State.mEntry.Strings.ReadSafe(PwDefs.PasswordField);
populateText(Resource.Id.entry_password, password);
populateText(Resource.Id.entry_confpassword, password);
setPasswordStyle();
String password = State.Entry.Strings.ReadSafe(PwDefs.PasswordField);
PopulateText(Resource.Id.entry_password, password);
PopulateText(Resource.Id.entry_confpassword, password);
SetPasswordStyle();
populateText(Resource.Id.entry_comment, State.mEntry.Strings.ReadSafe (PwDefs.NotesField));
PopulateText(Resource.Id.entry_comment, State.Entry.Strings.ReadSafe (PwDefs.NotesField));
LinearLayout container = (LinearLayout) FindViewById(Resource.Id.advanced_container);
foreach (var pair in State.mEntry.Strings)
foreach (var pair in State.Entry.Strings)
{
String key = pair.Key;
@ -838,22 +821,22 @@ namespace keepass2android
}
}
populateBinaries();
PopulateBinaries();
populateText(Resource.Id.entry_override_url, State.mEntry.OverrideUrl);
populateText(Resource.Id.entry_tags, StrUtil.TagsToString(State.mEntry.Tags, true));
PopulateText(Resource.Id.entry_override_url, State.Entry.OverrideUrl);
PopulateText(Resource.Id.entry_tags, StrUtil.TagsToString(State.Entry.Tags, true));
updateExpires();
UpdateExpires();
}
private String getDateTime(System.DateTime dt) {
private String getDateTime(DateTime dt) {
return dt.ToString ("g", CultureInfo.CurrentUICulture);
}
public void deleteAdvancedString(View view) {
public void DeleteAdvancedString(View view) {
var section = view.Parent;
LinearLayout container = (LinearLayout) FindViewById(Resource.Id.advanced_container);
State.mEntryModified = true;
State.EntryModified = true;
for (int i = 0; i < container.ChildCount; i++) {
var ees = container.GetChildAt(i);
if (ees == section) {
@ -865,7 +848,7 @@ namespace keepass2android
}
protected bool validateBeforeSaving() {
protected bool ValidateBeforeSaving() {
// Require title
String title = Util.getEditText(this, Resource.Id.entry_title);
if ( title.Length == 0 ) {
@ -883,15 +866,12 @@ namespace keepass2android
// Validate expiry date
DateTime newExpiry = new DateTime();
if ((State.mEntry.Expires) && (!DateTime.TryParse( Util.getEditText(this,Resource.Id.entry_expires), out newExpiry)))
if ((State.Entry.Expires) && (!DateTime.TryParse( Util.getEditText(this,Resource.Id.entry_expires), out newExpiry)))
{
Toast.MakeText(this, Resource.String.error_invalid_expiry_date, ToastLength.Long).Show();
return false;
}
else
{
State.mEntry.ExpiryTime = newExpiry;
}
State.Entry.ExpiryTime = newExpiry;
LinearLayout container = (LinearLayout) FindViewById(Resource.Id.advanced_container);
@ -912,16 +892,16 @@ namespace keepass2android
}
private void populateText(int viewId, String text) {
private void PopulateText(int viewId, String text) {
TextView tv = (TextView) FindViewById(viewId);
tv.Text = text;
tv.TextChanged += (sender, e) => {State.mEntryModified = true;};
tv.TextChanged += (sender, e) => {State.EntryModified = true;};
}
protected override void OnPause()
{
if (!mCloseForReload)
UpdateEntryFromUi(State.mEntry);
if (!_closeForReload)
UpdateEntryFromUi(State.Entry);
base.OnPause();

View File

@ -1,36 +1,24 @@
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
{
/// <summary>
/// Holds the state of the EntrryEditActivity. This is required to be able to keep a partially modified entry in memory
/// through the App variable. Serializing this state (especially the mEntry/mEntryInDatabase) can be a performance problem
/// through the App variable. Serializing this state (especially the Entry/EntryInDatabase) can be a performance problem
/// when there are big attachements.
/// </summary>
internal class EntryEditActivityState
{
internal PwEntry mEntry, mEntryInDatabase;
internal bool mShowPassword = false;
internal bool mIsNew;
internal PwIcon mSelectedIconID;
internal PwUuid mSelectedCustomIconID = PwUuid.Zero;
internal bool mSelectedIcon = false;
internal PwEntry Entry, EntryInDatabase;
internal bool ShowPassword = false;
internal bool IsNew;
internal PwIcon SelectedIconId;
internal PwUuid SelectedCustomIconId = PwUuid.Zero;
internal bool SelectedIcon = false;
internal PwGroup parentGroup;
internal PwGroup ParentGroup;
internal bool mEntryModified;
internal bool EntryModified;
}
}

View File

@ -16,14 +16,9 @@ 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;
@ -31,7 +26,7 @@ namespace keepass2android
{
[Activity (Label = "@string/app_name", Theme="@style/NoTitleBar")]
public class GeneratePasswordActivity : LockCloseActivity {
private int[] BUTTON_IDS = new int[] {Resource.Id.btn_length6, Resource.Id.btn_length8, Resource.Id.btn_length12, Resource.Id.btn_length16};
private readonly int[] _buttonIds = new[] {Resource.Id.btn_length6, Resource.Id.btn_length8, Resource.Id.btn_length12, Resource.Id.btn_length16};
public static void Launch(Activity act) {
Intent i = new Intent(act, typeof(GeneratePasswordActivity));
@ -43,11 +38,11 @@ namespace keepass2android
protected override void OnCreate(Bundle savedInstanceState) {
base.OnCreate(savedInstanceState);
SetContentView(Resource.Layout.generate_password);
SetResult(KeePass.EXIT_NORMAL);
SetResult(KeePass.ExitNormal);
foreach (int id in BUTTON_IDS) {
foreach (int id in _buttonIds) {
Button button = (Button) FindViewById(id);
button.Click += (object sender, EventArgs e) =>
button.Click += (sender, e) =>
{
Button b = (Button) sender;
@ -58,8 +53,8 @@ namespace keepass2android
}
Button genPassButton = (Button) FindViewById(Resource.Id.generate_password_button);
genPassButton.Click += (object sender, EventArgs e) => {
String password = generatePassword();
genPassButton.Click += (sender, e) => {
String password = GeneratePassword();
EditText txtPassword = (EditText) FindViewById(Resource.Id.password);
txtPassword.Text = password;
@ -68,20 +63,20 @@ namespace keepass2android
View acceptButton = FindViewById(Resource.Id.accept_button);
acceptButton.Click += (object sender, EventArgs e) => {
acceptButton.Click += (sender, e) => {
EditText password = (EditText) FindViewById(Resource.Id.password);
Intent intent = new Intent();
intent.PutExtra("keepass2android.password.generated_password", password.Text);
SetResult((Result)EntryEditActivity.RESULT_OK_PASSWORD_GENERATOR, intent);
SetResult((Result)EntryEditActivity.ResultOkPasswordGenerator, intent);
Finish();
};
View cancelButton = FindViewById(Resource.Id.cancel_button);
cancelButton.Click += (object sender, EventArgs e) =>
cancelButton.Click += (sender, e) =>
{
SetResult(Result.Canceled);
@ -90,11 +85,11 @@ namespace keepass2android
EditText txtPasswordToSet = (EditText) FindViewById(Resource.Id.password);
txtPasswordToSet.Text = generatePassword();
txtPasswordToSet.Text = GeneratePassword();
}
public String generatePassword() {
public String GeneratePassword() {
String password = "";
try {
@ -109,7 +104,7 @@ namespace keepass2android
PasswordGenerator generator = new PasswordGenerator(this);
password = generator.generatePassword(length,
password = generator.GeneratePassword(length,
((CheckBox) FindViewById(Resource.Id.cb_uppercase)).Checked,
((CheckBox) FindViewById(Resource.Id.cb_lowercase)).Checked,
((CheckBox) FindViewById(Resource.Id.cb_digits)).Checked,

View File

@ -16,14 +16,9 @@ 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;
@ -38,12 +33,12 @@ namespace keepass2android
[MetaData("android.app.default_searchable",Value="keepass2android.search.SearchResults")]
public class GroupActivity : GroupBaseActivity {
public const int UNINIT = -1;
public const int Uninit = -1;
protected bool addGroupEnabled = false;
protected bool addEntryEnabled = false;
protected bool AddGroupEnabled = false;
protected bool AddEntryEnabled = false;
private const String TAG = "Group Activity:";
private const String Tag = "Group Activity:";
public static void Launch(Activity act, AppTask appTask) {
Launch(act, null, appTask);
@ -51,30 +46,28 @@ namespace keepass2android
public static void Launch (Activity act, PwGroup g, AppTask appTask)
{
Intent i;
// Need to use PwDatabase since group may be null
PwDatabase db = App.getDB ().pm;
PwDatabase db = App.Kp2a.GetDb().KpDatabase;
if (db == null) {
// Reached if db is null
Log.Debug (TAG, "Tried to launch with null db");
Log.Debug (Tag, "Tried to launch with null db");
return;
}
i = new Intent(act, typeof(GroupActivity));
Intent i = new Intent(act, typeof(GroupActivity));
if ( g != null ) {
i.PutExtra(KEY_ENTRY, g.Uuid.ToHexString());
i.PutExtra(KeyEntry, g.Uuid.ToHexString());
}
appTask.ToIntent(i);
act.StartActivityForResult(i,0);
}
protected PwUuid retrieveGroupId(Intent i)
protected PwUuid RetrieveGroupId(Intent i)
{
String uuid = i.GetStringExtra(KEY_ENTRY);
String uuid = i.GetStringExtra(KeyEntry);
if ( String.IsNullOrEmpty(uuid) ) {
return null;
@ -82,10 +75,10 @@ namespace keepass2android
return new PwUuid(MemUtil.HexStringToByteArray(uuid));
}
protected void setupButtons()
protected void SetupButtons()
{
addGroupEnabled = true;
addEntryEnabled = !mGroup.Uuid.EqualsValue(App.getDB().root.Uuid);
AddGroupEnabled = true;
AddEntryEnabled = !Group.Uuid.EqualsValue(App.Kp2a.GetDb().Root.Uuid);
}
protected override void OnCreate (Bundle savedInstanceState)
@ -96,60 +89,60 @@ namespace keepass2android
return;
}
SetResult (KeePass.EXIT_NORMAL);
SetResult (KeePass.ExitNormal);
Log.Warn (TAG, "Creating group view");
Log.Warn (Tag, "Creating group view");
Intent intent = Intent;
PwUuid id = retrieveGroupId (intent);
PwUuid id = RetrieveGroupId (intent);
Database db = App.getDB ();
Database db = App.Kp2a.GetDb();
if (id == null) {
mGroup = db.root;
Group = db.Root;
} else {
mGroup = db.groups[id];
Group = db.Groups[id];
}
Log.Warn (TAG, "Retrieved group");
if (mGroup == null) {
Log.Warn (TAG, "Group was null");
Log.Warn (Tag, "Retrieved group");
if (Group == null) {
Log.Warn (Tag, "Group was null");
return;
}
setupButtons ();
SetupButtons ();
if (addGroupEnabled && addEntryEnabled) {
if (AddGroupEnabled && AddEntryEnabled) {
SetContentView (new GroupAddEntryView (this));
} else if (addGroupEnabled) {
} else if (AddGroupEnabled) {
SetContentView (new GroupRootView (this));
} else if (addEntryEnabled) {
} else if (AddEntryEnabled) {
throw new Exception ("This mode is not supported.");
} else {
SetContentView (new GroupViewOnlyView (this));
}
if (addGroupEnabled) {
if (AddGroupEnabled) {
// Add Group button
View addGroup = FindViewById (Resource.Id.add_group);
addGroup.Click += (object sender, EventArgs e) => {
GroupEditActivity.Launch (this, mGroup);
addGroup.Click += (sender, e) => {
GroupEditActivity.Launch (this, Group);
};
}
if (addEntryEnabled) {
if (AddEntryEnabled) {
// Add Entry button
View addEntry = FindViewById (Resource.Id.add_entry);
addEntry.Click += (object sender, EventArgs e) => {
EntryEditActivity.Launch (this, mGroup, mAppTask);
addEntry.Click += (sender, e) => {
EntryEditActivity.Launch (this, Group, AppTask);
};
}
setGroupTitle();
setGroupIcon();
SetGroupTitle();
SetGroupIcon();
ListAdapter = new PwGroupListAdapter(this, mGroup);
ListAdapter = new PwGroupListAdapter(this, Group);
RegisterForContextMenu(ListView);
Log.Warn(TAG, "Finished creating group");
Log.Warn(Tag, "Finished creating group");
}
@ -164,12 +157,12 @@ namespace keepass2android
public override void OnBackPressed()
{
base.OnBackPressed();
if ((mGroup != null) && (mGroup.ParentGroup != null))
if ((Group != null) && (Group.ParentGroup != null))
OverridePendingTransition(Resource.Animation.anim_enter_back, Resource.Animation.anim_leave_back);
}
public override bool OnContextItemSelected(IMenuItem item) {
Android.Widget.AdapterView.AdapterContextMenuInfo acmi = (Android.Widget.AdapterView.AdapterContextMenuInfo)item.MenuInfo;
AdapterView.AdapterContextMenuInfo acmi = (AdapterView.AdapterContextMenuInfo)item.MenuInfo;
ClickView cv = (ClickView) acmi.TargetView;
return cv.OnContextItemSelected(item);
@ -180,16 +173,17 @@ namespace keepass2android
switch (resultCode)
{
case Result.Ok:
String GroupName = data.Extras.GetString(GroupEditActivity.KEY_NAME);
int GroupIconID = data.Extras.GetInt(GroupEditActivity.KEY_ICON_ID);
String groupName = data.Extras.GetString(GroupEditActivity.KeyName);
int groupIconId = data.Extras.GetInt(GroupEditActivity.KeyIconId);
GroupBaseActivity act = this;
Handler handler = new Handler();
AddGroup task = AddGroup.getInstance(this, App.getDB(), GroupName, GroupIconID, mGroup, new RefreshTask(handler, this), false);
ProgressTask pt = new ProgressTask(act, task, Resource.String.saving_database);
pt.run();
AddGroup task = AddGroup.GetInstance(this, App.Kp2a.GetDb(), groupName, groupIconId, Group, new RefreshTask(handler, this), false);
ProgressTask pt = new ProgressTask(App.Kp2a, act, task, UiStringKey.saving_database);
pt.Run();
break;
case Result.Canceled:
break;
default:
base.OnActivityResult(requestCode, resultCode, data);
break;

View File

@ -16,10 +16,6 @@ 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;
@ -35,19 +31,20 @@ namespace keepass2android
{
public abstract class GroupBaseActivity : LockCloseListActivity {
public const String KEY_ENTRY = "entry";
public const String KEY_MODE = "mode";
public const String KeyEntry = "entry";
public const String KeyMode = "mode";
public virtual void LaunchActivityForEntry(KeePassLib.PwEntry pwEntry, int pos)
public virtual void LaunchActivityForEntry(PwEntry pwEntry, int pos)
{
EntryActivity.Launch(this, pwEntry, pos, mAppTask);
EntryActivity.Launch(this, pwEntry, pos, AppTask);
}
public GroupBaseActivity ()
protected GroupBaseActivity ()
{
}
public GroupBaseActivity (IntPtr javaReference, JniHandleOwnership transfer)
protected GroupBaseActivity (IntPtr javaReference, JniHandleOwnership transfer)
: base(javaReference, transfer)
{
@ -56,7 +53,7 @@ namespace keepass2android
protected override void OnSaveInstanceState(Bundle outState)
{
base.OnSaveInstanceState(outState);
mAppTask.ToBundle(outState);
AppTask.ToBundle(outState);
}
@ -64,24 +61,24 @@ namespace keepass2android
{
base.OnActivityResult(requestCode, resultCode, data);
if (resultCode == KeePass.EXIT_CLOSE_AFTER_TASK_COMPLETE)
if (resultCode == KeePass.ExitCloseAfterTaskComplete)
{
SetResult(KeePass.EXIT_CLOSE_AFTER_TASK_COMPLETE);
SetResult(KeePass.ExitCloseAfterTaskComplete);
Finish();
}
}
private ISharedPreferences prefs;
private ISharedPreferences _prefs;
protected PwGroup mGroup;
protected PwGroup Group;
internal AppTask mAppTask;
internal AppTask AppTask;
protected override void OnResume() {
base.OnResume();
refreshIfDirty();
RefreshIfDirty();
}
public override bool OnSearchRequested()
@ -90,10 +87,10 @@ namespace keepass2android
return true;
}
public void refreshIfDirty() {
Database db = App.getDB();
if ( db.dirty.Contains(mGroup) ) {
db.dirty.Remove(mGroup);
public void RefreshIfDirty() {
Database db = App.Kp2a.GetDb();
if ( db.Dirty.Contains(Group) ) {
db.Dirty.Remove(Group);
BaseAdapter adapter = (BaseAdapter) ListAdapter;
adapter.NotifyDataSetChanged();
@ -103,7 +100,7 @@ namespace keepass2android
protected override void OnListItemClick(ListView l, View v, int position, long id) {
base.OnListItemClick(l, v, position, id);
Android.Widget.IListAdapter adapt = ListAdapter;
IListAdapter adapt = ListAdapter;
ClickView cv = (ClickView) adapt.GetView(position, null, null);
cv.OnClick();
@ -112,24 +109,24 @@ namespace keepass2android
protected override void OnCreate(Bundle savedInstanceState) {
base.OnCreate(savedInstanceState);
mAppTask = AppTask.GetTaskInOnCreate(savedInstanceState, Intent);
AppTask = AppTask.GetTaskInOnCreate(savedInstanceState, Intent);
// Likely the app has been killed exit the activity
if ( ! App.getDB().Loaded ) {
if ( ! App.Kp2a.GetDb().Loaded ) {
Finish();
return;
}
prefs = PreferenceManager.GetDefaultSharedPreferences(this);
_prefs = PreferenceManager.GetDefaultSharedPreferences(this);
SetContentView(new GroupViewOnlyView(this));
SetResult(KeePass.EXIT_NORMAL);
SetResult(KeePass.ExitNormal);
styleScrollBars();
StyleScrollBars();
}
protected void styleScrollBars() {
protected void StyleScrollBars() {
ListView lv = ListView;
lv.ScrollBarStyle =ScrollbarStyles.InsideInset;
lv.TextFilterEnabled = true;
@ -137,11 +134,11 @@ namespace keepass2android
}
protected void setGroupTitle()
protected void SetGroupTitle()
{
String name = mGroup.Name;
String name = Group.Name;
String titleText;
bool clickable = (mGroup != null) && (mGroup.IsVirtual == false) && (mGroup.ParentGroup != null);
bool clickable = (Group != null) && (Group.IsVirtual == false) && (Group.ParentGroup != null);
if (!String.IsNullOrEmpty(name))
{
titleText = name;
@ -154,14 +151,14 @@ namespace keepass2android
Button tv = (Button)FindViewById(Resource.Id.group_name);
if (tv != null)
{
if (mGroup != null)
if (Group != null)
{
tv.Text = titleText;
}
if (clickable)
{
tv.Click += (object sender, EventArgs e) =>
tv.Click += (sender, e) =>
{
Finish();
};
@ -181,9 +178,9 @@ namespace keepass2android
}
protected void setGroupIcon() {
if (mGroup != null) {
Drawable drawable = App.getDB().drawFactory.getIconDrawable(Resources, App.getDB().pm, mGroup.IconId, mGroup.CustomIconUuid);
protected void SetGroupIcon() {
if (Group != null) {
Drawable drawable = App.Kp2a.GetDb().DrawableFactory.GetIconDrawable(Resources, App.Kp2a.GetDb().KpDatabase, Group.IconId, Group.CustomIconUuid);
ImageView iv = (ImageView) FindViewById(Resource.Id.icon);
if (iv != null)
iv.SetImageDrawable(drawable);
@ -206,8 +203,8 @@ namespace keepass2android
return true;
}
private void setSortMenuText(IMenu menu) {
bool sortByName = prefs.GetBoolean(GetString(Resource.String.sort_key), Resources.GetBoolean(Resource.Boolean.sort_default));
private void SetSortMenuText(IMenu menu) {
bool sortByName = _prefs.GetBoolean(GetString(Resource.String.sort_key), Resources.GetBoolean(Resource.Boolean.sort_default));
int resId;
if ( sortByName ) {
@ -225,7 +222,7 @@ namespace keepass2android
return false;
}
setSortMenuText(menu);
SetSortMenuText(menu);
return true;
}
@ -242,8 +239,8 @@ namespace keepass2android
return true;
case Resource.Id.menu_lock:
App.setShutdown();
SetResult(KeePass.EXIT_LOCK);
App.Kp2a.SetShutdown();
SetResult(KeePass.ExitLock);
Finish();
return true;
@ -257,11 +254,11 @@ namespace keepass2android
return true;
case Resource.Id.menu_change_master_key:
setPassword();
SetPassword();
return true;
case Resource.Id.menu_sort:
toggleSort();
ToggleSort();
return true;
case Resource.Id.menu_rate:
try {
@ -297,22 +294,22 @@ namespace keepass2android
return base.OnOptionsItemSelected(item);
}
private void toggleSort() {
private void ToggleSort() {
// Toggle setting
String sortKey = GetString(Resource.String.sort_key);
bool sortByName = prefs.GetBoolean(sortKey, Resources.GetBoolean(Resource.Boolean.sort_default));
ISharedPreferencesEditor editor = prefs.Edit();
bool sortByName = _prefs.GetBoolean(sortKey, Resources.GetBoolean(Resource.Boolean.sort_default));
ISharedPreferencesEditor editor = _prefs.Edit();
editor.PutBoolean(sortKey, ! sortByName);
EditorCompat.apply(editor);
EditorCompat.Apply(editor);
// Refresh menu titles
ActivityCompat.invalidateOptionsMenu(this);
ActivityCompat.InvalidateOptionsMenu(this);
// Mark all groups as dirty now to refresh them on load
Database db = App.getDB();
db.markAllGroupsAsDirty();
Database db = App.Kp2a.GetDb();
db.MarkAllGroupsAsDirty();
// We'll manually refresh this group so we can remove it
db.dirty.Remove(mGroup);
db.Dirty.Remove(Group);
// Tell the adapter to refresh it's list
BaseAdapter adapter = (BaseAdapter) ListAdapter;
@ -320,43 +317,43 @@ namespace keepass2android
}
private void setPassword() {
private void SetPassword() {
SetPasswordDialog dialog = new SetPasswordDialog(this);
dialog.Show();
}
public class RefreshTask : OnFinish {
GroupBaseActivity act;
readonly GroupBaseActivity _act;
public RefreshTask(Handler handler, GroupBaseActivity act):base(handler) {
this.act = act;
_act = act;
}
public override void run() {
if ( mSuccess) {
act.refreshIfDirty();
public override void Run() {
if ( Success) {
_act.RefreshIfDirty();
} else {
displayMessage(act);
DisplayMessage(_act);
}
}
}
public class AfterDeleteGroup : OnFinish {
GroupBaseActivity act;
readonly GroupBaseActivity _act;
public AfterDeleteGroup(Handler handler, GroupBaseActivity act):base(handler) {
this.act = act;
_act = act;
}
public override void run() {
if ( mSuccess) {
act.refreshIfDirty();
public override void Run() {
if ( Success) {
_act.RefreshIfDirty();
} else {
mHandler.Post( () => {
Toast.MakeText(act, "Unrecoverable error: " + mMessage, ToastLength.Long).Show();
Handler.Post( () => {
Toast.MakeText(_act, "Unrecoverable error: " + Message, ToastLength.Long).Show();
});
App.setShutdown();
act.Finish();
App.Kp2a.SetShutdown();
_act.Finish();
}
}

View File

@ -16,15 +16,9 @@ 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;
@ -33,18 +27,18 @@ namespace keepass2android
[Activity (Label = "@string/app_name", Theme="@style/Dialog")]
public class GroupEditActivity : LifecycleDebugActivity
{
public const String KEY_PARENT = "parent";
public const String KEY_NAME = "name";
public const String KEY_ICON_ID = "icon_id";
public const String KeyParent = "parent";
public const String KeyName = "name";
public const String KeyIconId = "icon_id";
private int mSelectedIconID;
private int _selectedIconId;
public static void Launch(Activity act, PwGroup pw)
{
Intent i = new Intent(act, typeof(GroupEditActivity));
PwGroup parent = pw;
i.PutExtra(KEY_PARENT, parent.Uuid.ToHexString());
i.PutExtra(KeyParent, parent.Uuid.ToHexString());
act.StartActivityForResult(i, 0);
}
@ -56,23 +50,23 @@ namespace keepass2android
SetTitle (Resource.String.add_group_title);
ImageButton iconButton = (ImageButton)FindViewById (Resource.Id.icon_button);
iconButton.Click += (object sender, EventArgs e) =>
iconButton.Click += (sender, e) =>
{
IconPickerActivity.Launch (this);
};
mSelectedIconID = (int) PwIcon.FolderOpen;
iconButton.SetImageResource(Icons.iconToResId((PwIcon)mSelectedIconID));
_selectedIconId = (int) PwIcon.FolderOpen;
iconButton.SetImageResource(Icons.IconToResId((PwIcon)_selectedIconId));
Button okButton = (Button)FindViewById (Resource.Id.ok);
okButton.Click += (object sender, EventArgs e) => {
okButton.Click += (sender, e) => {
TextView nameField = (TextView)FindViewById (Resource.Id.group_name);
String name = nameField.Text;
if (name.Length > 0) {
Intent intent = new Intent ();
intent.PutExtra (KEY_NAME, name);
intent.PutExtra (KEY_ICON_ID, mSelectedIconID);
intent.PutExtra (KeyName, name);
intent.PutExtra (KeyIconId, _selectedIconId);
SetResult (Result.Ok, intent);
Finish ();
@ -83,7 +77,7 @@ namespace keepass2android
Button cancel = (Button)FindViewById (Resource.Id.cancel);
cancel.Click += (object sender, EventArgs e) => {
cancel.Click += (sender, e) => {
Intent intent = new Intent ();
SetResult (Result.Canceled, intent);
@ -95,12 +89,10 @@ namespace keepass2android
{
switch ((int)resultCode)
{
case EntryEditActivity.RESULT_OK_ICON_PICKER:
mSelectedIconID = data.Extras.GetInt(IconPickerActivity.KEY_ICON_ID);
case EntryEditActivity.ResultOkIconPicker:
_selectedIconId = data.Extras.GetInt(IconPickerActivity.KeyIconId);
ImageButton currIconButton = (ImageButton) FindViewById(Resource.Id.icon_button);
currIconButton.SetImageResource(Icons.iconToResId((PwIcon)mSelectedIconID));
break;
default:
currIconButton.SetImageResource(Icons.IconToResId((PwIcon)_selectedIconId));
break;
}
}

View File

@ -16,14 +16,9 @@ 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;
@ -32,8 +27,8 @@ namespace keepass2android
[Activity (Label = "@string/app_name", Theme="@style/NoTitleBar")]
public class IconPickerActivity : LockCloseActivity
{
public const String KEY_ICON_ID = "icon_id";
public const String KEY_CUSTOM_ICON_ID = "custom_icon_id";
public const String KeyIconId = "icon_id";
public const String KeyCustomIconId = "custom_icon_id";
public static void Launch(Activity act)
{
@ -47,14 +42,14 @@ namespace keepass2android
SetContentView(Resource.Layout.icon_picker);
GridView currIconGridView = (GridView)FindViewById(Resource.Id.IconGridView);
currIconGridView.Adapter = new ImageAdapter(this, this);
currIconGridView.Adapter = new ImageAdapter(this);
currIconGridView.ItemClick += (sender, e) => {
Intent intent = new Intent();
intent.PutExtra(KEY_ICON_ID, e.Position);
SetResult((Result)EntryEditActivity.RESULT_OK_ICON_PICKER, intent);
intent.PutExtra(KeyIconId, e.Position);
SetResult((Result)EntryEditActivity.ResultOkIconPicker, intent);
Finish();
};
@ -62,14 +57,11 @@ namespace keepass2android
public class ImageAdapter : BaseAdapter
{
Context mContext;
readonly IconPickerActivity _act;
IconPickerActivity act;
public ImageAdapter(Context c, IconPickerActivity act)
public ImageAdapter(IconPickerActivity act)
{
mContext = c;
this.act = act;
_act = act;
}
public override int Count
@ -77,7 +69,7 @@ namespace keepass2android
get
{
/* Return number of KeePass icons */
return Icons.count();
return Icons.Count();
}
}
@ -96,7 +88,7 @@ namespace keepass2android
View currView;
if(convertView == null)
{
LayoutInflater li = (LayoutInflater) act.GetSystemService(Context.LayoutInflaterService);
LayoutInflater li = (LayoutInflater) _act.GetSystemService(LayoutInflaterService);
currView = li.Inflate(Resource.Layout.icon, null);
}
else
@ -107,7 +99,7 @@ namespace keepass2android
TextView tv = (TextView) currView.FindViewById(Resource.Id.icon_text);
tv.Text = "" + position;
ImageView iv = (ImageView) currView.FindViewById(Resource.Id.icon_image);
iv.SetImageResource(Icons.iconToResId((KeePassLib.PwIcon)position));
iv.SetImageResource(Icons.IconToResId((KeePassLib.PwIcon)position));
return currView;
}

View File

@ -18,41 +18,38 @@ using System;
using Android.App;
using Android.Content;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.OS;
using keepass2android.view;
using Android.Preferences;
using Android.Content.PM;
using Android.Text;
using Android.Text.Util;
using Android.Text.Method;
using KeePassLib.Serialization;
namespace keepass2android
{
/// <summary>
/// Launcher activity of Keepass2Android. This activity usually forwards to FileSelect but may show the revision dialog after installation or updates.
/// </summary>
[Activity (Label = AppNames.AppName, MainLauncher = true, Theme="@style/Base")]
public class KeePass : LifecycleDebugActivity
{
public const Android.App.Result EXIT_NORMAL = Android.App.Result.FirstUser;
public const Android.App.Result EXIT_LOCK = Android.App.Result.FirstUser+1;
public const Android.App.Result EXIT_REFRESH = Android.App.Result.FirstUser+2;
public const Android.App.Result EXIT_REFRESH_TITLE = Android.App.Result.FirstUser+3;
public const Android.App.Result EXIT_FORCE_LOCK = Android.App.Result.FirstUser+4;
public const Android.App.Result EXIT_QUICK_UNLOCK = Android.App.Result.FirstUser+5;
public const Android.App.Result EXIT_CLOSE_AFTER_TASK_COMPLETE = Android.App.Result.FirstUser+6;
public const Android.App.Result EXIT_CHANGE_DB = Android.App.Result.FirstUser+7;
public const Android.App.Result EXIT_FORCE_LOCK_AND_CHANGE_DB = Android.App.Result.FirstUser+8;
public const Android.App.Result EXIT_RELOAD_DB = Android.App.Result.FirstUser+9;
public const Result ExitNormal = Result.FirstUser;
public const Result ExitLock = Result.FirstUser+1;
public const Result ExitRefresh = Result.FirstUser+2;
public const Result ExitRefreshTitle = Result.FirstUser+3;
public const Result ExitForceLock = Result.FirstUser+4;
public const Result ExitQuickUnlock = Result.FirstUser+5;
public const Result ExitCloseAfterTaskComplete = Result.FirstUser+6;
public const Result ExitChangeDb = Result.FirstUser+7;
public const Result ExitForceLockAndChangeDb = Result.FirstUser+8;
public const Result ExitReloadDb = Result.FirstUser+9;
AppTask mAppTask;
AppTask _appTask;
protected override void OnCreate (Bundle bundle)
{
base.OnCreate (bundle);
mAppTask = AppTask.GetTaskInOnCreate(bundle, Intent);
_appTask = AppTask.GetTaskInOnCreate(bundle, Intent);
Android.Util.Log.Debug("DEBUG","KeePass.OnCreate");
}
@ -81,7 +78,7 @@ namespace keepass2android
ISharedPreferencesEditor edit = prefs.Edit();
edit.PutInt(GetString(Resource.String.LastInfoVersionCode_key), packageInfo.VersionCode);
EditorCompat.apply(edit);
EditorCompat.Apply(edit);
}
} catch (PackageManager.NameNotFoundException)
@ -102,13 +99,13 @@ namespace keepass2android
GetString(Resource.String.ChangeLog)
};
builder.SetPositiveButton(Android.Resource.String.Ok,new EventHandler<DialogClickEventArgs>((dlgSender, dlgEvt)=>{}));
builder.SetPositiveButton(Android.Resource.String.Ok,(dlgSender, dlgEvt)=>{});
builder.SetMessage("temp");
Dialog dialog = builder.Create();
dialog.DismissEvent += (object sender, EventArgs e) =>
dialog.DismissEvent += (sender, e) =>
{
startFileSelect();
StartFileSelect();
};
dialog.Show();
TextView message = (TextView) dialog.FindViewById(Android.Resource.Id.Message);
@ -121,7 +118,7 @@ namespace keepass2android
} else
{
startFileSelect();
StartFileSelect();
}
@ -159,13 +156,13 @@ namespace keepass2android
}
private void startFileSelect() {
private void StartFileSelect() {
Intent intent = new Intent(this, typeof(FileSelectActivity));
//TEST Intent intent = new Intent(this, typeof(EntryActivity));
//Intent intent = new Intent(this, typeof(SearchActivity));
//Intent intent = new Intent(this, typeof(QuickUnlock));
mAppTask.ToIntent(intent);
_appTask.ToIntent(intent);
StartActivityForResult(intent, 0);

View File

@ -16,40 +16,33 @@ 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
{
public abstract class LifecycleDebugActivity : Activity
{
public LifecycleDebugActivity (IntPtr javaReference, JniHandleOwnership transfer)
protected LifecycleDebugActivity (IntPtr javaReference, JniHandleOwnership transfer)
: base(javaReference, transfer)
{
}
public LifecycleDebugActivity()
protected LifecycleDebugActivity()
{
}
string className = null;
string _className;
string ClassName
{
get {
if (className == null)
className = this.GetType().Name;
return className;
if (_className == null)
_className = GetType().Name;
return _className;
}
}

View File

@ -15,29 +15,23 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file
along with Keepass2Android. If not, see <http://www.gnu.org/licenses/>.
*/
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.Serialization;
namespace keepass2android
{
/// <summary>
/// Base class for activities displaying sensitive information.
/// </summary>
/// Checks in OnResume whether the timeout occured and the database must be locked/closed.
public class LockCloseActivity : LockingActivity {
IOConnectionInfo mIoc;
IOConnectionInfo _ioc;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
mIoc = App.getDB().mIoc;
_ioc = App.Kp2a.GetDb().Ioc;
}
@ -45,13 +39,15 @@ namespace keepass2android
{
base.OnResume();
if (TimeoutHelper.checkShutdown(this, mIoc))
if (TimeoutHelper.CheckShutdown(this, _ioc))
return;
App.getDB().CheckForOpenFileChanged(this);
App.Kp2a.CheckForOpenFileChanged(this);
}
}
}

View File

@ -16,33 +16,28 @@ 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.Serialization;
namespace keepass2android
{
/// <summary>
/// Base class for list activities displaying sensitive information.
/// </summary>
/// Checks in OnResume whether the timeout occured and the database must be locked/closed.
public class LockCloseListActivity : LockingListActivity {
public LockCloseListActivity()
{
}
IOConnectionInfo mIoc;
IOConnectionInfo _ioc;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
mIoc = App.getDB().mIoc;
_ioc = App.Kp2a.GetDb().Ioc;
}
public LockCloseListActivity (IntPtr javaReference, JniHandleOwnership transfer)
@ -55,10 +50,10 @@ namespace keepass2android
{
base.OnResume();
if (TimeoutHelper.checkShutdown(this, mIoc))
if (TimeoutHelper.CheckShutdown(this, _ioc))
return;
App.getDB().CheckForOpenFileChanged(this);
App.Kp2a.CheckForOpenFileChanged(this);
}
}

View File

@ -16,20 +16,13 @@ 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
{
/// <summary>
/// Base class for activities. Notifies the TimeoutHelper whether the app is active or not.
/// </summary>
public class LockingActivity : LifecycleDebugActivity {
public LockingActivity (IntPtr javaReference, JniHandleOwnership transfer)
@ -45,7 +38,7 @@ namespace keepass2android
protected override void OnPause() {
base.OnPause();
TimeoutHelper.pause(this);
TimeoutHelper.Pause(this);
}
protected override void OnDestroy()
@ -57,7 +50,7 @@ namespace keepass2android
protected override void OnResume() {
base.OnResume();
TimeoutHelper.resume(this);
TimeoutHelper.Resume(this);
}
}
}

View File

@ -15,17 +15,7 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file
along with Keepass2Android. If not, see <http://www.gnu.org/licenses/>.
*/
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.Serialization;
namespace keepass2android
@ -34,18 +24,18 @@ namespace keepass2android
public class LockingClosePreferenceActivity : LockingPreferenceActivity {
IOConnectionInfo mIoc;
IOConnectionInfo _ioc;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
mIoc = App.getDB().mIoc;
_ioc = App.Kp2a.GetDb().Ioc;
}
protected override void OnResume() {
base.OnResume();
TimeoutHelper.checkShutdown(this, mIoc);
TimeoutHelper.CheckShutdown(this, _ioc);
}
}

View File

@ -16,20 +16,15 @@ 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
{
/// <summary>
/// Base class for list activities. Notifies the TimeoutHelper whether the app is active or not.
/// </summary>
public class LockingListActivity : ListActivity {
@ -43,20 +38,20 @@ namespace keepass2android
}
string className = null;
string _className;
string ClassName
{
get {
if (className == null)
className = this.GetType().Name;
return className;
if (_className == null)
_className = GetType().Name;
return _className;
}
}
protected override void OnResume()
{
base.OnResume();
TimeoutHelper.resume(this);
TimeoutHelper.Resume(this);
Android.Util.Log.Debug("DEBUG",ClassName+".OnResume");
}
@ -82,7 +77,7 @@ namespace keepass2android
protected override void OnPause()
{
base.OnPause();
TimeoutHelper.pause(this);
TimeoutHelper.Pause(this);
Android.Util.Log.Debug("DEBUG",ClassName+".OnPause");
}

View File

@ -16,16 +16,8 @@ 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 Android.Preferences;
namespace keepass2android
@ -43,20 +35,20 @@ namespace keepass2android
}
string className = null;
string _className = null;
string ClassName
{
get {
if (className == null)
className = this.GetType().Name;
return className;
if (_className == null)
_className = this.GetType().Name;
return _className;
}
}
protected override void OnResume()
{
base.OnResume();
TimeoutHelper.resume(this);
TimeoutHelper.Resume(this);
Android.Util.Log.Debug("DEBUG",ClassName+".OnResume");
}
@ -82,7 +74,7 @@ namespace keepass2android
protected override void OnPause()
{
base.OnPause();
TimeoutHelper.pause(this);
TimeoutHelper.Pause(this);
Android.Util.Log.Debug("DEBUG",ClassName+".OnPause");
}

View File

@ -16,10 +16,6 @@ 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;
@ -31,10 +27,8 @@ using Android.Preferences;
using Java.IO;
using Android.Text;
using Android.Content.PM;
using Android.Text.Method;
using KeePassLib.Keys;
using KeePassLib.Serialization;
using Android.Views.InputMethods;
namespace keepass2android
{
@ -43,22 +37,22 @@ namespace keepass2android
Theme="@style/Base")]
public class PasswordActivity : LockingActivity {
bool mShowPassword = false;
bool _showPassword;
public const String KEY_DEFAULT_FILENAME = "defaultFileName";
public const String KeyDefaultFilename = "defaultFileName";
public const String KEY_FILENAME = "fileName";
private const String KEY_KEYFILE = "keyFile";
private const String KEY_SERVERUSERNAME = "serverCredUser";
private const String KEY_SERVERPASSWORD = "serverCredPwd";
private const String KEY_SERVERCREDMODE = "serverCredRememberMode";
public const String KeyFilename = "fileName";
private const String KeyKeyfile = "keyFile";
private const String KeyServerusername = "serverCredUser";
private const String KeyServerpassword = "serverCredPwd";
private const String KeyServercredmode = "serverCredRememberMode";
private const String VIEW_INTENT = "android.intent.action.VIEW";
private const String ViewIntent = "android.intent.action.VIEW";
private IOConnectionInfo mIoConnection;
private String mKeyFile;
private bool mRememberKeyfile;
ISharedPreferences prefs;
private IOConnectionInfo _ioConnection;
private String _keyFile;
private bool _rememberKeyfile;
ISharedPreferences _prefs;
public PasswordActivity (IntPtr javaReference, JniHandleOwnership transfer)
: base(javaReference, transfer)
@ -72,31 +66,31 @@ namespace keepass2android
}
static void PutIoConnectionToIntent(IOConnectionInfo ioc, Android.Content.Intent i)
static void PutIoConnectionToIntent(IOConnectionInfo ioc, Intent i)
{
i.PutExtra(KEY_FILENAME, ioc.Path);
i.PutExtra(KEY_SERVERUSERNAME, ioc.UserName);
i.PutExtra(KEY_SERVERPASSWORD, ioc.Password);
i.PutExtra(KEY_SERVERCREDMODE, (int)ioc.CredSaveMode);
i.PutExtra(KeyFilename, ioc.Path);
i.PutExtra(KeyServerusername, ioc.UserName);
i.PutExtra(KeyServerpassword, ioc.Password);
i.PutExtra(KeyServercredmode, (int)ioc.CredSaveMode);
}
public static void SetIoConnectionFromIntent(IOConnectionInfo ioc, Intent i)
{
ioc.Path = i.GetStringExtra(KEY_FILENAME);
ioc.UserName = i.GetStringExtra(KEY_SERVERUSERNAME) ?? "";
ioc.Password = i.GetStringExtra(KEY_SERVERPASSWORD) ?? "";
ioc.CredSaveMode = (IOCredSaveMode)i.GetIntExtra(KEY_SERVERCREDMODE, (int) IOCredSaveMode.NoSave);
ioc.Path = i.GetStringExtra(KeyFilename);
ioc.UserName = i.GetStringExtra(KeyServerusername) ?? "";
ioc.Password = i.GetStringExtra(KeyServerpassword) ?? "";
ioc.CredSaveMode = (IOCredSaveMode)i.GetIntExtra(KeyServercredmode, (int) IOCredSaveMode.NoSave);
}
public static void Launch(Activity act, String fileName, AppTask appTask) {
Java.IO.File dbFile = new Java.IO.File(fileName);
File dbFile = new File(fileName);
if ( ! dbFile.Exists() ) {
throw new Java.IO.FileNotFoundException();
throw new FileNotFoundException();
}
Intent i = new Intent(act, typeof(PasswordActivity));
i.PutExtra(KEY_FILENAME, fileName);
i.PutExtra(KeyFilename, fileName);
appTask.ToIntent(i);
act.StartActivityForResult(i, 0);
@ -128,52 +122,52 @@ namespace keepass2android
public void LaunchNextActivity()
{
mAppTask.AfterUnlockDatabase(this);
AppTask.AfterUnlockDatabase(this);
}
void unloadDatabase()
void UnloadDatabase()
{
App.getDB().Clear();
App.Kp2a.GetDb().Clear();
StopService(new Intent(this, typeof(QuickUnlockForegroundService)));
}
void lockDatabase()
void LockDatabase()
{
SetResult(KeePass.EXIT_LOCK);
setEditText(Resource.Id.password, "");
if (App.getDB().QuickUnlockEnabled)
App.getDB().Locked = true;
SetResult(KeePass.ExitLock);
SetEditText(Resource.Id.password, "");
if (App.Kp2a.GetDb().QuickUnlockEnabled)
App.Kp2a.GetDb().Locked = true;
else
{
unloadDatabase();
UnloadDatabase();
}
}
void lockAndClose()
void LockAndClose()
{
lockDatabase();
LockDatabase();
Finish();
}
bool tryStartQuickUnlock()
bool TryStartQuickUnlock()
{
if (!App.getDB().QuickUnlockEnabled)
if (!App.Kp2a.GetDb().QuickUnlockEnabled)
return false;
if (App.getDB().pm.MasterKey.ContainsType(typeof(KcpPassword)) == false)
if (App.Kp2a.GetDb().KpDatabase.MasterKey.ContainsType(typeof(KcpPassword)) == false)
return false;
KcpPassword kcpPassword = (KcpPassword)App.getDB().pm.MasterKey.GetUserKey(typeof(KcpPassword));
KcpPassword kcpPassword = (KcpPassword)App.Kp2a.GetDb().KpDatabase.MasterKey.GetUserKey(typeof(KcpPassword));
String password = kcpPassword.Password.ReadString();
if (password.Length == 0)
return false;
App.getDB().Locked = true;
App.Kp2a.GetDb().Locked = true;
Intent i = new Intent(this, typeof(QuickUnlock));
PutIoConnectionToIntent(mIoConnection, i);
PutIoConnectionToIntent(_ioConnection, i);
Android.Util.Log.Debug("DEBUG","Starting QuickUnlock");
StartActivityForResult(i,0);
return true;
@ -181,22 +175,22 @@ namespace keepass2android
public void StartQuickUnlockForegroundService()
{
if (App.getDB().QuickUnlockEnabled)
if (App.Kp2a.GetDb().QuickUnlockEnabled)
{
StartService(new Intent(this, typeof(QuickUnlockForegroundService)));
}
}
bool startedWithActivityResult = false;
bool _startedWithActivityResult;
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
base.OnActivityResult(requestCode, resultCode, data);
startedWithActivityResult = true;
_startedWithActivityResult = true;
Android.Util.Log.Debug("DEBUG","PasswordActivity.OnActivityResult "+resultCode+"/"+requestCode);
if (resultCode != KeePass.EXIT_CLOSE_AFTER_TASK_COMPLETE)
if (resultCode != KeePass.ExitCloseAfterTaskComplete)
{
//Stop service when app activity is left
StopService(new Intent(this, typeof(CopyToClipboardService)));
@ -205,64 +199,63 @@ namespace keepass2android
//NOTE: original code from k eepassdroid used switch ((Android.App.Result)requestCode) { (but doesn't work here, although k eepassdroid works)
switch(resultCode) {
case KeePass.EXIT_NORMAL:
if (!tryStartQuickUnlock())
case KeePass.ExitNormal:
if (!TryStartQuickUnlock())
{
setEditText(Resource.Id.password, "");
;
SetEditText(Resource.Id.password, "");
}
break;
case KeePass.EXIT_LOCK:
if (!tryStartQuickUnlock())
case KeePass.ExitLock:
if (!TryStartQuickUnlock())
{
lockAndClose();
LockAndClose();
}
break;
case KeePass.EXIT_FORCE_LOCK:
setEditText(Resource.Id.password, "");
unloadDatabase();
case KeePass.ExitForceLock:
SetEditText(Resource.Id.password, "");
UnloadDatabase();
break;
case KeePass.EXIT_FORCE_LOCK_AND_CHANGE_DB:
unloadDatabase();
case KeePass.ExitForceLockAndChangeDb:
UnloadDatabase();
Finish();
break;
case KeePass.EXIT_CHANGE_DB:
lockAndClose();
case KeePass.ExitChangeDb:
LockAndClose();
break;
case KeePass.EXIT_CLOSE_AFTER_TASK_COMPLETE:
SetResult(KeePass.EXIT_CLOSE_AFTER_TASK_COMPLETE);
case KeePass.ExitCloseAfterTaskComplete:
SetResult(KeePass.ExitCloseAfterTaskComplete);
Finish();
break;
case KeePass.EXIT_QUICK_UNLOCK:
App.getDB().Locked = false;
case KeePass.ExitQuickUnlock:
App.Kp2a.GetDb().Locked = false;
LaunchNextActivity();
break;
case KeePass.EXIT_RELOAD_DB:
case KeePass.ExitReloadDb:
//if the activity was killed, fill password/keyfile so the user can directly hit load again
if (App.getDB().Loaded)
if (App.Kp2a.GetDb().Loaded)
{
if (App.getDB().pm.MasterKey.ContainsType(typeof(KcpPassword)))
if (App.Kp2a.GetDb().KpDatabase.MasterKey.ContainsType(typeof(KcpPassword)))
{
KcpPassword kcpPassword = (KcpPassword)App.getDB().pm.MasterKey.GetUserKey(typeof(KcpPassword));
KcpPassword kcpPassword = (KcpPassword)App.Kp2a.GetDb().KpDatabase.MasterKey.GetUserKey(typeof(KcpPassword));
String password = kcpPassword.Password.ReadString();
setEditText(Resource.Id.password, password);
SetEditText(Resource.Id.password, password);
}
if (App.getDB().pm.MasterKey.ContainsType(typeof(KcpKeyFile)))
if (App.Kp2a.GetDb().KpDatabase.MasterKey.ContainsType(typeof(KcpKeyFile)))
{
KcpKeyFile kcpKeyfile = (KcpKeyFile)App.getDB().pm.MasterKey.GetUserKey(typeof(KcpKeyFile));
KcpKeyFile kcpKeyfile = (KcpKeyFile)App.Kp2a.GetDb().KpDatabase.MasterKey.GetUserKey(typeof(KcpKeyFile));
setEditText(Resource.Id.pass_keyfile, kcpKeyfile.Path);
SetEditText(Resource.Id.pass_keyfile, kcpKeyfile.Path);
}
}
unloadDatabase();
UnloadDatabase();
break;
case Android.App.Result.Ok:
if (requestCode == Intents.REQUEST_CODE_FILE_BROWSE_FOR_KEYFILE) {
case Result.Ok:
if (requestCode == Intents.RequestCodeFileBrowseForKeyfile) {
string filename = Util.IntentToFilename(data);
if (filename != null) {
if (filename.StartsWith("file://")) {
@ -280,7 +273,7 @@ namespace keepass2android
}
internal AppTask mAppTask;
internal AppTask AppTask;
protected override void OnCreate(Bundle savedInstanceState)
{
@ -289,17 +282,17 @@ namespace keepass2android
Intent i = Intent;
String action = i.Action;
prefs = PreferenceManager.GetDefaultSharedPreferences(this);
mRememberKeyfile = prefs.GetBoolean(GetString(Resource.String.keyfile_key), Resources.GetBoolean(Resource.Boolean.keyfile_default));
_prefs = PreferenceManager.GetDefaultSharedPreferences(this);
_rememberKeyfile = _prefs.GetBoolean(GetString(Resource.String.keyfile_key), Resources.GetBoolean(Resource.Boolean.keyfile_default));
mIoConnection = new IOConnectionInfo();
_ioConnection = new IOConnectionInfo();
if (action != null && action.Equals(VIEW_INTENT))
if (action != null && action.Equals(ViewIntent))
{
mIoConnection.Path = i.DataString;
_ioConnection.Path = i.DataString;
if (! mIoConnection.Path.Substring(0, 7).Equals("file://"))
if (! _ioConnection.Path.Substring(0, 7).Equals("file://"))
{
//TODO: this might no longer be required as we can handle http(s) and ftp as well (but we need server credentials therefore)
Toast.MakeText(this, Resource.String.error_can_not_handle_uri, ToastLength.Long).Show();
@ -307,9 +300,9 @@ namespace keepass2android
return;
}
mIoConnection.Path = URLDecoder.Decode(mIoConnection.Path.Substring(7));
_ioConnection.Path = URLDecoder.Decode(_ioConnection.Path.Substring(7));
if (mIoConnection.Path.Length == 0)
if (_ioConnection.Path.Length == 0)
{
// No file name
Toast.MakeText(this, Resource.String.FileNotFound, ToastLength.Long).Show();
@ -317,7 +310,7 @@ namespace keepass2android
return;
}
File dbFile = new File(mIoConnection.Path);
File dbFile = new File(_ioConnection.Path);
if (! dbFile.Exists())
{
// File does not exist
@ -326,22 +319,22 @@ namespace keepass2android
return;
}
mKeyFile = getKeyFile(mIoConnection.Path);
_keyFile = GetKeyFile(_ioConnection.Path);
} else
{
SetIoConnectionFromIntent(mIoConnection, i);
mKeyFile = i.GetStringExtra(KEY_KEYFILE);
if (mKeyFile == null || mKeyFile.Length == 0)
SetIoConnectionFromIntent(_ioConnection, i);
_keyFile = i.GetStringExtra(KeyKeyfile);
if (string.IsNullOrEmpty(_keyFile))
{
mKeyFile = getKeyFile(mIoConnection.Path);
_keyFile = GetKeyFile(_ioConnection.Path);
}
}
mAppTask = AppTask.GetTaskInOnCreate(savedInstanceState, Intent);
AppTask = AppTask.GetTaskInOnCreate(savedInstanceState, Intent);
SetContentView(Resource.Layout.password);
populateView();
PopulateView();
EditText passwordEdit = FindViewById<EditText>(Resource.Id.password);
@ -350,33 +343,30 @@ namespace keepass2android
Window.SetSoftInputMode(SoftInput.StateVisible);
Button confirmButton = (Button)FindViewById(Resource.Id.pass_ok);
confirmButton.Click += (object sender, EventArgs e) =>
confirmButton.Click += (sender, e) =>
{
String pass = GetEditText(Resource.Id.password);
String key = GetEditText(Resource.Id.pass_keyfile);
if (pass.Length == 0 && key.Length == 0)
{
errorMessage(Resource.String.error_nopass);
ErrorMessage(Resource.String.error_nopass);
return;
}
String fileName = GetEditText(Resource.Id.filename);
// Clear before we load
unloadDatabase();
UnloadDatabase();
// Clear the shutdown flag
App.clearShutdown();
App.Kp2a.ClearShutdown();
CheckBox cbQuickUnlock = (CheckBox)FindViewById(Resource.Id.enable_quickunlock);
App.getDB().QuickUnlockEnabled = cbQuickUnlock.Checked;
App.getDB().QuickUnlockKeyLength = int.Parse(prefs.GetString(GetString(Resource.String.QuickUnlockLength_key), GetString(Resource.String.QuickUnlockLength_default)));
App.Kp2a.GetDb().QuickUnlockEnabled = cbQuickUnlock.Checked;
App.Kp2a.GetDb().QuickUnlockKeyLength = int.Parse(_prefs.GetString(GetString(Resource.String.QuickUnlockLength_key), GetString(Resource.String.QuickUnlockLength_default)));
Handler handler = new Handler();
LoadDB task = new LoadDB(App.getDB(), this, mIoConnection, pass, key, new AfterLoad(handler, this));
ProgressTask pt = new ProgressTask(this, task, Resource.String.loading_database);
pt.run();
LoadDb task = new LoadDb(App.Kp2a, _ioConnection, pass, key, new AfterLoad(handler, this));
ProgressTask pt = new ProgressTask(App.Kp2a, this, task, UiStringKey.loading_database);
pt.Run();
};
/*CheckBox checkBox = (CheckBox) FindViewById(Resource.Id.show_password);
@ -392,10 +382,10 @@ namespace keepass2android
};
*/
ImageButton btnTogglePassword = (ImageButton)FindViewById(Resource.Id.toggle_password);
btnTogglePassword.Click += (object sender, EventArgs e) => {
mShowPassword = !mShowPassword;
btnTogglePassword.Click += (sender, e) => {
_showPassword = !_showPassword;
TextView password = (TextView)FindViewById(Resource.Id.password);
if (mShowPassword)
if (_showPassword)
{
password.InputType = InputTypes.ClassText | InputTypes.TextVariationVisiblePassword;
} else
@ -405,49 +395,49 @@ namespace keepass2android
};
CheckBox defaultCheck = (CheckBox)FindViewById(Resource.Id.default_database);
///Don't allow the current file to be the default if we don't have stored credentials
if ((mIoConnection.IsLocalFile() == false) && (mIoConnection.CredSaveMode != IOCredSaveMode.SaveCred))
//Don't allow the current file to be the default if we don't have stored credentials
if ((_ioConnection.IsLocalFile() == false) && (_ioConnection.CredSaveMode != IOCredSaveMode.SaveCred))
{
defaultCheck.Enabled = false;
} else
{
defaultCheck.Enabled = true;
}
defaultCheck.CheckedChange += (object sender, CompoundButton.CheckedChangeEventArgs e) =>
defaultCheck.CheckedChange += (sender, e) =>
{
String newDefaultFileName;
if (e.IsChecked)
{
newDefaultFileName = mIoConnection.Path;
newDefaultFileName = _ioConnection.Path;
} else
{
newDefaultFileName = "";
}
ISharedPreferencesEditor editor = prefs.Edit();
editor.PutString(KEY_DEFAULT_FILENAME, newDefaultFileName);
EditorCompat.apply(editor);
ISharedPreferencesEditor editor = _prefs.Edit();
editor.PutString(KeyDefaultFilename, newDefaultFileName);
EditorCompat.Apply(editor);
};
ImageButton browse = (ImageButton)FindViewById(Resource.Id.browse_button);
browse.Click += (object sender, EventArgs evt) =>
browse.Click += (sender, evt) =>
{
string filename = null;
if (!String.IsNullOrEmpty(mIoConnection.Path))
if (!String.IsNullOrEmpty(_ioConnection.Path))
{
File keyfile = new File(mIoConnection.Path);
File keyfile = new File(_ioConnection.Path);
File parent = keyfile.ParentFile;
if (parent != null)
{
filename = parent.AbsolutePath;
}
}
Util.showBrowseDialog(filename, this, Intents.REQUEST_CODE_FILE_BROWSE_FOR_KEYFILE, false);
Util.showBrowseDialog(filename, this, Intents.RequestCodeFileBrowseForKeyfile, false);
};
retrieveSettings();
RetrieveSettings();
}
@ -455,7 +445,7 @@ namespace keepass2android
protected override void OnSaveInstanceState(Bundle outState)
{
base.OnSaveInstanceState(outState);
mAppTask.ToBundle(outState);
AppTask.ToBundle(outState);
}
protected override void OnResume() {
@ -463,45 +453,45 @@ namespace keepass2android
// If the application was shutdown make sure to clear the password field, if it
// was saved in the instance state
if (App.isShutdown()) {
lockDatabase();
if (App.Kp2a.IsShutdown()) {
LockDatabase();
}
// Clear the shutdown flag
App.clearShutdown();
App.Kp2a.ClearShutdown();
if (startedWithActivityResult)
if (_startedWithActivityResult)
return;
if (App.getDB().Loaded && (App.getDB().mIoc != null)
&& (mIoConnection != null) && (App.getDB().mIoc.GetDisplayName() == mIoConnection.GetDisplayName()))
if (App.Kp2a.GetDb().Loaded && (App.Kp2a.GetDb().Ioc != null)
&& (_ioConnection != null) && (App.Kp2a.GetDb().Ioc.GetDisplayName() == _ioConnection.GetDisplayName()))
{
if (App.getDB().Locked == false)
if (App.Kp2a.GetDb().Locked == false)
{
LaunchNextActivity();
}
else
{
tryStartQuickUnlock();
TryStartQuickUnlock();
}
}
}
private void retrieveSettings() {
String defaultFilename = prefs.GetString(KEY_DEFAULT_FILENAME, "");
if (!String.IsNullOrEmpty(mIoConnection.Path) && mIoConnection.Path.Equals(defaultFilename)) {
private void RetrieveSettings() {
String defaultFilename = _prefs.GetString(KeyDefaultFilename, "");
if (!String.IsNullOrEmpty(_ioConnection.Path) && _ioConnection.Path.Equals(defaultFilename)) {
CheckBox checkbox = (CheckBox) FindViewById(Resource.Id.default_database);
checkbox.Checked = true;
}
CheckBox cbQuickUnlock = (CheckBox)FindViewById(Resource.Id.enable_quickunlock);
cbQuickUnlock.Checked = prefs.GetBoolean(GetString(Resource.String.QuickUnlockDefaultEnabled_key), true);
cbQuickUnlock.Checked = _prefs.GetBoolean(GetString(Resource.String.QuickUnlockDefaultEnabled_key), true);
}
private String getKeyFile(String filename) {
if ( mRememberKeyfile ) {
FileDbHelper dbHelp = App.fileDbHelper;
private String GetKeyFile(String filename) {
if ( _rememberKeyfile ) {
FileDbHelper dbHelp = App.Kp2a.FileDbHelper;
String keyfile = dbHelp.getFileByName(filename);
String keyfile = dbHelp.GetFileByName(filename);
return keyfile;
} else {
@ -509,9 +499,9 @@ namespace keepass2android
}
}
private void populateView() {
setEditText(Resource.Id.filename, mIoConnection.GetDisplayName());
setEditText(Resource.Id.pass_keyfile, mKeyFile);
private void PopulateView() {
SetEditText(Resource.Id.filename, _ioConnection.GetDisplayName());
SetEditText(Resource.Id.pass_keyfile, _keyFile);
}
/*
@ -521,7 +511,7 @@ namespace keepass2android
}
*/
private void errorMessage(int resId)
private void ErrorMessage(int resId)
{
Toast.MakeText(this, resId, ToastLength.Long).Show();
}
@ -530,7 +520,7 @@ namespace keepass2android
return Util.getEditText(this, resId);
}
private void setEditText(int resId, String str) {
private void SetEditText(int resId, String str) {
TextView te = (TextView) FindViewById(resId);
//assert(te == null);
@ -564,20 +554,18 @@ namespace keepass2android
}
private class AfterLoad : OnFinish {
PasswordActivity act;
readonly PasswordActivity _act;
public AfterLoad(Handler handler, PasswordActivity act):base(handler) {
this.act = act;
_act = act;
}
public override void run() {
if ( mSuccess ) {
act.StartQuickUnlockForegroundService();
act.LaunchNextActivity();
public override void Run() {
if ( Success ) {
_act.StartQuickUnlockForegroundService();
_act.LaunchNextActivity();
} else {
displayMessage(act);
DisplayMessage(_act);
}
}
}

View File

@ -17,13 +17,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 Android.Preferences;
@ -36,19 +30,19 @@ namespace keepass2android
public class PwGroupListAdapter : BaseAdapter
{
private GroupBaseActivity mAct;
private PwGroup mGroup;
private List<PwGroup> groupsForViewing;
private List<PwEntry> entriesForViewing;
private readonly GroupBaseActivity _act;
private readonly PwGroup _group;
private List<PwGroup> _groupsForViewing;
private List<PwEntry> _entriesForViewing;
private ISharedPreferences prefs;
private readonly ISharedPreferences _prefs;
public PwGroupListAdapter(GroupBaseActivity act, PwGroup group) {
mAct = act;
mGroup = group;
prefs = PreferenceManager.GetDefaultSharedPreferences(act);
_act = act;
_group = group;
_prefs = PreferenceManager.GetDefaultSharedPreferences(act);
filterAndSort();
FilterAndSort();
}
@ -56,41 +50,41 @@ namespace keepass2android
public override void NotifyDataSetChanged() {
base.NotifyDataSetChanged();
filterAndSort();
FilterAndSort();
}
public override void NotifyDataSetInvalidated() {
base.NotifyDataSetInvalidated();
filterAndSort();
FilterAndSort();
}
private void filterAndSort() {
entriesForViewing = new List<PwEntry>();
private void FilterAndSort() {
_entriesForViewing = new List<PwEntry>();
foreach (PwEntry entry in mGroup.Entries)
foreach (PwEntry entry in _group.Entries)
{
entriesForViewing.Add(entry);
_entriesForViewing.Add(entry);
}
bool sortLists = prefs.GetBoolean(mAct.GetString(Resource.String.sort_key), mAct.Resources.GetBoolean(Resource.Boolean.sort_default));
bool sortLists = _prefs.GetBoolean(_act.GetString(Resource.String.sort_key), _act.Resources.GetBoolean(Resource.Boolean.sort_default));
if ( sortLists )
{
groupsForViewing = new List<PwGroup>(mGroup.Groups);
groupsForViewing.Sort( (PwGroup x,PwGroup y) => { return String.Compare (x.Name, y.Name, true); });
entriesForViewing.Sort( (PwEntry x, PwEntry y) =>
_groupsForViewing = new List<PwGroup>(_group.Groups);
_groupsForViewing.Sort( (x, y) => { return String.Compare (x.Name, y.Name, true); });
_entriesForViewing.Sort( (x, y) =>
{
String nameX = x.Strings.ReadSafe(PwDefs.TitleField);
String nameY = y.Strings.ReadSafe(PwDefs.TitleField);
if (nameX.ToLower() != nameY.ToLower())
return String.Compare (nameX,nameY,true);
return String.Compare(nameX, nameY, StringComparison.OrdinalIgnoreCase);
else
return x.CreationTime.CompareTo(y.CreationTime);
}
);
} else {
groupsForViewing = new List<PwGroup>(mGroup.Groups);
_groupsForViewing = new List<PwGroup>(_group.Groups);
}
}
@ -98,7 +92,7 @@ namespace keepass2android
{
get{
return groupsForViewing.Count + entriesForViewing.Count;
return _groupsForViewing.Count + _entriesForViewing.Count;
}
}
@ -111,42 +105,42 @@ namespace keepass2android
}
public override View GetView(int position, View convertView, ViewGroup parent) {
int size = groupsForViewing.Count;
int size = _groupsForViewing.Count;
if ( position < size ) {
return createGroupView(position, convertView);
return CreateGroupView(position, convertView);
} else {
return createEntryView(position - size, convertView);
return CreateEntryView(position - size, convertView);
}
}
private View createGroupView(int position, View convertView) {
PwGroup g = groupsForViewing[position];
private View CreateGroupView(int position, View convertView) {
PwGroup g = _groupsForViewing[position];
PwGroupView gv;
if (convertView == null || !(convertView is PwGroupView)) {
gv = PwGroupView.getInstance(mAct, g);
gv = PwGroupView.GetInstance(_act, g);
}
else {
gv = (PwGroupView) convertView;
gv.convertView(g);
gv.ConvertView(g);
}
return gv;
}
private PwEntryView createEntryView(int position, View convertView) {
PwEntry entry = entriesForViewing[position];
private PwEntryView CreateEntryView(int position, View convertView) {
PwEntry entry = _entriesForViewing[position];
PwEntryView ev;
if (convertView == null || !(convertView is PwEntryView)) {
ev = PwEntryView.getInstance(mAct, entry, position);
ev = PwEntryView.GetInstance(_act, entry, position);
}
else {
ev = (PwEntryView) convertView;
ev.convertView(entry, position);
ev.ConvertView(entry, position);
}
return ev;

View File

@ -16,14 +16,9 @@ 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;
using Android.Content.PM;
@ -37,16 +32,15 @@ namespace keepass2android
[Activity (Label = "@string/app_name", ConfigurationChanges=ConfigChanges.Orientation|ConfigChanges.KeyboardHidden, Theme="@style/Base")]
public class QuickUnlock : LifecycleDebugActivity
{
IOConnectionInfo mIoc;
IOConnectionInfo _ioc;
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
Intent i = Intent;
mIoc = App.getDB().mIoc;
_ioc = App.Kp2a.GetDb().Ioc;
if (mIoc == null)
if (_ioc == null)
{
Finish();
return;
@ -55,20 +49,19 @@ namespace keepass2android
SetContentView(Resource.Layout.QuickUnlock);
if (App.getDB().pm.Name != "")
if (App.Kp2a.GetDb().KpDatabase.Name != "")
{
FindViewById(Resource.Id.filename_label).Visibility = ViewStates.Invisible;
((TextView)FindViewById(Resource.Id.qu_filename)).Text = App.getDB().pm.Name;
((TextView)FindViewById(Resource.Id.qu_filename)).Text = App.Kp2a.GetDb().KpDatabase.Name;
} else
{
((TextView)FindViewById(Resource.Id.qu_filename)).Text = mIoc.Path;
((TextView)FindViewById(Resource.Id.qu_filename)).Text = _ioc.Path;
}
TextView txtLabel = (TextView)FindViewById(Resource.Id.QuickUnlock_label);
ISharedPreferences prefs = PreferenceManager.GetDefaultSharedPreferences(this);
int quickUnlockLength = App.getDB().QuickUnlockKeyLength;
int quickUnlockLength = App.Kp2a.GetDb().QuickUnlockKeyLength;
txtLabel.Text = GetString(Resource.String.QuickUnlock_label, new Java.Lang.Object[]{quickUnlockLength});
@ -79,21 +72,21 @@ namespace keepass2android
keyboard.ShowSoftInput(pwd, 0);
}, 50);
SetResult(KeePass.EXIT_CHANGE_DB);
SetResult(KeePass.ExitChangeDb);
Button btnUnlock = (Button)FindViewById(Resource.Id.QuickUnlock_button);
btnUnlock.Click += (object sender, EventArgs e) =>
{
KcpPassword kcpPassword = (KcpPassword)App.getDB().pm.MasterKey.GetUserKey(typeof(KcpPassword));
KcpPassword kcpPassword = (KcpPassword)App.Kp2a.GetDb().KpDatabase.MasterKey.GetUserKey(typeof(KcpPassword));
String password = kcpPassword.Password.ReadString();
String expectedPasswordPart = password.Substring(Math.Max(0,password.Length-quickUnlockLength),Math.Min(password.Length, quickUnlockLength));
if (pwd.Text == expectedPasswordPart)
{
SetResult(KeePass.EXIT_QUICK_UNLOCK);
SetResult(KeePass.ExitQuickUnlock);
}
else
{
SetResult(KeePass.EXIT_FORCE_LOCK);
SetResult(KeePass.ExitForceLock);
Toast.MakeText(this, GetString(Resource.String.QuickUnlock_fail), ToastLength.Long).Show();
}
Finish();
@ -102,7 +95,7 @@ namespace keepass2android
Button btnLock = (Button)FindViewById(Resource.Id.QuickUnlock_buttonLock);
btnLock.Click += (object sender, EventArgs e) =>
{
SetResult(KeePass.EXIT_FORCE_LOCK_AND_CHANGE_DB);
SetResult(KeePass.ExitForceLockAndChangeDb);
Finish();
};
}
@ -112,8 +105,8 @@ namespace keepass2android
{
base.OnResume();
if ( ! App.getDB().Loaded ) {
SetResult(KeePass.EXIT_CHANGE_DB);
if ( ! App.Kp2a.GetDb().Loaded ) {
SetResult(KeePass.ExitChangeDb);
Finish();
return;
}

File diff suppressed because it is too large Load Diff

View File

@ -15,15 +15,8 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file
along with Keepass2Android. If not, see <http://www.gnu.org/licenses/>.
*/
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
@ -32,22 +25,18 @@ namespace keepass2android
public class SetPasswordDialog : CancelDialog
{
internal String mKeyfile;
private FileOnFinish mFinish;
internal String Keyfile;
private readonly FileOnFinish _finish;
public SetPasswordDialog(Context context):base(context) {
}
public SetPasswordDialog(Context context, FileOnFinish finish):base(context) {
mFinish = finish;
_finish = finish;
}
public String keyfile() {
return mKeyfile;
}
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
@ -57,7 +46,7 @@ namespace keepass2android
// Ok button
Button okButton = (Button) FindViewById(Resource.Id.ok);
okButton.Click += (object sender, EventArgs e) =>
okButton.Click += (sender, e) =>
{
TextView passView = (TextView) FindViewById(Resource.Id.pass_password);
String pass = passView.Text;
@ -73,7 +62,7 @@ namespace keepass2android
TextView keyfileView = (TextView) FindViewById(Resource.Id.pass_keyfile);
String keyfile = keyfileView.Text;
mKeyfile = keyfile;
Keyfile = keyfile;
// Verify that a password or keyfile is set
if ( pass.Length == 0 && keyfile.Length == 0 ) {
@ -82,9 +71,9 @@ namespace keepass2android
}
SetPassword sp = new SetPassword(Context, App.getDB(), pass, keyfile, new AfterSave(this, mFinish, new Handler()));
ProgressTask pt = new ProgressTask(Context, sp, Resource.String.saving_database);
pt.run();
SetPassword sp = new SetPassword(Context, App.Kp2a.GetDb(), pass, keyfile, new AfterSave(this, _finish, new Handler()));
ProgressTask pt = new ProgressTask(App.Kp2a, Context, sp, UiStringKey.saving_database);
pt.Run();
};
@ -93,8 +82,8 @@ namespace keepass2android
Button cancelButton = (Button) FindViewById(Resource.Id.cancel);
cancelButton.Click += (sender,e) => {
Cancel();
if ( mFinish != null ) {
mFinish.run();
if ( _finish != null ) {
_finish.Run();
}
};
}
@ -102,28 +91,28 @@ namespace keepass2android
class AfterSave : OnFinish {
private FileOnFinish mFinish;
private readonly FileOnFinish _finish;
SetPasswordDialog dlg;
readonly SetPasswordDialog _dlg;
public AfterSave(SetPasswordDialog dlg, FileOnFinish finish, Handler handler): base(finish, handler) {
mFinish = finish;
this.dlg = dlg;
_finish = finish;
_dlg = dlg;
}
public override void run() {
if ( mSuccess ) {
if ( mFinish != null ) {
mFinish.setFilename(dlg.mKeyfile);
public override void Run() {
if ( Success ) {
if ( _finish != null ) {
_finish.Filename = _dlg.Keyfile;
}
dlg.Dismiss();
_dlg.Dismiss();
} else {
displayMessage(dlg.Context);
DisplayMessage(_dlg.Context);
}
base.run();
base.Run();
}
}

View File

@ -17,17 +17,13 @@ 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;
using keepass2android.view;
using Android.Content.PM;
namespace keepass2android
@ -54,35 +50,35 @@ namespace keepass2android
}
private Database mDb;
private Database _db;
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
SetResult(KeePass.EXIT_CLOSE_AFTER_TASK_COMPLETE);
SetResult(KeePass.ExitCloseAfterTaskComplete);
mDb = App.getDB();
_db = App.Kp2a.GetDb();
String searchUrl = ((SearchUrlTask)mAppTask).UrlToSearchFor;
String searchUrl = ((SearchUrlTask)AppTask).UrlToSearchFor;
if (!mDb.Loaded)
if (!_db.Loaded)
{
Intent intent = new Intent(this, typeof(FileSelectActivity));
mAppTask.ToIntent(intent);
AppTask.ToIntent(intent);
StartActivityForResult(intent, 0);
Finish();
}
else if (mDb.Locked)
else if (_db.Locked)
{
PasswordActivity.Launch(this,mDb.mIoc, mAppTask);
PasswordActivity.Launch(this,_db.Ioc, AppTask);
Finish();
}
else
{
query(searchUrl);
Query(searchUrl);
}
}
@ -90,7 +86,7 @@ namespace keepass2android
protected override void OnSaveInstanceState(Bundle outState)
{
base.OnSaveInstanceState(outState);
mAppTask.ToBundle(outState);
AppTask.ToBundle(outState);
}
public override void LaunchActivityForEntry(KeePassLib.PwEntry pwEntry, int pos)
@ -99,12 +95,12 @@ namespace keepass2android
Finish();
}
private void query(String url)
private void Query(String url)
{
//first: search for exact url
try
{
mGroup = mDb.SearchForExactUrl(url);
Group = _db.SearchForExactUrl(url);
} catch (Exception e)
{
Toast.MakeText(this, e.Message, ToastLength.Long).Show();
@ -112,11 +108,11 @@ namespace keepass2android
return;
}
//if no results, search for host (e.g. "accounts.google.com")
if (mGroup.Entries.Count() == 0)
if (!Group.Entries.Any())
{
try
{
mGroup = mDb.SearchForHost(url, false);
Group = _db.SearchForHost(url, false);
} catch (Exception e)
{
Toast.MakeText(this, e.Message, ToastLength.Long).Show();
@ -125,11 +121,11 @@ namespace keepass2android
}
}
//if still no results, search for host, allowing subdomains ("www.google.com" in entry is ok for "accounts.google.com" in search (but not the other way around)
if (mGroup.Entries.Count() == 0)
if (!Group.Entries.Any())
{
try
{
mGroup = mDb.SearchForHost(url, true);
Group = _db.SearchForHost(url, true);
} catch (Exception e)
{
Toast.MakeText(this, e.Message, ToastLength.Long).Show();
@ -138,14 +134,14 @@ namespace keepass2android
}
}
//if there is exactly one match: open the entry
if (mGroup.Entries.Count() == 1)
if (Group.Entries.Count() == 1)
{
LaunchActivityForEntry(mGroup.Entries.Single(),0);
LaunchActivityForEntry(Group.Entries.Single(),0);
return;
}
//show results:
if (mGroup == null || (mGroup.Entries.Count() < 1))
if (Group == null || (!Group.Entries.Any()))
{
//SetContentView(new GroupEmptyView(this));
SetContentView(Resource.Layout.searchurlresults_empty);
@ -155,31 +151,25 @@ namespace keepass2android
//SetContentView(new GroupViewOnlyView(this));
}
setGroupTitle();
SetGroupTitle();
ListAdapter = new PwGroupListAdapter(this, mGroup);
ListAdapter = new PwGroupListAdapter(this, Group);
View selectOtherEntry = FindViewById (Resource.Id.select_other_entry);
selectOtherEntry.Click += (object sender, EventArgs e) => {
selectOtherEntry.Click += (sender, e) => {
GroupActivity.Launch (this, new SelectEntryTask());
};
View createUrlEntry = FindViewById (Resource.Id.add_url_entry);
createUrlEntry.Click += (object sender, EventArgs e) => {
GroupActivity.Launch (this, new CreateEntryThenCloseTask() { Url = url } );
createUrlEntry.Click += (sender, e) => {
GroupActivity.Launch (this, new CreateEntryThenCloseTask { Url = url } );
Toast.MakeText(this, GetString(Resource.String.select_group_then_add, new Java.Lang.Object[]{GetString(Resource.String.add_entry)}), ToastLength.Long ).Show();
};
}
private String getSearchUrl(Intent queryIntent) {
String queryAction = queryIntent.Action;
return queryIntent.GetStringExtra(Intent.ExtraText);
}
public override bool OnSearchRequested()
{
if (base.OnSearchRequested())

View File

@ -21,20 +21,14 @@ using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Security.Cryptography;
using KeePass.Util.Spr;
using KeePassLib;
using KeePassLib.Collections;
using KeePassLib.Cryptography;
using KeePassLib.Cryptography.PasswordGenerator;
using KeePassLib.Delegates;
using KeePassLib.Security;
using KeePassLib.Utility;
using KeePassLib.Serialization;
namespace KeePass.Util
{
@ -46,7 +40,6 @@ namespace KeePass.Util
// Old format name (<= 2.14): "KeePassEntriesCF"
public const string ClipFormatEntries = "KeePassEntriesCX";
private static byte[] AdditionalEntropy = { 0xF8, 0x03, 0xFA, 0x51, 0x87, 0x18, 0x49, 0x5D };
public static string FillPlaceholders(string strText, SprContext ctx)
{

View File

@ -1,62 +0,0 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
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.Content.PM;
namespace keepass2android
{
public class Interaction {
/**
* Indicates whether the specified action can be used as an intent. This
* method queries the package manager for installed packages that can
* respond to an intent with the specified action. If no suitable package is
* found, this method returns false.
*
* @param context The application's environment.
* @param action The Intent action to check for availability.
*
* @return True if an Intent with the specified action can be sent and
* responded to, false otherwise.
*/
public static bool isIntentAvailable(Context context, String action, String type) {
PackageManager packageManager = context.PackageManager;
Intent intent = new Intent(action);
if (type != null)
intent.SetType(type);
IList<ResolveInfo> list =
packageManager.QueryIntentActivities(intent,
PackageInfoFlags.MatchDefaultOnly);
foreach (ResolveInfo i in list)
Android.Util.Log.Debug("DEBUG", i.ActivityInfo.ApplicationInfo.PackageName);
return list.Count > 0;
}
}
}

View File

@ -597,7 +597,7 @@ namespace KeePass.Util.Spr
if(!MightDeref(str)) return str;
SprContext ctx = new SprContext(pe,
App.getDB().pm,
App.Kp2a.GetDb().KpDatabase,
SprCompileFlags.Deref);
// ctx.ForcePlainTextPasswords = false;

View File

@ -102,19 +102,44 @@ namespace keepass2android
}
}
/**
* Indicates whether the specified action can be used as an intent. This
* method queries the package manager for installed packages that can
* respond to an intent with the specified action. If no suitable package is
* found, this method returns false.
*
* @param context The application's environment.
* @param action The Intent action to check for availability.
*
* @return True if an Intent with the specified action can be sent and
* responded to, false otherwise.
*/
static bool IsIntentAvailable(Context context, String action, String type)
{
PackageManager packageManager = context.PackageManager;
Intent intent = new Intent(action);
if (type != null)
intent.SetType(type);
IList<ResolveInfo> list =
packageManager.QueryIntentActivities(intent,
PackageInfoFlags.MatchDefaultOnly);
foreach (ResolveInfo i in list)
Android.Util.Log.Debug("DEBUG", i.ActivityInfo.ApplicationInfo.PackageName);
return list.Count > 0;
}
public static void showBrowseDialog(string filename, Activity act, int requestCodeBrowse, bool forSaving)
{
if ((!forSaving) && (Interaction.isIntentAvailable(act, Intent.ActionGetContent, "file/*"))) {
if ((!forSaving) && (IsIntentAvailable(act, Intent.ActionGetContent, "file/*"))) {
Intent i = new Intent(Intent.ActionGetContent);
i.SetType("file/*");
act.StartActivityForResult(i, requestCodeBrowse);
return;
}
if (Interaction.isIntentAvailable(act, Intents.FILE_BROWSE, null))
if (IsIntentAvailable(act, Intents.FileBrowse, null))
{
Intent i = new Intent(Intents.FILE_BROWSE);
Intent i = new Intent(Intents.FileBrowse);
if (filename != null)
i.SetData(Android.Net.Uri.Parse("file://" + filename));
try

View File

@ -16,20 +16,18 @@ 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.Serialization;
using Android.Preferences;
namespace keepass2android
{
#if NoNet
/// <summary>
/// Static strings containing App names for the Offline ("nonet") release
/// </summary>
public static class AppNames
{
public const string AppName = "@string/app_name_nonet";
@ -38,6 +36,9 @@ namespace keepass2android
public const string PackagePart = "keepass2android_nonet";
}
#else
/// <summary>
/// Static strings containing App names for the Online release
/// </summary>
public static class AppNames
{
public const string AppName = "@string/app_name";
@ -46,16 +47,185 @@ namespace keepass2android
public const string PackagePart = "keepass2android";
}
#endif
/// <summary>
/// Main implementation of the IKp2aApp interface for usage in the real app.
/// </summary>
public class Kp2aApp: IKp2aApp
{
public bool IsShutdown()
{
return _shutdown;
}
public void SetShutdown()
{
_shutdown = true;
}
public void ClearShutdown()
{
_shutdown = false;
}
private Database _db;
private bool _shutdown;
/// <summary>
/// See comments to EntryEditActivityState.
/// </summary>
internal EntryEditActivityState EntryEditActivityState = null;
public FileDbHelper FileDbHelper;
public Database GetDb()
{
if (_db == null)
{
_db = CreateNewDatabase();
}
return _db;
}
public bool GetBooleanPreference(PreferenceKey key)
{
Context ctx = Application.Context;
ISharedPreferences prefs = PreferenceManager.GetDefaultSharedPreferences(ctx);
switch (key)
{
case PreferenceKey.remember_keyfile:
return prefs.GetBoolean(ctx.Resources.GetString(Resource.String.keyfile_key), ctx.Resources.GetBoolean(Resource.Boolean.keyfile_default));
case PreferenceKey.UseFileTransactions:
return prefs.GetBoolean(ctx.Resources.GetString(Resource.String.UseFileTransactions_key), true);
default:
throw new Exception("unexpected key!");
}
}
public void CheckForOpenFileChanged(Activity activity)
{
if (_db.DidOpenFileChange())
{
if (_db.ReloadRequested)
{
activity.SetResult(KeePass.ExitReloadDb);
activity.Finish();
}
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.SetTitle(activity.GetString(Resource.String.AskReloadFile_title));
builder.SetMessage(activity.GetString(Resource.String.AskReloadFile));
builder.SetPositiveButton(activity.GetString(Android.Resource.String.Yes),
(dlgSender, dlgEvt) =>
{
_db.ReloadRequested = true;
activity.SetResult(KeePass.ExitReloadDb);
activity.Finish();
});
builder.SetNegativeButton(activity.GetString(Android.Resource.String.No), (dlgSender, dlgEvt) =>
{
});
Dialog dialog = builder.Create();
dialog.Show();
}
}
public void StoreOpenedFileAsRecent(IOConnectionInfo ioc, string keyfile)
{
FileDbHelper.CreateFile(ioc, keyfile);
}
public string GetResourceString(UiStringKey key)
{
var field = typeof (Resource.String).GetField(key.ToString());
if (field == null)
throw new Exception("Invalid key " + key);
return Application.Context.GetString((int)field.GetValue(null));
}
public void AskYesNoCancel(UiStringKey titleKey, UiStringKey messageKey,
EventHandler<DialogClickEventArgs> yesHandler,
EventHandler<DialogClickEventArgs> noHandler,
EventHandler<DialogClickEventArgs> cancelHandler,
Context ctx)
{
AlertDialog.Builder builder = new AlertDialog.Builder(ctx);
builder.SetTitle(GetResourceString(titleKey));
builder.SetMessage(GetResourceString(messageKey));
builder.SetPositiveButton(Resource.String.yes, yesHandler);
builder.SetNegativeButton(Resource.String.no, noHandler);
builder.SetNeutralButton(ctx.GetString(Android.Resource.String.Cancel),
cancelHandler);
Dialog dialog = builder.Create();
dialog.Show();
}
internal void OnTerminate()
{
if (_db != null)
{
_db.Clear();
}
if (FileDbHelper != null && FileDbHelper.IsOpen())
{
FileDbHelper.Close();
}
}
internal void OnCreate(Application app)
{
FileDbHelper = new FileDbHelper(app);
FileDbHelper.Open();
#if DEBUG
foreach (UiStringKey key in Enum.GetValues(typeof(UiStringKey)))
{
GetResourceString(key);
}
#else
this should case a compiler error when switching to release (and thus ensure DEBUG is defined in DEBUG)
#endif
}
public Database CreateNewDatabase()
{
_db = new Database(new DrawableFactory(), this);
return _db;
}
}
///Application class for Keepass2Android: Contains static Database variable to be used by all components.
#if NoNet
[Application(Debuggable=false, Label=AppNames.AppName)]
#else
#if RELEASE
#if RELEASE
[Application(Debuggable=false, Label=AppNames.AppName)]
#else
[Application(Debuggable=true, Label=AppNames.AppName)]
#endif
#else
[Application(Debuggable = true, Label = AppNames.AppName)]
#endif
#endif
public class App : Application {
@ -64,60 +234,21 @@ namespace keepass2android
{
}
private static Database db;
private static bool shutdown = false;
/// <summary>
/// See comments to EntryEditActivityState.
/// </summary>
internal static EntryEditActivityState entryEditActivityState = null;
public static FileDbHelper fileDbHelper;
public static Database getDB() {
if ( db == null ) {
db = new Database();
}
return db;
}
public static void setDB(Database d) {
db = d;
}
public static bool isShutdown() {
return shutdown;
}
public static void setShutdown() {
shutdown = true;
}
public static void clearShutdown() {
shutdown = false;
}
public static readonly Kp2aApp Kp2a = new Kp2aApp();
public override void OnCreate() {
base.OnCreate();
Android.Util.Log.Debug("DEBUG","Creating application");
fileDbHelper = new FileDbHelper(this);
fileDbHelper.open();
Kp2a.OnCreate(this);
}
public override void OnTerminate() {
base.OnTerminate();
Android.Util.Log.Debug("DEBUG","Terminating application");
if ( db != null ) {
db.Clear();
}
if ( fileDbHelper != null && fileDbHelper.isOpen() ) {
fileDbHelper.close();
}
Kp2a.OnTerminate();
}

View File

@ -15,7 +15,6 @@
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
using System;
using Android.App;
using Android.Content;
using Android.OS;
using System.Collections.Generic;
@ -64,8 +63,11 @@ namespace keepass2android
}
/// <summary>
/// base class for "tasks": this are things the user wants to do and which require several activities
/// base class for "tasks": these are things the user wants to do and which require several activities
/// </summary>
/// Therefore AppTasks need to be serializable to bundles and intents to "survive" saving to instance state and changing activities.
/// An AppTask has a type and may have several parameters ("extras").
/// Activities call the task at special points so tasks can change the behaviour at these points.
public abstract class AppTask
{
/// <summary>
@ -105,7 +107,7 @@ namespace keepass2android
}
public const String AppTask_key = "KP2A_APPTASK";
public const String AppTaskKey = "KP2A_APPTASK";
/// <summary>
/// Should be used in OnCreate to (re)create a task
@ -116,13 +118,13 @@ namespace keepass2android
AppTask task;
if (savedInstanceState != null)
{
task = AppTask.CreateFromBundle(savedInstanceState);
task = CreateFromBundle(savedInstanceState);
}
else
{
task = AppTask.CreateFromIntent(intent);
task = CreateFromIntent(intent);
}
Android.Util.Log.Debug("DEBUG", "Loaded task " + task.ToString());
Android.Util.Log.Debug("DEBUG", "Loaded task " + task);
return task;
}
@ -136,20 +138,23 @@ namespace keepass2android
if (b == null)
return new NullTask();
string taskType = b.GetString(AppTask_key);
string taskType = b.GetString(AppTaskKey);
if (string.IsNullOrEmpty(taskType))
return new NullTask();
try
{
AppTask task = (AppTask)Activator.CreateInstance(Type.GetType("keepass2android."+taskType));
Type type = Type.GetType("keepass2android." + taskType);
if (type == null)
return new NullTask();
AppTask task = (AppTask)Activator.CreateInstance(type);
task.Setup(b);
return task;
}
catch (Exception e)
{
Android.Util.Log.Debug("DEBUG", "Cannot convert " + taskType + " in task: " + e.ToString());
Android.Util.Log.Debug("DEBUG", "Cannot convert " + taskType + " in task: " + e);
return new NullTask();
}
@ -160,7 +165,7 @@ namespace keepass2android
/// </summary>
public void ToIntent(Intent intent)
{
AppTask.GetTypeExtra(GetType()).ToIntent(intent);
GetTypeExtra(GetType()).ToIntent(intent);
foreach (IExtra extra in Extras)
{
@ -173,7 +178,7 @@ namespace keepass2android
/// </summary>
public void ToBundle(Bundle bundle)
{
AppTask.GetTypeExtra(GetType()).ToBundle(bundle);
GetTypeExtra(GetType()).ToBundle(bundle);
foreach (IExtra extra in Extras)
{
@ -187,7 +192,7 @@ namespace keepass2android
/// </summary>
static IExtra GetTypeExtra(Type type)
{
return new StringExtra() { Key=AppTask_key, Value=type.Name};
return new StringExtra { Key=AppTaskKey, Value=type.Name};
}
}
@ -205,7 +210,7 @@ namespace keepass2android
/// </summary>
public class SearchUrlTask: AppTask
{
public const String UrlToSearch_key = "UrlToSearch";
public const String UrlToSearchKey = "UrlToSearch";
public string UrlToSearchFor
{
@ -215,13 +220,13 @@ namespace keepass2android
public override void Setup(Bundle b)
{
UrlToSearchFor = b.GetString(UrlToSearch_key);
UrlToSearchFor = b.GetString(UrlToSearchKey);
}
public override IEnumerable<IExtra> Extras
{
get
{
yield return new StringExtra() { Key=UrlToSearch_key, Value = UrlToSearchFor };
yield return new StringExtra { Key=UrlToSearchKey, Value = UrlToSearchFor };
}
}
public override void AfterUnlockDatabase(PasswordActivity act)
@ -254,7 +259,7 @@ namespace keepass2android
/// </summary>
public class CreateEntryThenCloseTask: AppTask
{
public const String Url_key = "CreateEntry_Url";
public const String UrlKey = "CreateEntry_Url";
public string Url
{
@ -264,14 +269,13 @@ namespace keepass2android
public override void Setup(Bundle b)
{
Url = b.GetString(Url_key);
Url = b.GetString(UrlKey);
}
public override IEnumerable<IExtra> Extras
{
get
{
yield return new StringExtra() { Key = Url_key, Value = Url };
yield break;
yield return new StringExtra { Key = UrlKey, Value = Url };
}
}
@ -285,7 +289,7 @@ namespace keepass2android
public override void AfterAddNewEntry(EntryEditActivity entryEditActivity, PwEntry newEntry)
{
EntryActivity.Launch(entryEditActivity, newEntry, -1, new SelectEntryTask());
entryEditActivity.SetResult(KeePass.EXIT_CLOSE_AFTER_TASK_COMPLETE);
entryEditActivity.SetResult(KeePass.ExitCloseAfterTaskComplete);
//no need to call Finish here, that's done in EntryEditActivity ("closeOrShowError")
}

View File

@ -16,38 +16,31 @@ 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 System.Reflection;
namespace keepass2android
{
public class ActivityCompat {
private static MethodInfo invalidateOptMenuMethod;
private static MethodInfo _invalidateOptMenuMethod;
public static void invalidateOptionsMenu(Activity act) {
public static void InvalidateOptionsMenu(Activity act) {
try {
invalidateOptMenuMethod = act.GetType ().GetMethod("InvalidateOptionsMenu", new Type[]{});
} catch (Exception) {
// Do nothing if method dosen't exist
_invalidateOptMenuMethod = act.GetType().GetMethod("InvalidateOptionsMenu", new Type[]{});
} catch (Exception)
{
// Do nothing if method doesn't exist
}
if (invalidateOptMenuMethod != null) {
if (_invalidateOptMenuMethod != null) {
try {
invalidateOptMenuMethod.Invoke(act, (new Object[]{}));
} catch (Exception) {
_invalidateOptMenuMethod.Invoke(act, (new Object[]{}));
} catch (Exception)
{
// Do nothing
}
}

View File

@ -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 System.Reflection;
namespace keepass2android
@ -34,7 +25,7 @@ namespace keepass2android
public class EditorCompat {
private static MethodInfo applyMethod;
public static void apply (ISharedPreferencesEditor edit)
public static void Apply (ISharedPreferencesEditor edit)
{
if (applyMethod == null) {
try {

View File

@ -1,88 +0,0 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
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.Serialization;
using KeePassLib.Keys;
namespace keepass2android
{
public class CreateDB : RunnableOnFinish {
private const int DEFAULT_ENCRYPTION_ROUNDS = 1000;
private IOConnectionInfo mIoc;
private bool mDontSave;
private Context mCtx;
public CreateDB(Context ctx, IOConnectionInfo ioc, OnFinish finish, bool dontSave): base(finish) {
mCtx = ctx;
mIoc = ioc;
mDontSave = dontSave;
}
public override void run() {
// Create new database record
Database db = new Database();
App.setDB(db);
db.pm = new KeePassLib.PwDatabase();
//Key will be changed/created immediately after creation:
CompositeKey tempKey = new CompositeKey();
db.pm.New(mIoc, tempKey);
db.pm.KeyEncryptionRounds = DEFAULT_ENCRYPTION_ROUNDS;
db.pm.Name = "Keepass2Android Password Database";
// Set Database state
db.root = db.pm.RootGroup;
db.mIoc = mIoc;
db.Loaded = true;
db.searchHelper = new SearchDbHelper(mCtx);
// Add a couple default groups
AddGroup internet = AddGroup.getInstance(mCtx, db, "Internet", 1, db.pm.RootGroup, null, true);
internet.run();
AddGroup email = AddGroup.getInstance(mCtx, db, "eMail", 19, db.pm.RootGroup, null, true);
email.run();
// Commit changes
SaveDB save = new SaveDB(mCtx, db, mFinish, mDontSave);
mFinish = null;
save.run();
}
}
}

View File

@ -1,146 +0,0 @@
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 abstract class DeleteRunnable : RunnableOnFinish
{
public DeleteRunnable(OnFinish finish):base(finish)
{
}
protected Database mDb;
protected Context mCtx;
protected void setMembers(Context ctx, Database db)
{
mCtx = ctx;
mDb = db;
}
private bool mDeletePermanently = true;
public bool DeletePermanently
{
get
{
return mDeletePermanently;
}
set
{
mDeletePermanently = value;
}
}
public abstract bool CanRecycle
{
get;
}
protected bool CanRecycleGroup(PwGroup pgParent)
{
bool bShiftPressed = false;
PwDatabase pd = mDb.pm;
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 ((mDb == null) || (mDb.pm == null)) { return; }
if(pgRecycleBin == mDb.pm.RootGroup)
{
pgRecycleBin = null;
}
if(pgRecycleBin == null)
{
pgRecycleBin = new PwGroup(true, true, mCtx.GetString(Resource.String.RecycleBin),
PwIcon.TrashBin);
pgRecycleBin.EnableAutoType = false;
pgRecycleBin.EnableSearching = false;
pgRecycleBin.IsExpanded = false;
mDb.pm.RootGroup.AddGroup(pgRecycleBin, true);
mDb.pm.RecycleBinUuid = pgRecycleBin.Uuid;
bGroupListUpdateRequired = true;
}
else { System.Diagnostics.Debug.Assert(pgRecycleBin.Uuid.EqualsValue(mDb.pm.RecycleBinUuid)); }
}
protected abstract int QuestionsResourceId
{
get;
}
public void start()
{
if (CanRecycle)
{
AlertDialog.Builder builder = new AlertDialog.Builder(mCtx);
builder.SetTitle(mCtx.GetString(Resource.String.AskDeletePermanently_title));
builder.SetMessage(mCtx.GetString(QuestionsResourceId));
builder.SetPositiveButton(Resource.String.yes, new EventHandler<DialogClickEventArgs>((dlgSender, dlgEvt) =>
{
DeletePermanently = true;
ProgressTask pt = new ProgressTask(mCtx, this, Resource.String.saving_database);
pt.run();
}));
builder.SetNegativeButton(Resource.String.no, new EventHandler<DialogClickEventArgs>((dlgSender, dlgEvt) => {
DeletePermanently = false;
ProgressTask pt = new ProgressTask(mCtx, this, Resource.String.saving_database);
pt.run();
}));
builder.SetNeutralButton(mCtx.GetString(Android.Resource.String.Cancel),
new EventHandler<DialogClickEventArgs>((dlgSender, dlgEvt) => {}));
Dialog dialog = builder.Create();
dialog.Show();
} else
{
ProgressTask pt = new ProgressTask(mCtx, this, Resource.String.saving_database);
pt.run();
}
}
}
}

View File

@ -1,119 +0,0 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
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.Preferences;
using KeePassLib.Serialization;
namespace keepass2android
{
public class LoadDB : RunnableOnFinish {
private IOConnectionInfo mIoc;
private String mPass;
private String mKey;
private Database mDb;
private Context mCtx;
private bool mRememberKeyfile;
public LoadDB(Database db, Context ctx, IOConnectionInfo ioc, String pass, String key, OnFinish finish): base(finish)
{
mDb = db;
mCtx = ctx;
mIoc = ioc;
mPass = pass;
mKey = key;
ISharedPreferences prefs = PreferenceManager.GetDefaultSharedPreferences(ctx);
mRememberKeyfile = prefs.GetBoolean(ctx.GetString(Resource.String.keyfile_key), ctx.Resources.GetBoolean(Resource.Boolean.keyfile_default));
}
public override void run ()
{
try {
mDb.LoadData (mCtx, mIoc, mPass, mKey, mStatus);
saveFileData (mIoc, mKey);
} catch (KeyFileException) {
finish(false, /*TODO Localize: use Keepass error text KPRes.KeyFileError (including "or invalid format")*/ mCtx.GetString(Resource.String.keyfile_does_not_exist));
}
catch (Exception e) {
finish(false, "An error occured: " + e.Message);
return;
}
/* catch (InvalidPasswordException e) {
finish(false, mCtx.GetString(Resource.String.InvalidPassword));
return;
} catch (FileNotFoundException e) {
finish(false, mCtx.GetString(Resource.String.FileNotFound));
return;
} catch (IOException e) {
finish(false, e.getMessage());
return;
} catch (KeyFileEmptyException e) {
finish(false, mCtx.GetString(Resource.String.keyfile_is_empty));
return;
} catch (InvalidAlgorithmException e) {
finish(false, mCtx.GetString(Resource.String.invalid_algorithm));
return;
} catch (InvalidKeyFileException e) {
finish(false, mCtx.GetString(Resource.String.keyfile_does_not_exist));
return;
} catch (InvalidDBSignatureException e) {
finish(false, mCtx.GetString(Resource.String.invalid_db_sig));
return;
} catch (InvalidDBVersionException e) {
finish(false, mCtx.GetString(Resource.String.unsupported_db_version));
return;
} catch (InvalidDBException e) {
finish(false, mCtx.GetString(Resource.String.error_invalid_db));
return;
} catch (OutOfMemoryError e) {
finish(false, mCtx.GetString(Resource.String.error_out_of_memory));
return;
}
*/
finish(true);
}
private void saveFileData(IOConnectionInfo ioc, String key) {
FileDbHelper db = App.fileDbHelper;
if ( ! mRememberKeyfile ) {
key = "";
}
db.createFile(ioc, key);
}
}
}

View File

@ -1,62 +0,0 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
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 RunnableOnFinish {
public OnFinish mFinish;
public UpdateStatus mStatus;
public RunnableOnFinish(OnFinish finish) {
mFinish = finish;
}
protected void finish(bool result, String message) {
if ( mFinish != null ) {
mFinish.setResult(result, message);
mFinish.run();
}
}
protected void finish(bool result) {
if ( mFinish != null ) {
mFinish.setResult(result);
mFinish.run();
}
}
public void setStatus(UpdateStatus status) {
mStatus = status;
}
abstract public void run();
}
}

View File

@ -15,22 +15,18 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file
along with Keepass2Android. If not, see <http://www.gnu.org/licenses/>.
*/
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.Content.PM;
namespace keepass2android
{
/// <summary>
/// Dialog to offer to install OpenIntent file manager if there's no other browser installed
/// </summary>
public class BrowserDialog : Dialog {
public BrowserDialog(Context context) : base(context)
@ -43,31 +39,28 @@ namespace keepass2android
SetTitle(Resource.String.file_browser);
Button cancel = (Button) FindViewById(Resource.Id.cancel);
cancel.Click += (sender, e) => {
this.Cancel();
}
;
cancel.Click += (sender, e) => Cancel();
Button market = (Button) FindViewById(Resource.Id.install_market);
market.Click += (sender, e) => {
Util.gotoUrl(Context, Resource.String.oi_filemanager_market);
this.Cancel();
Cancel();
}
;
if (!isMarketInstalled()) {
if (!IsMarketInstalled()) {
market.Visibility = ViewStates.Gone;
}
Button web = (Button) FindViewById(Resource.Id.install_web);
web.Click += (sender, e) => {
Util.gotoUrl(Context, Resource.String.oi_filemanager_web);
this.Cancel();
Cancel();
}
;
}
private bool isMarketInstalled() {
Android.Content.PM.PackageManager pm = Context.PackageManager;
private bool IsMarketInstalled() {
PackageManager pm = Context.PackageManager;
try {
pm.GetPackageInfo("com.android.vending", 0);

View File

@ -16,65 +16,56 @@ 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 System.Globalization;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.Database;
using Android.Database.Sqlite;
using KeePassLib.Serialization;
namespace keepass2android
{
/// <summary>
/// Class to store the recent files in a database
/// </summary>
public class FileDbHelper {
public const String LAST_FILENAME = "lastFile";
public const String LAST_KEYFILE = "lastKey";
public const String LastFilename = "lastFile";
public const String LastKeyfile = "lastKey";
private const String DATABASE_NAME = "keepass2android";
private const String FILE_TABLE = "files";
private const int DATABASE_VERSION = 1;
private const String DatabaseName = "keepass2android";
private const String FileTable = "files";
private const int DatabaseVersion = 1;
private const int MAX_FILES = 5;
private const int MaxFiles = 5;
public const String KEY_FILE_ID = "_id";
public const String KEY_FILE_FILENAME = "fileName";
public const String KEY_FILE_USERNAME = "username";
public const String KEY_FILE_PASSWORD = "password";
public const String KEY_FILE_CREDSAVEMODE = "credSaveMode";
public const String KEY_FILE_KEYFILE = "keyFile";
public const String KEY_FILE_UPDATED = "updated";
public const String KeyFileId = "_id";
public const String KeyFileFilename = "fileName";
public const String KeyFileUsername = "username";
public const String KeyFilePassword = "password";
public const String KeyFileCredsavemode = "credSaveMode";
public const String KeyFileKeyfile = "keyFile";
public const String KeyFileUpdated = "updated";
private const String DATABASE_CREATE =
"create table " + FILE_TABLE + " ( " + KEY_FILE_ID + " integer primary key autoincrement, "
+ KEY_FILE_FILENAME + " text not null, "
+ KEY_FILE_KEYFILE + " text, "
+ KEY_FILE_USERNAME + " text, "
+ KEY_FILE_PASSWORD + " text, "
+ KEY_FILE_CREDSAVEMODE + " integer not null,"
+ KEY_FILE_UPDATED + " integer not null);";
private const String DatabaseCreate =
"create table " + FileTable + " ( " + KeyFileId + " integer primary key autoincrement, "
+ KeyFileFilename + " text not null, "
+ KeyFileKeyfile + " text, "
+ KeyFileUsername + " text, "
+ KeyFilePassword + " text, "
+ KeyFileCredsavemode + " integer not null,"
+ KeyFileUpdated + " integer not null);";
private readonly Android.Content.Context mCtx;
private readonly Context mCtx;
private DatabaseHelper mDbHelper;
private SQLiteDatabase mDb;
private class DatabaseHelper : SQLiteOpenHelper {
private readonly Android.Content.Context mCtx;
public DatabaseHelper(Android.Content.Context ctx): base(ctx, DATABASE_NAME, null, DATABASE_VERSION) {
mCtx = ctx;
public DatabaseHelper(Context ctx): base(ctx, FileDbHelper.DatabaseName, null, DatabaseVersion) {
}
public override void OnCreate(SQLiteDatabase db) {
db.ExecSQL(DATABASE_CREATE);
db.ExecSQL(DatabaseCreate);
}
@ -89,27 +80,27 @@ namespace keepass2android
mCtx = ctx;
}
public FileDbHelper open() {
public FileDbHelper Open() {
mDbHelper = new DatabaseHelper(mCtx);
mDb = mDbHelper.WritableDatabase;
return this;
}
public bool isOpen() {
public bool IsOpen() {
return mDb.IsOpen;
}
public void close() {
public void Close() {
mDb.Close();
}
public long createFile(IOConnectionInfo ioc, String keyFile) {
public long CreateFile(IOConnectionInfo ioc, String keyFile) {
// Check to see if this filename is already used
ICursor cursor;
try {
cursor = mDb.Query(true, FILE_TABLE, new String[] {KEY_FILE_ID},
KEY_FILE_FILENAME + "=?", new String[] {ioc.Path}, null, null, null, null);
cursor = mDb.Query(true, FileTable, new[] {KeyFileId},
KeyFileFilename + "=?", new[] {ioc.Path}, null, null, null, null);
} catch (Exception ) {
return -1;
}
@ -126,34 +117,34 @@ namespace keepass2android
// If there is an existing entry update it
if ( cursor.Count > 0 ) {
cursor.MoveToFirst();
long id = cursor.GetLong(cursor.GetColumnIndexOrThrow(KEY_FILE_ID));
long id = cursor.GetLong(cursor.GetColumnIndexOrThrow(KeyFileId));
ContentValues vals = new ContentValues();
vals.Put(KEY_FILE_KEYFILE, keyFile);
vals.Put(KEY_FILE_UPDATED, Java.Lang.JavaSystem.CurrentTimeMillis());
var vals = new ContentValues();
vals.Put(KeyFileKeyfile, keyFile);
vals.Put(KeyFileUpdated, Java.Lang.JavaSystem.CurrentTimeMillis());
vals.Put(KEY_FILE_USERNAME, iocToStore.UserName);
vals.Put(KEY_FILE_PASSWORD, iocToStore.Password);
vals.Put(KEY_FILE_CREDSAVEMODE, (int)iocToStore.CredSaveMode);
vals.Put(KeyFileUsername, iocToStore.UserName);
vals.Put(KeyFilePassword, iocToStore.Password);
vals.Put(KeyFileCredsavemode, (int)iocToStore.CredSaveMode);
result = mDb.Update(FILE_TABLE, vals, KEY_FILE_ID + " = " + id, null);
result = mDb.Update(FileTable, vals, KeyFileId + " = " + id, null);
// Otherwise add the new entry
} else {
ContentValues vals = new ContentValues();
vals.Put(KEY_FILE_FILENAME, ioc.Path);
vals.Put(KEY_FILE_KEYFILE, keyFile);
vals.Put(KEY_FILE_USERNAME, iocToStore.UserName);
vals.Put(KEY_FILE_PASSWORD, iocToStore.Password);
vals.Put(KEY_FILE_CREDSAVEMODE, (int)iocToStore.CredSaveMode);
vals.Put(KEY_FILE_UPDATED, Java.Lang.JavaSystem.CurrentTimeMillis());
var vals = new ContentValues();
vals.Put(KeyFileFilename, ioc.Path);
vals.Put(KeyFileKeyfile, keyFile);
vals.Put(KeyFileUsername, iocToStore.UserName);
vals.Put(KeyFilePassword, iocToStore.Password);
vals.Put(KeyFileCredsavemode, (int)iocToStore.CredSaveMode);
vals.Put(KeyFileUpdated, Java.Lang.JavaSystem.CurrentTimeMillis());
result = mDb.Insert(FILE_TABLE, null, vals);
result = mDb.Insert(FileTable, null, vals);
}
// Delete all but the last five records
try {
deleteAllBut(MAX_FILES);
DeleteAllBut(MaxFiles);
} catch (Exception ex) {
Android.Util.Log.Error("ex",ex.StackTrace);
@ -165,53 +156,53 @@ namespace keepass2android
}
private void deleteAllBut(int limit) {
ICursor cursor = mDb.Query(FILE_TABLE, new String[] {KEY_FILE_UPDATED}, null, null, null, null, KEY_FILE_UPDATED);
private void DeleteAllBut(int limit) {
ICursor cursor = mDb.Query(FileTable, new[] {KeyFileUpdated}, null, null, null, null, KeyFileUpdated);
if ( cursor.Count > limit ) {
cursor.MoveToFirst();
long time = cursor.GetLong(cursor.GetColumnIndexOrThrow(KEY_FILE_UPDATED));
long time = cursor.GetLong(cursor.GetColumnIndexOrThrow(KeyFileUpdated));
mDb.ExecSQL("DELETE FROM " + FILE_TABLE + " WHERE " + KEY_FILE_UPDATED + "<" + time + ";");
mDb.ExecSQL("DELETE FROM " + FileTable + " WHERE " + KeyFileUpdated + "<" + time + ";");
}
cursor.Close();
}
public void deleteAllKeys() {
ContentValues vals = new ContentValues();
vals.Put(KEY_FILE_KEYFILE, "");
public void DeleteAllKeys() {
var vals = new ContentValues();
vals.Put(KeyFileKeyfile, "");
mDb.Update(FILE_TABLE, vals, null, null);
mDb.Update(FileTable, vals, null, null);
}
public void deleteFile(String filename) {
mDb.Delete(FILE_TABLE, KEY_FILE_FILENAME + " = ?", new String[] {filename});
public void DeleteFile(String filename) {
mDb.Delete(FileTable, KeyFileFilename + " = ?", new[] {filename});
}
static string[] getColumnList()
static string[] GetColumnList()
{
return new String[] {
KEY_FILE_ID,
KEY_FILE_FILENAME,
KEY_FILE_KEYFILE,
KEY_FILE_USERNAME,
KEY_FILE_PASSWORD,
KEY_FILE_CREDSAVEMODE
return new[] {
KeyFileId,
KeyFileFilename,
KeyFileKeyfile,
KeyFileUsername,
KeyFilePassword,
KeyFileCredsavemode
};
}
public ICursor fetchAllFiles() {
ICursor ret;
ret = mDb.Query(FILE_TABLE, getColumnList(),
null, null, null, null, KEY_FILE_UPDATED + " DESC", MAX_FILES.ToString());
public ICursor FetchAllFiles()
{
ICursor ret = mDb.Query(FileTable, GetColumnList(),
null, null, null, null, KeyFileUpdated + " DESC", MaxFiles.ToString(CultureInfo.InvariantCulture));
return ret;
}
public ICursor fetchFile(long fileId) {
ICursor cursor = mDb.Query(true, FILE_TABLE, getColumnList(),
KEY_FILE_ID + "=" + fileId, null, null, null, null, null);
public ICursor FetchFile(long fileId) {
ICursor cursor = mDb.Query(true, FileTable, GetColumnList(),
KeyFileId + "=" + fileId, null, null, null, null, null);
if ( cursor != null ) {
cursor.MoveToFirst();
@ -221,11 +212,11 @@ namespace keepass2android
}
public ICursor fetchFileByName(string fileName)
public ICursor FetchFileByName(string fileName)
{
ICursor cursor = mDb.Query(true, FILE_TABLE, getColumnList(),
KEY_FILE_FILENAME + " like " + DatabaseUtils.SqlEscapeString(fileName) , null, null, null, null, null);
ICursor cursor = mDb.Query(true, FileTable, GetColumnList(),
KeyFileFilename + " like " + DatabaseUtils.SqlEscapeString(fileName) , null, null, null, null, null);
if ( cursor != null ) {
cursor.MoveToFirst();
@ -235,9 +226,9 @@ namespace keepass2android
}
public String getFileByName(String name) {
ICursor cursor = mDb.Query(true, FILE_TABLE, getColumnList(),
KEY_FILE_FILENAME + "= ?", new String[] {name}, null, null, null, null);
public String GetFileByName(String name) {
ICursor cursor = mDb.Query(true, FileTable, GetColumnList(),
KeyFileFilename + "= ?", new[] {name}, null, null, null, null);
if ( cursor == null ) {
return "";
@ -246,7 +237,7 @@ namespace keepass2android
String keyfileFilename;
if ( cursor.MoveToFirst() ) {
keyfileFilename = cursor.GetString(cursor.GetColumnIndexOrThrow(KEY_FILE_KEYFILE));
keyfileFilename = cursor.GetString(cursor.GetColumnIndexOrThrow(KeyFileKeyfile));
} else {
// Cursor is empty
keyfileFilename = "";
@ -255,8 +246,8 @@ namespace keepass2android
return keyfileFilename;
}
public bool hasRecentFiles() {
ICursor cursor = fetchAllFiles();
public bool HasRecentFiles() {
ICursor cursor = FetchAllFiles();
bool hasRecent = cursor.Count > 0;
cursor.Close();
@ -264,23 +255,23 @@ namespace keepass2android
return hasRecent;
}
public IOConnectionInfo cursorToIoc(Android.Database.ICursor cursor)
public IOConnectionInfo CursorToIoc(ICursor cursor)
{
if (cursor == null)
return null;
IOConnectionInfo ioc = new IOConnectionInfo();
ioc.Path = cursor.GetString(cursor
.GetColumnIndexOrThrow(FileDbHelper.KEY_FILE_FILENAME));
var ioc = new IOConnectionInfo
{
Path = cursor.GetString(cursor
.GetColumnIndexOrThrow(KeyFileFilename)),
UserName = cursor.GetString(cursor
.GetColumnIndexOrThrow(KeyFileUsername)),
Password = cursor.GetString(cursor
.GetColumnIndexOrThrow(KeyFilePassword)),
CredSaveMode = (IOCredSaveMode) cursor.GetInt(cursor
.GetColumnIndexOrThrow(KeyFileCredsavemode)),
CredProtMode = IOCredProtMode.Obf
};
ioc.UserName = cursor.GetString(cursor
.GetColumnIndexOrThrow(FileDbHelper.KEY_FILE_USERNAME));
ioc.Password = cursor.GetString(cursor
.GetColumnIndexOrThrow(FileDbHelper.KEY_FILE_PASSWORD));
ioc.CredSaveMode = (IOCredSaveMode)cursor.GetInt(cursor
.GetColumnIndexOrThrow(FileDbHelper.KEY_FILE_CREDSAVEMODE));
ioc.CredProtMode = IOCredProtMode.Obf;
ioc.Obfuscate(false);
return ioc;
}

View File

@ -16,10 +16,6 @@ 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;
@ -27,13 +23,13 @@ using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.Content.PM;
using Android.Views.InputMethods;
using System.IO;
using KeePassLib.Serialization;
namespace keepass2android
{
/// <summary>
/// Activity to select the file to use
/// </summary>
[Activity (Label = "@string/app_name",
ConfigurationChanges=ConfigChanges.Orientation|
ConfigChanges.KeyboardHidden,
@ -54,21 +50,21 @@ namespace keepass2android
{
}
private const int CMENU_CLEAR = Menu.First;
private const int CmenuClear = Menu.First;
const string BundleKey_RecentMode = "RecentMode";
const string BundleKeyRecentMode = "RecentMode";
private FileDbHelper mDbHelper;
private FileDbHelper _DbHelper;
private bool recentMode = false;
view.FileSelectButtons fileSelectButtons;
bool createdWithActivityResult = false;
private bool _recentMode;
view.FileSelectButtons _fileSelectButtons;
bool _createdWithActivityResult;
internal AppTask mAppTask;
internal AppTask AppTask;
IOConnectionInfo loadIoc(string defaultFileName)
IOConnectionInfo LoadIoc(string defaultFileName)
{
return mDbHelper.cursorToIoc(mDbHelper.fetchFileByName(defaultFileName));
return _DbHelper.CursorToIoc(_DbHelper.FetchFileByName(defaultFileName));
}
void ShowFilenameDialog(bool showOpenButton, bool showCreateButton, bool showBrowseButton, string defaultFilename, string detailsText, int requestCodeBrowse)
@ -94,7 +90,8 @@ namespace keepass2android
openButton.Click += ( sender, evt) => {
String fileName = ((EditText)dialog.FindViewById(Resource.Id.file_filename)).Text;
IOConnectionInfo ioc = new IOConnectionInfo() {
IOConnectionInfo ioc = new IOConnectionInfo
{
Path = fileName
};
@ -165,25 +162,23 @@ namespace keepass2android
return;
}
// Prep an object to collect a password once the database has
// been created
CollectPassword password = new CollectPassword(
// Prep an object to collect a password once the database has been created
CollectPassword collectPassword = new CollectPassword(
new LaunchGroupActivity(IOConnectionInfo.FromPath(filename), this), this);
// Create the new database
CreateDB create = new CreateDB(this, IOConnectionInfo.FromPath(filename), password, true);
CreateDb create = new CreateDb(App.Kp2a, this, IOConnectionInfo.FromPath(filename), collectPassword, true);
ProgressTask createTask = new ProgressTask(
App.Kp2a,
this, create,
Resource.String.progress_create);
createTask.run();
UiStringKey.progress_create);
createTask.Run();
};
Button cancelButton = (Button)dialog.FindViewById(Resource.Id.fnv_cancel);
cancelButton.Click += (sender, e) => {
dialog.Dismiss();
};
cancelButton.Click += (sender, e) => dialog.Dismiss();
ImageButton browseButton = (ImageButton)dialog.FindViewById(Resource.Id.browse_button);
if (!showBrowseButton)
@ -208,28 +203,28 @@ namespace keepass2android
if (Intent.Action == Intent.ActionSend)
{
mAppTask = new SearchUrlTask() { UrlToSearchFor = Intent.GetStringExtra(Intent.ExtraText) };
AppTask = new SearchUrlTask { UrlToSearchFor = Intent.GetStringExtra(Intent.ExtraText) };
}
else
{
mAppTask = AppTask.CreateFromIntent(Intent);
AppTask = AppTask.CreateFromIntent(Intent);
}
mDbHelper = App.fileDbHelper;
if (mDbHelper.hasRecentFiles())
_DbHelper = App.Kp2a.FileDbHelper;
if (_DbHelper.HasRecentFiles())
{
recentMode = true;
_recentMode = true;
SetContentView(Resource.Layout.file_selection);
fileSelectButtons = new keepass2android.view.FileSelectButtons(this);
_fileSelectButtons = new view.FileSelectButtons(this);
((ListView)FindViewById(Android.Resource.Id.List)).AddFooterView(
fileSelectButtons);
_fileSelectButtons);
} else
{
SetContentView(Resource.Layout.file_selection_no_recent);
fileSelectButtons = (view.FileSelectButtons)FindViewById(Resource.Id.file_select);
_fileSelectButtons = (view.FileSelectButtons)FindViewById(Resource.Id.file_select);
}
@ -237,11 +232,11 @@ namespace keepass2android
Button openFileButton = (Button)FindViewById(Resource.Id.start_open_file);
EventHandler openFileButtonClick = (object sender, EventArgs e) =>
EventHandler openFileButtonClick = (sender, e) =>
{
string defaultFilename = Android.OS.Environment.ExternalStorageDirectory + GetString(Resource.String.default_file_path);
string detailsText = "";
ShowFilenameDialog(true, false, true, defaultFilename, detailsText, Intents.REQUEST_CODE_FILE_BROWSE_FOR_OPEN);
const string detailsText = "";
ShowFilenameDialog(true, false, true, defaultFilename, detailsText, Intents.RequestCodeFileBrowseForOpen);
};
@ -253,18 +248,12 @@ namespace keepass2android
openUrlButton.Visibility = ViewStates.Gone;
#endif
EventHandler openUrlButtonClick = (object sender, EventArgs e) =>
{
ShowFilenameDialog(true, false, false, "", GetString(Resource.String.enter_filename_details_url), Intents.REQUEST_CODE_FILE_BROWSE_FOR_OPEN);
};
EventHandler openUrlButtonClick = (sender, e) => ShowFilenameDialog(true, false, false, "", GetString(Resource.String.enter_filename_details_url), Intents.RequestCodeFileBrowseForOpen);
openUrlButton.Click += openUrlButtonClick;
//CREATE NEW
Button createNewButton = (Button)FindViewById(Resource.Id.start_create);
EventHandler createNewButtonClick = (object sender, EventArgs e) =>
{
ShowFilenameDialog(false, true, true, Android.OS.Environment.ExternalStorageDirectory + GetString(Resource.String.default_file_path), "", Intents.REQUEST_CODE_FILE_BROWSE_FOR_CREATE);
};
EventHandler createNewButtonClick = (sender, e) => ShowFilenameDialog(false, true, true, Android.OS.Environment.ExternalStorageDirectory + GetString(Resource.String.default_file_path), "", Intents.RequestCodeFileBrowseForCreate);
createNewButton.Click += createNewButtonClick;
/*//CREATE + IMPORT
@ -281,14 +270,14 @@ namespace keepass2android
};*/
fillData();
FillData();
RegisterForContextMenu(ListView);
if (savedInstanceState != null)
{
mAppTask = AppTask.CreateFromBundle(savedInstanceState);
recentMode = savedInstanceState.GetBoolean(BundleKey_RecentMode, recentMode);
AppTask = AppTask.CreateFromBundle(savedInstanceState);
_recentMode = savedInstanceState.GetBoolean(BundleKeyRecentMode, _recentMode);
}
@ -299,65 +288,64 @@ namespace keepass2android
protected override void OnSaveInstanceState(Bundle outState)
{
base.OnSaveInstanceState(outState);
mAppTask.ToBundle(outState);
outState.PutBoolean(BundleKey_RecentMode, recentMode);
AppTask.ToBundle(outState);
outState.PutBoolean(BundleKeyRecentMode, _recentMode);
}
private class LaunchGroupActivity : FileOnFinish {
FileSelectActivity activity;
private IOConnectionInfo mIoc;
readonly FileSelectActivity _activity;
private readonly IOConnectionInfo _ioc;
public LaunchGroupActivity(IOConnectionInfo ioc, FileSelectActivity activity): base(null) {
this.activity = activity;
mIoc = ioc;
_activity = activity;
_ioc = ioc;
}
public override void run() {
if (mSuccess) {
public override void Run() {
if (Success) {
// Add to recent files
FileDbHelper dbHelper = App.fileDbHelper;
FileDbHelper dbHelper = App.Kp2a.FileDbHelper;
//TODO: getFilename always returns "" -> bug?
dbHelper.createFile(mIoc, getFilename());
dbHelper.CreateFile(_ioc, Filename);
GroupActivity.Launch(activity, activity.mAppTask);
GroupActivity.Launch(_activity, _activity.AppTask);
} else {
IOConnection.DeleteFile(mIoc);
IOConnection.DeleteFile(_ioc);
}
}
}
private class CollectPassword: FileOnFinish {
FileSelectActivity activity;
FileOnFinish mFileOnFinish;
readonly FileSelectActivity _activity;
readonly FileOnFinish _fileOnFinish;
public CollectPassword(FileOnFinish finish,FileSelectActivity activity):base(finish) {
this.activity = activity;
mFileOnFinish = finish;
_activity = activity;
_fileOnFinish = finish;
}
public override void run() {
SetPasswordDialog password = new SetPasswordDialog(activity, mFileOnFinish);
public override void Run() {
SetPasswordDialog password = new SetPasswordDialog(_activity, _fileOnFinish);
password.Show();
}
}
private void fillData() {
private void FillData() {
// Get all of the rows from the database and create the item list
Android.Database.ICursor filesCursor = mDbHelper.fetchAllFiles();
Android.Database.ICursor filesCursor = _DbHelper.FetchAllFiles();
StartManagingCursor(filesCursor);
// Create an array to specify the fields we want to display in the list
// (only TITLE)
String[] from = new String[] { FileDbHelper.KEY_FILE_FILENAME };
String[] from = new[] { FileDbHelper.KeyFileFilename };
// and an array of the fields we want to bind those fields to (in this
// case just text1)
int[] to = new int[] { Resource.Id.file_filename };
int[] to = new[] { Resource.Id.file_filename };
// Now create a simple cursor adapter and set it to display
SimpleCursorAdapter notes = new SimpleCursorAdapter(this,
@ -375,7 +363,7 @@ namespace keepass2android
//Build dialog to query credentials:
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.SetTitle(GetString(Resource.String.credentials_dialog_title));
builder.SetPositiveButton(GetString(Android.Resource.String.Ok), new EventHandler<DialogClickEventArgs>((dlgSender, dlgEvt) =>
builder.SetPositiveButton(GetString(Android.Resource.String.Ok), (dlgSender, dlgEvt) =>
{
Dialog dlg = (Dialog)dlgSender;
string username = ((EditText)dlg.FindViewById(Resource.Id.cred_username)).Text;
@ -384,11 +372,11 @@ namespace keepass2android
ioc.UserName = username;
ioc.Password = password;
ioc.CredSaveMode = (IOCredSaveMode)credentialRememberMode;
PasswordActivity.Launch(this, ioc, mAppTask);
}));
PasswordActivity.Launch(this, ioc, AppTask);
});
builder.SetView(LayoutInflater.Inflate(Resource.Layout.url_credentials, null));
builder.SetNeutralButton(GetString(Android.Resource.String.Cancel),
new EventHandler<DialogClickEventArgs>((dlgSender, dlgEvt) => {}));
(dlgSender, dlgEvt) => {});
Dialog dialog = builder.Create();
dialog.Show();
((EditText)dialog.FindViewById(Resource.Id.cred_username)).Text = ioc.UserName;
@ -399,7 +387,7 @@ namespace keepass2android
{
try
{
PasswordActivity.Launch(this, ioc, mAppTask);
PasswordActivity.Launch(this, ioc, AppTask);
} catch (Java.IO.FileNotFoundException)
{
Toast.MakeText(this, Resource.String.FileNotFound, ToastLength.Long).Show();
@ -410,10 +398,10 @@ namespace keepass2android
protected override void OnListItemClick(ListView l, View v, int position, long id) {
base.OnListItemClick(l, v, position, id);
Android.Database.ICursor cursor = mDbHelper.fetchFile(id);
Android.Database.ICursor cursor = _DbHelper.FetchFile(id);
StartManagingCursor(cursor);
IOConnectionInfo ioc = mDbHelper.cursorToIoc(cursor);
IOConnectionInfo ioc = _DbHelper.CursorToIoc(cursor);
LaunchPasswordActivityForIoc(ioc);
@ -425,18 +413,18 @@ namespace keepass2android
{
base.OnActivityResult(requestCode, resultCode, data);
createdWithActivityResult = true;
_createdWithActivityResult = true;
if (resultCode == KeePass.EXIT_CLOSE_AFTER_TASK_COMPLETE)
if (resultCode == KeePass.ExitCloseAfterTaskComplete)
{
Finish();
return;
}
fillData();
FillData();
if ( (requestCode == Intents.REQUEST_CODE_FILE_BROWSE_FOR_CREATE
|| requestCode == Intents.REQUEST_CODE_FILE_BROWSE_FOR_OPEN)
if ( (requestCode == Intents.RequestCodeFileBrowseForCreate
|| requestCode == Intents.RequestCodeFileBrowseForOpen)
&& resultCode == Result.Ok) {
string filename = Util.IntentToFilename(data);
if (filename != null) {
@ -446,18 +434,19 @@ namespace keepass2android
filename = Java.Net.URLDecoder.Decode(filename);
if (requestCode == Intents.REQUEST_CODE_FILE_BROWSE_FOR_OPEN)
if (requestCode == Intents.RequestCodeFileBrowseForOpen)
{
IOConnectionInfo ioc = new IOConnectionInfo
{
IOConnectionInfo ioc = new IOConnectionInfo() {
Path = filename
};
LaunchPasswordActivityForIoc(ioc);
}
if (requestCode == Intents.REQUEST_CODE_FILE_BROWSE_FOR_CREATE)
if (requestCode == Intents.RequestCodeFileBrowseForCreate)
{
ShowFilenameDialog(false, true, true, filename, "", Intents.REQUEST_CODE_FILE_BROWSE_FOR_CREATE);
ShowFilenameDialog(false, true, true, filename, "", Intents.RequestCodeFileBrowseForCreate);
}
}
@ -471,28 +460,28 @@ namespace keepass2android
Android.Util.Log.Debug("DEBUG", "FileSelect.OnResume");
// Check to see if we need to change modes
if (mDbHelper.hasRecentFiles() != recentMode)
if (_DbHelper.HasRecentFiles() != _recentMode)
{
// Restart the activity
Intent intent = this.Intent;
Intent intent = Intent;
StartActivity(intent);
Finish();
}
fileSelectButtons.updateExternalStorageWarning();
_fileSelectButtons.UpdateExternalStorageWarning();
if (!createdWithActivityResult)
if (!_createdWithActivityResult)
{
if ((Intent.Action == Intent.ActionSend) && (App.getDB().Loaded))
if ((Intent.Action == Intent.ActionSend) && (App.Kp2a.GetDb().Loaded))
{
PasswordActivity.Launch(this, App.getDB().mIoc , mAppTask);
PasswordActivity.Launch(this, App.Kp2a.GetDb().Ioc , AppTask);
} else
{
// Load default database
ISharedPreferences prefs = Android.Preferences.PreferenceManager.GetDefaultSharedPreferences(this);
String defaultFileName = prefs.GetString(PasswordActivity.KEY_DEFAULT_FILENAME, "");
String defaultFileName = prefs.GetString(PasswordActivity.KeyDefaultFilename, "");
if (defaultFileName.Length > 0)
{
@ -502,7 +491,7 @@ namespace keepass2android
{
try
{
PasswordActivity.Launch(this, loadIoc(defaultFileName), mAppTask);
PasswordActivity.Launch(this, LoadIoc(defaultFileName), AppTask);
} catch (Exception e)
{
Toast.MakeText(this, e.Message, ToastLength.Long);
@ -520,7 +509,7 @@ namespace keepass2android
base.OnStart();
Android.Util.Log.Debug("DEBUG", "FileSelect.OnStart");
}
public override bool OnCreateOptionsMenu(Android.Views.IMenu menu) {
public override bool OnCreateOptionsMenu(IMenu menu) {
base.OnCreateOptionsMenu(menu);
MenuInflater inflater = MenuInflater;
@ -548,7 +537,7 @@ namespace keepass2android
Android.Util.Log.Debug("DEBUG", "FileSelect.OnStop");
}
public override bool OnOptionsItemSelected(Android.Views.IMenuItem item) {
public override bool OnOptionsItemSelected(IMenuItem item) {
switch (item.ItemId) {
case Resource.Id.menu_donate:
try {
@ -573,24 +562,24 @@ namespace keepass2android
return base.OnOptionsItemSelected(item);
}
public override void OnCreateContextMenu(Android.Views.IContextMenu menu, View v,
Android.Views.IContextMenuContextMenuInfo menuInfo) {
public override void OnCreateContextMenu(IContextMenu menu, View v,
IContextMenuContextMenuInfo menuInfo) {
base.OnCreateContextMenu(menu, v, menuInfo);
menu.Add(0, CMENU_CLEAR, 0, Resource.String.remove_from_filelist);
menu.Add(0, CmenuClear, 0, Resource.String.remove_from_filelist);
}
public override bool OnContextItemSelected(Android.Views.IMenuItem item) {
public override bool OnContextItemSelected(IMenuItem item) {
base.OnContextItemSelected(item);
if ( item.ItemId == CMENU_CLEAR ) {
if ( item.ItemId == CmenuClear ) {
AdapterView.AdapterContextMenuInfo acmi = (AdapterView.AdapterContextMenuInfo) item.MenuInfo;
TextView tv = (TextView) acmi.TargetView;
String filename = tv.Text;
mDbHelper.deleteFile(filename);
_DbHelper.DeleteFile(filename);
refreshList();
RefreshList();
return true;
@ -599,7 +588,7 @@ namespace keepass2android
return false;
}
private void refreshList() {
private void RefreshList() {
CursorAdapter ca = (CursorAdapter) ListAdapter;
Android.Database.ICursor cursor = ca.Cursor;
cursor.Requery();

View File

@ -15,16 +15,7 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file
along with Keepass2Android. If not, see <http://www.gnu.org/licenses/>.
*/
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;
@ -33,82 +24,84 @@ using Android.Graphics;
namespace keepass2android
{
public class DrawableFactory
/// <summary>
/// Factory to create password icons
/// </summary>
public class DrawableFactory: IDrawableFactory
{
private static Drawable blank = null;
private static int blankWidth = -1;
private static int blankHeight = -1;
private static Drawable _blank;
private static int _blankWidth = -1;
private static int _blankHeight = -1;
/** customIconMap
* Cache for icon drawable.
* Keys: UUID, Values: Drawables
*/
private Dictionary<PwUuid, Drawable> customIconMap = new Dictionary<PwUuid, Drawable>(new PwUuidEqualityComparer());
private readonly Dictionary<PwUuid, Drawable> _customIconMap = new Dictionary<PwUuid, Drawable>(new PwUuidEqualityComparer());
/** standardIconMap
* Cache for icon drawable.
* Keys: Integer, Values: Drawables
*/
private Dictionary<int/*resId*/, Drawable> standardIconMap = new Dictionary<int, Drawable>();
private readonly Dictionary<int/*resId*/, Drawable> _standardIconMap = new Dictionary<int, Drawable>();
public void assignDrawableTo (ImageView iv, Resources res, PwDatabase db, PwIcon icon, PwUuid customIconId)
public void AssignDrawableTo (ImageView iv, Resources res, PwDatabase db, PwIcon icon, PwUuid customIconId)
{
Drawable draw = getIconDrawable (res, db, icon, customIconId);
Drawable draw = GetIconDrawable (res, db, icon, customIconId);
iv.SetImageDrawable (draw);
}
public Drawable getIconDrawable (Resources res, PwDatabase db, PwIcon icon, PwUuid customIconId)
public Drawable GetIconDrawable (Resources res, PwDatabase db, PwIcon icon, PwUuid customIconId)
{
if (!customIconId.EqualsValue(PwUuid.Zero)) {
return getIconDrawable (res, db, customIconId);
} else {
return getIconDrawable (res, icon);
return GetIconDrawable (res, db, customIconId);
}
return GetIconDrawable (res, icon);
}
private static void InitBlank (Resources res)
{
if (_blank == null) {
_blank = res.GetDrawable (Resource.Drawable.ic99_blank);
_blankWidth = _blank.IntrinsicWidth;
_blankHeight = _blank.IntrinsicHeight;
}
}
private static void initBlank (Resources res)
public Drawable GetIconDrawable (Resources res, PwIcon icon)
{
if (blank == null) {
blank = res.GetDrawable (Resource.Drawable.ic99_blank);
blankWidth = blank.IntrinsicWidth;
blankHeight = blank.IntrinsicHeight;
}
}
public Drawable getIconDrawable (Resources res, PwIcon icon)
{
int resId = Icons.iconToResId (icon);
int resId = Icons.IconToResId (icon);
Drawable draw;
if (!standardIconMap.TryGetValue(resId, out draw))
if (!_standardIconMap.TryGetValue(resId, out draw))
{
draw = res.GetDrawable(resId);
standardIconMap[resId] = draw;
_standardIconMap[resId] = draw;
}
return draw;
}
public Drawable getIconDrawable (Resources res, PwDatabase db, PwUuid icon)
public Drawable GetIconDrawable (Resources res, PwDatabase db, PwUuid icon)
{
initBlank (res);
InitBlank (res);
if (icon.EqualsValue(PwUuid.Zero)) {
return blank;
return _blank;
}
Drawable draw = null;
if (!customIconMap.TryGetValue(icon, out draw))
Drawable draw;
if (!_customIconMap.TryGetValue(icon, out draw))
{
Bitmap bitmap = db.GetCustomIcon(icon);
// Could not understand custom icon
if (bitmap == null) {
return blank;
return _blank;
}
bitmap = resize (bitmap);
draw = BitmapDrawableCompat.getBitmapDrawable (res, bitmap);
customIconMap[icon] = draw;
draw = new BitmapDrawable(res, bitmap);
_customIconMap[icon] = draw;
}
return draw;
@ -123,17 +116,17 @@ namespace keepass2android
int width = bitmap.Width;
int height = bitmap.Height;
if (width == blankWidth && height == blankHeight) {
if (width == _blankWidth && height == _blankHeight) {
return bitmap;
}
return Bitmap.CreateScaledBitmap (bitmap, blankWidth, blankHeight, true);
return Bitmap.CreateScaledBitmap (bitmap, _blankWidth, _blankHeight, true);
}
public void Clear ()
{
standardIconMap.Clear ();
customIconMap.Clear ();
_standardIconMap.Clear ();
_customIconMap.Clear ();
}
}

View File

@ -17,66 +17,67 @@ 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 System.Reflection;
using KeePassLib;
using Android.Util;
namespace keepass2android
{
/// <summary>
/// Stores the default pw entry icons
/// </summary>
public class Icons
{
private static Dictionary<PwIcon, int> _icons;
public class Icons {
private static Dictionary<PwIcon,int> icons = null;
private static void BuildList()
{
if (_icons != null) return;
private static void buildList() {
if (icons == null) {
icons = new Dictionary<PwIcon,int>();
_icons = new Dictionary<PwIcon, int>();
FieldInfo[] fields = typeof(Resource.Drawable).GetFields(BindingFlags.Static | BindingFlags.Public);
for (int i = 0; i < fields.Length; i++) {
String fieldName = fields[i].Name;
foreach (FieldInfo fieldInfo in fields)
{
String fieldName = fieldInfo.Name;
if (fieldName.StartsWith("ic") && (fieldName.Length >= 4))
{
String sNum = fieldName.Substring(2, 2);
int num;
if (int.TryParse(sNum,out num) && (num < (int)PwIcon.Count))
if (int.TryParse(sNum, out num) && (num < (int)PwIcon.Count))
{
int resId;
try {
resId = (int)fields[i].GetValue(null);
} catch (Exception) {
try
{
resId = (int)fieldInfo.GetValue(null);
}
catch (Exception)
{
continue;
}
icons[(PwIcon)num] = resId;
}
_icons[(PwIcon)num] = resId;
}
}
}
}
public static int iconToResId(PwIcon iconId) {
buildList();
int resId = Resource.Drawable.ic99_blank;
icons.TryGetValue(iconId, out resId);
public static int IconToResId(PwIcon iconId)
{
BuildList();
int resId;
if (_icons.TryGetValue(iconId, out resId))
return resId;
return Resource.Drawable.ic99_blank;
}
public static int count() {
buildList();
public static int Count()
{
BuildList();
return icons.Count;
return _icons.Count;
}
}

View File

@ -16,34 +16,26 @@ 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
{
/// <summary>
/// Contains constants to be used in intents
/// </summary>
public class Intents {
public const String TIMEOUT = "keepass2android.timeout";
public const String Timeout = "keepass2android.timeout";
public const String COPY_USERNAME = "keepass2android.copy_username";
public const String COPY_PASSWORD = "keepass2android.copy_password";
public const String CHECK_KEYBOARD = "keepass2android.check_keyboard";
public const String CopyUsername = "keepass2android.copy_username";
public const String CopyPassword = "keepass2android.copy_password";
public const String CheckKeyboard = "keepass2android.check_keyboard";
public const String FILE_BROWSE = "org.openintents.action.PICK_FILE";
public const int REQUEST_CODE_FILE_BROWSE_FOR_OPEN = 987321;
public const int REQUEST_CODE_FILE_BROWSE_FOR_CREATE = 987322;
public const int REQUEST_CODE_FILE_BROWSE_FOR_BINARY = 987323;
public const int REQUEST_CODE_FILE_BROWSE_FOR_KEYFILE = 987324;
public const String FileBrowse = "org.openintents.action.PICK_FILE";
public const int RequestCodeFileBrowseForOpen = 987321;
public const int RequestCodeFileBrowseForCreate = 987322;
public const int RequestCodeFileBrowseForBinary = 987323;
public const int RequestCodeFileBrowseForKeyfile = 987324;
public const String SHOW_NOTIFICATION = "keepass2android.show_notification";
public const String ShowNotification = "keepass2android.show_notification";
}
}

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
@ -77,28 +77,19 @@
<Reference Include="Mono.Android.Support.v4" />
</ItemGroup>
<ItemGroup>
<Compile Include="icons\DrawableFactory.cs" />
<Compile Include="icons\Icons.cs" />
<Compile Include="Resources\Resource.designer.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
<Compile Include="KeePass.cs" />
<Compile Include="database\edit\OnFinish.cs" />
<Compile Include="database\edit\FileOnFinish.cs" />
<Compile Include="app\App.cs" />
<Compile Include="Database.cs" />
<Compile Include="fileselect\FileSelectActivity.cs" />
<Compile Include="fileselect\FileDbHelper.cs" />
<Compile Include="search\SearchProvider.cs" />
<Compile Include="Utils\Util.cs" />
<Compile Include="Utils\Interaction.cs" />
<Compile Include="intents\Intents.cs" />
<Compile Include="fileselect\BrowserDialog.cs" />
<Compile Include="timeout\TimeoutHelper.cs" />
<Compile Include="timers\Timeout.cs" />
<Compile Include="database\edit\LoadDB.cs" />
<Compile Include="database\edit\RunnableOnFinish.cs" />
<Compile Include="UpdateStatus.cs" />
<Compile Include="ProgressTask.cs" />
<Compile Include="icons\DrawableFactory.cs" />
<Compile Include="search\SearchDbHelper.cs" />
<Compile Include="GroupActivity.cs" />
<Compile Include="GroupBaseActivity.cs" />
<Compile Include="LockCloseListActivity.cs" />
@ -112,16 +103,9 @@
<Compile Include="settings\PrefsUtil.cs" />
<Compile Include="views\PwEntryView.cs" />
<Compile Include="views\GroupHeaderView.cs" />
<Compile Include="PwUuidEqualityComparer.cs" />
<Compile Include="icons\Icons.cs" />
<Compile Include="BitmapDrawableCompat.cs" />
<Compile Include="GroupEditActivity.cs" />
<Compile Include="database\edit\AddGroup.cs" />
<Compile Include="database\edit\SaveDB.cs" />
<Compile Include="EntryEditActivity.cs" />
<Compile Include="LockCloseActivity.cs" />
<Compile Include="database\edit\AddEntry.cs" />
<Compile Include="database\edit\UpdateEntry.cs" />
<Compile Include="EntryActivity.cs" />
<Compile Include="GeneratePasswordActivity.cs" />
<Compile Include="password\PasswordGenerator.cs" />
@ -135,20 +119,13 @@
<Compile Include="LockingPreferenceActivity.cs" />
<Compile Include="SetPasswordDialog.cs" />
<Compile Include="CancelDialog.cs" />
<Compile Include="database\edit\SetPassword.cs" />
<Compile Include="database\edit\CreateDB.cs" />
<Compile Include="AboutDialog.cs" />
<Compile Include="settings\AppSettingsActivity.cs" />
<Compile Include="settings\RoundsPreference.cs" />
<Compile Include="KeyFileException.cs" />
<Compile Include="PasswordActivity.cs" />
<Compile Include="database\edit\DeleteGroup.cs" />
<Compile Include="PwGroupEqualityFromIdComparer.cs" />
<Compile Include="database\edit\DeleteEntry.cs" />
<Compile Include="search\SearchResults.cs" />
<Compile Include="compat\EditorCompat.cs" />
<Compile Include="compat\ActivityCompat.cs" />
<Compile Include="database\edit\ActionOnFinish.cs" />
<Compile Include="ShareUrlResults.cs" />
<Compile Include="services\TimeoutService.cs" />
<Compile Include="services\CopyToClipboardService.cs" />
@ -158,7 +135,6 @@
<Compile Include="LifecycleDebugActivity.cs" />
<Compile Include="services\QuickUnlockForegroundService.cs" />
<Compile Include="AssemblyInfo.cs" />
<Compile Include="database\edit\DeleteRunnable.cs" />
<Compile Include="views\FileSelectButtons.cs" />
<Compile Include="EntryEditActivityState.cs" />
<Compile Include="AttachmentContentProvider.cs" />
@ -658,62 +634,17 @@
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath)\Novell\Novell.MonoDroid.CSharp.targets" />
<ItemGroup>
<Folder Include="database\" />
<Folder Include="database\edit\" />
<Folder Include="app\" />
<Folder Include="fileselect\" />
<Folder Include="Utils\" />
<Folder Include="intents\" />
<Folder Include="views\" />
<Folder Include="timeout\" />
<Folder Include="timers\" />
<Folder Include="services\" />
<Folder Include="icons\" />
<Folder Include="search\" />
<Folder Include="settings\" />
<Folder Include="password\" />
<Folder Include="compat\" />
<Folder Include="Resources\menu-v11\" />
<Folder Include="Resources\drawable-hdpi\" />
<Folder Include="Resources\drawable-ldpi\" />
<Folder Include="Resources\drawable-mdpi\" />
<Folder Include="Resources\drawable-xhdpi\" />
<Folder Include="Resources\drawable-xxhdpi\" />
<Folder Include="Resources\drawable-v11\" />
<Folder Include="Resources\values-de\" />
<Folder Include="Resources\values-ca\" />
<Folder Include="Resources\values-cs\" />
<Folder Include="Resources\values-da\" />
<Folder Include="Resources\values-es\" />
<Folder Include="Resources\values-fr\" />
<Folder Include="Resources\values-hu\" />
<Folder Include="Resources\values-it\" />
<Folder Include="Resources\values-ja\" />
<Folder Include="Resources\values-nl\" />
<Folder Include="Resources\values-nn\" />
<Folder Include="Resources\values-pl\" />
<Folder Include="Resources\values-pt-rBR\" />
<Folder Include="Resources\values-ru\" />
<Folder Include="Resources\values-sk\" />
<Folder Include="Resources\values-uk\" />
<Folder Include="Resources\values-zh-rCN\" />
<Folder Include="Resources\values-zh-rTW\" />
<Folder Include="SupportLib\" />
<Folder Include="Assets\" />
<Folder Include="libs\" />
<Folder Include="libs\armeabi-v7a\" />
<Folder Include="libs\armeabi\" />
<Folder Include="libs\mips\" />
<Folder Include="Resources\values-v14\" />
<Folder Include="Resources\layout-v14\" />
<Folder Include="Resources\anim\" />
<Folder Include="Utils\Spr\" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\KeePassLib2Android\KeePassLib2Android.csproj">
<Project>{545B4A6B-8BBA-4FBE-92FC-4AC060122A54}</Project>
<Name>KeePassLib2Android</Name>
</ProjectReference>
<ProjectReference Include="..\Kp2aBusinessLogic\Kp2aBusinessLogic.csproj">
<Project>{53a9cb7f-6553-4bc0-b56b-9410bb2e59aa}</Project>
<Name>Kp2aBusinessLogic</Name>
</ProjectReference>
<ProjectReference Include="..\kp2akeytransform\kp2akeytransform.csproj">
<Project>{A57B3ACE-5634-469A-88C4-858BB409F356}</Project>
<Name>kp2akeytransform</Name>

View File

@ -16,44 +16,38 @@ 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
{
/// <summary>
/// Password generator
/// </summary>
public class PasswordGenerator {
private const String upperCaseChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
private const String lowerCaseChars = "abcdefghijklmnopqrstuvwxyz";
private const String digitChars = "0123456789";
private const String minusChars = "-";
private const String underlineChars = "_";
private const String spaceChars = " ";
private const String specialChars = "!\"#$%&'*+,./:;=?@\\^`";
private const String bracketChars = "[]{}()<>";
private const String UpperCaseChars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
private const String LowerCaseChars = "abcdefghijklmnopqrstuvwxyz";
private const String DigitChars = "0123456789";
private const String MinusChars = "-";
private const String UnderlineChars = "_";
private const String SpaceChars = " ";
private const String SpecialChars = "!\"#$%&'*+,./:;=?@\\^`";
private const String BracketChars = "[]{}()<>";
private Context cxt;
private readonly Context _cxt;
public PasswordGenerator(Context cxt) {
this.cxt = cxt;
_cxt = cxt;
}
public String generatePassword(int length, bool upperCase, bool lowerCase, bool digits, bool minus, bool underline, bool space, bool specials, bool brackets) {
public String GeneratePassword(int length, bool upperCase, bool lowerCase, bool digits, bool minus, bool underline, bool space, bool specials, bool brackets) {
if (length <= 0)
throw new ArgumentException(cxt.GetString(Resource.String.error_wrong_length));
throw new ArgumentException(_cxt.GetString(Resource.String.error_wrong_length));
if (!upperCase && !lowerCase && !digits && !minus && !underline && !space && !specials && !brackets)
throw new ArgumentException(cxt.GetString(Resource.String.error_pass_gen_type));
throw new ArgumentException(_cxt.GetString(Resource.String.error_pass_gen_type));
String characterSet = getCharacterSet(upperCase, lowerCase, digits, minus, underline, space, specials, brackets);
String characterSet = GetCharacterSet(upperCase, lowerCase, digits, minus, underline, space, specials, brackets);
int size = characterSet.Length;
@ -72,32 +66,32 @@ namespace keepass2android
return buffer.ToString();
}
public String getCharacterSet(bool upperCase, bool lowerCase, bool digits, bool minus, bool underline, bool space, bool specials, bool brackets) {
public String GetCharacterSet(bool upperCase, bool lowerCase, bool digits, bool minus, bool underline, bool space, bool specials, bool brackets) {
StringBuilder charSet = new StringBuilder();
if (upperCase)
charSet.Append(upperCaseChars);
charSet.Append(UpperCaseChars);
if (lowerCase)
charSet.Append(lowerCaseChars);
charSet.Append(LowerCaseChars);
if (digits)
charSet.Append(digitChars);
charSet.Append(DigitChars);
if (minus)
charSet.Append(minusChars);
charSet.Append(MinusChars);
if (underline)
charSet.Append(underlineChars);
charSet.Append(UnderlineChars);
if (space)
charSet.Append(spaceChars);
charSet.Append(SpaceChars);
if (specials)
charSet.Append(specialChars);
charSet.Append(SpecialChars);
if (brackets)
charSet.Append(bracketChars);
charSet.Append(BracketChars);
return charSet.ToString();
}

View File

@ -16,21 +16,18 @@ 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;
using KeePassLib;
using keepass2android.search;
namespace keepass2android
{
/// <summary>
/// Activity to display search options
/// </summary>
[Activity (Label = "@string/app_name", Theme="@style/Base")]
public class SearchActivity : LifecycleDebugActivity
{
@ -44,38 +41,35 @@ namespace keepass2android
base.OnCreate(bundle);
SetContentView(Resource.Layout.search);
SearchParameters sp = new SearchParameters();
populateCheckBox(Resource.Id.cbSearchInTitle, sp.SearchInTitles);
populateCheckBox(Resource.Id.cbSearchInUsername, sp.SearchInUserNames);
populateCheckBox(Resource.Id.cbSearchInNotes, sp.SearchInNotes);
populateCheckBox(Resource.Id.cbSearchInPassword, sp.SearchInPasswords);
populateCheckBox(Resource.Id.cbSearchInTags, sp.SearchInTags);
populateCheckBox(Resource.Id.cbSearchInGroupName, sp.SearchInGroupNames);
populateCheckBox(Resource.Id.cbSearchInUrl, sp.SearchInUrls);
populateCheckBox(Resource.Id.cbSearchInOtherStrings, sp.SearchInOther);
populateCheckBox(Resource.Id.cbRegEx, sp.RegularExpression);
PopulateCheckBox(Resource.Id.cbSearchInTitle, sp.SearchInTitles);
PopulateCheckBox(Resource.Id.cbSearchInUsername, sp.SearchInUserNames);
PopulateCheckBox(Resource.Id.cbSearchInNotes, sp.SearchInNotes);
PopulateCheckBox(Resource.Id.cbSearchInPassword, sp.SearchInPasswords);
PopulateCheckBox(Resource.Id.cbSearchInTags, sp.SearchInTags);
PopulateCheckBox(Resource.Id.cbSearchInGroupName, sp.SearchInGroupNames);
PopulateCheckBox(Resource.Id.cbSearchInUrl, sp.SearchInUrls);
PopulateCheckBox(Resource.Id.cbSearchInOtherStrings, sp.SearchInOther);
PopulateCheckBox(Resource.Id.cbRegEx, sp.RegularExpression);
StringComparison sc = sp.ComparisonMode;
bool caseSensitive = ((sc != StringComparison.CurrentCultureIgnoreCase) &&
(sc != StringComparison.InvariantCultureIgnoreCase) &&
(sc != StringComparison.OrdinalIgnoreCase));
populateCheckBox(Resource.Id.cbCaseSensitive, caseSensitive);
populateCheckBox(Resource.Id.cbExcludeExpiredEntries, sp.ExcludeExpired);
PopulateCheckBox(Resource.Id.cbCaseSensitive, caseSensitive);
PopulateCheckBox(Resource.Id.cbExcludeExpiredEntries, sp.ExcludeExpired);
ImageButton btnSearch = (ImageButton)FindViewById(Resource.Id.search_button);
btnSearch.Click += (object sender, EventArgs e) =>
{
PerformSearch();
};
btnSearch.Click += (sender, e) => PerformSearch();
FindViewById<EditText>(Resource.Id.searchEditText).EditorAction += (object sender, TextView.EditorActionEventArgs e) =>
FindViewById<EditText>(Resource.Id.searchEditText).EditorAction += (sender, e) =>
{
if (e.ActionId == Android.Views.InputMethods.ImeAction.Search) {
PerformSearch();
}
};
}
void populateCheckBox(int resId, bool value)
void PopulateCheckBox(int resId, bool value)
{
((CheckBox) FindViewById(resId)).Checked = value;
}
@ -85,7 +79,6 @@ namespace keepass2android
String searchString = ((EditText)FindViewById(Resource.Id.searchEditText)).Text;
if (String.IsNullOrWhiteSpace(searchString))
return;
SearchParameters spNew = new SearchParameters();
Intent searchIntent = new Intent(this, typeof(SearchResults));
searchIntent.PutExtra("SearchInTitles", GetCheckBoxValue(Resource.Id.cbSearchInTitle));
searchIntent.PutExtra("SearchInUrls", GetCheckBoxValue(Resource.Id.cbSearchInUrl));

View File

@ -15,15 +15,10 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file
along with Keepass2Android. If not, see <http://www.gnu.org/licenses/>.
*/
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 keepass2android.view;
using KeePassLib;
@ -31,12 +26,15 @@ using Android.Support.V4.App;
namespace keepass2android.search
{
/// <summary>
/// Activity to show search results
/// </summary>
[Activity (Label = "@string/app_name", Theme="@style/NoTitleBar", LaunchMode=Android.Content.PM.LaunchMode.SingleTop)]
[MetaData("android.app.searchable",Resource="@xml/searchable")]
[IntentFilter(new[]{Intent.ActionSearch}, Categories=new[]{Intent.CategoryDefault})]
public class SearchResults : GroupBaseActivity
{
private Database mDb;
private Database _db;
protected override void OnCreate (Bundle bundle)
{
@ -46,7 +44,7 @@ namespace keepass2android.search
return;
}
SetResult(KeePass.EXIT_NORMAL);
SetResult(KeePass.ExitNormal);
ProcessIntent(Intent);
}
@ -58,18 +56,18 @@ namespace keepass2android.search
private void ProcessIntent(Intent intent)
{
mDb = App.getDB();
_db = App.Kp2a.GetDb();
// Likely the app has been killed exit the activity
if (!mDb.Open)
{
if ( ! _db.Open ) {
Finish();
}
if (intent.Action == Intent.ActionView)
{
var entryIntent = new Intent(this, typeof(EntryActivity));
entryIntent.PutExtra(EntryActivity.KEY_ENTRY, intent.Data.LastPathSegment);
entryIntent.PutExtra(EntryActivity.KeyEntry, intent.Data.LastPathSegment);
Finish(); // Close this activity so that the entry activity is navigated to from the main activity, not this one.
StartActivity(entryIntent);
@ -77,14 +75,14 @@ namespace keepass2android.search
else
{
// Action may either by ActionSearch (from search widget) or null (if called from SearchActivity directly)
query(getSearch(intent));
Query(getSearch(intent));
}
}
private void query (SearchParameters searchParams)
private void Query (SearchParameters searchParams)
{
try {
mGroup = mDb.Search (searchParams);
Group = _db.Search (searchParams);
} catch (Exception e) {
Toast.MakeText(this,e.Message, ToastLength.Long).Show();
Finish();
@ -93,22 +91,21 @@ namespace keepass2android.search
if ( mGroup == null || (mGroup.Entries.Count() < 1) ) {
if ( Group == null || (!Group.Entries.Any()) ) {
SetContentView(new GroupEmptyView(this));
} else {
SetContentView(new GroupViewOnlyView(this));
}
setGroupTitle();
SetGroupTitle();
ListAdapter = new PwGroupListAdapter(this, mGroup);
ListAdapter = new PwGroupListAdapter(this, Group);
}
private SearchParameters getSearch(Intent queryIntent) {
// get and process search query here
SearchParameters sp = new SearchParameters();
sp.SearchString = queryIntent.GetStringExtra(SearchManager.Query);
sp.SearchInTitles = queryIntent.GetBooleanExtra("SearchInTitles", sp.SearchInTitles);
sp.SearchInUrls = queryIntent.GetBooleanExtra("SearchInUrls", sp.SearchInUrls);
sp.SearchInPasswords = queryIntent.GetBooleanExtra("SearchInPasswords", sp.SearchInPasswords);
@ -134,10 +131,8 @@ namespace keepass2android.search
{
Finish();
return true;
} else
{
return false;
}
return false;
}
}
}

View File

@ -18,14 +18,12 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Java.Util;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.Preferences;
using KeePassLib;
@ -35,15 +33,21 @@ using KeePass.Util.Spr;
namespace keepass2android
{
/// <summary>
/// Service to show the notifications to make the current entry accessible through clipboard or the KP2A keyboard.
/// </summary>
/// The name reflects only the possibility through clipboard because keyboard was introduced later.
/// The notifications require to be displayed by a service in order to be kept when the activity is closed
/// after searching for a URL.
[Service]
public class CopyToClipboardService: Service
{
public const int NOTIFY_USERNAME = 1;
public const int NOTIFY_PASSWORD = 2;
public const int NOTIFY_KEYBOARD = 3;
public const int CLEAR_CLIPBOARD = 4;
public const int NotifyUsername = 1;
public const int NotifyPassword = 2;
public const int NotifyKeyboard = 3;
public const int ClearClipboard = 4;
public CopyToClipboardService (IntPtr javaReference, JniHandleOwnership transfer)
@ -51,18 +55,14 @@ namespace keepass2android
{
}
CopyToClipboardBroadcastReceiver mCopyToClipBroadcastReceiver;
NotificationDeletedBroadcastReceiver mNotificationDeletedBroadcastReceiver;
CopyToClipboardBroadcastReceiver _copyToClipBroadcastReceiver;
NotificationDeletedBroadcastReceiver _notificationDeletedBroadcastReceiver;
public CopyToClipboardService()
{
}
public override void OnCreate()
{
base.OnCreate();
}
public override IBinder OnBind(Intent intent)
@ -74,17 +74,17 @@ namespace keepass2android
{
Android.Util.Log.Debug("DEBUG","Received intent to provide access to entry");
String uuidBytes = intent.GetStringExtra(EntryActivity.KEY_ENTRY);
bool closeAfterCreate = intent.GetBooleanExtra(EntryActivity.KEY_CLOSE_AFTER_CREATE, false);
String uuidBytes = intent.GetStringExtra(EntryActivity.KeyEntry);
bool closeAfterCreate = intent.GetBooleanExtra(EntryActivity.KeyCloseAfterCreate, false);
PwUuid entryId = PwUuid.Zero;
if (uuidBytes != null)
entryId = new KeePassLib.PwUuid(MemUtil.HexStringToByteArray(uuidBytes));
entryId = new PwUuid(MemUtil.HexStringToByteArray(uuidBytes));
PwEntry entry;
try
{
entry = App.getDB().entries[entryId];
entry = App.Kp2a.GetDb().Entries[entryId];
}
catch(Exception)
{
@ -93,29 +93,29 @@ namespace keepass2android
return StartCommandResult.NotSticky;
}
displayAccessNotifications(entry, closeAfterCreate);
DisplayAccessNotifications(entry, closeAfterCreate);
return StartCommandResult.RedeliverIntent;
}
private NotificationManager mNM;
private int mNumElementsToWaitFor = 0;
private NotificationManager _notificationManager;
private int _numElementsToWaitFor;
public override void OnDestroy()
{
// These members might never get initialized if the app timed out
if (mCopyToClipBroadcastReceiver != null)
if (_copyToClipBroadcastReceiver != null)
{
UnregisterReceiver(mCopyToClipBroadcastReceiver);
UnregisterReceiver(_copyToClipBroadcastReceiver);
}
if (mNotificationDeletedBroadcastReceiver != null)
if (_notificationDeletedBroadcastReceiver != null)
{
UnregisterReceiver(mNotificationDeletedBroadcastReceiver);
UnregisterReceiver(_notificationDeletedBroadcastReceiver);
}
if ( mNM != null ) {
mNM.CancelAll();
mNumElementsToWaitFor= 0;
if ( _notificationManager != null ) {
_notificationManager.CancelAll();
_numElementsToWaitFor= 0;
clearKeyboard();
}
@ -124,13 +124,13 @@ namespace keepass2android
base.OnDestroy();
}
static string ACTION_NOTIFICATION_CANCELLED = "notification_cancelled";
private const string ActionNotificationCancelled = "notification_cancelled";
//creates a delete intent (started when notification is cancelled by user or something else)
//requires different request codes for every item (otherwise the intents are identical)
PendingIntent createDeleteIntent(int requestCode)
PendingIntent CreateDeleteIntent(int requestCode)
{
Intent intent = new Intent(ACTION_NOTIFICATION_CANCELLED);
Intent intent = new Intent(ActionNotificationCancelled);
Bundle extra = new Bundle();
extra.PutInt("requestCode", requestCode);
intent.PutExtras(extra);
@ -138,39 +138,39 @@ namespace keepass2android
return PendingIntent.GetBroadcast(this, requestCode, intent, PendingIntentFlags.CancelCurrent);
}
public void displayAccessNotifications(PwEntry entry, bool closeAfterCreate)
public void DisplayAccessNotifications(PwEntry entry, bool closeAfterCreate)
{
// Notification Manager
mNM = (NotificationManager)GetSystemService(NotificationService);
_notificationManager = (NotificationManager)GetSystemService(NotificationService);
mNM.CancelAll();
mNumElementsToWaitFor = 0;
_notificationManager.CancelAll();
_numElementsToWaitFor = 0;
clearKeyboard();
String entryName = entry.Strings.ReadSafe(PwDefs.TitleField);
ISharedPreferences prefs = Android.Preferences.PreferenceManager.GetDefaultSharedPreferences(this);
ISharedPreferences prefs = PreferenceManager.GetDefaultSharedPreferences(this);
if (prefs.GetBoolean(GetString(Resource.String.CopyToClipboardNotification_key), Resources.GetBoolean(Resource.Boolean.CopyToClipboardNotification_default)))
{
if (GetStringAndReplacePlaceholders(entry, PwDefs.PasswordField).Length > 0)
{
// only show notification if password is available
Notification password = GetNotification(Intents.COPY_PASSWORD, Resource.String.copy_password, Resource.Drawable.notify, entryName);
Notification password = GetNotification(Intents.CopyPassword, Resource.String.copy_password, Resource.Drawable.notify, entryName);
password.DeleteIntent = createDeleteIntent(NOTIFY_PASSWORD);
mNM.Notify(NOTIFY_PASSWORD, password);
mNumElementsToWaitFor++;
password.DeleteIntent = CreateDeleteIntent(NotifyPassword);
_notificationManager.Notify(NotifyPassword, password);
_numElementsToWaitFor++;
}
if (GetStringAndReplacePlaceholders(entry, PwDefs.UserNameField).Length > 0)
{
// only show notification if username is available
Notification username = GetNotification(Intents.COPY_USERNAME, Resource.String.copy_username, Resource.Drawable.notify, entryName);
username.DeleteIntent = createDeleteIntent(NOTIFY_USERNAME);
mNumElementsToWaitFor++;
mNM.Notify(NOTIFY_USERNAME, username);
Notification username = GetNotification(Intents.CopyUsername, Resource.String.copy_username, Resource.Drawable.notify, entryName);
username.DeleteIntent = CreateDeleteIntent(NotifyUsername);
_numElementsToWaitFor++;
_notificationManager.Notify(NotifyUsername, username);
}
}
@ -178,17 +178,17 @@ namespace keepass2android
{
//keyboard
if (makeAccessibleForKeyboard(entry))
if (MakeAccessibleForKeyboard(entry))
{
// only show notification if username is available
Notification keyboard = GetNotification(Intents.CHECK_KEYBOARD, Resource.String.available_through_keyboard, Resource.Drawable.notify_keyboard, entryName);
keyboard.DeleteIntent = createDeleteIntent(NOTIFY_KEYBOARD);
mNumElementsToWaitFor++;
mNM.Notify(NOTIFY_KEYBOARD, keyboard);
Notification keyboard = GetNotification(Intents.CheckKeyboard, Resource.String.available_through_keyboard, Resource.Drawable.notify_keyboard, entryName);
keyboard.DeleteIntent = CreateDeleteIntent(NotifyKeyboard);
_numElementsToWaitFor++;
_notificationManager.Notify(NotifyKeyboard, keyboard);
//if the app is about to be closed again (e.g. after searching for a URL and returning to the browser:
// automatically bring up the Keyboard selection dialog
if ((closeAfterCreate) && (prefs.GetBoolean(GetString(Resource.String.OpenKp2aKeyboardAutomatically_key), Resources.GetBoolean(Resource.Boolean.OpenKp2aKeyboardAutomatically_default)) == true))
if ((closeAfterCreate) && prefs.GetBoolean(GetString(Resource.String.OpenKp2aKeyboardAutomatically_key), Resources.GetBoolean(Resource.Boolean.OpenKp2aKeyboardAutomatically_default)))
{
ActivateKp2aKeyboard(this);
}
@ -196,28 +196,28 @@ namespace keepass2android
}
if (mNumElementsToWaitFor == 0)
if (_numElementsToWaitFor == 0)
{
StopSelf();
return;
}
mCopyToClipBroadcastReceiver = new CopyToClipboardBroadcastReceiver(entry, this);
_copyToClipBroadcastReceiver = new CopyToClipboardBroadcastReceiver(entry, this);
IntentFilter filter = new IntentFilter();
filter.AddAction(Intents.COPY_USERNAME);
filter.AddAction(Intents.COPY_PASSWORD);
filter.AddAction(Intents.CHECK_KEYBOARD);
RegisterReceiver(mCopyToClipBroadcastReceiver, filter);
filter.AddAction(Intents.CopyUsername);
filter.AddAction(Intents.CopyPassword);
filter.AddAction(Intents.CheckKeyboard);
RegisterReceiver(_copyToClipBroadcastReceiver, filter);
//register receiver to get notified when notifications are discarded in which case we can shutdown the service
mNotificationDeletedBroadcastReceiver = new NotificationDeletedBroadcastReceiver(this);
_notificationDeletedBroadcastReceiver = new NotificationDeletedBroadcastReceiver(this);
IntentFilter deletefilter = new IntentFilter();
deletefilter.AddAction(ACTION_NOTIFICATION_CANCELLED);
RegisterReceiver(mNotificationDeletedBroadcastReceiver, deletefilter);
deletefilter.AddAction(ActionNotificationCancelled);
RegisterReceiver(_notificationDeletedBroadcastReceiver, deletefilter);
}
bool makeAccessibleForKeyboard(PwEntry entry)
bool MakeAccessibleForKeyboard(PwEntry entry)
{
bool hasData = false;
Keepass2android.Kbbridge.KeyboardDataBuilder kbdataBuilder = new Keepass2android.Kbbridge.KeyboardDataBuilder();
@ -271,18 +271,18 @@ namespace keepass2android
static string GetStringAndReplacePlaceholders(PwEntry entry, string key)
{
String value = entry.Strings.ReadSafe(key);
value = SprEngine.Compile(value, new SprContext(entry, App.getDB().pm, SprCompileFlags.All));
value = SprEngine.Compile(value, new SprContext(entry, App.Kp2a.GetDb().KpDatabase, SprCompileFlags.All));
return value;
}
public void OnWaitElementDeleted(int itemId)
{
mNumElementsToWaitFor--;
if (mNumElementsToWaitFor <= 0)
_numElementsToWaitFor--;
if (_numElementsToWaitFor <= 0)
{
StopSelf();
}
if (itemId == NOTIFY_KEYBOARD)
if (itemId == NotifyKeyboard)
{
//keyboard notification was deleted -> clear entries in keyboard
clearKeyboard();
@ -295,9 +295,9 @@ namespace keepass2android
Keepass2android.Kbbridge.KeyboardData.EntryName = null;
}
private Timer mTimer = new Timer();
private readonly Timer _timer = new Timer();
internal void timeoutCopyToClipboard(String text) {
internal void TimeoutCopyToClipboard(String text) {
Util.copyToClipboard(this, text);
ISharedPreferences prefs = PreferenceManager.GetDefaultSharedPreferences(this);
@ -306,31 +306,31 @@ namespace keepass2android
long clipClearTime = long.Parse(sClipClear);
if ( clipClearTime > 0 ) {
mNumElementsToWaitFor++;
mTimer.Schedule(new ClearClipboardTask(this, text, uiThreadCallback), clipClearTime);
_numElementsToWaitFor++;
_timer.Schedule(new ClearClipboardTask(this, text, _uiThreadCallback), clipClearTime);
}
}
// Task which clears the clipboard, and sends a toast to the foreground.
private class ClearClipboardTask : Java.Util.TimerTask {
private class ClearClipboardTask : TimerTask {
private String mClearText;
private CopyToClipboardService mService;
private Handler handler;
private readonly String _clearText;
private readonly CopyToClipboardService _service;
private readonly Handler _handler;
public ClearClipboardTask(CopyToClipboardService service, String clearText, Handler handler) {
mClearText = clearText;
mService = service;
this.handler = handler;
_clearText = clearText;
_service = service;
_handler = handler;
}
public override void Run() {
String currentClip = Util.getClipboard(mService);
handler.Post( () => { mService.OnWaitElementDeleted(CLEAR_CLIPBOARD); });
if ( currentClip.Equals(mClearText) ) {
Util.copyToClipboard(mService, "");
handler.Post( () => {
Toast.MakeText(mService, Resource.String.ClearClipboard, ToastLength.Long).Show();
String currentClip = Util.getClipboard(_service);
_handler.Post( () => _service.OnWaitElementDeleted(ClearClipboard));
if ( currentClip.Equals(_clearText) ) {
Util.copyToClipboard(_service, "");
_handler.Post( () => {
Toast.MakeText(_service, Resource.String.ClearClipboard, ToastLength.Long).Show();
});
}
}
@ -338,7 +338,7 @@ namespace keepass2android
// Setup to allow the toast to happen in the foreground
Handler uiThreadCallback = new Handler();
readonly Handler _uiThreadCallback = new Handler();
private Notification GetNotification(String intentText, int descResId, int drawableResId, String entryName) {
String desc = GetString(descResId);
@ -362,36 +362,37 @@ namespace keepass2android
class CopyToClipboardBroadcastReceiver: BroadcastReceiver
{
CopyToClipboardService mService;
readonly CopyToClipboardService _service;
readonly PwEntry _entry;
public CopyToClipboardBroadcastReceiver(PwEntry entry, CopyToClipboardService service)
{
mEntry = entry;
this.mService = service;
_entry = entry;
_service = service;
}
PwEntry mEntry;
public override void OnReceive(Context context, Intent intent)
{
String action = intent.Action;
if (action.Equals(Intents.COPY_USERNAME))
if (action.Equals(Intents.CopyUsername))
{
String username = GetStringAndReplacePlaceholders(mEntry, PwDefs.UserNameField);
String username = GetStringAndReplacePlaceholders(_entry, PwDefs.UserNameField);
if (username.Length > 0)
{
mService.timeoutCopyToClipboard(username);
_service.TimeoutCopyToClipboard(username);
}
} else if (action.Equals(Intents.COPY_PASSWORD))
} else if (action.Equals(Intents.CopyPassword))
{
String password = GetStringAndReplacePlaceholders(mEntry, PwDefs.PasswordField);
String password = GetStringAndReplacePlaceholders(_entry, PwDefs.PasswordField);
if (password.Length > 0)
{
mService.timeoutCopyToClipboard(password);
_service.TimeoutCopyToClipboard(password);
}
} else if (action.Equals(Intents.CHECK_KEYBOARD))
} else if (action.Equals(Intents.CheckKeyboard))
{
CopyToClipboardService.ActivateKp2aKeyboard(mService);
ActivateKp2aKeyboard(_service);
}
}
@ -399,18 +400,18 @@ namespace keepass2android
class NotificationDeletedBroadcastReceiver: BroadcastReceiver
{
CopyToClipboardService mService;
readonly CopyToClipboardService _service;
public NotificationDeletedBroadcastReceiver(CopyToClipboardService service)
{
this.mService = service;
_service = service;
}
#region implemented abstract members of BroadcastReceiver
public override void OnReceive(Context context, Intent intent)
{
if (intent.Action == CopyToClipboardService.ACTION_NOTIFICATION_CANCELLED)
if (intent.Action == ActionNotificationCancelled)
{
mService.OnWaitElementDeleted(intent.Extras.GetInt("requestCode"));
_service.OnWaitElementDeleted(intent.Extras.GetInt("requestCode"));
}
}
#endregion
@ -424,7 +425,7 @@ namespace keepass2android
string kp2aIme = service.PackageName + "/keepass2android.softkeyboard.KP2AKeyboard";
InputMethodManager imeManager = (InputMethodManager)service.ApplicationContext.GetSystemService(Context.InputMethodService);
InputMethodManager imeManager = (InputMethodManager)service.ApplicationContext.GetSystemService(InputMethodService);
if (currentIme == kp2aIme)
{

View File

@ -15,25 +15,19 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll.
along with Keepass2Android. If not, see <http://www.gnu.org/licenses/>.
*/
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.Support.V4.App;
using Android.Graphics;
namespace keepass2android
{
//This service is started as soon as a Database with QuickUnlock enabled is opened.
//Its only purpose is to be a foreground service which prevents the App from being killed (in most situations)
[Service]
/// <summary>
/// This service is started as soon as a Database with QuickUnlock enabled is opened.
/// Its only purpose is to be a foreground service which prevents the App from being killed (in most situations)
/// </summary>
[Service]
public class QuickUnlockForegroundService : Service
{
public override IBinder OnBind(Intent intent)

View File

@ -16,44 +16,41 @@ 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 Android.Util;
namespace keepass2android
{
/// <summary>
/// Manages timeout to lock the database after some idle time
/// </summary>
[Service]
public class TimeoutService : Service {
private const String TAG = "KeePass2Android Timer";
private BroadcastReceiver mIntentReceiver;
private const String Tag = "KeePass2Android Timer";
private BroadcastReceiver _intentReceiver;
public TimeoutService (IntPtr javaReference, JniHandleOwnership transfer)
: base(javaReference, transfer)
{
mBinder = new TimeoutBinder(this);
_binder = new TimeoutBinder(this);
}
public TimeoutService()
{
mBinder = new TimeoutBinder(this);
_binder = new TimeoutBinder(this);
}
public override void OnCreate() {
base.OnCreate();
mIntentReceiver = new MyBroadcastReceiver(this);
_intentReceiver = new MyBroadcastReceiver(this);
IntentFilter filter = new IntentFilter();
filter.AddAction(Intents.TIMEOUT);
RegisterReceiver(mIntentReceiver, filter);
filter.AddAction(Intents.Timeout);
RegisterReceiver(_intentReceiver, filter);
}
@ -61,12 +58,12 @@ namespace keepass2android
public override void OnStart(Intent intent, int startId) {
base.OnStart(intent, startId);
Log.Debug(TAG, "Timeout service started");
Log.Debug(Tag, "Timeout service started");
}
private void timeout(Context context) {
Log.Debug(TAG, "Timeout");
App.setShutdown();
private void Timeout() {
Log.Debug(Tag, "Timeout");
App.Kp2a.SetShutdown();
NotificationManager nm = (NotificationManager) GetSystemService(NotificationService);
nm.CancelAll();
@ -77,30 +74,30 @@ namespace keepass2android
public override void OnDestroy() {
base.OnDestroy();
Log.Debug(TAG, "Timeout service stopped");
Log.Debug(Tag, "Timeout service stopped");
UnregisterReceiver(mIntentReceiver);
UnregisterReceiver(_intentReceiver);
}
public class TimeoutBinder : Binder
{
TimeoutService service;
readonly TimeoutService _service;
public TimeoutBinder(TimeoutService service)
{
this.service = service;
_service = service;
}
public TimeoutService getService() {
return service;
public TimeoutService GetService() {
return _service;
}
}
private IBinder mBinder;
private readonly IBinder _binder;
public override IBinder OnBind(Intent intent) {
return mBinder;
return _binder;
}
[BroadcastReceiver]
@ -112,17 +109,17 @@ namespace keepass2android
throw new NotImplementedException();
}
TimeoutService timeoutService;
readonly TimeoutService _timeoutService;
public MyBroadcastReceiver (TimeoutService timeoutService)
{
this.timeoutService = timeoutService;
_timeoutService = timeoutService;
}
public override void OnReceive(Context context, Intent intent) {
String action = intent.Action;
if ( action.Equals(Intents.TIMEOUT) ) {
timeoutService.timeout(context);
if ( action.Equals(Intents.Timeout) ) {
_timeoutService.Timeout();
}
}
}

View File

@ -16,24 +16,22 @@ 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 System.Globalization;
using Android.App;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.Preferences;
using KeePassLib.Cryptography.Cipher;
namespace keepass2android
{
/// <summary>
/// Activity to configure the app
/// </summary>
[Activity (Label = "@string/app_name", Theme="@style/NoTitleBar")]
public class AppSettingsActivity : LockingClosePreferenceActivity {
public static bool KEYFILE_DEFAULT = false;
public static bool KeyfileDefault = false;
public static void Launch(Context ctx) {
Intent i = new Intent(ctx, typeof(AppSettingsActivity));
@ -47,74 +45,67 @@ namespace keepass2android
AddPreferencesFromResource(Resource.Xml.preferences);
Preference keyFile = FindPreference(GetString(Resource.String.keyfile_key));
keyFile.PreferenceChange += (object sender, Preference.PreferenceChangeEventArgs e) =>
keyFile.PreferenceChange += (sender, e) =>
{
bool value = (bool) e.NewValue;
if ( ! value ) {
FileDbHelper helper = App.fileDbHelper;
FileDbHelper helper = App.Kp2a.FileDbHelper;
helper.deleteAllKeys();
helper.DeleteAllKeys();
}
return;
};
Database db = App.getDB();
Database db = App.Kp2a.GetDb();
if ( db.Open ) {
Preference rounds = FindPreference(GetString(Resource.String.rounds_key));
rounds.PreferenceChange += (object sender, Preference.PreferenceChangeEventArgs e) =>
rounds.PreferenceChange += (sender, e) =>
{
setRounds(App.getDB(), e.Preference);
return;
setRounds(App.Kp2a.GetDb(), e.Preference);
};
Preference defaultUser = FindPreference(GetString(Resource.String.default_username_key));
((EditTextPreference)defaultUser).EditText.Text = db.pm.DefaultUserName;
((EditTextPreference)defaultUser).Text = db.pm.DefaultUserName;
defaultUser.PreferenceChange += (object sender, Preference.PreferenceChangeEventArgs e) =>
((EditTextPreference)defaultUser).EditText.Text = db.KpDatabase.DefaultUserName;
((EditTextPreference)defaultUser).Text = db.KpDatabase.DefaultUserName;
defaultUser.PreferenceChange += (sender, e) =>
{
DateTime previousUsernameChanged = db.pm.DefaultUserNameChanged;
String previousUsername = db.pm.DefaultUserName;
db.pm.DefaultUserName = e.NewValue.ToString();
DateTime previousUsernameChanged = db.KpDatabase.DefaultUserNameChanged;
String previousUsername = db.KpDatabase.DefaultUserName;
db.KpDatabase.DefaultUserName = e.NewValue.ToString();
Handler handler = new Handler();
SaveDB save = new SaveDB(this, App.getDB(), new ActionOnFinish( (success, message) =>
SaveDb save = new SaveDb(this, App.Kp2a.GetDb(), new ActionOnFinish( (success, message) =>
{
if (!success)
{
db.pm.DefaultUserName = previousUsername;
db.pm.DefaultUserNameChanged = previousUsernameChanged;
db.KpDatabase.DefaultUserName = previousUsername;
db.KpDatabase.DefaultUserNameChanged = previousUsernameChanged;
Toast.MakeText(this, message, ToastLength.Long).Show();
}
}));
ProgressTask pt = new ProgressTask(this, save, Resource.String.saving_database);
pt.run();
ProgressTask pt = new ProgressTask(App.Kp2a, this, save, UiStringKey.saving_database);
pt.Run();
};
Preference databaseName = FindPreference(GetString(Resource.String.database_name_key));
((EditTextPreference)databaseName).EditText.Text = db.pm.Name;
((EditTextPreference)databaseName).Text = db.pm.Name;
databaseName.PreferenceChange += (object sender, Preference.PreferenceChangeEventArgs e) =>
((EditTextPreference)databaseName).EditText.Text = db.KpDatabase.Name;
((EditTextPreference)databaseName).Text = db.KpDatabase.Name;
databaseName.PreferenceChange += (sender, e) =>
{
DateTime previousNameChanged = db.pm.NameChanged;
String previousName = db.pm.Name;
db.pm.Name = e.NewValue.ToString();
DateTime previousNameChanged = db.KpDatabase.NameChanged;
String previousName = db.KpDatabase.Name;
db.KpDatabase.Name = e.NewValue.ToString();
Handler handler = new Handler();
SaveDB save = new SaveDB(this, App.getDB(), new ActionOnFinish( (success, message) =>
SaveDb save = new SaveDb(this, App.Kp2a.GetDb(), new ActionOnFinish( (success, message) =>
{
if (!success)
{
db.pm.Name = previousName;
db.pm.NameChanged = previousNameChanged;
db.KpDatabase.Name = previousName;
db.KpDatabase.NameChanged = previousNameChanged;
Toast.MakeText(this, message, ToastLength.Long).Show();
}
}));
ProgressTask pt = new ProgressTask(this, save, Resource.String.saving_database);
pt.run();
ProgressTask pt = new ProgressTask(App.Kp2a, this, save, UiStringKey.saving_database);
pt.Run();
};
@ -131,18 +122,13 @@ namespace keepass2android
}
protected override void OnStop() {
base.OnStop();
}
private void setRounds(Database db, Preference rounds) {
rounds.Summary = db.pm.KeyEncryptionRounds.ToString();
rounds.Summary = db.KpDatabase.KeyEncryptionRounds.ToString(CultureInfo.InvariantCulture);
}
private void setAlgorithm(Database db, Preference algorithm) {
algorithm.Summary = CipherPool.GlobalPool.GetCipher(db.pm.DataCipherUuid).DisplayName;
algorithm.Summary = CipherPool.GlobalPool.GetCipher(db.KpDatabase.DataCipherUuid).DisplayName;
}

View File

@ -16,30 +16,23 @@ 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 Android.Preferences;
namespace keepass2android
{
/// <summary>
/// Utility class to simplify access to the app preferences
/// </summary>
public class PrefsUtil {
public static float getListTextSize(Context ctx) {
public static float GetListTextSize(Context ctx) {
ISharedPreferences prefs = PreferenceManager.GetDefaultSharedPreferences(ctx);
return float.Parse(prefs.GetString(ctx.GetString(Resource.String.list_size_key), ctx.GetString(Resource.String.list_size_default)));
}
public static float getListDetailTextSize(Context ctx) {
return (float)Math.Round(getListTextSize(ctx)*3.0f/4.0f);
public static float GetListDetailTextSize(Context ctx) {
return (float)Math.Round(GetListTextSize(ctx)*3.0f/4.0f);
}
}

View File

@ -15,38 +15,34 @@ This file is part of Keepass2Android, Copyright 2013 Philipp Crocoll. This file
along with Keepass2Android. If not, see <http://www.gnu.org/licenses/>.
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Android.App;
using System.Globalization;
using Android.Content;
using Android.OS;
using Android.Runtime;
using Android.Views;
using Android.Widget;
using Android.Preferences;
using KeePassLib;
using Android.Util;
using keepass2android;
namespace keepass2android.settings
{
/// <summary>
/// Represents the setting for the number of key transformation rounds. Changing this requires to save the database.
/// </summary>
public class RoundsPreference : DialogPreference {
internal PwDatabase mPM;
internal TextView mRoundsView;
internal PwDatabase PwDatabase;
internal TextView RoundsView;
protected override View OnCreateDialogView() {
View view = base.OnCreateDialogView();
mRoundsView = (TextView) view.FindViewById(Resource.Id.rounds);
RoundsView = (TextView) view.FindViewById(Resource.Id.rounds);
Database db = App.getDB();
mPM = db.pm;
ulong numRounds = mPM.KeyEncryptionRounds;
mRoundsView.Text = numRounds.ToString();
Database db = App.Kp2a.GetDb();
PwDatabase = db.KpDatabase;
ulong numRounds = PwDatabase.KeyEncryptionRounds;
RoundsView.Text = numRounds.ToString(CultureInfo.InvariantCulture);
return view;
}
@ -63,7 +59,7 @@ namespace keepass2android.settings
if ( positiveResult ) {
ulong rounds;
String strRounds = mRoundsView.Text;
String strRounds = RoundsView.Text;
if (!(ulong.TryParse(strRounds,out rounds)))
{
Toast.MakeText(Context, Resource.String.error_rounds_not_number, ToastLength.Long).Show();
@ -74,48 +70,48 @@ namespace keepass2android.settings
rounds = 1;
}
ulong oldRounds = mPM.KeyEncryptionRounds;
ulong oldRounds = PwDatabase.KeyEncryptionRounds;
if (oldRounds == rounds)
{
return;
}
mPM.KeyEncryptionRounds = rounds;
PwDatabase.KeyEncryptionRounds = rounds;
Handler handler = new Handler();
SaveDB save = new SaveDB(Context, App.getDB(), new AfterSave(Context, handler, oldRounds, this));
ProgressTask pt = new ProgressTask(Context, save, Resource.String.saving_database);
pt.run();
SaveDb save = new SaveDb(Context, App.Kp2a.GetDb(), new AfterSave(Context, handler, oldRounds, this));
ProgressTask pt = new ProgressTask(App.Kp2a, Context, save, UiStringKey.saving_database);
pt.Run();
}
}
private class AfterSave : OnFinish {
private ulong mOldRounds;
private Context mCtx;
private RoundsPreference pref;
private readonly ulong _oldRounds;
private readonly Context _ctx;
private readonly RoundsPreference _pref;
public AfterSave(Context ctx, Handler handler, ulong oldRounds, RoundsPreference pref):base(handler) {
this.pref = pref;
mCtx = ctx;
mOldRounds = oldRounds;
_pref = pref;
_ctx = ctx;
_oldRounds = oldRounds;
}
public override void run() {
if ( mSuccess ) {
public override void Run() {
if ( Success ) {
if ( pref.OnPreferenceChangeListener != null ) {
pref.OnPreferenceChangeListener.OnPreferenceChange(pref, null);
if ( _pref.OnPreferenceChangeListener != null ) {
_pref.OnPreferenceChangeListener.OnPreferenceChange(_pref, null);
}
} else {
displayMessage(mCtx);
pref.mPM.KeyEncryptionRounds = mOldRounds;
DisplayMessage(_ctx);
_pref.PwDatabase.KeyEncryptionRounds = _oldRounds;
}
base.run();
base.Run();
}
}

View File

@ -16,27 +16,75 @@ 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 Android.Preferences;
using Android.Util;
using KeePassLib.Serialization;
namespace keepass2android
{
/// <summary>
/// Helper class to simplify usage of timeout (lock after idle time) from the activities
/// </summary>
public class TimeoutHelper {
private const long DEFAULT_TIMEOUT = 5 * 60 * 1000; // 5 minutes
class Timeout
{
private const int RequestId = 0;
private const long DefaultTimeout = 5 * 60 * 1000; // 5 minutes
private const String Tag = "Keepass2Android Timeout";
public static void pause(Activity act) {
private static PendingIntent BuildIntent(Context ctx)
{
Intent intent = new Intent(Intents.Timeout);
PendingIntent sender = PendingIntent.GetBroadcast(ctx, RequestId, intent, PendingIntentFlags.CancelCurrent);
return sender;
}
public static void Start(Context ctx)
{
ISharedPreferences prefs = PreferenceManager.GetDefaultSharedPreferences(ctx);
String sTimeout = prefs.GetString(ctx.GetString(Resource.String.app_timeout_key), ctx.GetString(Resource.String.clipboard_timeout_default));
long timeout;
if (!long.TryParse(sTimeout, out timeout))
{
timeout = DefaultTimeout;
}
if (timeout == -1)
{
// No timeout don't start timeout service
return;
}
ctx.StartService(new Intent(ctx, typeof(TimeoutService)));
long triggerTime = Java.Lang.JavaSystem.CurrentTimeMillis() + timeout;
AlarmManager am = (AlarmManager)ctx.GetSystemService(Context.AlarmService);
Log.Debug(Tag, "Timeout start");
am.Set(AlarmType.Rtc, triggerTime, BuildIntent(ctx));
}
public static void Cancel(Context ctx)
{
AlarmManager am = (AlarmManager)ctx.GetSystemService(Context.AlarmService);
Log.Debug(Tag, "Timeout cancel");
am.Cancel(BuildIntent(ctx));
ctx.StopService(new Intent(ctx, typeof(TimeoutService)));
}
}
public static void Pause(Activity act) {
// Record timeout time in case timeout service is killed
long time = Java.Lang.JavaSystem.CurrentTimeMillis();
@ -44,58 +92,57 @@ namespace keepass2android
ISharedPreferencesEditor edit = prefs.Edit();
edit.PutLong(act.GetString(Resource.String.timeout_key), time);
EditorCompat.apply(edit);
EditorCompat.Apply(edit);
if ( App.getDB().Open ) {
Timeout.start(act);
if ( App.Kp2a.GetDb().Open ) {
Timeout.Start(act);
}
}
public static void resume(Activity act) {
if ( App.getDB().Loaded ) {
Timeout.cancel(act);
public static void Resume(Activity act) {
if ( App.Kp2a.GetDb().Loaded ) {
Timeout.Cancel(act);
}
// Check whether the timeout has expired
long cur_time = Java.Lang.JavaSystem.CurrentTimeMillis();
long curTime = Java.Lang.JavaSystem.CurrentTimeMillis();
ISharedPreferences prefs = PreferenceManager.GetDefaultSharedPreferences(act);
long timeout_start = prefs.GetLong(act.GetString(Resource.String.timeout_key), -1);
long timeoutStart = prefs.GetLong(act.GetString(Resource.String.timeout_key), -1);
// The timeout never started
if (timeout_start == -1) {
if (timeoutStart == -1) {
return;
}
String sTimeout = prefs.GetString(act.GetString(Resource.String.app_timeout_key), act.GetString(Resource.String.clipboard_timeout_default));
long timeout = DEFAULT_TIMEOUT;
long.TryParse(sTimeout,out timeout);
long timeout;
if (!long.TryParse(sTimeout, out timeout))
{
// We are set to never timeout
if (timeout == -1) {
return;
}
long diff = cur_time - timeout_start;
long diff = curTime - timeoutStart;
if (diff >= timeout) {
// We have timed out
App.setShutdown();
App.Kp2a.SetShutdown();
}
}
static bool iocChanged(IOConnectionInfo ioc, IOConnectionInfo other)
static bool IocChanged(IOConnectionInfo ioc, IOConnectionInfo other)
{
if ((ioc == null) || (other == null)) return false;
return ioc.GetDisplayName() != other.GetDisplayName();
}
public static bool checkShutdown(Activity act, IOConnectionInfo ioc) {
if (( App.getDB().Loaded && (App.isShutdown() || App.getDB().Locked) )
|| (iocChanged(ioc, App.getDB().mIoc))) //file was changed from ActionSend-Intent
public static bool CheckShutdown(Activity act, IOConnectionInfo ioc) {
if (( App.Kp2a.GetDb().Loaded && (App.Kp2a.IsShutdown() || App.Kp2a.GetDb().Locked) )
|| (IocChanged(ioc, App.Kp2a.GetDb().Ioc))) //file was changed from ActionSend-Intent
{
act.SetResult(KeePass.EXIT_LOCK);
act.SetResult(KeePass.ExitLock);
act.Finish();
return true;
}

View File

@ -1,85 +0,0 @@
/*
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 <http://www.gnu.org/licenses/>.
*/
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.Preferences;
using Android.Util;
namespace keepass2android
{
public class Timeout {
private const int REQUEST_ID = 0;
private const long DEFAULT_TIMEOUT = 5 * 60 * 1000; // 5 minutes
private static String TAG = "Keepass2Android Timeout";
private static PendingIntent buildIntent(Context ctx) {
Intent intent = new Intent(Intents.TIMEOUT);
PendingIntent sender = PendingIntent.GetBroadcast(ctx, REQUEST_ID, intent, PendingIntentFlags.CancelCurrent);
return sender;
}
public static void start(Context ctx) {
ISharedPreferences prefs = PreferenceManager.GetDefaultSharedPreferences(ctx);
String sTimeout = prefs.GetString(ctx.GetString(Resource.String.app_timeout_key), ctx.GetString(Resource.String.clipboard_timeout_default));
long timeout;
if (!long.TryParse(sTimeout, out timeout))
{
timeout = DEFAULT_TIMEOUT;
}
if ( timeout == -1 ) {
// No timeout don't start timeout service
return;
}
ctx.StartService(new Intent(ctx, typeof(TimeoutService)));
long triggerTime = Java.Lang.JavaSystem.CurrentTimeMillis() + timeout;
AlarmManager am = (AlarmManager) ctx.GetSystemService(Context.AlarmService);
Log.Debug(TAG, "Timeout start");
am.Set(AlarmType.Rtc, triggerTime, buildIntent(ctx));
}
public static void cancel(Context ctx) {
AlarmManager am = (AlarmManager) ctx.GetSystemService(Context.AlarmService);
Log.Debug(TAG, "Timeout cancel");
am.Cancel(buildIntent(ctx));
ctx.StopService(new Intent(ctx, typeof(TimeoutService)));
}
}
}

View File

@ -16,29 +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.Util;
using Android.Views;
using Android.Widget;
namespace keepass2android.view
{
public abstract class ClickView : LinearLayout {
public ClickView (IntPtr javaReference, JniHandleOwnership transfer)
protected ClickView (IntPtr javaReference, JniHandleOwnership transfer)
: base(javaReference, transfer)
{
}
public ClickView(Context context) :base(context)
protected ClickView(Context context) :base(context)
{
}

View File

@ -36,15 +36,15 @@ namespace keepass2android.view
}
public EntryContentsView(Context context):base(context, null) {
inflate(context);
InflateView();
}
public EntryContentsView(Context context, IAttributeSet attrs): base(context, attrs) {
inflate(context);
InflateView();
}
private void inflate(Context context) {
private void InflateView() {
LayoutInflater inflater = (LayoutInflater) Context.GetSystemService(Context.LayoutInflaterService);
inflater.Inflate(Resource.Layout.entry_view_contents, this);

Some files were not shown because too many files have changed in this diff Show More