PluginHost-Test project: modified EntryActivity for receiving actions and fields
This commit is contained in:
		| @@ -25,6 +25,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "KP2AKdbLibraryBinding", "KP | ||||
| EndProject | ||||
| Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "ArtTestApp", "ArtTestApp\ArtTestApp.csproj", "{1FF6C335-A627-43C9-AAA7-CBAC2E74CD18}" | ||||
| EndProject | ||||
| Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PluginHostTest", "PluginHostTest\PluginHostTest.csproj", "{C9F4AE81-0996-4E17-B3F2-D0F652F6AC50}" | ||||
| EndProject | ||||
| Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "PluginSdkBinding", "PluginSdkBinding\PluginSdkBinding.csproj", "{3DA3911E-36DE-465E-8F15-F1991B6437E5}" | ||||
| EndProject | ||||
| Global | ||||
| 	GlobalSection(SolutionConfigurationPlatforms) = preSolution | ||||
| 		Debug|Any CPU = Debug|Any CPU | ||||
| @@ -284,6 +288,48 @@ Global | ||||
| 		{1FF6C335-A627-43C9-AAA7-CBAC2E74CD18}.ReleaseNoNet|Mixed Platforms.Deploy.0 = Release|Any CPU | ||||
| 		{1FF6C335-A627-43C9-AAA7-CBAC2E74CD18}.ReleaseNoNet|Win32.ActiveCfg = Release|Any CPU | ||||
| 		{1FF6C335-A627-43C9-AAA7-CBAC2E74CD18}.ReleaseNoNet|x64.ActiveCfg = Release|Any CPU | ||||
| 		{C9F4AE81-0996-4E17-B3F2-D0F652F6AC50}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||||
| 		{C9F4AE81-0996-4E17-B3F2-D0F652F6AC50}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||||
| 		{C9F4AE81-0996-4E17-B3F2-D0F652F6AC50}.Debug|Any CPU.Deploy.0 = Debug|Any CPU | ||||
| 		{C9F4AE81-0996-4E17-B3F2-D0F652F6AC50}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU | ||||
| 		{C9F4AE81-0996-4E17-B3F2-D0F652F6AC50}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU | ||||
| 		{C9F4AE81-0996-4E17-B3F2-D0F652F6AC50}.Debug|Mixed Platforms.Deploy.0 = Debug|Any CPU | ||||
| 		{C9F4AE81-0996-4E17-B3F2-D0F652F6AC50}.Debug|Win32.ActiveCfg = Debug|Any CPU | ||||
| 		{C9F4AE81-0996-4E17-B3F2-D0F652F6AC50}.Debug|x64.ActiveCfg = Debug|Any CPU | ||||
| 		{C9F4AE81-0996-4E17-B3F2-D0F652F6AC50}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||||
| 		{C9F4AE81-0996-4E17-B3F2-D0F652F6AC50}.Release|Any CPU.Build.0 = Release|Any CPU | ||||
| 		{C9F4AE81-0996-4E17-B3F2-D0F652F6AC50}.Release|Any CPU.Deploy.0 = Release|Any CPU | ||||
| 		{C9F4AE81-0996-4E17-B3F2-D0F652F6AC50}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU | ||||
| 		{C9F4AE81-0996-4E17-B3F2-D0F652F6AC50}.Release|Mixed Platforms.Build.0 = Release|Any CPU | ||||
| 		{C9F4AE81-0996-4E17-B3F2-D0F652F6AC50}.Release|Mixed Platforms.Deploy.0 = Release|Any CPU | ||||
| 		{C9F4AE81-0996-4E17-B3F2-D0F652F6AC50}.Release|Win32.ActiveCfg = Release|Any CPU | ||||
| 		{C9F4AE81-0996-4E17-B3F2-D0F652F6AC50}.Release|x64.ActiveCfg = Release|Any CPU | ||||
| 		{C9F4AE81-0996-4E17-B3F2-D0F652F6AC50}.ReleaseNoNet|Any CPU.ActiveCfg = Release|Any CPU | ||||
| 		{C9F4AE81-0996-4E17-B3F2-D0F652F6AC50}.ReleaseNoNet|Any CPU.Build.0 = Release|Any CPU | ||||
| 		{C9F4AE81-0996-4E17-B3F2-D0F652F6AC50}.ReleaseNoNet|Any CPU.Deploy.0 = Release|Any CPU | ||||
| 		{C9F4AE81-0996-4E17-B3F2-D0F652F6AC50}.ReleaseNoNet|Mixed Platforms.ActiveCfg = Release|Any CPU | ||||
| 		{C9F4AE81-0996-4E17-B3F2-D0F652F6AC50}.ReleaseNoNet|Mixed Platforms.Build.0 = Release|Any CPU | ||||
| 		{C9F4AE81-0996-4E17-B3F2-D0F652F6AC50}.ReleaseNoNet|Mixed Platforms.Deploy.0 = Release|Any CPU | ||||
| 		{C9F4AE81-0996-4E17-B3F2-D0F652F6AC50}.ReleaseNoNet|Win32.ActiveCfg = Release|Any CPU | ||||
| 		{C9F4AE81-0996-4E17-B3F2-D0F652F6AC50}.ReleaseNoNet|x64.ActiveCfg = Release|Any CPU | ||||
| 		{3DA3911E-36DE-465E-8F15-F1991B6437E5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU | ||||
| 		{3DA3911E-36DE-465E-8F15-F1991B6437E5}.Debug|Any CPU.Build.0 = Debug|Any CPU | ||||
| 		{3DA3911E-36DE-465E-8F15-F1991B6437E5}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU | ||||
| 		{3DA3911E-36DE-465E-8F15-F1991B6437E5}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU | ||||
| 		{3DA3911E-36DE-465E-8F15-F1991B6437E5}.Debug|Win32.ActiveCfg = Debug|Any CPU | ||||
| 		{3DA3911E-36DE-465E-8F15-F1991B6437E5}.Debug|x64.ActiveCfg = Debug|Any CPU | ||||
| 		{3DA3911E-36DE-465E-8F15-F1991B6437E5}.Release|Any CPU.ActiveCfg = Release|Any CPU | ||||
| 		{3DA3911E-36DE-465E-8F15-F1991B6437E5}.Release|Any CPU.Build.0 = Release|Any CPU | ||||
| 		{3DA3911E-36DE-465E-8F15-F1991B6437E5}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU | ||||
| 		{3DA3911E-36DE-465E-8F15-F1991B6437E5}.Release|Mixed Platforms.Build.0 = Release|Any CPU | ||||
| 		{3DA3911E-36DE-465E-8F15-F1991B6437E5}.Release|Win32.ActiveCfg = Release|Any CPU | ||||
| 		{3DA3911E-36DE-465E-8F15-F1991B6437E5}.Release|x64.ActiveCfg = Release|Any CPU | ||||
| 		{3DA3911E-36DE-465E-8F15-F1991B6437E5}.ReleaseNoNet|Any CPU.ActiveCfg = Release|Any CPU | ||||
| 		{3DA3911E-36DE-465E-8F15-F1991B6437E5}.ReleaseNoNet|Any CPU.Build.0 = Release|Any CPU | ||||
| 		{3DA3911E-36DE-465E-8F15-F1991B6437E5}.ReleaseNoNet|Mixed Platforms.ActiveCfg = Release|Any CPU | ||||
| 		{3DA3911E-36DE-465E-8F15-F1991B6437E5}.ReleaseNoNet|Mixed Platforms.Build.0 = Release|Any CPU | ||||
| 		{3DA3911E-36DE-465E-8F15-F1991B6437E5}.ReleaseNoNet|Win32.ActiveCfg = Release|Any CPU | ||||
| 		{3DA3911E-36DE-465E-8F15-F1991B6437E5}.ReleaseNoNet|x64.ActiveCfg = Release|Any CPU | ||||
| 	EndGlobalSection | ||||
| 	GlobalSection(SolutionProperties) = preSolution | ||||
| 		HideSolutionNode = FALSE | ||||
|   | ||||
							
								
								
									
										37
									
								
								src/PluginHostTest/App.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								src/PluginHostTest/App.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,37 @@ | ||||
| using KeePassLib; | ||||
| using KeePassLib.Keys; | ||||
| using KeePassLib.Serialization; | ||||
|  | ||||
| namespace keepass2android | ||||
| { | ||||
| 	public class App | ||||
| 	{ | ||||
| 		public class Kp2A | ||||
| 		{ | ||||
| 			private static Db _mDb; | ||||
|  | ||||
| 			public  class Db | ||||
| 			{ | ||||
| 				public void SetEntry(PwEntry e) | ||||
| 				{ | ||||
| 					KpDatabase = new PwDatabase(); | ||||
| 					KpDatabase.New(new IOConnectionInfo(), new CompositeKey()); | ||||
|  | ||||
| 					KpDatabase.RootGroup.AddEntry(e, true); | ||||
| 				} | ||||
|  | ||||
| 				public PwDatabase KpDatabase | ||||
| 				{ | ||||
| 					get; set; | ||||
| 				} | ||||
| 			} | ||||
|  | ||||
| 			public static Db GetDb() | ||||
| 			{ | ||||
| 				if (_mDb == null) | ||||
| 					_mDb = new Db(); | ||||
| 				return _mDb; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										14
									
								
								src/PluginHostTest/CopyToClipboardService.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								src/PluginHostTest/CopyToClipboardService.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | ||||
| using Android.Content; | ||||
| using Android.Widget; | ||||
| using KeePassLib.Security; | ||||
|  | ||||
| namespace keepass2android | ||||
| { | ||||
| 	internal class CopyToClipboardService | ||||
| 	{ | ||||
| 		public static void CopyValueToClipboardWithTimeout(Context ctx, string text) | ||||
| 		{ | ||||
| 			Toast.MakeText(ctx, text, ToastLength.Short).Show(); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @@ -19,10 +19,12 @@ using System; | ||||
| using System.Collections.Generic; | ||||
| using System.Text; | ||||
| using System.Linq; | ||||
|  | ||||
| using System.Threading; | ||||
| using Android.App; | ||||
| using Android.Content; | ||||
| using Android.OS; | ||||
| using Android.Runtime; | ||||
| using Android.Text; | ||||
| using Android.Views; | ||||
| using Android.Widget; | ||||
| using Android.Preferences; | ||||
| @@ -32,79 +34,412 @@ using Android.Content.PM; | ||||
| using Android.Webkit; | ||||
| using Android.Graphics; | ||||
| using Java.IO; | ||||
| using KeePassLib; | ||||
| using KeePassLib.Security; | ||||
| using Keepass2android.Pluginsdk; | ||||
| using PluginHostTest; | ||||
| using Uri = Android.Net.Uri; | ||||
|  | ||||
| namespace keepass2android | ||||
| { | ||||
| 	[Activity (Label = "@string/app_name", ConfigurationChanges=ConfigChanges.Orientation|ConfigChanges.KeyboardHidden, Theme="@style/NoTitleBar")]			 | ||||
| 	public class EntryActivity : Activity { | ||||
|  | ||||
| 	[Activity(Label = "@string/app_name", ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.KeyboardHidden, | ||||
| 		Theme = "@style/NoTitleBar")] | ||||
| 	public class EntryActivity : Activity | ||||
| 	{ | ||||
| 		public const String KeyEntry = "entry"; | ||||
| 		public const String KeyRefreshPos = "refresh_pos"; | ||||
| 		public const String KeyCloseAfterCreate = "close_after_create"; | ||||
|  | ||||
| 		protected PwEntry Entry = new PwEntry(true, true); | ||||
|  | ||||
| 		private static Typeface _passwordFont; | ||||
|  | ||||
| 		private bool _showPassword; | ||||
| 		internal bool _showPassword; | ||||
| 		private int _pos; | ||||
|  | ||||
| 		private List<TextView> _protectedTextViews; | ||||
|  | ||||
| 		private readonly Dictionary<string, List<IPopupMenuItem>> _popupMenuItems = | ||||
| 			new Dictionary<string, List<IPopupMenuItem>>(); | ||||
|  | ||||
| 		protected void SetEntryView() { | ||||
| 		private readonly Dictionary<string, IStringView> _stringViews = new Dictionary<string, IStringView>(); | ||||
| 		private readonly List<PluginMenuOption> _pendingMenuOptions = new List<PluginMenuOption>(); | ||||
| 		private IMenu _menu; | ||||
|  | ||||
| 		protected void SetEntryView() | ||||
| 		{ | ||||
| 			SetContentView(Resource.Layout.entry_view); | ||||
| 		} | ||||
| 		 | ||||
| 		protected void SetupEditButtons() { | ||||
| 			View edit =  FindViewById(Resource.Id.entry_edit); | ||||
|  | ||||
| 		protected void SetupEditButtons() | ||||
| 		{ | ||||
| 			View edit = FindViewById(Resource.Id.entry_edit); | ||||
| 			if (true) | ||||
| 			{ | ||||
| 				edit.Visibility = ViewStates.Visible; | ||||
| 				edit.Click += (sender, e) => | ||||
| 				{ | ||||
| 					 | ||||
| 				};	 | ||||
| 					{ | ||||
|  | ||||
| 					}; | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				edit.Visibility = ViewStates.Gone; | ||||
| 			} | ||||
| 			 | ||||
|  | ||||
| 		} | ||||
| 		 | ||||
|  | ||||
| 		private class PluginActionReceiver : BroadcastReceiver | ||||
| 		{ | ||||
| 			private readonly EntryActivity _activity; | ||||
|  | ||||
| 			public PluginActionReceiver(EntryActivity activity) | ||||
| 			{ | ||||
| 				_activity = activity; | ||||
| 			} | ||||
|  | ||||
| 			public override void OnReceive(Context context, Intent intent) | ||||
| 			{ | ||||
| 				var pluginPackage = intent.GetStringExtra(Strings.ExtraSender); | ||||
| 				if (new PluginDatabase(context).IsValidAccessToken(pluginPackage, | ||||
| 				                                                   intent.GetStringExtra(Strings.ExtraAccessToken), | ||||
| 				                                                   Strings.ScopeCurrentEntry)) | ||||
| 				{ | ||||
| 					if (intent.GetStringExtra(Strings.ExtraEntryId) != _activity.Entry.Uuid.ToHexString()) | ||||
| 					{ | ||||
| 						Kp2aLog.Log("received action for wrong entry " + intent.GetStringExtra(Strings.ExtraEntryId)); | ||||
| 						return; | ||||
| 					} | ||||
| 					_activity.AddPluginAction(pluginPackage, | ||||
| 					                          intent.GetStringExtra(Strings.ExtraFieldId), | ||||
| 					                          intent.GetStringExtra(Strings.ExtraActionDisplayText), | ||||
| 					                          intent.GetIntExtra(Strings.ExtraActionIconResId, -1), | ||||
| 					                          intent.GetBundleExtra(Strings.ExtraActionData)); | ||||
| 				} | ||||
| 				else | ||||
| 				{ | ||||
| 					Kp2aLog.Log("received invalid request. Plugin not authorized."); | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		private class PluginFieldReceiver : BroadcastReceiver | ||||
| 		{ | ||||
| 			private readonly EntryActivity _activity; | ||||
|  | ||||
| 			public PluginFieldReceiver(EntryActivity activity) | ||||
| 			{ | ||||
| 				_activity = activity; | ||||
| 			} | ||||
|  | ||||
| 			public override void OnReceive(Context context, Intent intent) | ||||
| 			{ | ||||
| 				if (intent.GetStringExtra(Strings.ExtraEntryId) != _activity.Entry.Uuid.ToHexString()) | ||||
| 				{ | ||||
| 					Kp2aLog.Log("received field for wrong entry " + intent.GetStringExtra(Strings.ExtraEntryId)); | ||||
| 					return; | ||||
| 				} | ||||
| 				if (!new PluginDatabase(context).IsValidAccessToken(intent.GetStringExtra(Strings.ExtraSender), | ||||
| 				                                                    intent.GetStringExtra(Strings.ExtraAccessToken), | ||||
| 				                                                    Strings.ScopeCurrentEntry)) | ||||
| 				{ | ||||
| 					Kp2aLog.Log("received field with invalid access token from " + intent.GetStringExtra(Strings.ExtraSender)); | ||||
| 					return; | ||||
| 				} | ||||
| 				string key = intent.GetStringExtra(Strings.ExtraFieldId); | ||||
| 				string value = intent.GetStringExtra(Strings.ExtraFieldValue); | ||||
| 				bool isProtected = intent.GetBooleanExtra(Strings.ExtraFieldProtected, false); | ||||
| 				_activity.SetPluginField(key, value, isProtected); | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		private void SetPluginField(string key, string value, bool isProtected) | ||||
| 		{ | ||||
| 			IStringView existingField; | ||||
| 			if (_stringViews.TryGetValue(key, out existingField)) | ||||
| 			{ | ||||
| 				existingField.Text = value; | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				ViewGroup extraGroup = (ViewGroup) FindViewById(Resource.Id.extra_strings); | ||||
| 				var view = CreateExtraSection(key, value, isProtected); | ||||
| 				extraGroup.AddView(view.View); | ||||
| 			} | ||||
|  | ||||
| 		} | ||||
|  | ||||
| 		private void AddPluginAction(string pluginPackage, string fieldId, string displayText, int iconId, Bundle bundleExtra) | ||||
| 		{ | ||||
| 			if (fieldId != null) | ||||
| 			{ | ||||
| 				_popupMenuItems[fieldId].Add(new PluginPopupMenuItem(this, pluginPackage, fieldId, displayText, iconId, bundleExtra)); | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				//we need to add an option to the  menu. | ||||
| 				//As it is not sure that OnCreateOptionsMenu was called yet, we cannot access _menu without a check: | ||||
|  | ||||
| 				Intent i = new Intent(Strings.ActionEntryActionSelected); | ||||
| 				i.SetPackage(pluginPackage); | ||||
| 				i.PutExtra(Strings.ExtraActionData, bundleExtra); | ||||
| 				i.PutExtra(Strings.ExtraSender, PackageName); | ||||
|  | ||||
| 				var menuOption = new PluginMenuOption() | ||||
| 					{ | ||||
| 						DisplayText = displayText, | ||||
| 						Icon = PackageManager.GetResourcesForApplication(pluginPackage).GetDrawable(iconId), | ||||
| 						Intent = i | ||||
| 					}; | ||||
|  | ||||
| 				if (_menu != null) | ||||
| 				{ | ||||
| 					AddMenuOption(menuOption); | ||||
| 				} | ||||
| 				else | ||||
| 				{ | ||||
| 					lock (_pendingMenuOptions) | ||||
| 					{ | ||||
| 						_pendingMenuOptions.Add(menuOption); | ||||
| 					} | ||||
|  | ||||
| 				} | ||||
|  | ||||
|  | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		private void AddMenuOption(PluginMenuOption menuOption) | ||||
| 		{ | ||||
| 			var menuItem = _menu.Add(menuOption.DisplayText); | ||||
| 			menuItem.SetIcon(menuOption.Icon); | ||||
| 			menuItem.SetIntent(menuOption.Intent); | ||||
| 		} | ||||
|  | ||||
| 		public override bool OnCreateOptionsMenu(IMenu menu) | ||||
| 		{ | ||||
| 			_menu = menu; | ||||
| 			base.OnCreateOptionsMenu(menu); | ||||
|  | ||||
| 			MenuInflater inflater = MenuInflater; | ||||
| 			inflater.Inflate(Resource.Menu.entry, menu); | ||||
|  | ||||
| 			lock (_pendingMenuOptions) | ||||
| 			{ | ||||
| 				foreach (var option in _pendingMenuOptions) | ||||
| 					AddMenuOption(option); | ||||
| 				_pendingMenuOptions.Clear(); | ||||
| 			} | ||||
|  | ||||
|  | ||||
| 			UpdateTogglePasswordMenu(); | ||||
|  | ||||
| 			IMenuItem gotoUrl = menu.FindItem(Resource.Id.menu_goto_url); | ||||
| 			//Disabled IMenuItem copyUser = menu.FindItem(Resource.Id.menu_copy_user); | ||||
| 			//Disabled IMenuItem copyPass = menu.FindItem(Resource.Id.menu_copy_pass); | ||||
|  | ||||
| 			// In API >= 11 onCreateOptionsMenu may be called before onCreate completes | ||||
| 			// so _entry may not be set | ||||
| 			if (Entry == null) | ||||
| 			{ | ||||
| 				gotoUrl.SetVisible(false); | ||||
| 				//Disabled copyUser.SetVisible(false); | ||||
| 				//Disabled copyPass.SetVisible(false); | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				String url = Entry.Strings.ReadSafe(PwDefs.UrlField); | ||||
| 				if (String.IsNullOrEmpty(url)) | ||||
| 				{ | ||||
| 					// disable button if url is not available | ||||
| 					gotoUrl.SetVisible(false); | ||||
| 				} | ||||
| 				if (String.IsNullOrEmpty(Entry.Strings.ReadSafe(PwDefs.UserNameField))) | ||||
| 				{ | ||||
| 					// disable button if username is not available | ||||
| 					//Disabled copyUser.SetVisible(false); | ||||
| 				} | ||||
| 				if (String.IsNullOrEmpty(Entry.Strings.ReadSafe(PwDefs.PasswordField))) | ||||
| 				{ | ||||
| 					// disable button if password is not available | ||||
| 					//Disabled copyPass.SetVisible(false); | ||||
| 				} | ||||
| 			} | ||||
| 			return true; | ||||
| 		} | ||||
|  | ||||
| 		public override bool OnOptionsItemSelected(IMenuItem item) | ||||
| 		{ | ||||
| 			//check if this is a plugin action | ||||
| 			if ((item.Intent != null) && (item.Intent.Action == Strings.ActionEntryActionSelected)) | ||||
| 			{ | ||||
| 				//yes. let the plugin handle the click: | ||||
| 				SendBroadcast(item.Intent); | ||||
| 				return true; | ||||
| 			} | ||||
|  | ||||
| 			switch (item.ItemId) | ||||
| 			{ | ||||
| 				case Resource.Id.menu_donate: | ||||
| 					try | ||||
| 					{ | ||||
| 						//						Util.GotoDonateUrl(this); | ||||
| 					} | ||||
| 					catch (ActivityNotFoundException) | ||||
| 					{ | ||||
| 						Toast.MakeText(this, Resource.String.error_failed_to_launch_link, ToastLength.Long).Show(); | ||||
| 						return false; | ||||
| 					} | ||||
|  | ||||
| 					return true; | ||||
| 				case Resource.Id.menu_toggle_pass: | ||||
| 					if (_showPassword) | ||||
| 					{ | ||||
| 						item.SetTitle(Resource.String.show_password); | ||||
| 						_showPassword = false; | ||||
| 					} | ||||
| 					else | ||||
| 					{ | ||||
| 						item.SetTitle(Resource.String.menu_hide_password); | ||||
| 						_showPassword = true; | ||||
| 					} | ||||
| 					SetPasswordStyle(); | ||||
|  | ||||
| 					return true; | ||||
|  | ||||
| 				case Resource.Id.menu_goto_url: | ||||
| 					string url = _stringViews[PwDefs.UrlField].Text; | ||||
| 					if (url == null) return false; | ||||
|  | ||||
| 					// Default http:// if no protocol specified | ||||
| 					if (!url.Contains("://")) | ||||
| 					{ | ||||
| 						url = "http://" + url; | ||||
| 					} | ||||
|  | ||||
| 					try | ||||
| 					{ | ||||
|  | ||||
| 					} | ||||
| 					catch (ActivityNotFoundException) | ||||
| 					{ | ||||
| 						Toast.MakeText(this, Resource.String.no_url_handler, ToastLength.Long).Show(); | ||||
| 					} | ||||
| 					return true; | ||||
| 					/* TODO: required? | ||||
| 			case Resource.Id.menu_copy_user: | ||||
| 				timeoutCopyToClipboard(_entry.Strings.ReadSafe (PwDefs.UserNameField)); | ||||
| 				return true; | ||||
| 				 | ||||
| 			case Resource.Id.menu_copy_pass: | ||||
| 				timeoutCopyToClipboard(_entry.Strings.ReadSafe (PwDefs.UserNameField)); | ||||
| 				return true; | ||||
| 				*/ | ||||
| 				case Resource.Id.menu_rate: | ||||
| 					try | ||||
| 					{ | ||||
| 					} | ||||
| 					catch (ActivityNotFoundException) | ||||
| 					{ | ||||
| 						Toast.MakeText(this, Resource.String.no_url_handler, ToastLength.Long).Show(); | ||||
| 					} | ||||
| 					return true; | ||||
| 				case Resource.Id.menu_suggest_improvements: | ||||
| 					try | ||||
| 					{ | ||||
| 					} | ||||
| 					catch (ActivityNotFoundException) | ||||
| 					{ | ||||
| 						Toast.MakeText(this, Resource.String.no_url_handler, ToastLength.Long).Show(); | ||||
| 					} | ||||
| 					return true; | ||||
| 				case Resource.Id.menu_lock: | ||||
| 					return true; | ||||
| 				case Resource.Id.menu_translate: | ||||
| 					try | ||||
| 					{ | ||||
|  | ||||
| 					} | ||||
| 					catch (ActivityNotFoundException) | ||||
| 					{ | ||||
| 						Toast.MakeText(this, Resource.String.no_url_handler, ToastLength.Long).Show(); | ||||
| 					} | ||||
| 					return true; | ||||
| 				case Android.Resource.Id.Home: | ||||
| 					//Currently the action bar only displays the home button when we come from a previous activity. | ||||
| 					//So we can simply Finish. See this page for information on how to do this in more general (future?) cases: | ||||
| 					//http://developer.android.com/training/implementing-navigation/ancestral.html | ||||
| 					Finish(); | ||||
|  | ||||
| 					return true; | ||||
| 			} | ||||
|  | ||||
|  | ||||
| 			return base.OnOptionsItemSelected(item); | ||||
| 		} | ||||
|  | ||||
|  | ||||
| 		protected override void OnCreate(Bundle savedInstanceState) | ||||
| 		{ | ||||
| 			 | ||||
|  | ||||
| 			ISharedPreferences prefs = PreferenceManager.GetDefaultSharedPreferences(this); | ||||
|  | ||||
| 			long usageCount = prefs.GetLong(GetString(Resource.String.UsageCount_key), 0); | ||||
|  | ||||
| 			ISharedPreferencesEditor edit = prefs.Edit(); | ||||
| 			edit.PutLong(GetString(Resource.String.UsageCount_key), usageCount+1); | ||||
| 			edit.PutLong(GetString(Resource.String.UsageCount_key), usageCount + 1); | ||||
| 			edit.Commit(); | ||||
|  | ||||
| 			_showPassword = ! 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)); | ||||
|  | ||||
| 			Entry.Strings.Set(PwDefs.UserNameField, new ProtectedString(false, "philipp ")); | ||||
| 			Entry.Strings.Set(PwDefs.PasswordField, new ProtectedString(true, "password value")); | ||||
| 			Entry.Strings.Set(PwDefs.UrlField, new ProtectedString(false, "https://www.google.com")); | ||||
| 			Entry.Strings.Set("field header", new ProtectedString(true, "protected field value")); | ||||
| 			Entry.Strings.Set("public field header", new ProtectedString(false, "public field value")); | ||||
|  | ||||
| 			base.OnCreate(savedInstanceState); | ||||
| 			SetEntryView(); | ||||
|  | ||||
| 			FillData(false); | ||||
| 			 | ||||
| 			FillData(); | ||||
|  | ||||
| 			SetupEditButtons(); | ||||
|  | ||||
| 			 | ||||
| 			RegisterReceiver(new PluginActionReceiver(this), new IntentFilter(Strings.ActionAddEntryAction)); | ||||
| 			RegisterReceiver(new PluginFieldReceiver(this), new IntentFilter(Strings.ActionSetEntryField)); | ||||
|  | ||||
| 			new Thread(NotifyPluginsOnOpen).Start(); | ||||
| 		} | ||||
|  | ||||
| 		private void NotifyPluginsOnOpen() | ||||
| 		{ | ||||
| 			App.Kp2A.GetDb().SetEntry(Entry); | ||||
|  | ||||
| 			Intent i = new Intent(Strings.ActionOpenEntry); | ||||
| 			i.PutExtra(Strings.ExtraSender, PackageName); | ||||
| 			PluginHost.AddEntryToIntent(i, Entry); | ||||
|  | ||||
| 			foreach (var plugin in new PluginDatabase(this).GetPluginsWithAcceptedScope(Strings.ScopeCurrentEntry)) | ||||
| 			{ | ||||
| 				i.SetPackage(plugin); | ||||
| 				SendBroadcast(i); | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		public void CompleteOnCreate() | ||||
| 		{ | ||||
| 			 | ||||
|  | ||||
| 		} | ||||
|  | ||||
|  | ||||
| 		private String getDateTime(DateTime dt) { | ||||
| 			return dt.ToString ("g", CultureInfo.CurrentUICulture); | ||||
| 		private String getDateTime(DateTime dt) | ||||
| 		{ | ||||
| 			return dt.ToString("g", CultureInfo.CurrentUICulture); | ||||
| 		} | ||||
|  | ||||
| 		String concatTags(List<string> tags) | ||||
| 		private String concatTags(List<string> tags) | ||||
| 		{ | ||||
| 			StringBuilder sb = new StringBuilder(); | ||||
| 			foreach (string tag in tags) | ||||
| @@ -113,70 +448,98 @@ namespace keepass2android | ||||
| 				sb.Append(", "); | ||||
| 			} | ||||
| 			if (tags.Count > 0) | ||||
| 				sb.Remove(sb.Length-2,2); | ||||
| 				sb.Remove(sb.Length - 2, 2); | ||||
| 			return sb.ToString(); | ||||
| 		} | ||||
|  | ||||
| 		void PopulateExtraStrings(bool trimList) | ||||
| 		private void PopulateExtraStrings() | ||||
| 		{ | ||||
| 			ViewGroup extraGroup = (ViewGroup)FindViewById(Resource.Id.extra_strings); | ||||
| 			if (trimList) | ||||
| 			ViewGroup extraGroup = (ViewGroup) FindViewById(Resource.Id.extra_strings); | ||||
| 			foreach (var pair in Entry.Strings.Where(pair => !PwDefs.IsStandardField(pair.Key)).OrderBy(pair => pair.Key)) | ||||
| 			{ | ||||
| 				extraGroup.RemoveAllViews(); | ||||
| 				var stringView = CreateExtraSection(pair.Key, pair.Value.ReadString(), pair.Value.IsProtected); | ||||
| 				extraGroup.AddView(stringView.View); | ||||
| 			} | ||||
| 			bool hasExtraFields = false; | ||||
| 			foreach (var view in from pair in new Dictionary<string, string>() { { "Field header", "field value" }, { "another header", "_aiaeiae" } } | ||||
| 								 orderby pair.Key  | ||||
| 								 select CreateEditSection(pair.Key, pair.Value, true)) | ||||
| 			{ | ||||
| 				extraGroup.AddView(view); | ||||
| 				hasExtraFields = true; | ||||
| 			} | ||||
| 			FindViewById(Resource.Id.entry_extra_strings_label).Visibility = hasExtraFields ? ViewStates.Visible : ViewStates.Gone; | ||||
|  | ||||
| 		} | ||||
|  | ||||
| 		View CreateEditSection(string key, string value, bool isProtected) | ||||
| 		private ExtraStringView CreateExtraSection(string key, string value, bool isProtected) | ||||
| 		{ | ||||
| 			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); | ||||
| 			LinearLayout.LayoutParams layoutParams = new LinearLayout.LayoutParams(ViewGroup.LayoutParams.FillParent, | ||||
| 			                                                                       ViewGroup.LayoutParams.WrapContent); | ||||
|  | ||||
| 			layout.LayoutParameters = layoutParams; | ||||
| 			View viewInflated = LayoutInflater.Inflate(Resource.Layout.entry_extrastring_title,null); | ||||
| 			TextView keyView = (TextView)viewInflated; | ||||
| 			View viewInflated = LayoutInflater.Inflate(Resource.Layout.entry_extrastring_title, null); | ||||
| 			TextView keyView = viewInflated.FindViewById<TextView>(Resource.Id.entry_title); | ||||
| 			if (key != null) | ||||
| 				keyView.Text = key; | ||||
| 			 | ||||
| 			layout.AddView(keyView); | ||||
| 			TextView valueView = (TextView)LayoutInflater.Inflate(Resource.Layout.entry_extrastring_value, null); | ||||
|  | ||||
| 			layout.AddView(viewInflated); | ||||
| 			RelativeLayout valueViewContainer = | ||||
| 				(RelativeLayout) LayoutInflater.Inflate(Resource.Layout.entry_extrastring_value, null); | ||||
| 			var valueView = valueViewContainer.FindViewById<TextView>(Resource.Id.entry_extra); | ||||
| 			if (value != null) | ||||
| 				valueView.Text = value; | ||||
| 			SetPasswordTypeface(valueView); | ||||
| 			if (isProtected) | ||||
| 			{ | ||||
| 				RegisterProtectedTextView(valueView); | ||||
| 				valueView.TransformationMethod = PasswordTransformationMethod.Instance; | ||||
| 			} | ||||
|  | ||||
| 			layout.AddView(valueViewContainer); | ||||
| 			var stringView = new ExtraStringView(layout, valueView, keyView); | ||||
|  | ||||
| 			_stringViews.Add(key, stringView); | ||||
| 			RegisterTextPopup(valueViewContainer, valueViewContainer.FindViewById(Resource.Id.extra_vdots), key, isProtected); | ||||
|  | ||||
| 			return stringView; | ||||
|  | ||||
| 			if ((int)Build.VERSION.SdkInt >= 11) | ||||
| 				valueView.SetTextIsSelectable(true); | ||||
| 			layout.AddView(valueView); | ||||
| 			return layout; | ||||
| 		} | ||||
|  | ||||
| 		private List<IPopupMenuItem> RegisterPopup(string popupKey, View clickView, View anchorView) | ||||
| 		{ | ||||
| 			clickView.Click += (sender, args) => | ||||
| 				{ | ||||
| 					ShowPopup(anchorView, popupKey); | ||||
| 				}; | ||||
| 			_popupMenuItems[popupKey] = new List<IPopupMenuItem>(); | ||||
| 			return _popupMenuItems[popupKey]; | ||||
| 		} | ||||
|  | ||||
|  | ||||
| 		private void RegisterProtectedTextView(TextView protectedTextView) | ||||
| 		{ | ||||
| 			_protectedTextViews.Add(protectedTextView); | ||||
| 		} | ||||
|  | ||||
|  | ||||
| 		void PopulateBinaries(bool trimList) | ||||
| 		private void PopulateBinaries() | ||||
| 		{ | ||||
| 			ViewGroup binariesGroup = (ViewGroup)FindViewById(Resource.Id.binaries); | ||||
| 			if (trimList) | ||||
| 			{ | ||||
| 				binariesGroup.RemoveAllViews(); | ||||
| 			} | ||||
| 			foreach (KeyValuePair<string, string> pair in new Dictionary<string, string>() { {"abc",""}, {"test.png","uia"} }) | ||||
| 			ViewGroup binariesGroup = (ViewGroup) FindViewById(Resource.Id.binaries); | ||||
| 			foreach (KeyValuePair<string, string> pair in new Dictionary<string, string>() {{"abc", ""}, {"test.png", "uia"}}) | ||||
| 			{ | ||||
| 				String key = pair.Key; | ||||
|  | ||||
|  | ||||
| 				RelativeLayout valueViewContainer = | ||||
| 					(RelativeLayout) LayoutInflater.Inflate(Resource.Layout.entry_extrastring_value, null); | ||||
| 				var valueView = valueViewContainer.FindViewById<TextView>(Resource.Id.entry_extra); | ||||
| 				if (key != null) | ||||
| 					valueView.Text = key; | ||||
|  | ||||
| 				string popupKey = Strings.PrefixBinary + key; | ||||
|  | ||||
| 				var itemList = RegisterPopup(popupKey, valueViewContainer, valueViewContainer.FindViewById(Resource.Id.extra_vdots)); | ||||
| 				itemList.Add(new WriteBinaryToFilePopupItem(key, this)); | ||||
| 				itemList.Add(new OpenBinaryPopupItem(key, this)); | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| 				binariesGroup.AddView(valueViewContainer); | ||||
| 				/* | ||||
| 				Button binaryButton = new Button(this); | ||||
| 				RelativeLayout.LayoutParams layoutParams = new RelativeLayout.LayoutParams(ViewGroup.LayoutParams.FillParent, ViewGroup.LayoutParams.WrapContent); | ||||
| 				binaryButton.Text = key; | ||||
| @@ -206,8 +569,8 @@ namespace keepass2android | ||||
|  | ||||
| 				}; | ||||
| 				binariesGroup.AddView(binaryButton,layoutParams); | ||||
| 				*/ | ||||
|  | ||||
| 				 | ||||
| 			} | ||||
| 			FindViewById(Resource.Id.entry_binaries_label).Visibility = true ? ViewStates.Visible : ViewStates.Gone; | ||||
| 		} | ||||
| @@ -217,7 +580,8 @@ namespace keepass2android | ||||
| 		{ | ||||
| 			String type = null; | ||||
| 			String extension = MimeTypeMap.GetFileExtensionFromUrl(url); | ||||
| 			if (extension != null) { | ||||
| 			if (extension != null) | ||||
| 			{ | ||||
| 				MimeTypeMap mime = MimeTypeMap.Singleton; | ||||
| 				type = mime.GetMimeTypeFromExtension(extension); | ||||
| 			} | ||||
| @@ -229,94 +593,182 @@ namespace keepass2android | ||||
| 			base.OnBackPressed(); | ||||
| 		} | ||||
|  | ||||
| 		protected void FillData(bool trimList) | ||||
| 		protected void FillData() | ||||
| 		{ | ||||
| 			_protectedTextViews = new List<TextView>(); | ||||
| 			ImageView iv = (ImageView)FindViewById(Resource.Id.entry_icon); | ||||
| 			ImageView iv = (ImageView) FindViewById(Resource.Id.entry_icon); | ||||
| 			if (iv != null) | ||||
| 			{ | ||||
| 				iv.SetImageDrawable(Resources.GetDrawable(Resource.Drawable.ic00)); | ||||
| 			} | ||||
| 			 | ||||
| 			 | ||||
|  | ||||
|  | ||||
|  | ||||
| 			ActionBar.Title = "Entry title"; | ||||
| 			ActionBar.SetDisplayHomeAsUpEnabled(true); | ||||
| 			 | ||||
| 			PopulateText(Resource.Id.entry_user_name, Resource.Id.entry_user_name_label, "user name"); | ||||
| 			 | ||||
| 			PopulateText(Resource.Id.entry_url, Resource.Id.entry_url_label, "www.google.com"); | ||||
| 			PopulateText(Resource.Id.entry_password, Resource.Id.entry_password_label, "my password"); | ||||
|  | ||||
|  | ||||
|  | ||||
| 			PopulateStandardText(Resource.Id.entry_user_name, Resource.Id.entryfield_container_username, PwDefs.UserNameField); | ||||
| 			PopulateStandardText(Resource.Id.entry_url, Resource.Id.entryfield_container_url, PwDefs.UrlField); | ||||
| 			PopulateStandardText(Resource.Id.entry_password, Resource.Id.entryfield_container_password, PwDefs.PasswordField); | ||||
| 			RegisterProtectedTextView(FindViewById<TextView>(Resource.Id.entry_password)); | ||||
| 			SetPasswordTypeface(FindViewById<TextView>(Resource.Id.entry_password)); | ||||
| 			 | ||||
| 			 | ||||
| 			PopulateText(Resource.Id.entry_created, Resource.Id.entry_created_label, getDateTime(DateTime.Now)); | ||||
| 			PopulateText(Resource.Id.entry_modified, Resource.Id.entry_modified_label, getDateTime(DateTime.Now)); | ||||
| 			 | ||||
| 			if (true) | ||||
| 			{ | ||||
| 				FindViewById(Resource.Id.entry_expires).Visibility = ViewStates.Visible; | ||||
| 				FindViewById(Resource.Id.entry_expires_label).Visibility = ViewStates.Visible; | ||||
| 				 | ||||
| 				PopulateText(Resource.Id.entry_expires, Resource.Id.entry_expires_label, getDateTime(DateTime.Now)); | ||||
|  | ||||
| 			}  | ||||
| 			RegisterTextPopup(FindViewById<RelativeLayout>(Resource.Id.username_container), | ||||
| 			                  FindViewById(Resource.Id.username_vdots), PwDefs.UserNameField); | ||||
| 			RegisterTextPopup(FindViewById<RelativeLayout>(Resource.Id.url_container), | ||||
| 			                  FindViewById(Resource.Id.url_vdots), PwDefs.UrlField) | ||||
| 				.Add(new GotoUrlMenuItem(this)); | ||||
| 			RegisterTextPopup(FindViewById<RelativeLayout>(Resource.Id.password_container), | ||||
| 			                  FindViewById(Resource.Id.password_vdots), PwDefs.PasswordField); | ||||
|  | ||||
|  | ||||
| 			PopulateText(Resource.Id.entry_created, Resource.Id.entryfield_container_created, getDateTime(Entry.CreationTime)); | ||||
| 			PopulateText(Resource.Id.entry_modified, Resource.Id.entryfield_container_modified, getDateTime(Entry.LastModificationTime)); | ||||
|  | ||||
| 			if (Entry.Expires) | ||||
| 			{ | ||||
| 				PopulateText(Resource.Id.entry_expires, Resource.Id.entryfield_container_expires, getDateTime(Entry.ExpiryTime)); | ||||
|  | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				FindViewById(Resource.Id.entry_expires).Visibility = ViewStates.Gone; | ||||
| 				FindViewById(Resource.Id.entry_expires_label).Visibility = ViewStates.Gone; | ||||
| 				PopulateText(Resource.Id.entry_expires, Resource.Id.entryfield_container_expires, null); | ||||
| 			} | ||||
| 			PopulateText(Resource.Id.entry_comment, Resource.Id.entry_comment_label, "some text about this entry"); | ||||
| 			PopulateStandardText(Resource.Id.entry_comment, Resource.Id.entryfield_container_comment, PwDefs.NotesField); | ||||
| 			PopulateText(Resource.Id.entry_tags, Resource.Id.entryfield_container_tags, concatTags(Entry.Tags)); | ||||
| 			PopulateText(Resource.Id.entry_override_url, Resource.Id.entryfield_container_overrideurl, Entry.OverrideUrl); | ||||
|  | ||||
| 			PopulateText(Resource.Id.entry_tags, Resource.Id.entry_tags_label, "bla; blubb; blablubb"); | ||||
| 			PopulateExtraStrings(); | ||||
|  | ||||
| 			PopulateExtraStrings(trimList); | ||||
|  | ||||
| 			PopulateBinaries(trimList); | ||||
| 			PopulateBinaries(); | ||||
|  | ||||
| 			SetPasswordStyle(); | ||||
| 		} | ||||
|  | ||||
| 		protected override void OnActivityResult(int requestCode, Result resultCode, Intent data) | ||||
| 		{ | ||||
| 			base.OnActivityResult(requestCode, resultCode, data); | ||||
| 			if (resultCode == /*TODO*/ 0) | ||||
| 			{ | ||||
| 				if (resultCode == /*TODO*/ 0) | ||||
| 				{ | ||||
| 					RequiresRefresh(); | ||||
| 				} | ||||
| 				Recreate(); | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		protected override void OnDestroy() | ||||
| 		{ | ||||
| 			NotifyPluginsOnClose(); | ||||
| 			base.OnDestroy(); | ||||
| 		} | ||||
|  | ||||
| 		private void NotifyPluginsOnClose() | ||||
| 		{ | ||||
| 			Intent i = new Intent(Strings.ActionCloseEntryView); | ||||
| 			i.PutExtra(Strings.ExtraSender, PackageName); | ||||
| 			foreach (var plugin in new PluginDatabase(this).GetPluginsWithAcceptedScope(Strings.ScopeCurrentEntry)) | ||||
| 			{ | ||||
| 				i.SetPackage(plugin); | ||||
| 				SendBroadcast(i); | ||||
| 			} | ||||
| 		} | ||||
| 		private List<IPopupMenuItem> RegisterTextPopup(View container, View anchor, string fieldKey) | ||||
| 		{ | ||||
| 			return RegisterTextPopup(container, anchor, fieldKey, Entry.Strings.GetSafe(fieldKey).IsProtected); | ||||
| 		} | ||||
|  | ||||
| 		private List<IPopupMenuItem> RegisterTextPopup(View container, View anchor, string fieldKey, bool isProtected) | ||||
| 		{ | ||||
| 			string popupKey = Strings.PrefixString + fieldKey; | ||||
| 			var popupItems = RegisterPopup( | ||||
| 				popupKey, | ||||
| 				container, | ||||
| 				anchor); | ||||
| 			popupItems.Add(new CopyToClipboardPopupMenuIcon(this, _stringViews[fieldKey])); | ||||
| 			if (isProtected) | ||||
| 				popupItems.Add(new ToggleVisibilityPopupMenuItem(this)); | ||||
| 			return popupItems; | ||||
| 		} | ||||
|  | ||||
|  | ||||
|  | ||||
| 		private void ShowPopup(View anchor, string popupKey) | ||||
| 		{ | ||||
| 			//PopupMenu popupMenu = new PopupMenu(this, FindViewById(Resource.Id.entry_user_name)); | ||||
| 			PopupMenu popupMenu = new PopupMenu(this, anchor); | ||||
|  | ||||
| 			AccessManager.PreparePopup(popupMenu); | ||||
| 			int itemId = 0; | ||||
| 			foreach (IPopupMenuItem popupItem in _popupMenuItems[popupKey]) | ||||
| 			{ | ||||
| 				popupMenu.Menu.Add(0, itemId, 0, popupItem.Text) | ||||
| 				         .SetIcon(popupItem.Icon); | ||||
| 				itemId++; | ||||
| 			} | ||||
|  | ||||
| 			popupMenu.MenuItemClick += delegate(object sender, PopupMenu.MenuItemClickEventArgs args) | ||||
| 				{ | ||||
| 					_popupMenuItems[popupKey][args.Item.ItemId].HandleClick(); | ||||
| 				}; | ||||
| 			popupMenu.Show(); | ||||
| 		} | ||||
|  | ||||
| 		private void ShowPopup(int resAnchor, string popupKey) | ||||
| 		{ | ||||
| 			ShowPopup(FindViewById(resAnchor), popupKey); | ||||
| 		} | ||||
|  | ||||
| 		private void SetPasswordTypeface(TextView textView) | ||||
| 		{ | ||||
| 			 | ||||
|  | ||||
| 		} | ||||
|  | ||||
| 		private void PopulateText(int viewId, int headerViewId,int resId) { | ||||
| 			View header = FindViewById(headerViewId); | ||||
| 			TextView tv = (TextView)FindViewById(viewId); | ||||
| 		private void PopulateText(int viewId, int containerViewId, int resId) | ||||
| 		{ | ||||
| 			View header = FindViewById(containerViewId); | ||||
| 			TextView tv = (TextView) FindViewById(viewId); | ||||
|  | ||||
| 			header.Visibility = tv.Visibility = ViewStates.Visible; | ||||
| 			tv.SetText (resId); | ||||
| 			tv.SetText(resId); | ||||
| 		} | ||||
| 		 | ||||
| 		private void PopulateText(int viewId, int headerViewId, String text) | ||||
|  | ||||
| 		private void PopulateText(int viewId, int containerViewId, String text) | ||||
| 		{ | ||||
| 			View header = FindViewById(headerViewId); | ||||
| 			TextView tv = (TextView)FindViewById(viewId); | ||||
| 			View container = FindViewById(containerViewId); | ||||
| 			TextView tv = (TextView) FindViewById(viewId); | ||||
| 			if (String.IsNullOrEmpty(text)) | ||||
| 			{ | ||||
| 				header.Visibility = tv.Visibility = ViewStates.Gone; | ||||
| 				container.Visibility = tv.Visibility = ViewStates.Gone; | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				header.Visibility = tv.Visibility = ViewStates.Visible; | ||||
| 				container.Visibility = tv.Visibility = ViewStates.Visible; | ||||
| 				tv.Text = text; | ||||
|  | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		void RequiresRefresh () | ||||
| 		private void PopulateStandardText(int viewId, int containerViewId, String key) | ||||
| 		{ | ||||
| 			Intent ret = new Intent (); | ||||
| 			ret.PutExtra (KeyRefreshPos, _pos); | ||||
| 			 | ||||
| 			PopulateText(viewId, containerViewId, Entry.Strings.ReadSafe(key)); | ||||
| 			_stringViews.Add(key, new StandardStringView(viewId, containerViewId, this)); | ||||
| 		} | ||||
| 		 | ||||
| 		 | ||||
| 		 | ||||
| 		private void SetPasswordStyle() { | ||||
|  | ||||
| 		private void RequiresRefresh() | ||||
| 		{ | ||||
| 			Intent ret = new Intent(); | ||||
| 			ret.PutExtra(KeyRefreshPos, _pos); | ||||
|  | ||||
| 		} | ||||
|  | ||||
|  | ||||
|  | ||||
| 		private void SetPasswordStyle() | ||||
| 		{ | ||||
| 			foreach (TextView password in _protectedTextViews) | ||||
| 			{ | ||||
|  | ||||
| @@ -330,12 +782,13 @@ namespace keepass2android | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		protected override void OnResume() | ||||
| 		{ | ||||
| 			 | ||||
|  | ||||
| 			base.OnResume(); | ||||
| 		} | ||||
| 		 | ||||
|  | ||||
| 		/// <summary> | ||||
| 		/// brings up a dialog asking the user whether he wants to add the given URL to the entry for automatic finding | ||||
| 		/// </summary> | ||||
| @@ -344,24 +797,50 @@ namespace keepass2android | ||||
| 			AlertDialog.Builder builder = new AlertDialog.Builder(this); | ||||
| 			builder.SetTitle(GetString(Resource.String.AddUrlToEntryDialog_title)); | ||||
|  | ||||
| 			builder.SetMessage(GetString(Resource.String.AddUrlToEntryDialog_text, new Java.Lang.Object[] { url } )); | ||||
| 			builder.SetMessage(GetString(Resource.String.AddUrlToEntryDialog_text, new Java.Lang.Object[] {url})); | ||||
|  | ||||
| 			builder.SetPositiveButton(GetString(Resource.String.yes), (dlgSender, dlgEvt) => | ||||
| 				{ | ||||
| 					 | ||||
|  | ||||
| 				}); | ||||
|  | ||||
| 			builder.SetNegativeButton(GetString(Resource.String.no), (dlgSender, dlgEvt) => | ||||
| 			{ | ||||
| 				CompleteOnCreate(); | ||||
| 			}); | ||||
| 				{ | ||||
| 					CompleteOnCreate(); | ||||
| 				}); | ||||
|  | ||||
| 			Dialog dialog = builder.Create(); | ||||
| 			dialog.Show(); | ||||
|  | ||||
| 		} | ||||
|  | ||||
| 		public void ToggleVisibility() | ||||
| 		{ | ||||
| 			_showPassword = !_showPassword; | ||||
| 			SetPasswordStyle(); | ||||
| 			UpdateTogglePasswordMenu(); | ||||
| 		} | ||||
|  | ||||
| 		public Android.Net.Uri WriteBinaryToFile(string key, bool writeToCacheDirectory) | ||||
| 		{ | ||||
| 			return Android.Net.Uri.Empty; | ||||
| 			//TODO | ||||
| 		} | ||||
|  | ||||
| 		private void UpdateTogglePasswordMenu() | ||||
| 		{ | ||||
| 			//todo use real method | ||||
| 		} | ||||
|  | ||||
| 		public void GotoUrl() | ||||
| 		{ | ||||
| 			//TODO | ||||
| 			 | ||||
| 		} | ||||
|  | ||||
| 		public void OpenBinaryFile(Uri newUri) | ||||
| 		{ | ||||
| 			Toast.MakeText(this, "opening file TODO", ToastLength.Short).Show(); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| } | ||||
|  | ||||
| } | ||||
							
								
								
									
										44
									
								
								src/PluginHostTest/EntryActivityClasses/ExtraStringView.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								src/PluginHostTest/EntryActivityClasses/ExtraStringView.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,44 @@ | ||||
| using System; | ||||
| using Android.Views; | ||||
| using Android.Widget; | ||||
|  | ||||
| namespace keepass2android | ||||
| { | ||||
| 	internal class ExtraStringView : IStringView | ||||
| 	{ | ||||
| 		private readonly View _container; | ||||
| 		private readonly TextView _valueView; | ||||
| 		private readonly TextView _keyView; | ||||
|  | ||||
| 		public ExtraStringView(LinearLayout container, TextView valueView, TextView keyView) | ||||
| 		{ | ||||
| 			_container = container; | ||||
| 			_valueView = valueView; | ||||
| 			_keyView = keyView; | ||||
| 		} | ||||
|  | ||||
| 		public View View | ||||
| 		{ | ||||
| 			get { return _container; } | ||||
| 		} | ||||
|  | ||||
| 		public string Text | ||||
| 		{ | ||||
| 			get { return _valueView.Text; } | ||||
| 			set | ||||
| 			{ | ||||
| 				if (String.IsNullOrEmpty(value)) | ||||
| 				{ | ||||
| 					_valueView.Visibility = ViewStates.Gone; | ||||
| 					_keyView.Visibility = ViewStates.Gone; | ||||
| 				} | ||||
| 				else | ||||
| 				{ | ||||
| 					_valueView.Visibility = ViewStates.Visible; | ||||
| 					_keyView.Visibility = ViewStates.Visible; | ||||
| 					_valueView.Text = value; | ||||
| 				} | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										112
									
								
								src/PluginHostTest/EntryActivityClasses/IPopupMenuItem.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										112
									
								
								src/PluginHostTest/EntryActivityClasses/IPopupMenuItem.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,112 @@ | ||||
| using System; | ||||
| using Android.Content; | ||||
| using Android.Graphics.Drawables; | ||||
| using KeePassLib; | ||||
| using PluginHostTest; | ||||
|  | ||||
| namespace keepass2android | ||||
| { | ||||
| 	internal interface IPopupMenuItem	 | ||||
| 	{ | ||||
| 		Drawable Icon { get; } | ||||
| 		String Text { get; } | ||||
|  | ||||
| 		void HandleClick(); | ||||
| 	} | ||||
|  | ||||
| 	class GotoUrlMenuItem : IPopupMenuItem | ||||
| 	{ | ||||
| 		private readonly EntryActivity _ctx; | ||||
|  | ||||
| 		public GotoUrlMenuItem(EntryActivity ctx) | ||||
| 		{ | ||||
| 			_ctx = ctx; | ||||
| 		} | ||||
|  | ||||
| 		public Drawable Icon | ||||
| 		{ | ||||
| 			get { return _ctx.Resources.GetDrawable(Android.Resource.Drawable.IcMenuUpload); } | ||||
| 		} | ||||
|  | ||||
| 		public string Text | ||||
| 		{ | ||||
| 			get { return _ctx.Resources.GetString(Resource.String.menu_url); } | ||||
| 		} | ||||
|  | ||||
| 		public void HandleClick() | ||||
| 		{ | ||||
| 			//TODO | ||||
| 			_ctx.GotoUrl(); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	class ToggleVisibilityPopupMenuItem : IPopupMenuItem | ||||
| 	{ | ||||
| 		private readonly EntryActivity _activity; | ||||
| 		 | ||||
|  | ||||
| 		public ToggleVisibilityPopupMenuItem(EntryActivity activity) | ||||
| 		{ | ||||
| 			_activity = activity; | ||||
| 			 | ||||
| 		} | ||||
|  | ||||
| 		public Drawable Icon  | ||||
| 		{  | ||||
| 			get | ||||
| 			{ | ||||
| 				//return new TextDrawable("\uF06E", _activity); | ||||
| 				return _activity.Resources.GetDrawable(Resource.Drawable.ic_action_eye_open); | ||||
| 				 | ||||
| 			} | ||||
| 		} | ||||
| 		public string Text | ||||
| 		{ | ||||
| 			get | ||||
| 			{ | ||||
| 				return _activity.Resources.GetString( | ||||
| 					_activity._showPassword ?  | ||||
| 						Resource.String.menu_hide_password  | ||||
| 						: Resource.String.show_password); | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		 | ||||
| 		public void HandleClick() | ||||
| 		{ | ||||
| 			_activity.ToggleVisibility(); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	class CopyToClipboardPopupMenuIcon : IPopupMenuItem | ||||
| 	{ | ||||
| 		private readonly Context _context; | ||||
| 		private readonly IStringView _stringView; | ||||
|  | ||||
| 		public CopyToClipboardPopupMenuIcon(Context context, IStringView stringView) | ||||
| 		{ | ||||
| 			_context = context; | ||||
| 			_stringView = stringView; | ||||
| 			 | ||||
| 		} | ||||
|  | ||||
| 		public Drawable Icon  | ||||
| 		{  | ||||
| 			get | ||||
| 			{ | ||||
| 				return _context.Resources.GetDrawable(Resource.Drawable.ic_menu_copy_holo_light); | ||||
| 			} | ||||
| 		} | ||||
| 		public string Text | ||||
| 		{ | ||||
| 			//TODO localize | ||||
| 			get { return "Copy to clipboard"; } | ||||
| 		} | ||||
|  | ||||
| 		 | ||||
| 		public void HandleClick() | ||||
| 		{ | ||||
| 			CopyToClipboardService.CopyValueToClipboardWithTimeout(_context, _stringView.Text); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										7
									
								
								src/PluginHostTest/EntryActivityClasses/IStringView.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								src/PluginHostTest/EntryActivityClasses/IStringView.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | ||||
| namespace keepass2android | ||||
| { | ||||
| 	internal interface IStringView | ||||
| 	{ | ||||
| 		string Text { set; get; } | ||||
| 	} | ||||
| } | ||||
| @@ -0,0 +1,37 @@ | ||||
| using Android.Graphics.Drawables; | ||||
| using PluginHostTest; | ||||
|  | ||||
| namespace keepass2android | ||||
| { | ||||
| 	internal class OpenBinaryPopupItem : IPopupMenuItem | ||||
| 	{ | ||||
| 		private readonly string _key; | ||||
| 		private readonly EntryActivity _entryActivity; | ||||
|  | ||||
| 		public OpenBinaryPopupItem(string key, EntryActivity entryActivity) | ||||
| 		{ | ||||
| 			_key = key; | ||||
| 			_entryActivity = entryActivity; | ||||
| 		} | ||||
|  | ||||
| 		public Drawable Icon | ||||
| 		{ | ||||
| 			get { return _entryActivity.Resources.GetDrawable(Android.Resource.Drawable.IcMenuShare); } | ||||
| 		} | ||||
|  | ||||
| 		public string Text | ||||
| 		{ | ||||
| 			get { return _entryActivity.Resources.GetString(Resource.String.SaveAttachmentDialog_open); } | ||||
| 		} | ||||
|  | ||||
| 		public void HandleClick() | ||||
| 		{ | ||||
| 			Android.Net.Uri newUri = _entryActivity.WriteBinaryToFile(_key, true); | ||||
| 			if (newUri != null) | ||||
| 			{ | ||||
| 				_entryActivity.OpenBinaryFile(newUri); | ||||
| 			} | ||||
| 			 | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										14
									
								
								src/PluginHostTest/EntryActivityClasses/PluginMenuOption.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								src/PluginHostTest/EntryActivityClasses/PluginMenuOption.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | ||||
| using Android.Content; | ||||
| using Android.Graphics.Drawables; | ||||
|  | ||||
| namespace keepass2android | ||||
| { | ||||
| 	class PluginMenuOption | ||||
| 	{ | ||||
| 		public string DisplayText { get; set; } | ||||
|  | ||||
| 		public Drawable Icon { get; set; } | ||||
|  | ||||
| 		public Intent Intent { get; set; } | ||||
| 	} | ||||
| } | ||||
| @@ -0,0 +1,47 @@ | ||||
| using Android.Content; | ||||
| using Android.Graphics.Drawables; | ||||
| using Android.OS; | ||||
| using Keepass2android.Pluginsdk; | ||||
|  | ||||
| namespace keepass2android | ||||
| { | ||||
| 	class PluginPopupMenuItem : IPopupMenuItem | ||||
| 	{ | ||||
| 		private readonly Context _ctx; | ||||
| 		private readonly string _pluginPackage; | ||||
| 		private readonly string _fieldId; | ||||
| 		private readonly string _displayText; | ||||
| 		private readonly int _iconId; | ||||
| 		private readonly Bundle _bundleExtra; | ||||
|  | ||||
| 		public PluginPopupMenuItem(Context ctx, string pluginPackage, string fieldId, string displayText, int iconId, Bundle bundleExtra) | ||||
| 		{ | ||||
| 			_ctx = ctx; | ||||
| 			_pluginPackage = pluginPackage; | ||||
| 			_fieldId = fieldId; | ||||
| 			_displayText = displayText; | ||||
| 			_iconId = iconId; | ||||
| 			_bundleExtra = bundleExtra; | ||||
| 		} | ||||
|  | ||||
| 		public Drawable Icon  | ||||
| 		{  | ||||
| 			get { return _ctx.PackageManager.GetResourcesForApplication(_pluginPackage).GetDrawable(_iconId); } | ||||
| 		} | ||||
| 		public string Text  | ||||
| 		{  | ||||
| 			get { return _displayText; }  | ||||
| 		} | ||||
| 		public void HandleClick() | ||||
| 		{ | ||||
| 			Intent i = new Intent(Strings.ActionEntryActionSelected); | ||||
| 			i.SetPackage(_pluginPackage); | ||||
| 			i.PutExtra(Strings.ExtraActionData, _bundleExtra); | ||||
| 			i.PutExtra(Strings.ExtraFieldId, _fieldId); | ||||
| 			i.PutExtra(Strings.ExtraSender, _ctx.PackageName); | ||||
| 			PluginHost.AddEntryToIntent(i, Entry); | ||||
|  | ||||
| 			_ctx.SendBroadcast(i); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @@ -0,0 +1,44 @@ | ||||
| using System; | ||||
| using Android.App; | ||||
| using Android.Views; | ||||
| using Android.Widget; | ||||
|  | ||||
| namespace keepass2android | ||||
| { | ||||
| 	internal class StandardStringView : IStringView | ||||
| 	{ | ||||
| 		private readonly int _viewId; | ||||
| 		private readonly int _containerViewId; | ||||
| 		private readonly Activity _activity; | ||||
|  | ||||
| 		public StandardStringView(int viewId, int containerViewId, Activity activity) | ||||
| 		{ | ||||
| 			_viewId = viewId; | ||||
| 			_containerViewId = containerViewId; | ||||
| 			_activity = activity; | ||||
| 		} | ||||
|  | ||||
| 		public string Text | ||||
| 		{ | ||||
| 			set | ||||
| 			{ | ||||
| 				View container = _activity.FindViewById(_containerViewId); | ||||
| 				TextView tv = (TextView) _activity.FindViewById(_viewId); | ||||
| 				if (String.IsNullOrEmpty(value)) | ||||
| 				{ | ||||
| 					container.Visibility = tv.Visibility = ViewStates.Gone; | ||||
| 				} | ||||
| 				else | ||||
| 				{ | ||||
| 					container.Visibility = tv.Visibility = ViewStates.Visible; | ||||
| 					tv.Text = value; | ||||
| 				} | ||||
| 			} | ||||
| 			get | ||||
| 			{ | ||||
| 				TextView tv = (TextView) _activity.FindViewById(_viewId); | ||||
| 				return tv.Text; | ||||
| 			} | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @@ -0,0 +1,32 @@ | ||||
| using Android.Graphics.Drawables; | ||||
| using PluginHostTest; | ||||
|  | ||||
| namespace keepass2android | ||||
| { | ||||
| 	internal class WriteBinaryToFilePopupItem : IPopupMenuItem | ||||
| 	{ | ||||
| 		private readonly string _key; | ||||
| 		private readonly EntryActivity _activity; | ||||
|  | ||||
| 		public WriteBinaryToFilePopupItem(string key, EntryActivity activity) | ||||
| 		{ | ||||
| 			_key = key; | ||||
| 			_activity = activity; | ||||
| 		} | ||||
|  | ||||
| 		public Drawable Icon | ||||
| 		{ | ||||
| 			get { return _activity.Resources.GetDrawable(Android.Resource.Drawable.IcMenuSave); } | ||||
| 		} | ||||
|  | ||||
| 		public string Text | ||||
| 		{ | ||||
| 			get { return _activity.Resources.GetString(Resource.String.SaveAttachmentDialog_save); } | ||||
| 		} | ||||
|  | ||||
| 		public void HandleClick() | ||||
| 		{ | ||||
| 			_activity.WriteBinaryToFile(_key, false); | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @@ -1,3 +1,6 @@ | ||||
| using Android.Content.PM; | ||||
| using Android.Content.Res; | ||||
| using Android.Graphics.Drawables; | ||||
| using Android.Widget; | ||||
| using Android.Content; | ||||
| using Android.Views; | ||||
| @@ -11,26 +14,32 @@ namespace keepass2android | ||||
| 	public class PluginItem | ||||
| 	{ | ||||
| 		private readonly string _package; | ||||
| 		private readonly Context _ctx; | ||||
| 		private readonly Resources _pluginRes; | ||||
|  | ||||
| 		public PluginItem(string package, string _label, int _icon, string _version, string _enabledStatus) | ||||
| 		public PluginItem(string package, string enabledStatus, Context ctx) | ||||
| 		{ | ||||
| 			_package = package; | ||||
| 			Label = _label; | ||||
| 			Icon = _icon; | ||||
| 			Version = _version; | ||||
| 			EnabledStatus = _enabledStatus; | ||||
| 			_ctx = ctx; | ||||
| 			EnabledStatus = enabledStatus; | ||||
| 			_pluginRes = _ctx.PackageManager.GetResourcesForApplication(_package); | ||||
| 		} | ||||
|  | ||||
| 		public string Label | ||||
| 		{ | ||||
| 			get; | ||||
| 			set; | ||||
| 			get | ||||
| 			{ | ||||
| 				return PluginDetailsActivity.GetStringFromPlugin(_pluginRes, _package, "kp2aplugin_title"); | ||||
| 			} | ||||
| 			 | ||||
| 		} | ||||
|  | ||||
| 		public string Version | ||||
| 		{ | ||||
| 			get; | ||||
| 			set; | ||||
| 			get | ||||
| 			{ | ||||
| 				return _ctx.PackageManager.GetPackageInfo(_package, 0).VersionName; | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		public string EnabledStatus | ||||
| @@ -39,10 +48,12 @@ namespace keepass2android | ||||
| 			set; | ||||
| 		} | ||||
|  | ||||
| 		public int Icon | ||||
| 		public Drawable Icon | ||||
| 		{ | ||||
| 			get; | ||||
| 			set; | ||||
| 			get | ||||
| 			{ | ||||
| 				return _ctx.PackageManager.GetApplicationIcon(_package); | ||||
| 			} | ||||
| 		} | ||||
|  | ||||
| 		public string Package | ||||
| @@ -104,7 +115,7 @@ namespace keepass2android | ||||
| 			holder.txtTitle.Text = item.Label; | ||||
| 			holder.txtVersion.Text = item.Version; | ||||
| 			holder.txtEnabledStatus.Text = item.EnabledStatus; | ||||
| 			holder.imgIcon.SetImageResource(item.Icon); | ||||
| 			holder.imgIcon.SetImageDrawable(item.Icon); | ||||
|  | ||||
| 			return row; | ||||
| 		} | ||||
|   | ||||
| @@ -125,6 +125,18 @@ namespace keepass2android | ||||
|  | ||||
| 		public bool IsValidAccessToken(string pluginPackage, string accessToken, string scope) | ||||
| 		{ | ||||
| 			if (pluginPackage == null) | ||||
| 			{ | ||||
| 				Log.Warn(_tag, "No pluginPackage specified!"); | ||||
| 				return false; | ||||
| 			} | ||||
|  | ||||
| 			if (accessToken == null) | ||||
| 			{ | ||||
| 				Log.Warn(_tag, "No accessToken specified!"); | ||||
| 				return false; | ||||
| 			}  | ||||
|  | ||||
| 			var prefs = GetPreferencesForPlugin(pluginPackage); | ||||
| 			if (prefs.GetString(_accessToken, null) != accessToken) | ||||
| 			{ | ||||
|   | ||||
| @@ -96,7 +96,7 @@ namespace PluginHostTest | ||||
| 				FindViewById<TextView>(resourceId).Visibility = ViewStates.Gone; | ||||
| 		} | ||||
|  | ||||
| 		private static string GetStringFromPlugin(Resources pluginRes, string pluginPackage, string stringId) | ||||
| 		public static string GetStringFromPlugin(Resources pluginRes, string pluginPackage, string stringId) | ||||
| 		{ | ||||
| 			int titleId = pluginRes.GetIdentifier(pluginPackage + ":string/"+stringId, null, null); | ||||
| 			string title = null; | ||||
|   | ||||
| @@ -1,8 +1,9 @@ | ||||
| using System; | ||||
| using System.Collections.Generic; | ||||
| using System.IO; | ||||
| using System.Linq; | ||||
| using System.Text; | ||||
|  | ||||
| using System.Xml.Linq; | ||||
| using Android.App; | ||||
| using Android.Content; | ||||
| using Android.Content.PM; | ||||
| @@ -11,9 +12,12 @@ using Android.Runtime; | ||||
| using Android.Util; | ||||
| using Android.Views; | ||||
| using Android.Widget; | ||||
|  | ||||
| using KeePassLib; | ||||
| using KeePassLib.Serialization; | ||||
| using KeePassLib.Utility; | ||||
| using Keepass2android; | ||||
| using Keepass2android.Pluginsdk; | ||||
| using Org.Json; | ||||
| using PluginHostTest; | ||||
|  | ||||
| namespace keepass2android | ||||
| @@ -26,7 +30,7 @@ namespace keepass2android | ||||
| 		private const string _tag = "KP2A_PluginHost"; | ||||
| 		 | ||||
|  | ||||
| 		private static readonly string[] _validScopes = { Strings.ScopeDatabaseActions }; | ||||
| 		private static readonly string[] _validScopes = { Strings.ScopeDatabaseActions, Strings.ScopeCurrentEntry }; | ||||
|  | ||||
| 		public static void TriggerRequests(Context ctx) | ||||
| 		{ | ||||
| @@ -138,6 +142,34 @@ namespace keepass2android | ||||
| 			return true; | ||||
| 		} | ||||
|  | ||||
| 		 | ||||
| 		public static void AddEntryToIntent(Intent intent, PwEntry entry) | ||||
| 		{ | ||||
| 			/*//add the entry XML | ||||
| 			not yet implemented. What to do with attachments? | ||||
| 			MemoryStream memStream = new MemoryStream(); | ||||
| 			KdbxFile.WriteEntries(memStream, new[] {entry}); | ||||
| 			string entryData = StrUtil.Utf8.GetString(memStream.ToArray()); | ||||
| 			intent.PutExtra(Strings.ExtraEntryData, entryData); | ||||
| 			*/ | ||||
| 			//add the compiled string array (placeholders replaced taking into account the db context) | ||||
| 			Dictionary<string, string> compiledFields = new Dictionary<string, string>(); | ||||
| 			foreach (var pair in entry.Strings) | ||||
| 			{ | ||||
| 				String key = pair.Key; | ||||
|  | ||||
| 				String value = entry.Strings.ReadSafe(key); | ||||
| 				value = SprEngine.Compile(value, new SprContext(entry, App.Kp2A.GetDb().KpDatabase, SprCompileFlags.All)); | ||||
|  | ||||
| 				compiledFields.Add(StrUtil.SafeXmlString(pair.Key), value); | ||||
| 				 | ||||
| 			} | ||||
|  | ||||
| 			JSONObject json = new JSONObject(compiledFields); | ||||
| 			var jsonStr = json.ToString(); | ||||
| 			intent.PutExtra(Strings.ExtraCompiledEntryData, jsonStr); | ||||
|  | ||||
| 			intent.PutExtra(Strings.ExtraEntryId, entry.Uuid.ToHexString()); | ||||
|  | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
| @@ -56,24 +56,38 @@ | ||||
|   </ItemGroup> | ||||
|   <ItemGroup> | ||||
|     <Compile Include="Activity1.cs" /> | ||||
|     <Compile Include="App.cs" /> | ||||
|     <Compile Include="ClickView.cs" /> | ||||
|     <Compile Include="CopyToClipboardService.cs" /> | ||||
|     <Compile Include="EntryActivity.cs" /> | ||||
|     <Compile Include="EntryContentsView.cs" /> | ||||
|     <Compile Include="EntrySection.cs" /> | ||||
|     <Compile Include="EntryActivityClasses\ExtraStringView.cs" /> | ||||
|     <Compile Include="EntryActivityClasses\IPopupMenuItem.cs" /> | ||||
|     <Compile Include="EntryActivityClasses\IStringView.cs" /> | ||||
|     <Compile Include="Kp2aShortHelpView.cs" /> | ||||
|     <Compile Include="EntryActivityClasses\OpenBinaryPopupItem.cs" /> | ||||
|     <Compile Include="PluginDatabase.cs" /> | ||||
|     <Compile Include="PluginDetailsActivity.cs" /> | ||||
|     <Compile Include="PluginArrayAdapter.cs" /> | ||||
|     <Compile Include="PluginListActivity.cs" /> | ||||
|     <Compile Include="PluginHost.cs" /> | ||||
|     <Compile Include="EntryActivityClasses\PluginMenuOption.cs" /> | ||||
|     <Compile Include="EntryActivityClasses\PluginPopupMenuItem.cs" /> | ||||
|     <Compile Include="Resources\Resource.Designer.cs" /> | ||||
|     <Compile Include="Properties\AssemblyInfo.cs" /> | ||||
|     <Compile Include="SprCompileFlags.cs" /> | ||||
|     <Compile Include="SprContext.cs" /> | ||||
|     <Compile Include="SprEngine.cs" /> | ||||
|     <Compile Include="EntryActivityClasses\StandardStringView.cs" /> | ||||
|     <Compile Include="TextDrawable.cs" /> | ||||
|     <Compile Include="TextViewSelect.cs" /> | ||||
|     <Compile Include="TextWithHelp.cs" /> | ||||
|     <Compile Include="EntryActivityClasses\WriteBinaryToFilePopupItem.cs" /> | ||||
|   </ItemGroup> | ||||
|   <ItemGroup> | ||||
|     <TransformFile Include="Assets\DejaVuSansMono.ttf" /> | ||||
|     <TransformFile Include="Assets\fontawesome-webfont.ttf" /> | ||||
|     <AndroidAsset Include="Assets\DejaVuSansMono.ttf" /> | ||||
|     <AndroidAsset Include="Assets\fontawesome-webfont.ttf" /> | ||||
|     <None Include="Resources\AboutResources.txt" /> | ||||
|     <None Include="Assets\AboutAssets.txt" /> | ||||
|     <AndroidResource Include="Resources\Layout\plugin_list.xml"> | ||||
| @@ -93,6 +107,10 @@ | ||||
|     <TransformFile Include="Properties\AndroidManifest.xml" /> | ||||
|   </ItemGroup> | ||||
|   <ItemGroup> | ||||
|     <ProjectReference Include="..\KeePassLib2Android\KeePassLib2Android.csproj"> | ||||
|       <Project>{545B4A6B-8BBA-4FBE-92FC-4AC060122A54}</Project> | ||||
|       <Name>KeePassLib2Android</Name> | ||||
|     </ProjectReference> | ||||
|     <ProjectReference Include="..\PluginSdkBinding\PluginSdkBinding.csproj"> | ||||
|       <Project>{3da3911e-36de-465e-8f15-f1991b6437e5}</Project> | ||||
|       <Name>PluginSdkBinding</Name> | ||||
| @@ -567,6 +585,18 @@ | ||||
|   <ItemGroup> | ||||
|     <AndroidResource Include="Resources\Layout\entry_view.xml" /> | ||||
|   </ItemGroup> | ||||
|   <ItemGroup> | ||||
|     <AndroidResource Include="Resources\Drawable\vdots_holodark.png" /> | ||||
|   </ItemGroup> | ||||
|   <ItemGroup> | ||||
|     <AndroidResource Include="Resources\Drawable\vdots.png" /> | ||||
|   </ItemGroup> | ||||
|   <ItemGroup> | ||||
|     <AndroidResource Include="Resources\Drawable\ic_menu_copy_holo_light.png" /> | ||||
|   </ItemGroup> | ||||
|   <ItemGroup> | ||||
|     <AndroidResource Include="Resources\Menu\entry.xml" /> | ||||
|   </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. | ||||
|   | ||||
| @@ -14,6 +14,7 @@ namespace keepass2android | ||||
| 	public class PluginListActivity : ListActivity | ||||
| 	{ | ||||
| 		private PluginArrayAdapter _pluginArrayAdapter; | ||||
| 		private List<PluginItem> _items; | ||||
|  | ||||
| 		protected override void OnCreate(Bundle bundle) | ||||
| 		{ | ||||
| @@ -22,31 +23,35 @@ namespace keepass2android | ||||
| 			//TODO _design.ApplyTheme(); | ||||
|  | ||||
| 			SetContentView(Resource.Layout.plugin_list); | ||||
| 			 | ||||
| 			ListView listView = FindViewById<ListView>(Android.Resource.Id.List); | ||||
| 			listView.ItemClick += | ||||
| 				(sender, args) => | ||||
| 					{ | ||||
| 						Intent i = new Intent(this, typeof(PluginDetailsActivity)); | ||||
| 						i.PutExtra("PluginPackage", _items[args.Position].Package); | ||||
| 						StartActivity(i); | ||||
| 					}; | ||||
| 			 | ||||
| 			// Create your application here | ||||
| 		} | ||||
| 		protected override void OnResume() | ||||
| 		{ | ||||
| 			base.OnResume(); | ||||
| 			PluginDatabase pluginDb = new PluginDatabase(this); | ||||
|  | ||||
| 			List<PluginItem> items = (from pluginPackage in pluginDb.GetAllPluginPackages() | ||||
| 			                          let version = PackageManager.GetPackageInfo(pluginPackage, 0).VersionName | ||||
| 									  let enabledStatus = pluginDb.IsEnabled(pluginPackage) ? GetString(Resource.String.plugin_enabled) : GetString(Resource.String.plugin_disabled) | ||||
| 			                          select new PluginItem(pluginPackage, "the plugin", Resource.Drawable.Icon, version, enabledStatus)).ToList(); | ||||
| 			_items = (from pluginPackage in pluginDb.GetAllPluginPackages() | ||||
| 			          let version = PackageManager.GetPackageInfo(pluginPackage, 0).VersionName | ||||
| 			          let enabledStatus = pluginDb.IsEnabled(pluginPackage) ? GetString(Resource.String.plugin_enabled) : GetString(Resource.String.plugin_disabled) | ||||
| 			          select new PluginItem(pluginPackage, enabledStatus, this)).ToList(); | ||||
| 			/* | ||||
| 				{ | ||||
| 					new PluginItem("PluginA", Resource.Drawable.Icon, "keepass2android.plugina", "connected"), | ||||
| 					new PluginItem("KeepassNFC", Resource.Drawable.Icon, "com.bla.blubb.plugina", "disconnected") | ||||
| 				}; | ||||
| 			 * */ | ||||
| 			_pluginArrayAdapter = new PluginArrayAdapter(this, Resource.Layout.ListViewPluginRow, items); | ||||
| 			_pluginArrayAdapter = new PluginArrayAdapter(this, Resource.Layout.ListViewPluginRow, _items); | ||||
| 			ListAdapter = _pluginArrayAdapter; | ||||
|  | ||||
| 			ListView listView = FindViewById<ListView>(Android.Resource.Id.List); | ||||
| 			listView.ItemClick += | ||||
| 				(sender, args) => | ||||
| 					{ | ||||
| 						Intent i = new Intent(this, typeof(PluginDetailsActivity)); | ||||
| 						i.PutExtra("PluginPackage", items[args.Position].Package); | ||||
| 						StartActivity(i); | ||||
| 					}; | ||||
| 			 | ||||
| 			// Create your application here | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 199 B | 
							
								
								
									
										
											BIN
										
									
								
								src/PluginHostTest/Resources/Drawable/vdots.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								src/PluginHostTest/Resources/Drawable/vdots.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 319 B | 
							
								
								
									
										
											BIN
										
									
								
								src/PluginHostTest/Resources/Drawable/vdots_holodark.png
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								src/PluginHostTest/Resources/Drawable/vdots_holodark.png
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 309 B | 
| @@ -1,7 +1,12 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <TextView xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     android:layout_width="wrap_content" | ||||
|     android:layout_height="wrap_content" | ||||
|     android:text="Title" | ||||
|     android:layout_marginLeft="10dp" | ||||
|     style="@style/ExtraFieldHeader" /> | ||||
| <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" | ||||
| 			  android:id="@+id/extra_title_container" | ||||
| android:layout_width="fill_parent" | ||||
| android:layout_height="wrap_content"> | ||||
| 	<TextView | ||||
| 		android:id="@+id/entry_title" | ||||
| 		android:layout_width="fill_parent" | ||||
| 		android:layout_height="wrap_content" | ||||
| 		android:text="Title" | ||||
| 		style="@style/EntryFieldHeader" /> | ||||
| </LinearLayout> | ||||
| @@ -1,8 +1,26 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <TextView xmlns:android="http://schemas.android.com/apk/res/android" | ||||
|     android:layout_width="fill_parent" | ||||
|     android:layout_height="wrap_content" | ||||
|     android:typeface="monospace" | ||||
|     android:text="Value" | ||||
|     android:layout_marginLeft="30dp" | ||||
|     style="@style/EntryItem" /> | ||||
| <RelativeLayout  | ||||
| 			xmlns:android="http://schemas.android.com/apk/res/android" | ||||
| 			android:id="@+id/extra_container" | ||||
| 			android:layout_height="wrap_content"	 | ||||
| 			android:layout_width="fill_parent" | ||||
| 			android:orientation="horizontal" | ||||
| 			android:clickable="true" | ||||
| 			android:background="?android:attr/selectableItemBackground"> | ||||
| 	<ImageView | ||||
| 		android:id="@+id/extra_vdots" | ||||
| 		android:layout_width="wrap_content" | ||||
| 		android:layout_height="15dp" | ||||
| 			   android:src="@drawable/vdots" | ||||
| 			   android:gravity="right|bottom" | ||||
| 			   android:layout_alignParentRight="true" | ||||
| 			   android:layout_alignParentBottom="true" | ||||
| 				   /> | ||||
| 	<TextView | ||||
| 		android:id="@+id/entry_extra" | ||||
| 		android:layout_width="fill_parent" | ||||
| 		android:layout_height="wrap_content" | ||||
| 		android:typeface="monospace" | ||||
| 		android:layout_toLeftOf="@id/extra_vdots" | ||||
| 		style="@style/EntryItem" /> | ||||
| </RelativeLayout> | ||||
| @@ -5,162 +5,260 @@ | ||||
|     android:layout_width="fill_parent" | ||||
|     android:orientation="vertical"> | ||||
|  | ||||
| 	<!-- Username --> | ||||
| 	<TextView | ||||
|         android:id="@+id/entry_user_name_label" | ||||
|         android:layout_width="fill_parent" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:text="@string/entry_user_name" | ||||
|         style="@style/EntryFieldHeader" | ||||
|  | ||||
| 	<LinearLayout android:id="@+id/entryfield_container_username" | ||||
| 		android:layout_height="wrap_content" | ||||
| 		android:layout_width="fill_parent" | ||||
| 		android:orientation="vertical"> | ||||
|  | ||||
| 		<TextView | ||||
| 			android:id="@+id/entry_user_name_label" | ||||
| 			android:layout_width="fill_parent" | ||||
| 			android:layout_height="wrap_content" | ||||
| 			android:text="@string/entry_user_name" | ||||
| 			 | ||||
| 			style="@style/EntryFieldHeader" | ||||
|          /> | ||||
| 	<TextView | ||||
|         android:id="@+id/entry_user_name" | ||||
|         android:layout_width="fill_parent" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:textIsSelectable="true" | ||||
|         style="@style/EntryItem" /> | ||||
| 	<!--  URL --> | ||||
| 	<TextView | ||||
|         android:id="@+id/entry_url_label" | ||||
|         android:layout_width="fill_parent" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:text="@string/entry_url" | ||||
|         style="@style/EntryFieldHeader" | ||||
|          /> | ||||
| 	<TextView | ||||
|         android:id="@+id/entry_url" | ||||
|         android:layout_width="fill_parent" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:autoLink="all" | ||||
|         android:textIsSelectable="true" | ||||
|         style="@style/EntryItem" /> | ||||
| 	<!-- Password --> | ||||
| 	<TextView | ||||
|         android:id="@+id/entry_password_label" | ||||
|         android:layout_width="fill_parent" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:text="@string/entry_password" | ||||
|         style="@style/EntryFieldHeader" | ||||
|          /> | ||||
| 	<TextView | ||||
|         android:id="@+id/entry_password" | ||||
|         android:layout_width="fill_parent" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:password="true" | ||||
|         android:textIsSelectable="true" | ||||
|         android:typeface="monospace" | ||||
|         style="@style/EntryItem" /> | ||||
| 	<!-- Comment --> | ||||
| 	<TextView | ||||
|         android:id="@+id/entry_comment_label" | ||||
|         android:layout_width="fill_parent" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:text="@string/entry_comment" | ||||
|         style="@style/EntryFieldHeader" | ||||
|          /> | ||||
| 	<TextView | ||||
|         android:id="@+id/entry_comment" | ||||
|         android:layout_width="fill_parent" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:textIsSelectable="true" | ||||
|         style="@style/EntryItem" /> | ||||
|  | ||||
| 		<!-- Username --> | ||||
| 		<RelativeLayout android:id="@+id/username_container" | ||||
| 					  android:layout_height="wrap_content" | ||||
| 		android:layout_width="fill_parent" | ||||
| 		android:orientation="horizontal" | ||||
| 		android:clickable="true" | ||||
| 		android:background="?android:attr/selectableItemBackground"> | ||||
|  | ||||
|  | ||||
| 	<TextView | ||||
|         android:id="@+id/entry_extra_strings_label" | ||||
|         android:layout_width="fill_parent" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:text="@string/entry_extra_strings" | ||||
|         style="@style/EntryFieldHeader" | ||||
|          /> | ||||
| 	<LinearLayout | ||||
|         android:id="@+id/extra_strings" | ||||
|         android:layout_width="fill_parent" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:layout_marginLeft="12dp" | ||||
|         android:layout_marginRight="12dp" | ||||
|         android:orientation="vertical" /> | ||||
| 	<!-- file attachments --> | ||||
| 	<TextView | ||||
|         android:id="@+id/entry_binaries_label" | ||||
|         android:layout_width="fill_parent" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:text="@string/entry_binaries" | ||||
|         style="@style/EntryFieldHeader" | ||||
|          /> | ||||
| 	<LinearLayout | ||||
|         android:id="@+id/binaries" | ||||
|         android:layout_width="fill_parent" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:orientation="vertical" /> | ||||
| 	<!--Tags --> | ||||
| 	<TextView | ||||
|         android:id="@+id/entry_tags_label" | ||||
|         android:layout_width="fill_parent" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:text="@string/entry_tags" | ||||
|         style="@style/EntryFieldHeader" | ||||
|          /> | ||||
| 	<TextView | ||||
|         android:id="@+id/entry_tags" | ||||
|         android:layout_width="fill_parent" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:textIsSelectable="true" | ||||
|         style="@style/EntryItem" /> | ||||
| 	<!--Override URL--> | ||||
| 	<TextView | ||||
|         android:id="@+id/entry_override_url_label" | ||||
|         android:layout_width="fill_parent" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:text="@string/entry_override_url" | ||||
|         style="@style/EntryFieldHeader" | ||||
|          /> | ||||
| 	<TextView | ||||
|         android:id="@+id/entry_override_url" | ||||
|         android:layout_width="fill_parent" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:autoLink="all" | ||||
|         android:textIsSelectable="true" | ||||
|         style="@style/EntryItem" /> | ||||
| 			<ImageView | ||||
| 				android:id="@+id/username_vdots" | ||||
| 				android:layout_width="wrap_content" | ||||
| 				android:layout_height="15dp" | ||||
| 					   android:src="@drawable/vdots" | ||||
| 					   android:gravity="right|bottom" | ||||
| 					   android:layout_alignParentRight="true" | ||||
| 					   android:layout_alignParentBottom="true" | ||||
| 				   /> | ||||
| 			<TextView | ||||
| 				android:id="@+id/entry_user_name" | ||||
| 				android:layout_width="fill_parent" | ||||
| 				android:layout_height="wrap_content" | ||||
| 				android:layout_toLeftOf="@id/username_vdots" | ||||
| 				style="@style/EntryItem" /> | ||||
| 		</RelativeLayout> | ||||
| 	</LinearLayout> | ||||
|  | ||||
| 	<!-- Created --> | ||||
| 	<TextView | ||||
|         android:id="@+id/entry_created_label" | ||||
|         android:layout_width="fill_parent" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:text="@string/entry_created" | ||||
|         style="@style/EntryFieldHeader" | ||||
| 	<LinearLayout android:id="@+id/entryfield_container_url" | ||||
| 		android:layout_height="wrap_content" | ||||
| 		android:layout_width="fill_parent" | ||||
| 		android:orientation="vertical"> | ||||
|  | ||||
| 		<!--  URL --> | ||||
| 		<TextView | ||||
| 			android:id="@+id/entry_url_label" | ||||
| 			android:layout_width="fill_parent" | ||||
| 			android:layout_height="wrap_content" | ||||
| 			android:text="@string/entry_url" | ||||
| 			style="@style/EntryFieldHeader" | ||||
| 			/> | ||||
| 		<RelativeLayout android:id="@+id/url_container" | ||||
| 						  android:layout_height="wrap_content" | ||||
| 				android:layout_width="fill_parent" | ||||
| 				android:orientation="horizontal" | ||||
| 				android:clickable="true" | ||||
| 				android:background="?android:attr/selectableItemBackground"> | ||||
| 			<ImageView | ||||
| 				android:id="@+id/url_vdots" | ||||
| 				android:layout_width="wrap_content" | ||||
| 				android:layout_height="15dp" | ||||
| 					   android:src="@drawable/vdots" | ||||
| 					   android:gravity="right|bottom" | ||||
| 					   android:layout_alignParentRight="true" | ||||
| 					   android:layout_alignParentBottom="true" | ||||
| 				   /> | ||||
| 			<TextView | ||||
| 				android:id="@+id/entry_url" | ||||
| 				android:layout_width="fill_parent" | ||||
| 				android:layout_height="wrap_content" | ||||
| 				android:autoLink="all" | ||||
| 				android:layout_toLeftOf="@id/url_vdots" | ||||
| 				style="@style/EntryItem" /> | ||||
| 		</RelativeLayout> | ||||
| 	</LinearLayout> | ||||
| 	<LinearLayout android:id="@+id/entryfield_container_password" | ||||
| 		android:layout_height="wrap_content" | ||||
| 		android:layout_width="fill_parent" | ||||
| 		android:orientation="vertical"> | ||||
|  | ||||
| 		<!-- Password --> | ||||
| 		<TextView | ||||
| 			android:id="@+id/entry_password_label" | ||||
| 			android:layout_width="fill_parent" | ||||
| 			android:layout_height="wrap_content" | ||||
| 			android:text="@string/entry_password" | ||||
| 			style="@style/EntryFieldHeader" | ||||
|          /> | ||||
| 	<TextView | ||||
|         android:id="@+id/entry_created" | ||||
|         android:layout_width="fill_parent" | ||||
|         android:layout_height="wrap_content" | ||||
|         style="@style/EntryItem" /> | ||||
| 	<!-- Modified --> | ||||
| 	<TextView | ||||
|         android:id="@+id/entry_modified_label" | ||||
|         android:layout_width="fill_parent" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:text="@string/entry_modified" | ||||
|         style="@style/EntryFieldHeader" | ||||
| 		<RelativeLayout android:id="@+id/password_container" | ||||
| 						  android:layout_height="wrap_content" | ||||
| 				android:layout_width="fill_parent" | ||||
| 				android:orientation="horizontal" | ||||
| 				android:clickable="true" | ||||
| 				android:background="?android:attr/selectableItemBackground"> | ||||
| 			<ImageView | ||||
| 				android:id="@+id/password_vdots" | ||||
| 				android:layout_width="wrap_content" | ||||
| 				android:layout_height="15dp" | ||||
| 					   android:src="@drawable/vdots" | ||||
| 					   android:gravity="right|bottom" | ||||
| 					   android:layout_alignParentRight="true" | ||||
| 					   android:layout_alignParentBottom="true" | ||||
| 				   /> | ||||
| 			<TextView | ||||
| 				android:id="@+id/entry_password" | ||||
| 				android:layout_width="fill_parent" | ||||
| 				android:layout_height="wrap_content" | ||||
| 				android:password="true" | ||||
| 				android:typeface="monospace" | ||||
| 				android:layout_toLeftOf="@id/password_vdots" | ||||
| 				style="@style/EntryItem" /> | ||||
| 		</RelativeLayout> | ||||
| 	</LinearLayout> | ||||
| 	<LinearLayout android:id="@+id/entryfield_container_comment" | ||||
| 		android:layout_height="wrap_content" | ||||
| 		android:layout_width="fill_parent" | ||||
| 		android:orientation="vertical"> | ||||
|  | ||||
| 		<!-- Comment --> | ||||
| 		<TextView | ||||
| 			android:id="@+id/entry_comment_label" | ||||
| 			android:layout_width="fill_parent" | ||||
| 			android:layout_height="wrap_content" | ||||
| 			android:text="@string/entry_comment" | ||||
| 			style="@style/EntryFieldHeader" | ||||
|          /> | ||||
| 	<TextView | ||||
|         android:id="@+id/entry_modified" | ||||
|         android:layout_width="fill_parent" | ||||
|         android:layout_height="wrap_content" | ||||
|         style="@style/EntryItem" /> | ||||
| 	<!-- Expires --> | ||||
| 	<TextView | ||||
|         android:id="@+id/entry_expires_label" | ||||
|         android:layout_width="fill_parent" | ||||
|         android:layout_height="wrap_content" | ||||
|         android:text="@string/entry_expires" | ||||
|         style="@style/EntryFieldHeader" | ||||
| 		<TextView | ||||
| 			android:id="@+id/entry_comment" | ||||
| 			android:layout_width="fill_parent" | ||||
| 			android:layout_height="wrap_content" | ||||
| 			android:textIsSelectable="true" | ||||
| 			style="@style/EntryItem" /> | ||||
| 	</LinearLayout> | ||||
|  | ||||
| 		<LinearLayout | ||||
| 			android:id="@+id/extra_strings" | ||||
| 			android:layout_width="fill_parent" | ||||
| 			android:layout_height="wrap_content" | ||||
| 			android:layout_marginTop="8dp" | ||||
| 			android:orientation="vertical" /> | ||||
| 		<!-- file attachments --> | ||||
| 		<TextView | ||||
| 			android:id="@+id/entry_binaries_label" | ||||
| 			android:layout_width="fill_parent" | ||||
| 			android:layout_height="wrap_content" | ||||
| 			android:text="@string/entry_binaries" | ||||
| 			style="@style/EntryFieldHeader" | ||||
|          /> | ||||
| 	<TextView | ||||
|         android:id="@+id/entry_expires" | ||||
|         android:layout_width="fill_parent" | ||||
|         android:layout_height="wrap_content" | ||||
|         style="@style/EntryItem" /> | ||||
| 	<!-- Property Change Conflict | id:@+id/entry_url_label --> | ||||
| 		<LinearLayout | ||||
| 			android:id="@+id/binaries" | ||||
| 			android:layout_width="fill_parent" | ||||
| 			android:layout_height="wrap_content" | ||||
| 			android:orientation="vertical" /> | ||||
| 		<!--Tags --> | ||||
| 	<LinearLayout android:id="@+id/entryfield_container_tags" | ||||
| 		android:layout_height="wrap_content" | ||||
| 		android:layout_width="fill_parent" | ||||
| 		android:orientation="vertical"> | ||||
|  | ||||
| 		<TextView | ||||
| 			android:id="@+id/entry_tags_label" | ||||
| 			android:layout_width="fill_parent" | ||||
| 			android:layout_height="wrap_content" | ||||
| 			android:text="@string/entry_tags" | ||||
| 			style="@style/EntryFieldHeader" | ||||
|          /> | ||||
| 		<TextView | ||||
| 			android:id="@+id/entry_tags" | ||||
| 			android:layout_width="fill_parent" | ||||
| 			android:layout_height="wrap_content" | ||||
| 			android:textIsSelectable="true" | ||||
| 			style="@style/EntryItem" /> | ||||
| 	</LinearLayout> | ||||
| 	<LinearLayout android:id="@+id/entryfield_container_overrideurl" | ||||
| 		android:layout_height="wrap_content" | ||||
| 		android:layout_width="fill_parent" | ||||
| 		android:orientation="vertical"> | ||||
|  | ||||
| 		<!--Override URL--> | ||||
| 		<TextView | ||||
| 			android:id="@+id/entry_override_url_label" | ||||
| 			android:layout_width="fill_parent" | ||||
| 			android:layout_height="wrap_content" | ||||
| 			android:text="@string/entry_override_url" | ||||
| 			style="@style/EntryFieldHeader" | ||||
|          /> | ||||
| 		<TextView | ||||
| 			android:id="@+id/entry_override_url" | ||||
| 			android:layout_width="fill_parent" | ||||
| 			android:layout_height="wrap_content" | ||||
| 			android:autoLink="all" | ||||
| 			android:textIsSelectable="true" | ||||
| 			style="@style/EntryItem" /> | ||||
| 	</LinearLayout> | ||||
| 	<LinearLayout android:id="@+id/entryfield_container_created" | ||||
| 		android:layout_height="wrap_content" | ||||
| 		android:layout_width="fill_parent" | ||||
| 		android:orientation="vertical"> | ||||
|  | ||||
|  | ||||
| 		<!-- Created --> | ||||
| 		<TextView | ||||
| 			android:id="@+id/entry_created_label" | ||||
| 			android:layout_width="fill_parent" | ||||
| 			android:layout_height="wrap_content" | ||||
| 			android:text="@string/entry_created" | ||||
| 			style="@style/EntryFieldHeader" | ||||
|          /> | ||||
| 		<TextView | ||||
| 			android:id="@+id/entry_created" | ||||
| 			android:layout_width="fill_parent" | ||||
| 			android:layout_height="wrap_content" | ||||
| 			style="@style/EntryItem" /> | ||||
| 	</LinearLayout> | ||||
| 	<LinearLayout android:id="@+id/entryfield_container_modified" | ||||
| 		android:layout_height="wrap_content" | ||||
| 		android:layout_width="fill_parent" | ||||
| 		android:orientation="vertical"> | ||||
|  | ||||
| 		<!-- Modified --> | ||||
| 		<TextView | ||||
| 			android:id="@+id/entry_modified_label" | ||||
| 			android:layout_width="fill_parent" | ||||
| 			android:layout_height="wrap_content" | ||||
| 			android:text="@string/entry_modified" | ||||
| 			style="@style/EntryFieldHeader" | ||||
|          /> | ||||
| 		<TextView | ||||
| 			android:id="@+id/entry_modified" | ||||
| 			android:layout_width="fill_parent" | ||||
| 			android:layout_height="wrap_content" | ||||
| 			style="@style/EntryItem" /> | ||||
| 	</LinearLayout> | ||||
| 	<LinearLayout android:id="@+id/entryfield_container_expires" | ||||
| 		android:layout_height="wrap_content" | ||||
| 		android:layout_width="fill_parent" | ||||
| 		android:orientation="vertical"> | ||||
|  | ||||
| 		<!-- Expires --> | ||||
| 		<TextView | ||||
| 			android:id="@+id/entry_expires_label" | ||||
| 			android:layout_width="fill_parent" | ||||
| 			android:layout_height="wrap_content" | ||||
| 			android:text="@string/entry_expires" | ||||
| 			style="@style/EntryFieldHeader" | ||||
|          /> | ||||
| 		<TextView | ||||
| 			android:id="@+id/entry_expires" | ||||
| 			android:layout_width="fill_parent" | ||||
| 			android:layout_height="wrap_content" | ||||
| 			style="@style/EntryItem" /> | ||||
| 	</LinearLayout> | ||||
| </LinearLayout> | ||||
							
								
								
									
										54
									
								
								src/PluginHostTest/Resources/Menu/entry.xml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								src/PluginHostTest/Resources/Menu/entry.xml
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,54 @@ | ||||
| <?xml version="1.0" encoding="utf-8"?> | ||||
| <!-- | ||||
|  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/>. | ||||
| --> | ||||
| <menu xmlns:android="http://schemas.android.com/apk/res/android"> | ||||
|     <item android:id="@+id/menu_donate" | ||||
|         android:icon="@android:drawable/ic_menu_share" | ||||
|         android:title="@string/menu_donate" | ||||
|     /> | ||||
|     <item android:id="@+id/menu_toggle_pass" | ||||
|         android:icon="@android:drawable/ic_menu_view" | ||||
|         android:title="@string/show_password" | ||||
|     /> | ||||
|     <item android:id="@+id/menu_goto_url" | ||||
|         android:icon="@android:drawable/ic_menu_upload" | ||||
|         android:title="@string/menu_url" | ||||
|     /> | ||||
|     <!--<item android:id="@+id/menu_copy_user" | ||||
|         android:icon="@android:drawable/ic_menu_set_as" | ||||
|         android:title="@string/menu_copy_user" | ||||
|     /> | ||||
|     <item android:id="@+id/menu_copy_pass" | ||||
|         android:icon="@android:drawable/ic_menu_agenda" | ||||
|         android:title="@string/menu_copy_pass" | ||||
|     />--> | ||||
|     <item android:id="@+id/menu_lock" | ||||
|         android:icon="@android:drawable/ic_lock_lock" | ||||
|         android:title="@string/menu_lock" | ||||
|     /> | ||||
|     <item android:id="@+id/menu_suggest_improvements" | ||||
|         android:icon="@android:drawable/ic_menu_directions" | ||||
|         android:title="@string/suggest_improvements" | ||||
|     /> | ||||
|     <item android:id="@+id/menu_rate" | ||||
|         android:icon="@android:drawable/star_off" | ||||
|         android:title="@string/rate_app" | ||||
|     /> | ||||
|     <item android:id="@+id/menu_translate" | ||||
|         android:title="@string/translate_app" | ||||
|        /> | ||||
| </menu> | ||||
| @@ -54,7 +54,7 @@ | ||||
|         <item name="android:layout_marginRight">12dip</item> | ||||
|         <item name="android:paddingLeft">4dp</item> | ||||
|         <item name="android:textColor">?android:attr/textColorSecondary</item> | ||||
|         <item name="android:textSize">18sp</item> | ||||
|         <item name="android:textSize">16sp</item> | ||||
|      | ||||
| 	</style> | ||||
| 	<style name="EntryFieldHeader"> | ||||
| @@ -63,11 +63,11 @@ | ||||
|         <item name="android:layout_marginLeft">12dip</item> | ||||
|         <item name="android:layout_marginRight">12dip</item> | ||||
|         <item name="android:layout_marginBottom">3dp</item> | ||||
|         <item name="android:layout_marginTop">8dp</item> | ||||
|         <item name="android:layout_marginTop">14dp</item> | ||||
|         <item name="android:paddingLeft">4dp</item> | ||||
|         <item name="android:textAllCaps">true</item> | ||||
|         <item name="android:textColor">?android:attr/textColorPrimary</item> | ||||
|         <item name="android:textSize">18sp</item> | ||||
|         <item name="android:textSize">16sp</item> | ||||
|         <item name="android:textStyle">bold</item> | ||||
|     </style> | ||||
|     | ||||
|   | ||||
| @@ -8,6 +8,6 @@ | ||||
| 	<string name="SCOPE_DATABASE_ACTIONS_explanation">Plugin will be notified when a database is opened, closed or saved.</string> | ||||
|  | ||||
| 	<string name="SCOPE_CURRENT_ENTRY_title">Current entry data</string> | ||||
| 	<string name="SCOPE_CURRENT_ENTRY_explanation">Plugin will receive all data about the current database entry and will be allowed to offer actions on it.</string> | ||||
| 	<string name="SCOPE_CURRENT_ENTRY_explanation">Plugin will receive all data about the current database entry and will be allowed to offer actions and modify the display of it.</string> | ||||
|  | ||||
| </resources> | ||||
|   | ||||
							
								
								
									
										7
									
								
								src/PluginHostTest/SprCompileFlags.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								src/PluginHostTest/SprCompileFlags.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | ||||
| namespace keepass2android | ||||
| { | ||||
| 	public enum SprCompileFlags | ||||
| 	{ | ||||
| 		All | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										13
									
								
								src/PluginHostTest/SprContext.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								src/PluginHostTest/SprContext.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| using System; | ||||
| using KeePassLib; | ||||
|  | ||||
| namespace keepass2android | ||||
| { | ||||
| 	public class SprContext | ||||
| 	{ | ||||
| 		public SprContext(PwEntry entry, PwDatabase kpDatabase, object all) | ||||
| 		{ | ||||
| 			 | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										11
									
								
								src/PluginHostTest/SprEngine.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								src/PluginHostTest/SprEngine.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| namespace keepass2android | ||||
| { | ||||
| 	public class SprEngine | ||||
|  | ||||
| 	{ | ||||
| 		public static string Compile(string value, SprContext sprContext) | ||||
| 		{ | ||||
| 			return value; | ||||
| 		} | ||||
| 	} | ||||
| } | ||||
							
								
								
									
										56
									
								
								src/PluginHostTest/TextDrawable.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										56
									
								
								src/PluginHostTest/TextDrawable.cs
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,56 @@ | ||||
| using System; | ||||
| using Android.Content; | ||||
| using Android.Graphics; | ||||
| using Android.Graphics.Drawables; | ||||
|  | ||||
| namespace keepass2android | ||||
| { | ||||
| 	/// <summary> | ||||
| 	/// Shows text as a drawable. | ||||
| 	/// </summary> | ||||
| 	/// Based on http://stackoverflow.com/questions/3972445/how-to-put-text-in-a-drawable | ||||
| 	public class TextDrawable: Drawable { | ||||
|  | ||||
| 		private readonly String _text; | ||||
| 		private readonly Paint _paint; | ||||
| 		private static Typeface _iconFont; | ||||
|  | ||||
| 		public TextDrawable(String text, Context ctx) { | ||||
|  | ||||
| 			_text = text; | ||||
|  | ||||
|  | ||||
| 			if (_iconFont == null) | ||||
| 				_iconFont = Typeface.CreateFromAsset(ctx.Assets, "fontawesome-webfont.ttf"); | ||||
|  | ||||
| 			_paint = new Paint {Color = (Color.White), TextSize = 22f, AntiAlias = true}; | ||||
| 			//_paint.SetTypeface(_iconFont); | ||||
| 			_paint.SetShadowLayer(6f, 0, 0, Color.Black); | ||||
| 			_paint.SetStyle(Paint.Style.Fill); | ||||
| 			_paint.TextAlign = Paint.Align.Left; | ||||
| 		} | ||||
|  | ||||
| 		 | ||||
| 		public override void Draw(Canvas canvas) { | ||||
| 			canvas.DrawText("x"+_text, 0, 0, _paint); | ||||
| 		} | ||||
|  | ||||
| 		 | ||||
| 		public override void SetAlpha(int alpha) { | ||||
| 			_paint.Alpha = alpha; | ||||
| 		} | ||||
|  | ||||
|  | ||||
| 		public override void SetColorFilter(ColorFilter cf) | ||||
| 		{ | ||||
| 			_paint.SetColorFilter(cf); | ||||
| 		} | ||||
|  | ||||
| 		public override int Opacity | ||||
| 		{ | ||||
| 			get { return -3; /*translucent*/ } | ||||
| 		} | ||||
|  | ||||
| 		 | ||||
| 	} | ||||
| } | ||||
| @@ -1,5 +1,7 @@ | ||||
| package keepass2android.pluginsdk; | ||||
|  | ||||
| import java.lang.reflect.Field; | ||||
| import java.lang.reflect.Method; | ||||
| import java.util.ArrayList; | ||||
|  | ||||
| import org.json.JSONArray; | ||||
| @@ -10,10 +12,15 @@ import android.content.Intent; | ||||
| import android.content.SharedPreferences; | ||||
| import android.content.SharedPreferences.Editor; | ||||
| import android.preference.PreferenceManager; | ||||
| import android.text.TextUtils; | ||||
| import android.util.Log; | ||||
| import android.view.View; | ||||
| import android.widget.PopupMenu; | ||||
|  | ||||
|  | ||||
| public class AccessManager  | ||||
| { | ||||
| 	private static final String _tag = "Kp2aPluginSDK"; | ||||
| 	private static final String PREF_KEY_SCOPE = "scope"; | ||||
| 	private static final String PREF_KEY_TOKEN = "token"; | ||||
|  | ||||
| @@ -49,19 +56,40 @@ public class AccessManager | ||||
| 	public static void storeAccessToken(Context ctx, String hostPackage, String accessToken, ArrayList<String> scopes) | ||||
| 	{ | ||||
| 		 SharedPreferences prefs = getPrefsForHost(ctx, hostPackage); | ||||
| 		  | ||||
| 		 // | ||||
| 		 if (accessToken.equals(prefs.getString(PREF_KEY_TOKEN, ""))) | ||||
| 		 { | ||||
| 			 //token already available | ||||
| 			 return; | ||||
| 		 } | ||||
| 		  | ||||
| 		   | ||||
| 		 Editor edit = prefs.edit(); | ||||
| 		 edit.putString(PREF_KEY_TOKEN, accessToken); | ||||
| 		 edit.putString(PREF_KEY_SCOPE, stringArrayToString(scopes)); | ||||
| 		 String scopesString = stringArrayToString(scopes); | ||||
| 		 edit.putString(PREF_KEY_SCOPE, scopesString); | ||||
| 		 edit.commit(); | ||||
| 		 Log.d(_tag, "stored access token " + accessToken.substring(0, 4)+"... for "+scopes.size()+" scopes ("+scopesString+")."); | ||||
| 		  | ||||
| 		  | ||||
| 	} | ||||
| 	 | ||||
| 	public static void preparePopup(Object popupMenu) | ||||
| 	{ | ||||
| 		try | ||||
| 		{ | ||||
| 			Field[] fields = popupMenu.getClass().getDeclaredFields(); | ||||
| 			for (Field field : fields) { | ||||
| 				if ("mPopup".equals(field.getName())) { | ||||
| 					field.setAccessible(true); | ||||
| 					Object menuPopupHelper = field.get(popupMenu); | ||||
| 					Class<?> classPopupHelper = Class.forName(menuPopupHelper | ||||
| 							.getClass().getName()); | ||||
| 					Method setForceIcons = classPopupHelper.getMethod( | ||||
| 							"setForceShowIcon", boolean.class); | ||||
| 					setForceIcons.invoke(menuPopupHelper, true); | ||||
| 					break; | ||||
| 				} | ||||
| 			} | ||||
| 			 | ||||
| 		} | ||||
| 		catch (Exception e) | ||||
| 		{ | ||||
| 			e.printStackTrace(); | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	private static SharedPreferences getPrefsForHost(Context ctx, | ||||
| @@ -72,14 +100,22 @@ public class AccessManager | ||||
|  | ||||
| 	public static String tryGetAccessToken(Context ctx, String hostPackage, ArrayList<String> scopes) { | ||||
| 		 | ||||
| 		if (TextUtils.isEmpty(hostPackage)) | ||||
| 		{ | ||||
| 			Log.d(_tag, "hostPackage is empty!"); | ||||
| 			return null; | ||||
| 		} | ||||
| 		SharedPreferences prefs = getPrefsForHost(ctx, hostPackage); | ||||
| 		ArrayList<String> currentScope = stringToStringArray(prefs.getString(PREF_KEY_SCOPE, "")); | ||||
| 		String scopesString = prefs.getString(PREF_KEY_SCOPE, ""); | ||||
| 		Log.d(_tag, "scopes: "+ scopesString); | ||||
| 		ArrayList<String> currentScope = stringToStringArray(scopesString); | ||||
| 		if (isSubset(scopes, currentScope)) | ||||
| 		{ | ||||
| 			return prefs.getString(PREF_KEY_TOKEN, null); | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| 			Log.d(_tag, "looks like scope changed. Access token invalid."); | ||||
| 			return null; | ||||
| 		} | ||||
| 	} | ||||
| @@ -88,7 +124,10 @@ public class AccessManager | ||||
| 			ArrayList<String> availableScopes) { | ||||
| 		for (String r: requiredScopes){ | ||||
| 			if (availableScopes.indexOf(r)<0) | ||||
| 			{ | ||||
| 				Log.d(_tag, "Scope "+r+" not available. "+availableScopes.size()); | ||||
| 				return false; | ||||
| 			} | ||||
| 		} | ||||
| 		return true; | ||||
| 	} | ||||
| @@ -106,4 +145,15 @@ public class AccessManager | ||||
| 		} | ||||
| 	  | ||||
| 	} | ||||
|  | ||||
| 	/** | ||||
| 	 * Returns a valid access token or throws PluginAccessException | ||||
| 	 */ | ||||
| 	public static String getAccessToken(Context context, String hostPackage, | ||||
| 			ArrayList<String> scopes) throws PluginAccessException { | ||||
| 		String accessToken = tryGetAccessToken(context, hostPackage, scopes); | ||||
| 		if (accessToken == null) | ||||
| 			throw new PluginAccessException(hostPackage, scopes); | ||||
| 		return accessToken; | ||||
| 	} | ||||
| } | ||||
|   | ||||
| @@ -34,6 +34,8 @@ public abstract class PluginAccessBroadcastReceiver extends BroadcastReceiver { | ||||
| 	public void onReceive(Context ctx, Intent intent) { | ||||
| 		String action = intent.getAction(); | ||||
| 		android.util.Log.d("KP2A.pluginsdk", "received broadcast with action="+action); | ||||
| 		if (action == null) | ||||
| 			return; | ||||
| 		if (action.equals(Strings.ACTION_TRIGGER_REQUEST_ACCESS)) | ||||
| 		{ | ||||
| 			requestAccess(ctx, intent);	 | ||||
|   | ||||
| @@ -1,19 +1,114 @@ | ||||
| package keepass2android.pluginsdk; | ||||
|  | ||||
| public class Strings { | ||||
| 	/** | ||||
| 	 * Plugin is notified about actions like open/close/update a database. | ||||
| 	 */ | ||||
| 	public static final String SCOPE_DATABASE_ACTIONS = "keepass2android.SCOPE_DATABASE_ACTIONS"; | ||||
| 	/** | ||||
| 	 * Plugin is notified when an entry is opened.  | ||||
| 	 */ | ||||
| 	public static final String SCOPE_CURRENT_ENTRY = "keepass2android.SCOPE_CURRENT_ENTRY"; | ||||
| 	 | ||||
| 	/** | ||||
| 	 * Extra key to transfer a (json serialized) list of scopes | ||||
| 	 */ | ||||
| 	public static final String EXTRA_SCOPES = "keepass2android.EXTRA_SCOPES"; | ||||
| 	 | ||||
| 	/** | ||||
| 	 * Extra key for sending the package name of the sender of a broadcast. | ||||
| 	 * Should be set in every broadcast.  | ||||
| 	 */ | ||||
| 	public static final String EXTRA_SENDER = "keepass2android.EXTRA_SENDER"; | ||||
| 	 | ||||
| 	/** | ||||
| 	 * Extra key for sending a request token. The request token is passed from  | ||||
| 	 * KP2A to the plugin. It's used in the authorization process.  | ||||
| 	 */ | ||||
| 	public static final String EXTRA_REQUEST_TOKEN = "keepass2android.EXTRA_REQUEST_TOKEN"; | ||||
|  | ||||
| 	/** | ||||
| 	 * Action sent from KP2A to the plugin to indicate that the plugin should request | ||||
| 	 * access (sending it's scopes) | ||||
| 	 */ | ||||
| 	public static final String ACTION_TRIGGER_REQUEST_ACCESS = "keepass2android.ACTION_TRIGGER_REQUEST_ACCESS"; | ||||
| 	/**  | ||||
| 	 * Action sent from the plugin to KP2A including the scopes. | ||||
| 	 */ | ||||
| 	public static final String ACTION_REQUEST_ACCESS = "keepass2android.ACTION_REQUEST_ACCESS"; | ||||
| 	/** | ||||
| 	 * Action sent from the KP2A to the plugin when the user grants access. | ||||
| 	 * Will contain an access token. | ||||
| 	 */ | ||||
| 	public static final String ACTION_RECEIVE_ACCESS = "keepass2android.ACTION_RECEIVE_ACCESS"; | ||||
| 	/** | ||||
| 	 * Action sent from KP2A to the plugin to indicate that access is not or no longer valid. | ||||
| 	 */ | ||||
| 	public static final String ACTION_REVOKE_ACCESS = "keepass2android.ACTION_REVOKE_ACCESS"; | ||||
|  | ||||
| 	public static final String EXTRA_ACCESS_TOKEN = "EXTRA_ACCESS_TOKEN"; | ||||
| 	 | ||||
| 	//static final String SCOPE_DATABASE_ACTIONS = "keepass2android.SCOPE_DATABASE_ACTIONS"; | ||||
| 	/** | ||||
| 	 * Action sent from KP2A to the plugin to indicate that an entry was opened. | ||||
| 	 * The Intent contains the full entry data. | ||||
| 	 */ | ||||
| 	public static final String ACTION_OPEN_ENTRY= "keepass2android.ACTION_OPEN_ENTRY"; | ||||
| 	 | ||||
| 	/** | ||||
| 	 * Action sent from KP2A to the plugin to indicate that an entry activity was closed. | ||||
| 	 */ | ||||
| 	public static final String ACTION_CLOSE_ENTRY_VIEW= "keepass2android.ACTION_CLOSE_ENTRY_VIEW"; | ||||
| 	 | ||||
| 	/** | ||||
| 	 * Extra key for a string containing the GUID of the entry.  | ||||
| 	 */ | ||||
| 	public static final String EXTRA_ENTRY_ID= "keepass2android.EXTRA_ENTRY_DATA"; | ||||
| 	 | ||||
| 	/**  | ||||
| 	 * Json serialized data of the PwEntry (C# class) representing the opened entry. | ||||
| 	 * currently not implemented. | ||||
| 	 */ | ||||
| 	//public static final String EXTRA_ENTRY_DATA = "keepass2android.EXTRA_ENTRY_DATA"; | ||||
| 	 | ||||
| 	/** | ||||
| 	 * Json serialized list of fields, compiled using the database context (i.e. placeholders are replaced already) | ||||
| 	 */ | ||||
| 	public static final String EXTRA_COMPILED_ENTRY_DATA = "keepass2android.EXTRA_COMPILED_ENTRY_DATA"; | ||||
|  | ||||
| 	/** | ||||
| 	 * Extra key for passing the access token (both ways) | ||||
| 	 */ | ||||
| 	public static final String EXTRA_ACCESS_TOKEN = "keepass2android.EXTRA_ACCESS_TOKEN"; | ||||
| 	 | ||||
| 	/** | ||||
| 	 * Action for an intent from the plugin to KP2A to add menu options regarding the currently open entry. | ||||
| 	 * Requires SCOPE_CURRENT_ENTRY.  | ||||
| 	 */ | ||||
| 	public static final String ACTION_ADD_ENTRY_ACTION = "keepass2android.ACTION_ADD_ENTRY_ACTION"; | ||||
| 	 | ||||
| 	public static final String EXTRA_ACTION_DISPLAY_TEXT = "keepass2android.EXTRA_ACTION_DISPLAY_TEXT"; | ||||
| 	public static final String EXTRA_ACTION_ICON_RES_ID = "keepass2android.EXTRA_ACTION_ICON_RES_ID"; | ||||
|  | ||||
| 	public static final String EXTRA_FIELD_ID = "keepass2android.EXTRA_FIELD_ID"; | ||||
|  | ||||
| 	/** Extra for ACTION_ADD_ENTRY_ACTION and ACTION_ENTRY_ACTION_SELECTED to pass data specifying the action parameters.*/ | ||||
| 	public static final String EXTRA_ACTION_DATA = "keepass2android.EXTRA_ACTION_DATA"; | ||||
| 	 | ||||
| 	/** | ||||
| 	 * Action for an intent from KP2A to the plugin when an action added with ACTION_ADD_ENTRY_ACTION was selected by the user. | ||||
| 	 *  | ||||
| 	 */ | ||||
| 	public static final String ACTION_ENTRY_ACTION_SELECTED = "keepass2android.ACTION_ENTRY_ACTION_SELECTED"; | ||||
| 	 | ||||
| 	/** | ||||
| 	 * Action for an intent from the plugin to KP2A to set (i.e. add or update) a field in the entry. | ||||
| 	 * May be used to update existing or add new fields at any time while the entry is opened. | ||||
| 	 */ | ||||
| 	public static final String ACTION_SET_ENTRY_FIELD = "keepass2android.ACTION_SET_ENTRY_FIELD"; | ||||
| 	 | ||||
| 	public static final String EXTRA_FIELD_VALUE = "keepass2android.EXTRA_FIELD_VALUE"; | ||||
| 	public static final String EXTRA_FIELD_PROTECTED = "keepass2android.EXTRA_FIELD_PROTECTED"; | ||||
| 	 | ||||
| 	public static final String PREFIX_STRING = "STRING_"; | ||||
| 	public static final String PREFIX_BINARY = "BINARY_"; | ||||
| 	 | ||||
|  | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Philipp Crocoll
					Philipp Crocoll