Skip to content

Commit

Permalink
Merge pull request #2502 from PhilippC/totp-improvements
Browse files Browse the repository at this point in the history
TOTP improvements
  • Loading branch information
PhilippC authored Jan 5, 2024
2 parents be2c288 + c354612 commit 3997b21
Show file tree
Hide file tree
Showing 27 changed files with 642 additions and 203 deletions.
24 changes: 23 additions & 1 deletion src/Kp2aBusinessLogic/SearchDbHelper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -91,7 +91,29 @@ public PwGroup SearchForExactUrl (Database database, string url)

}

private static String ExtractHost(String url)
public PwGroup SearchForUuid(Database database, string uuid)
{
SearchParameters sp = SearchParameters.None;
sp.SearchInUuids = true;
sp.SearchString = uuid;

if (sp.RegularExpression) // Validate regular expression
{
new Regex(sp.SearchString);
}

string strGroupName = _app.GetResourceString(UiStringKey.search_results);
PwGroup pgResults = new PwGroup(true, true, strGroupName, PwIcon.EMailSearch) { IsVirtual = true };

PwObjectList<PwEntry> listResults = pgResults.Entries;

database.Root.SearchEntries(sp, listResults, new NullStatusLogger());

return pgResults;

}

private static String ExtractHost(String url)
{
return UrlUtil.GetHost(url.Trim());
}
Expand Down
13 changes: 10 additions & 3 deletions src/Kp2aBusinessLogic/database/Database.cs
Original file line number Diff line number Diff line change
Expand Up @@ -174,10 +174,17 @@ public PwGroup SearchForExactUrl(String url) {
PwGroup group = SearchHelper.SearchForExactUrl(this, url);

return group;

}

public PwGroup SearchForHost(String url, bool allowSubdomains) {
}
public PwGroup SearchForUuid(String uuid)
{
PwGroup group = SearchHelper.SearchForUuid(this, uuid);

return group;

}

public PwGroup SearchForHost(String url, bool allowSubdomains) {
PwGroup group = SearchHelper.SearchForHost(this, url, allowSubdomains);

return group;
Expand Down
82 changes: 69 additions & 13 deletions src/keepass2android/EntryActivity.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ You should have received a copy of the GNU General Public License
using System.Globalization;
using System.IO;
using System.Net;
using System.Threading.Tasks;
using Android.Content.PM;
using Android.Webkit;
using Android.Graphics;
Expand All @@ -49,7 +50,9 @@ You should have received a copy of the GNU General Public License
using File = Java.IO.File;
using Uri = Android.Net.Uri;
using keepass2android.fileselect;
using KeeTrayTOTP.Libraries;
using Boolean = Java.Lang.Boolean;
using Android.Util;

namespace keepass2android
{
Expand Down Expand Up @@ -286,6 +289,8 @@ private void SetPluginField(string key, string value, bool isProtected)
extraGroup.AddView(view.View);
}

SetPasswordStyle();

//update the Entry output in the App database and notify the CopyToClipboard service

if (App.Kp2a.LastOpenedEntry != null)
Expand Down Expand Up @@ -488,10 +493,11 @@ protected override void OnCreate(Bundle savedInstanceState)
_pluginFieldReceiver = new PluginFieldReceiver(this);
RegisterReceiver(_pluginFieldReceiver, new IntentFilter(Strings.ActionSetEntryField));

new Thread(NotifyPluginsOnOpen).Start();
var notifyPluginsOnOpenThread = new Thread(NotifyPluginsOnOpen);
notifyPluginsOnOpenThread.Start();

//the rest of the things to do depends on the current app task:
AppTask.CompleteOnCreateEntryActivity(this);
AppTask.CompleteOnCreateEntryActivity(this, notifyPluginsOnOpenThread);
}

private void RemoveFromHistory()
Expand Down Expand Up @@ -664,7 +670,7 @@ private void PopulateExtraStrings()
EditModeBase editMode = new DefaultEdit();
if (KpEntryTemplatedEdit.IsTemplated(App.Kp2a.CurrentDb, this.Entry))
editMode = new KpEntryTemplatedEdit(App.Kp2a.CurrentDb, this.Entry);
foreach (var key in editMode.SortExtraFieldKeys(Entry.Strings.GetKeys().Where(key=> !PwDefs.IsStandardField(key))))
foreach (var key in editMode.SortExtraFieldKeys(Entry.Strings.GetKeys().Where(key=> !PwDefs.IsStandardField(key) && key != Kp2aTotp.TotpKey)))
{
if (editMode.IsVisible(key))
{
Expand Down Expand Up @@ -840,7 +846,7 @@ private void RegisterProtectedTextView(string fieldKey, TextView protectedTextVi
{
if (!_showPassword.ContainsKey(protectedTextView))
{
_showPassword[protectedTextView] = fieldKey == UpdateTotpTimerTask.TotpKey ? _showTotpDefault : _showPasswordDefault;
_showPassword[protectedTextView] = fieldKey == Kp2aTotp.TotpKey ? _showTotpDefault : _showPasswordDefault;
}
var protectedTextviewGroup = new ProtectedTextviewGroup { ProtectedField = protectedTextView, VisibleProtectedField = visibleTextView};
_protectedTextViews.Add(protectedTextviewGroup);
Expand Down Expand Up @@ -946,11 +952,13 @@ protected void FillData()

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(new List<int> { Resource.Id.entry_password, Resource.Id.entry_password_visible}, Resource.Id.entryfield_container_password, PwDefs.PasswordField);
PopulateStandardText(new List<int> { Resource.Id.entry_totp, Resource.Id.entry_totp_visible }, Resource.Id.entryfield_container_totp, Kp2aTotp.TotpKey);
PopulateStandardText(new List<int> { Resource.Id.entry_password, Resource.Id.entry_password_visible}, Resource.Id.entryfield_container_password, PwDefs.PasswordField);

RegisterProtectedTextView(PwDefs.PasswordField, FindViewById<TextView>(Resource.Id.entry_password), FindViewById<TextView>(Resource.Id.entry_password_visible));
RegisterProtectedTextView(Kp2aTotp.TotpKey, FindViewById<TextView>(Resource.Id.entry_totp), FindViewById<TextView>(Resource.Id.entry_totp_visible));

RegisterTextPopup(FindViewById<RelativeLayout> (Resource.Id.groupname_container),
RegisterTextPopup(FindViewById<RelativeLayout> (Resource.Id.groupname_container),
FindViewById (Resource.Id.entry_group_name), KeyGroupFullPath);

RegisterTextPopup(FindViewById<RelativeLayout>(Resource.Id.username_container),
Expand All @@ -961,9 +969,11 @@ protected void FillData()
.Add(new GotoUrlMenuItem(this, PwDefs.UrlField));
RegisterTextPopup(FindViewById<RelativeLayout>(Resource.Id.password_container),
FindViewById(Resource.Id.password_vdots), PwDefs.PasswordField);
RegisterTextPopup(FindViewById<RelativeLayout>(Resource.Id.totp_container),
FindViewById(Resource.Id.totp_vdots), Kp2aTotp.TotpKey);


PopulateText(Resource.Id.entry_created, Resource.Id.entryfield_container_created, getDateTime(Entry.CreationTime));
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)
Expand All @@ -990,6 +1000,40 @@ protected void FillData()

SetPasswordStyle();
}

private async Task UpdateTotpCountdown()
{
if (App.Kp2a.LastOpenedEntry == null)
return;
var totpData = new Kp2aTotp().TryGetTotpData(App.Kp2a.LastOpenedEntry);

if (totpData == null || !totpData.IsTotpEntry)
return;

var totpProvider = new TOTPProvider(totpData);

var progressBar = FindViewById<ProgressBar>(Resource.Id.TotpCountdownProgressBar);

int lastSecondsLeft = -1;
while (!isPaused && progressBar != null)
{

int secondsLeft = totpProvider.Timer;

if (secondsLeft != lastSecondsLeft)
{
lastSecondsLeft = secondsLeft;
// Update the progress bar on the UI thread
RunOnUiThread(() =>
{
progressBar.Progress = secondsLeft;
progressBar.Max = totpProvider.Duration;
});
}

await Task.Delay(1000);
}
}

private void PopulatePreviousVersions()
{
Expand Down Expand Up @@ -1042,7 +1086,7 @@ private void NotifyPluginsOnClose()
}
private List<IPopupMenuItem> RegisterTextPopup(View container, View anchor, string fieldKey)
{
return RegisterTextPopup(container, anchor, fieldKey, Entry.Strings.GetSafe(fieldKey).IsProtected);
return RegisterTextPopup(container, anchor, fieldKey, Entry.Strings.GetSafe(fieldKey).IsProtected || fieldKey == Kp2aTotp.TotpKey);
}

private List<IPopupMenuItem> RegisterTextPopup(View container, View anchor, string fieldKey, bool isProtected)
Expand All @@ -1055,7 +1099,12 @@ private List<IPopupMenuItem> RegisterTextPopup(View container, View anchor, stri
popupItems.Add(new CopyToClipboardPopupMenuIcon(this, _stringViews[fieldKey], isProtected));
if (isProtected)
{
var valueView = container.FindViewById<TextView>(fieldKey == PwDefs.PasswordField ? Resource.Id.entry_password : Resource.Id.entry_extra);
var valueView = container.FindViewById<TextView>(fieldKey switch
{
PwDefs.PasswordField => Resource.Id.entry_password,
Kp2aTotp.TotpKey => Resource.Id.entry_totp,
_ => Resource.Id.entry_extra
});
popupItems.Add(new ToggleVisibilityPopupMenuItem(this, valueView));
}

Expand Down Expand Up @@ -1282,11 +1331,16 @@ public override bool OnPrepareOptionsMenu(IMenu menu)
return base.OnPrepareOptionsMenu(menu);
}

bool isPaused = false;


protected override void OnPause()
{
base.OnPause();
isPaused = true;
}

private void UpdateTogglePasswordMenu()

private void UpdateTogglePasswordMenu()
{
IMenuItem togglePassword = _menu.FindItem(Resource.Id.menu_toggle_pass);
if (_showPassword.Values.All(x => x))
Expand Down Expand Up @@ -1323,7 +1377,9 @@ protected override void OnResume()
ClearCache();
base.OnResume();
_activityDesign.ReapplyTheme();
}
isPaused = false;
Task.Run(UpdateTotpCountdown);
}

public void ClearCache()
{
Expand Down
2 changes: 1 addition & 1 deletion src/keepass2android/QueryCredentialsActivity.cs
Original file line number Diff line number Diff line change
Expand Up @@ -140,7 +140,7 @@ private void StartQuery()
//will return the results later
Intent i = new Intent(this, typeof (SelectCurrentDbActivity));
//don't show user notifications when an entry is opened.
var task = new SearchUrlTask() {UrlToSearchFor = _requestedUrl, ShowUserNotifications = ShowUserNotificationsMode.WhenTotp};
var task = new SearchUrlTask() {UrlToSearchFor = _requestedUrl, ShowUserNotifications = ActivationCondition.WhenTotp, ActivateKeyboard = ActivationCondition.Never };
task.ToIntent(i);
StartActivityForResult(i, RequestCodeQuery);
_startedQuery = true;
Expand Down
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
62 changes: 62 additions & 0 deletions src/keepass2android/Resources/layout/entry_view_contents.xml
Original file line number Diff line number Diff line change
Expand Up @@ -184,6 +184,68 @@
</RelativeLayout>
</LinearLayout>
</LinearLayout>
<LinearLayout
android:id="@+id/entryfield_container_totp"
style="@style/EntryEditSingleLine_container">
<ImageView
style="@style/EntryEditSingleLine_ImageView"
android:src="@drawable/ic_entry_totp" />

<LinearLayout

android:layout_height="wrap_content"
android:layout_width="fill_parent"
android:orientation="vertical">
<!-- TOTP -->
<TextView
android:id="@+id/entry_totp_label"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:text="@string/TOTP"
style="@style/EntryFieldHeader" />
<RelativeLayout
android:id="@+id/totp_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/totp_vdots"
android:layout_width="wrap_content"
android:layout_height="15dp"
android:src="@drawable/vdots"
android:gravity="right|bottom"
android:layout_alignParentRight="true" />
<TextView
android:id="@+id/entry_totp"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:password="true"
android:typeface="monospace"
android:layout_toLeftOf="@id/totp_vdots"
style="@style/EntryItem" />
<TextView
android:id="@+id/entry_totp_visible"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:layout_toLeftOf="@id/totp_vdots"
style="@style/EntryItem" />
</RelativeLayout>


<ProgressBar
android:id="@+id/TotpCountdownProgressBar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:layout_alignParentBottom="true"
android:layout_marginRight="30dp" />

</LinearLayout>
</LinearLayout>

<LinearLayout
android:id="@+id/entryfield_container_comment"
style="@style/EntryEditSingleLine_container">
Expand Down
1 change: 1 addition & 0 deletions src/keepass2android/Resources/values/config.xml
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
<string name="oi_filemanager_web">https://openintents.googlecode.com/files/FileManager-2.0.2.apk</string>
<string name="permission_desc2">KP2A Search</string>
<string name="permission_desc3">KP2A Choose autofill dataset</string>
<string name="AutoFillTotp_prefs_screen_key">AutoFillTotp_prefs_screen_key</string>


<!-- Preference settings -->
Expand Down
11 changes: 11 additions & 0 deletions src/keepass2android/Resources/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -402,6 +402,16 @@
<string name="ShowSeparateNotifications_summary">Show separate notifications for copying username and password to clipboard and activating the keyboard.</string>
<string name="AccServiceAutoFill_prefs">AutoFill Accessibility-Service</string>
<string name="AutoFill_prefs">AutoFill Service</string>
<string name="AutoFillTotp_prefs_ShowNotification_summary">When autofilling an entry with TOTP, show the entry notification with a Copy TOTP button</string>
<string name="AutoFillTotp_prefs_ShowNotification_title">Show entry notification</string>
<string name="AutoFillTotp_prefs_title">Autofill for TOTP entries</string>
<string name="AutoFillTotp_prefs_CopyTotpToClipboard_title">Copy TOTP to clipboard</string>
<string name="AutoFillTotp_prefs_CopyTotpToClipboard_summary">When autofilling an entry with TOTP, copy the TOTP to the clipboard</string>
<string name="AutoFillTotp_prefs_ActivateKeyboard_summary">When autofilling an entry with TOTP, activate the built-in keyboard. The keyboard has a TOTP button.</string>
<string name="AutoFillTotp_prefs_ActivateKeyboard_title">Activate built-in keyboard</string>

<string name="TotpCopiedToClipboard">Copied TOTP to clipboard</string>

<string name="ShowKp2aKeyboardNotification_title">KP2A keyboard notification</string>
<string name="ShowKp2aKeyboardNotification_summary">Make full entry accessible through the KP2A keyboard (recommended).</string>
<string name="OpenKp2aKeyboardAutomatically_title">Switch keyboard</string>
Expand Down Expand Up @@ -589,6 +599,7 @@
<string name="CouldntLoadChalAuxFile_Hint">Please use the KeeChallenge plugin in KeePass 2.x (PC) to configure your database for use with challenge-response!</string>
<string name="ErrorUpdatingChalAuxFile">Error updating OTP auxiliary file!</string>
<string name="TrayTotp_SeedField_title">TOTP Seed field name</string>
<string name="TOTP">TOTP</string>
<string name="TrayTotp_SeedField_summary">If you are using the Keepass 2 plugin "TrayTotp" with non-default settings, enter the field name for the seed field here according to the settings on the PC.</string>
<string name="TrayTotp_SettingsField_title">TOTP Settings field name</string>
<string name="TrayTotp_SettingsField_summary">Enter the field name of the settings field for TrayTotp here.</string>
Expand Down
35 changes: 34 additions & 1 deletion src/keepass2android/Resources/xml/preferences.xml
Original file line number Diff line number Diff line change
Expand Up @@ -461,7 +461,8 @@
android:defaultValue="false"
android:title="@string/LogAutofillView_title"
android:key="@string/LogAutofillView_key" />




<CheckBoxPreference
android:enabled="true"
Expand All @@ -476,6 +477,38 @@
android:summary="@string/AutofillDisabledQueriesPreference_summary"
android:persistent="false"
android:key="AutofillDisabledQueriesPreference_key"/>

<PreferenceScreen
android:key="@string/AutoFillTotp_prefs_screen_key"
android:title="@string/AutoFillTotp_prefs_title"
>
<keepass2android.ToolbarPreference
android:key="@string/AutoFillTotp_prefs_screen_key"
android:title="@string/AutoFillTotp_prefs_title" />

<CheckBoxPreference android:key="AutoFillTotp_prefs_ShowNotification_key"
android:enabled="true"
android:persistent="true"
android:summary="@string/AutoFillTotp_prefs_ShowNotification_summary"
android:defaultValue="true"
android:title="@string/AutoFillTotp_prefs_ShowNotification_title"
/>
<CheckBoxPreference android:key="AutoFillTotp_prefs_CopyTotpToClipboard_key"
android:enabled="true"
android:persistent="true"
android:summary="@string/AutoFillTotp_prefs_CopyTotpToClipboard_summary"
android:defaultValue="true"
android:title="@string/AutoFillTotp_prefs_CopyTotpToClipboard_title"
/>
<CheckBoxPreference android:key="AutoFillTotp_prefs_ActivateKeyboard_key"
android:enabled="true"
android:persistent="true"
android:summary="@string/AutoFillTotp_prefs_ActivateKeyboard_summary"
android:defaultValue="false"
android:title="@string/AutoFillTotp_prefs_ActivateKeyboard_title"
/>

</PreferenceScreen>

</PreferenceScreen>

Expand Down
Loading

0 comments on commit 3997b21

Please sign in to comment.