diff --git a/src/keepass2android/GroupBaseActivity.cs b/src/keepass2android/GroupBaseActivity.cs index c6d70bb4..b4d323c2 100644 --- a/src/keepass2android/GroupBaseActivity.cs +++ b/src/keepass2android/GroupBaseActivity.cs @@ -1140,6 +1140,15 @@ namespace keepass2android public abstract ElementAndDatabaseId FullGroupId { get; } + public virtual bool MayPreviewTotp + { + get + { + return !PreferenceManager.GetDefaultSharedPreferences(this).GetBoolean(GetString(Resource.String.masktotp_key), + Resources.GetBoolean(Resource.Boolean.masktotp_default)); + } + } + public override bool OnPrepareOptionsMenu(IMenu menu) { diff --git a/src/keepass2android/search/SearchTotpResults.cs b/src/keepass2android/search/SearchTotpResults.cs new file mode 100644 index 00000000..59395782 --- /dev/null +++ b/src/keepass2android/search/SearchTotpResults.cs @@ -0,0 +1,162 @@ +/* +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 3 of the License, or + (at your option) any later version. + + Keepass2Android is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Keepass2Android. If not, see . + */ +using System; +using System.Linq; +using System.Text.RegularExpressions; +using Android.App; +using Android.Content; +using Android.Content.PM; +using Android.OS; +using Android.Preferences; +using Android.Views; +using Android.Widget; +using keepass2android.view; +using KeePassLib; + +namespace keepass2android.search +{ + /// + /// Activity to show search results + /// + [Activity(Label = "@string/app_name", Theme = "@style/MyTheme_ActionBar", LaunchMode = Android.Content.PM.LaunchMode.SingleTop, ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.Keyboard | ConfigChanges.KeyboardHidden)] + public class SearchTotpResults : GroupBaseActivity + { + + public static void Launch(Activity act, AppTask appTask, ActivityFlags? flags = null) + { + Intent i = new Intent(act, typeof(SearchTotpResults)); + + + if (flags != null) + i.SetFlags((ActivityFlags)flags); + + appTask.ToIntent(i); + if (flags != null && (((ActivityFlags)flags) | ActivityFlags.ForwardResult) == ActivityFlags.ForwardResult) + act.StartActivity(i); + else + act.StartActivityForResult(i, 0); + } + + public override bool MayPreviewTotp + { + get + { + return true; + } + } + + protected override void OnCreate (Bundle bundle) + { + base.OnCreate (bundle); + + if ( IsFinishing ) { + return; + } + + SetResult(KeePass.ExitNormal); + + // Likely the app has been killed exit the activity + if (!App.Kp2a.DatabaseIsUnlocked) + { + Finish(); + } + + Group = new PwGroup() + { + Name = GetString(Resource.String.TOTP) + }; + try + { + foreach (var db in App.Kp2a.OpenDatabases) + { + foreach (var entry in db.EntriesById.Values) + { + var totpData = new Kp2aTotp().TryGetTotpData(new PwEntryOutput(entry, db)); + if (totpData?.IsTotpEntry == true) + Group.AddEntry(entry, false); + } + + } + } + catch (Exception e) + { + Kp2aLog.LogUnexpectedError(e); + Toast.MakeText(this, e.Message, ToastLength.Long).Show(); + Finish(); + return; + } + + if (Group == null || (!Group.Entries.Any())) + { + SetContentView(Resource.Layout.group_empty); + } + + SetGroupTitle(); + + FragmentManager.FindFragmentById(Resource.Id.list_fragment).ListAdapter = new PwGroupListAdapter(this, Group); + + } + + public override bool EntriesBelongToCurrentDatabaseOnly + { + get { return false; } + } + + public override ElementAndDatabaseId FullGroupId + { + get { return null; } + } + + + + + + public override void OnCreateContextMenu(IContextMenu menu, View v, + IContextMenuContextMenuInfo menuInfo) + { + + AdapterView.AdapterContextMenuInfo acmi = (AdapterView.AdapterContextMenuInfo) menuInfo; + ClickView cv = (ClickView) acmi.TargetView; + cv.OnCreateMenu(menu, menuInfo); + } + + public override bool OnContextItemSelected(IMenuItem item) { + AdapterView.AdapterContextMenuInfo acmi = (AdapterView.AdapterContextMenuInfo)item.MenuInfo; + ClickView cv = (ClickView) acmi.TargetView; + + bool result; + + return cv.OnContextItemSelected(item); + } + + + public override bool OnSearchRequested() + { + Intent i = new Intent(this, typeof(SearchActivity)); + this.AppTask.ToIntent(i); + i.SetFlags(ActivityFlags.ForwardResult); + StartActivity(i); + return true; + } + + public override bool IsSearchResult + { + get { return true; } + } + } +} + diff --git a/src/keepass2android/views/PwEntryView.cs b/src/keepass2android/views/PwEntryView.cs index 177ef1de..fd5489e6 100644 --- a/src/keepass2android/views/PwEntryView.cs +++ b/src/keepass2android/views/PwEntryView.cs @@ -28,7 +28,8 @@ using Android.Preferences; using KeePass.Util.Spr; using KeeTrayTOTP.Libraries; using PluginTOTP; -using Microsoft.Graph; +using Android.Content; +using System.ComponentModel; namespace keepass2android.view @@ -92,6 +93,13 @@ namespace keepass2android.view _totpText = ev.FindViewById(Resource.Id.totp_text); _totpLayout = ev.FindViewById(Resource.Id.totp_layout); + _totpLayout.LongClick += (sender, args) => + { + string totp = UpdateTotp(); + if (!String.IsNullOrEmpty(totp)) + CopyToClipboardService.CopyValueToClipboardWithTimeout(_groupActivity, totp, true); + }; + _showDetail = PreferenceManager.GetDefaultSharedPreferences(groupActivity).GetBoolean( groupActivity.GetString(Resource.String.ShowUsernameInList_key), Resources.GetBoolean(Resource.Boolean.ShowUsernameInList_default)); @@ -200,16 +208,7 @@ namespace keepass2android.view UpdateTotp(); - if (_totpData?.IsTotpEntry == true) - { - _totpLayout.Visibility = ViewStates.Visible; - - - } - else - { - _totpLayout.Visibility = ViewStates.Gone; - } + @@ -283,14 +282,25 @@ namespace keepass2android.view private Database _db; - public void UpdateTotp() + public string UpdateTotp() { - - _totpData = new Kp2aTotp().TryGetTotpData(new PwEntryOutput(_entry, _db)); + ISharedPreferences prefs = PreferenceManager.GetDefaultSharedPreferences(_groupActivity); + bool showTotpDefault = _groupActivity.MayPreviewTotp; + + + if (showTotpDefault) + _totpData = new Kp2aTotp().TryGetTotpData(new PwEntryOutput(_entry, _db)); + else + _totpData = null; + + if (_totpData?.IsTotpEntry != true) + { + _totpLayout.Visibility = ViewStates.Gone; + return null; + } + + _totpLayout.Visibility = ViewStates.Visible; - if (_totpData == null) - return; - Kp2aLog.Log("UpdateTotp"); TOTPProvider prov = new TOTPProvider(_totpData); string totp = prov.GenerateByByte(_totpData.TotpSecret); @@ -298,6 +308,8 @@ namespace keepass2android.view var progressBar = _totpCountdown; progressBar.Progress = prov.Timer; progressBar.Max = prov.Duration; + + return totp; } } }