Compare commits

..

58 Commits

Author SHA1 Message Date
Philipp Crocoll
5cbddb4fcc explicitly remove READ_PHONE_STATE permission to close #2300; manifest for 1.09e-r7 2023-04-08 08:30:36 +02:00
Philipp Crocoll
b3a73f20d4 fix to potential crash when reloading the database. related to 4910c73a5e 2023-04-08 08:25:09 +02:00
Philipp Crocoll
badf99c20d Manifest for 1.09e-r6 2023-04-07 10:05:22 +02:00
Philipp Crocoll
b8318f7fa5 Merge branch 'master' of https://github.com/PhilippC/keepass2android 2023-04-07 09:19:43 +02:00
PhilippC
f0e30459a2 Merge pull request #2294 from PhilippC/l10n_master2
New Crowdin updates
2023-04-07 08:10:29 +02:00
Philipp Crocoll
e101ffb01e add regression test for the crash fixed in 9933fa1f9d 2023-04-07 08:10:10 +02:00
PhilippC
a05ef51d44 New translations strings.xml (Japanese) 2023-04-03 10:08:32 +02:00
PhilippC
8aacdf683b New translations strings.xml (Dutch) 2023-04-02 10:10:05 +02:00
PhilippC
0502efde14 New translations strings.xml (Dutch) 2023-04-02 09:00:39 +02:00
Philipp Crocoll
94ede3a696 output current Configuration during build 2023-03-31 08:01:25 +02:00
Philipp Crocoll
9933fa1f9d fix to potential crash in Autofill. Couldn't add a test yet, still waiting for corresponding Autofill structure. 2023-03-31 08:01:10 +02:00
Philipp Crocoll
4910c73a5e fix to potential crash when reloading database 2023-03-31 08:00:44 +02:00
Philipp Crocoll
cf222a2db1 remove Flavor from build-properties, adjust Manifest for debug build 2023-03-31 07:59:34 +02:00
PhilippC
a9ad3725dc Merge pull request #2265 from PhilippC/l10n_master2
New Crowdin updates
2023-03-31 07:58:27 +02:00
PhilippC
40d3fe1cd9 New translations strings.xml (Ukrainian) 2023-03-22 22:56:58 +01:00
PhilippC
1e90a52275 New translations strings.xml (Ukrainian) 2023-03-22 21:15:28 +01:00
PhilippC
8596edaa67 New translations strings.xml (Greek) 2023-03-22 10:59:35 +01:00
PhilippC
38f1aa4d3d New translations strings.xml (Greek) 2023-03-22 10:59:34 +01:00
PhilippC
984da3fd3b New translations strings.xml (Greek) 2023-03-22 09:53:14 +01:00
PhilippC
ed7138991d New translations strings.xml (German) 2023-03-21 21:45:15 +01:00
PhilippC
1e78527164 New translations strings.xml (Italian) 2023-03-21 00:17:53 +01:00
PhilippC
a6540b4462 New translations strings.xml (Japanese) 2023-03-20 13:56:48 +01:00
PhilippC
230b3941e8 New translations strings.xml (Japanese) 2023-03-20 12:42:13 +01:00
Philipp Crocoll
554f88c723 add make target "clean_rm" to remove build artifacts using rm. Created a new release based on this clean to see if it helps with #2263. 2023-03-20 09:51:58 +01:00
Philipp Crocoll
4cd32d30c6 removing unused duplicated files 2023-03-20 09:47:38 +01:00
PhilippC
a76c43a800 New translations strings.xml (Chinese Traditional) 2023-03-19 11:40:16 +01:00
Philipp Crocoll
d0da83182f manifest for 1.09e-r5 2023-03-19 10:01:25 +01:00
Philipp Crocoll
ec5f26e0cd reduce log output 2023-03-18 20:34:45 +01:00
Philipp Crocoll
6110166af8 code simplification and fix for Autofill not being able to save credentials, closes https://github.com/PhilippC/keepass2android/issues/2269 2023-03-16 20:27:22 +01:00
Philipp Crocoll
6f10a04589 revert most of the added debug outputs 2023-03-16 20:25:57 +01:00
PhilippC
eedeeafd80 New translations strings.xml (Chinese Simplified) 2023-03-16 03:34:05 +01:00
Philipp Crocoll
e0c003fcb2 add debugging output 2023-03-14 20:19:08 +01:00
PhilippC
ad3b1500bb New translations strings.xml (Finnish) 2023-03-12 23:25:28 +01:00
PhilippC
5f2a976fde New translations strings.xml (Finnish) 2023-03-12 22:20:54 +01:00
PhilippC
dd0becdfd8 New translations strings.xml (Slovenian) 2023-03-12 20:04:54 +01:00
PhilippC
cacd204ac2 New translations strings.xml (Chinese Simplified) 2023-03-10 04:06:30 +01:00
PhilippC
728fd2f8ae New translations strings.xml (Portuguese, Brazilian) 2023-03-09 21:38:11 +01:00
Philipp Crocoll
944f44bc4b Manifest for v1.09e-r4 2023-03-09 20:45:25 +01:00
Philipp Crocoll
58047d5386 Merge branch 'master' of https://github.com/PhilippC/keepass2android 2023-03-09 20:44:29 +01:00
PhilippC
c0a06c9f3a Merge pull request #2264 from PhilippC/l10n_master2
New Crowdin updates
2023-03-09 20:44:02 +01:00
Philipp Crocoll
d0c041a0e2 remove debugging code 2023-03-09 20:16:24 +01:00
PhilippC
df060e2f4b New translations strings.xml (Portuguese, Brazilian) 2023-03-09 19:56:04 +01:00
PhilippC
aea55dad45 New translations strings.xml (Chinese Traditional) 2023-03-09 19:56:01 +01:00
PhilippC
5442dbf441 New translations strings.xml (Chinese Simplified) 2023-03-09 19:56:00 +01:00
PhilippC
317476d9b5 New translations strings.xml (Ukrainian) 2023-03-09 19:55:59 +01:00
PhilippC
ad0acb7a69 New translations strings.xml (Slovenian) 2023-03-09 19:55:56 +01:00
PhilippC
b66ae5d264 New translations strings.xml (Polish) 2023-03-09 19:55:53 +01:00
PhilippC
d87706fa43 New translations strings.xml (Japanese) 2023-03-09 19:55:51 +01:00
PhilippC
cb25d12709 New translations strings.xml (Greek) 2023-03-09 19:55:46 +01:00
PhilippC
dce536009e New translations strings.xml (German) 2023-03-09 19:55:45 +01:00
PhilippC
656e785214 New translations strings.xml (Danish) 2023-03-09 19:55:44 +01:00
PhilippC
35d50a6eb0 New translations strings.xml (French) 2023-03-09 19:55:39 +01:00
PhilippC
786bb646c2 New translations strings.xml (Slovak) 2023-03-09 19:55:37 +01:00
Philipp Crocoll
72cc6ff768 wrap adding fields and hints to dictionary, avoiding to add a duplicate key. Should close #2262 (but I can't reproduce) 2023-03-09 19:46:28 +01:00
Philipp Crocoll
404e07e5c0 Merge remote-tracking branch 'remotes/origin/l10n_master2' 2023-03-09 19:40:36 +01:00
PhilippC
2378cd0d7c New translations strings.xml (Greek) 2023-03-08 16:54:54 +01:00
PhilippC
b149bab761 New translations strings.xml (Chinese Simplified) 2023-03-07 03:36:36 +01:00
PhilippC
5ebd8e5e33 New translations strings.xml (Portuguese, Brazilian) 2023-03-06 14:12:17 +01:00
38 changed files with 948 additions and 1064 deletions

View File

@@ -314,6 +314,18 @@ clean_KP2AKdbLibrary:
cd src/java/KP2AKdbLibrary && $(GRADLEW) clean
clean_PluginQR:
cd src/java/PluginQR && $(GRADLEW) clean
clean_rm:
rm -rf src/*/obj
rm -rf src/*/bin
rm -rf src/java/*/app/build
rm -rf src/java/argon2/obj
rm -rf src/java/argon2/libs
rm -rf src/packages
rm -rf src/java/KP2AKdbLibrary/app/.cxx
rm -rf src/java/KP2ASoftkeyboard_AS/app/.cxx
rm -rf src/SamsungPass/Xamarin.SamsungPass/SamsungPass/bin
rm -rf src/SamsungPass/Xamarin.SamsungPass/SamsungPass/obj
# https://learn.microsoft.com/en-us/nuget/consume-packages/package-restore-troubleshooting#other-potential-conditions
clean_nuget:

View File

@@ -134,10 +134,10 @@ namespace Kp2aAutofillParser
/// </summary>
public class FilledAutofillFieldCollection<FieldT> where FieldT:InputField
{
public Dictionary<string, FilledAutofillField<FieldT>> HintMap { get; }
public Dictionary<string, FilledAutofillField> HintMap { get; }
public string DatasetName { get; set; }
public FilledAutofillFieldCollection(Dictionary<string, FilledAutofillField<FieldT>> hintMap, string datasetName = "")
public FilledAutofillFieldCollection(Dictionary<string, FilledAutofillField> hintMap, string datasetName = "")
{
//recreate hint map making sure we compare case insensitive
HintMap = BuildHintMap();
@@ -149,9 +149,9 @@ namespace Kp2aAutofillParser
public FilledAutofillFieldCollection() : this(BuildHintMap())
{ }
private static Dictionary<string, FilledAutofillField<FieldT>> BuildHintMap()
private static Dictionary<string, FilledAutofillField> BuildHintMap()
{
return new Dictionary<string, FilledAutofillField<FieldT>>(StringComparer.OrdinalIgnoreCase);
return new Dictionary<string, FilledAutofillField>(StringComparer.OrdinalIgnoreCase);
}
/// <summary>
@@ -159,7 +159,7 @@ namespace Kp2aAutofillParser
/// </summary>
/// <returns>The add.</returns>
/// <param name="filledAutofillField">Filled autofill field.</param>
public void Add(FilledAutofillField<FieldT> filledAutofillField)
public void Add(FilledAutofillField filledAutofillField)
{
foreach (string hint in filledAutofillField.AutofillHints)
{
@@ -572,7 +572,7 @@ namespace Kp2aAutofillParser
}
}
public class FilledAutofillField<FieldT> where FieldT : InputField
public class FilledAutofillField
{
private string[] _autofillHints;
public string TextValue { get; set; }
@@ -611,13 +611,13 @@ namespace Kp2aAutofillParser
public FilledAutofillField()
{ }
public FilledAutofillField(FieldT inputField)
public FilledAutofillField(InputField inputField)
: this(inputField, inputField.AutofillHints)
{
}
public FilledAutofillField(FieldT inputField, string[] hints)
public FilledAutofillField(InputField inputField, string[] hints)
{
string[] rawHints = AutofillHintsHelper.FilterForSupportedHints(hints);
@@ -665,6 +665,7 @@ namespace Kp2aAutofillParser
}
}
AutofillHints = AutofillHintsHelper.ConvertToCanonicalLowerCaseHints(hintList.ToArray()).ToArray();
inputField.FillFilledAutofillValue(this);
}
@@ -679,7 +680,7 @@ namespace Kp2aAutofillParser
if (this == obj) return true;
if (obj == null || GetType() != obj.GetType()) return false;
FilledAutofillField<FieldT> that = (FilledAutofillField<FieldT>)obj;
FilledAutofillField that = (FilledAutofillField)obj;
if (!TextValue?.Equals(that.TextValue) ?? that.TextValue != null)
return false;
@@ -717,6 +718,8 @@ namespace Kp2aAutofillParser
public string HtmlInfoTag { get; set; }
public string HtmlInfoTypeAttribute { get; set; }
public abstract void FillFilledAutofillValue(FilledAutofillField filledField);
}
/// <summary>
@@ -838,7 +841,7 @@ namespace Kp2aAutofillParser
continue;
if (viewHints.Select(AutofillHintsHelper.ToCanonicalHint).Intersect(_autofillHintsForLogin).Any())
{
FieldsMappedToHints.Add(viewNode, viewHints.Select(AutofillHintsHelper.ToCanonicalHint).ToHashSet().ToArray());
AddFieldToHintMap(viewNode, viewHints.Select(AutofillHintsHelper.ToCanonicalHint).ToHashSet().ToArray());
}
}
@@ -873,9 +876,9 @@ namespace Kp2aAutofillParser
if (passwordFields.Concat(usernameFields).Any(f => f.IsFocused))
{
foreach (var uf in usernameFields)
FieldsMappedToHints.Add(uf, new string[] { AutofillHintsHelper.AutofillHintUsername });
AddFieldToHintMap(uf, new string[] { AutofillHintsHelper.AutofillHintUsername });
foreach (var pf in passwordFields.Except(usernameFields))
FieldsMappedToHints.Add(pf, new string[] { AutofillHintsHelper.AutofillHintPassword });
AddFieldToHintMap(pf, new string[] { AutofillHintsHelper.AutofillHintPassword });
}
}
@@ -895,6 +898,18 @@ namespace Kp2aAutofillParser
return result;
}
private void AddFieldToHintMap(FieldT field, string[] hints)
{
if (FieldsMappedToHints.ContainsKey(field))
{
FieldsMappedToHints[field] = FieldsMappedToHints[field].Concat(hints).ToArray();
}
else
{
FieldsMappedToHints[field] = hints;
}
}
public bool LogAutofillView { get; set; }
private bool IsEditText(FieldT f)
@@ -944,11 +959,6 @@ namespace Kp2aAutofillParser
private static bool IsPassword(InputField f)
{
if (f.IdEntry?.Contains("password") == true)
{
f = f;
}
InputTypes inputType = f.InputType;
return
@@ -963,7 +973,7 @@ namespace Kp2aAutofillParser
|| IsInputTypeVariation(inputType, InputTypes.TextVariationWebPassword)
)
)
|| (f.AutofillHints != null && f.AutofillHints.First() == "passwordAuto")
|| (f.AutofillHints != null && f.AutofillHints.FirstOrDefault() == "passwordAuto")
|| (f.HtmlInfoTypeAttribute == "password")
);
}

View File

@@ -18,6 +18,9 @@ namespace Kp2aAutofillParserTest
class TestInputField: InputField
{
public string[] ExpectedAssignedHints { get; set; }
public override void FillFilledAutofillValue(FilledAutofillField filledField)
{
}
}
[Fact]
@@ -27,11 +30,18 @@ namespace Kp2aAutofillParserTest
RunTestFromAutofillInput(resourceName, "com.servicenet.mobile");
}
[Fact]
public void TestCrashRegressionEmptySequence()
{
var resourceName = "Kp2aAutofillParserTest.imdb.json";
RunTestFromAutofillInput(resourceName, "com.vivaldi.browser", "m.imdb.com");
}
[Fact]
public void TestFocusedPasswordAutoIsFilled()
{
var resourceName = "Kp2aAutofillParserTest.com-servicenet-mobile-focused.json";
RunTestFromAutofillInput(resourceName, "com.servicenet.mobile" );
RunTestFromAutofillInput(resourceName, "com.servicenet.mobile");
}
[Fact]

View File

@@ -15,6 +15,7 @@
<None Remove="com-servicenet-mobile-focused.json" />
<None Remove="com-servicenet-mobile-no-focus.json" />
<None Remove="firefox-amazon-it.json" />
<None Remove="imdb.json" />
</ItemGroup>
<ItemGroup>
@@ -53,6 +54,9 @@
<EmbeddedResource Include="com-servicenet-mobile-no-focus.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</EmbeddedResource>
<EmbeddedResource Include="imdb.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</EmbeddedResource>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,728 @@
{
"InputFields": [
{
"IdEntry": null,
"Hint": null,
"ClassName": "android.widget.FrameLayout",
"AutofillHints": null,
"IsFocused": false,
"InputType": 0,
"HtmlInfoTag": null,
"HtmlInfoTypeAttribute": null
},
{
"IdEntry": "action_bar_root",
"Hint": null,
"ClassName": "android.widget.FrameLayout",
"AutofillHints": null,
"IsFocused": false,
"InputType": 0,
"HtmlInfoTag": null,
"HtmlInfoTypeAttribute": null
},
{
"IdEntry": "custom_tabs_handle_view_stub",
"Hint": null,
"ClassName": "android.view.View",
"AutofillHints": null,
"IsFocused": false,
"InputType": 0,
"HtmlInfoTag": null,
"HtmlInfoTypeAttribute": null
},
{
"IdEntry": "coordinator",
"Hint": null,
"ClassName": "android.view.ViewGroup",
"AutofillHints": null,
"IsFocused": false,
"InputType": 0,
"HtmlInfoTag": null,
"HtmlInfoTypeAttribute": null
},
{
"IdEntry": "compositor_view_holder",
"Hint": null,
"ClassName": "android.widget.FrameLayout",
"AutofillHints": null,
"IsFocused": false,
"InputType": 0,
"HtmlInfoTag": null,
"HtmlInfoTypeAttribute": null
},
{
"IdEntry": null,
"Hint": null,
"ClassName": "android.widget.FrameLayout",
"AutofillHints": null,
"IsFocused": true,
"InputType": 0,
"HtmlInfoTag": "form",
"HtmlInfoTypeAttribute": null
},
{
"IdEntry": null,
"Hint": "",
"ClassName": null,
"AutofillHints": [],
"IsFocused": false,
"InputType": 0,
"HtmlInfoTag": "input",
"HtmlInfoTypeAttribute": "checkbox"
},
{
"IdEntry": null,
"Hint": "Search IMDb",
"ClassName": null,
"AutofillHints": [
"off"
],
"IsFocused": true,
"InputType": 0,
"HtmlInfoTag": "input",
"HtmlInfoTypeAttribute": "text"
},
{
"IdEntry": "main_tab_switcher",
"Hint": null,
"ClassName": "android.widget.RelativeLayout",
"AutofillHints": null,
"IsFocused": false,
"InputType": 0,
"HtmlInfoTag": null,
"HtmlInfoTypeAttribute": null
},
{
"IdEntry": "ar_view_holder",
"Hint": null,
"ClassName": "android.widget.FrameLayout",
"AutofillHints": null,
"IsFocused": false,
"InputType": 0,
"HtmlInfoTag": null,
"HtmlInfoTypeAttribute": null
},
{
"IdEntry": "capture_overlay",
"Hint": null,
"ClassName": "android.view.View",
"AutofillHints": null,
"IsFocused": false,
"InputType": 0,
"HtmlInfoTag": null,
"HtmlInfoTypeAttribute": null
},
{
"IdEntry": "overview_list_layout_holder",
"Hint": null,
"ClassName": "android.widget.FrameLayout",
"AutofillHints": null,
"IsFocused": false,
"InputType": 0,
"HtmlInfoTag": null,
"HtmlInfoTypeAttribute": null
},
{
"IdEntry": "bottom_container",
"Hint": null,
"ClassName": "android.widget.FrameLayout",
"AutofillHints": null,
"IsFocused": false,
"InputType": 0,
"HtmlInfoTag": null,
"HtmlInfoTypeAttribute": null
},
{
"IdEntry": "keyboard_accessory_sheet_stub",
"Hint": null,
"ClassName": "android.view.View",
"AutofillHints": null,
"IsFocused": false,
"InputType": 0,
"HtmlInfoTag": null,
"HtmlInfoTypeAttribute": null
},
{
"IdEntry": "bottombar_stub",
"Hint": null,
"ClassName": "android.view.View",
"AutofillHints": null,
"IsFocused": false,
"InputType": 0,
"HtmlInfoTag": null,
"HtmlInfoTypeAttribute": null
},
{
"IdEntry": "tab_modal_dialog_container_stub",
"Hint": null,
"ClassName": "android.view.View",
"AutofillHints": null,
"IsFocused": false,
"InputType": 0,
"HtmlInfoTag": null,
"HtmlInfoTypeAttribute": null
},
{
"IdEntry": "tab_modal_dialog_container_sibling_view",
"Hint": null,
"ClassName": "android.view.View",
"AutofillHints": null,
"IsFocused": false,
"InputType": 0,
"HtmlInfoTag": null,
"HtmlInfoTypeAttribute": null
},
{
"IdEntry": "omnibox_results_container_stub",
"Hint": null,
"ClassName": "android.view.View",
"AutofillHints": null,
"IsFocused": false,
"InputType": 0,
"HtmlInfoTag": null,
"HtmlInfoTypeAttribute": null
},
{
"IdEntry": "panel_stub",
"Hint": null,
"ClassName": "android.view.View",
"AutofillHints": null,
"IsFocused": false,
"InputType": 0,
"HtmlInfoTag": null,
"HtmlInfoTypeAttribute": null
},
{
"IdEntry": "search_engine_suggestion_stub",
"Hint": null,
"ClassName": "android.view.View",
"AutofillHints": null,
"IsFocused": false,
"InputType": 0,
"HtmlInfoTag": null,
"HtmlInfoTypeAttribute": null
},
{
"IdEntry": "action_bar_black_background",
"Hint": null,
"ClassName": "android.view.View",
"AutofillHints": null,
"IsFocused": false,
"InputType": 0,
"HtmlInfoTag": null,
"HtmlInfoTypeAttribute": null
},
{
"IdEntry": "bottom_controls",
"Hint": null,
"ClassName": "android.widget.FrameLayout",
"AutofillHints": null,
"IsFocused": false,
"InputType": 0,
"HtmlInfoTag": null,
"HtmlInfoTypeAttribute": null
},
{
"IdEntry": "bottom_controls_wrapper",
"Hint": null,
"ClassName": "android.widget.LinearLayout",
"AutofillHints": null,
"IsFocused": false,
"InputType": 0,
"HtmlInfoTag": null,
"HtmlInfoTypeAttribute": null
},
{
"IdEntry": "tab_group_ui_bottom_container",
"Hint": null,
"ClassName": "android.widget.FrameLayout",
"AutofillHints": null,
"IsFocused": false,
"InputType": 0,
"HtmlInfoTag": null,
"HtmlInfoTypeAttribute": null
},
{
"IdEntry": "tab_group_ui_toolbar_view",
"Hint": null,
"ClassName": "android.widget.FrameLayout",
"AutofillHints": null,
"IsFocused": false,
"InputType": 0,
"HtmlInfoTag": null,
"HtmlInfoTypeAttribute": null
},
{
"IdEntry": "bottom_container_slot",
"Hint": null,
"ClassName": "android.widget.FrameLayout",
"AutofillHints": null,
"IsFocused": false,
"InputType": 0,
"HtmlInfoTag": null,
"HtmlInfoTypeAttribute": null
},
{
"IdEntry": "bottom_toolbar",
"Hint": null,
"ClassName": "android.widget.FrameLayout",
"AutofillHints": null,
"IsFocused": false,
"InputType": 0,
"HtmlInfoTag": null,
"HtmlInfoTypeAttribute": null
},
{
"IdEntry": "bottom_toolbar_browsing",
"Hint": null,
"ClassName": "android.widget.LinearLayout",
"AutofillHints": null,
"IsFocused": false,
"InputType": 0,
"HtmlInfoTag": null,
"HtmlInfoTypeAttribute": null
},
{
"IdEntry": "tab_switcher_tab_layout_toggle",
"Hint": null,
"ClassName": "android.widget.RelativeLayout",
"AutofillHints": null,
"IsFocused": false,
"InputType": 0,
"HtmlInfoTag": null,
"HtmlInfoTypeAttribute": null
},
{
"IdEntry": "tab_switcher_tab_layout",
"Hint": null,
"ClassName": "android.widget.HorizontalScrollView",
"AutofillHints": null,
"IsFocused": false,
"InputType": 0,
"HtmlInfoTag": null,
"HtmlInfoTypeAttribute": null
},
{
"IdEntry": null,
"Hint": null,
"ClassName": "android.widget.TextView",
"AutofillHints": null,
"IsFocused": false,
"InputType": 0,
"HtmlInfoTag": null,
"HtmlInfoTypeAttribute": null
},
{
"IdEntry": null,
"Hint": null,
"ClassName": "android.widget.TextView",
"AutofillHints": null,
"IsFocused": false,
"InputType": 0,
"HtmlInfoTag": null,
"HtmlInfoTypeAttribute": null
},
{
"IdEntry": null,
"Hint": null,
"ClassName": "android.widget.TextView",
"AutofillHints": null,
"IsFocused": false,
"InputType": 0,
"HtmlInfoTag": null,
"HtmlInfoTypeAttribute": null
},
{
"IdEntry": null,
"Hint": null,
"ClassName": "android.widget.TextView",
"AutofillHints": null,
"IsFocused": false,
"InputType": 0,
"HtmlInfoTag": null,
"HtmlInfoTypeAttribute": null
},
{
"IdEntry": "control_container",
"Hint": null,
"ClassName": "android.widget.FrameLayout",
"AutofillHints": null,
"IsFocused": false,
"InputType": 0,
"HtmlInfoTag": null,
"HtmlInfoTypeAttribute": null
},
{
"IdEntry": "find_toolbar_stub",
"Hint": null,
"ClassName": "android.view.View",
"AutofillHints": null,
"IsFocused": false,
"InputType": 0,
"HtmlInfoTag": null,
"HtmlInfoTypeAttribute": null
},
{
"IdEntry": "find_toolbar_tablet_stub",
"Hint": null,
"ClassName": "android.view.View",
"AutofillHints": null,
"IsFocused": false,
"InputType": 0,
"HtmlInfoTag": null,
"HtmlInfoTypeAttribute": null
},
{
"IdEntry": "toolbar_container",
"Hint": null,
"ClassName": "android.widget.FrameLayout",
"AutofillHints": null,
"IsFocused": false,
"InputType": 0,
"HtmlInfoTag": null,
"HtmlInfoTypeAttribute": null
},
{
"IdEntry": "tab_group_ui_top_container",
"Hint": null,
"ClassName": "android.widget.FrameLayout",
"AutofillHints": null,
"IsFocused": false,
"InputType": 0,
"HtmlInfoTag": null,
"HtmlInfoTypeAttribute": null
},
{
"IdEntry": "toolbar",
"Hint": null,
"ClassName": "android.widget.FrameLayout",
"AutofillHints": null,
"IsFocused": false,
"InputType": 0,
"HtmlInfoTag": null,
"HtmlInfoTypeAttribute": null
},
{
"IdEntry": "location_bar",
"Hint": null,
"ClassName": "android.widget.FrameLayout",
"AutofillHints": null,
"IsFocused": false,
"InputType": 0,
"HtmlInfoTag": null,
"HtmlInfoTypeAttribute": null
},
{
"IdEntry": "location_bar_status_view_left_space",
"Hint": null,
"ClassName": "android.view.View",
"AutofillHints": null,
"IsFocused": false,
"InputType": 0,
"HtmlInfoTag": null,
"HtmlInfoTypeAttribute": null
},
{
"IdEntry": "location_bar_status",
"Hint": null,
"ClassName": "android.widget.LinearLayout",
"AutofillHints": null,
"IsFocused": false,
"InputType": 0,
"HtmlInfoTag": null,
"HtmlInfoTypeAttribute": null
},
{
"IdEntry": "location_bar_incognito_badge_stub",
"Hint": null,
"ClassName": "android.view.View",
"AutofillHints": null,
"IsFocused": false,
"InputType": 0,
"HtmlInfoTag": null,
"HtmlInfoTypeAttribute": null
},
{
"IdEntry": "location_bar_status_icon_view",
"Hint": null,
"ClassName": "android.widget.LinearLayout",
"AutofillHints": null,
"IsFocused": false,
"InputType": 0,
"HtmlInfoTag": null,
"HtmlInfoTypeAttribute": null
},
{
"IdEntry": "location_bar_status_icon_frame",
"Hint": null,
"ClassName": "android.widget.FrameLayout",
"AutofillHints": null,
"IsFocused": false,
"InputType": 0,
"HtmlInfoTag": null,
"HtmlInfoTypeAttribute": null
},
{
"IdEntry": "location_bar_status_icon_bg",
"Hint": null,
"ClassName": "android.view.View",
"AutofillHints": null,
"IsFocused": false,
"InputType": 0,
"HtmlInfoTag": null,
"HtmlInfoTypeAttribute": null
},
{
"IdEntry": "location_bar_status_icon_holding_space",
"Hint": null,
"ClassName": "android.view.View",
"AutofillHints": null,
"IsFocused": false,
"InputType": 0,
"HtmlInfoTag": null,
"HtmlInfoTypeAttribute": null
},
{
"IdEntry": "location_bar_verbose_status",
"Hint": null,
"ClassName": "android.widget.TextView",
"AutofillHints": null,
"IsFocused": false,
"InputType": 0,
"HtmlInfoTag": null,
"HtmlInfoTypeAttribute": null
},
{
"IdEntry": "location_bar_verbose_status_separator",
"Hint": null,
"ClassName": "android.view.View",
"AutofillHints": null,
"IsFocused": false,
"InputType": 0,
"HtmlInfoTag": null,
"HtmlInfoTypeAttribute": null
},
{
"IdEntry": "location_bar_verbose_status_extra_space",
"Hint": null,
"ClassName": "android.view.View",
"AutofillHints": null,
"IsFocused": false,
"InputType": 0,
"HtmlInfoTag": null,
"HtmlInfoTypeAttribute": null
},
{
"IdEntry": "location_bar_status_view_right_space",
"Hint": null,
"ClassName": "android.view.View",
"AutofillHints": null,
"IsFocused": false,
"InputType": 0,
"HtmlInfoTag": null,
"HtmlInfoTypeAttribute": null
},
{
"IdEntry": "url_action_container",
"Hint": null,
"ClassName": "android.widget.LinearLayout",
"AutofillHints": null,
"IsFocused": false,
"InputType": 0,
"HtmlInfoTag": null,
"HtmlInfoTypeAttribute": null
},
{
"IdEntry": "toolbar_buttons",
"Hint": null,
"ClassName": "android.widget.LinearLayout",
"AutofillHints": null,
"IsFocused": false,
"InputType": 0,
"HtmlInfoTag": null,
"HtmlInfoTypeAttribute": null
},
{
"IdEntry": "optional_button_stub",
"Hint": null,
"ClassName": "android.view.View",
"AutofillHints": null,
"IsFocused": false,
"InputType": 0,
"HtmlInfoTag": null,
"HtmlInfoTypeAttribute": null
},
{
"IdEntry": "menu_button_wrapper",
"Hint": null,
"ClassName": "android.widget.FrameLayout",
"AutofillHints": null,
"IsFocused": false,
"InputType": 0,
"HtmlInfoTag": null,
"HtmlInfoTypeAttribute": null
},
{
"IdEntry": "tab_switcher_toolbar_stub",
"Hint": null,
"ClassName": "android.view.View",
"AutofillHints": null,
"IsFocused": false,
"InputType": 0,
"HtmlInfoTag": null,
"HtmlInfoTypeAttribute": null
},
{
"IdEntry": "bottom_toolbar_tab_switcher_mode",
"Hint": null,
"ClassName": "android.widget.LinearLayout",
"AutofillHints": null,
"IsFocused": false,
"InputType": 0,
"HtmlInfoTag": null,
"HtmlInfoTypeAttribute": null
},
{
"IdEntry": "grid_tab_switcher_view_holder_stub",
"Hint": null,
"ClassName": "android.view.View",
"AutofillHints": null,
"IsFocused": false,
"InputType": 0,
"HtmlInfoTag": null,
"HtmlInfoTypeAttribute": null
},
{
"IdEntry": "message_container",
"Hint": null,
"ClassName": "android.widget.FrameLayout",
"AutofillHints": null,
"IsFocused": false,
"InputType": 0,
"HtmlInfoTag": null,
"HtmlInfoTypeAttribute": null
},
{
"IdEntry": "status_indicator_stub",
"Hint": null,
"ClassName": "android.view.View",
"AutofillHints": null,
"IsFocused": false,
"InputType": 0,
"HtmlInfoTag": null,
"HtmlInfoTypeAttribute": null
},
{
"IdEntry": "empty_container_stub",
"Hint": null,
"ClassName": "android.view.View",
"AutofillHints": null,
"IsFocused": false,
"InputType": 0,
"HtmlInfoTag": null,
"HtmlInfoTypeAttribute": null
},
{
"IdEntry": "sheet_container",
"Hint": null,
"ClassName": "android.widget.FrameLayout",
"AutofillHints": null,
"IsFocused": false,
"InputType": 0,
"HtmlInfoTag": null,
"HtmlInfoTypeAttribute": null
},
{
"IdEntry": "survey_container",
"Hint": null,
"ClassName": "android.widget.FrameLayout",
"AutofillHints": null,
"IsFocused": false,
"InputType": 0,
"HtmlInfoTag": null,
"HtmlInfoTypeAttribute": null
},
{
"IdEntry": "page_zoom_container",
"Hint": null,
"ClassName": "android.view.View",
"AutofillHints": null,
"IsFocused": false,
"InputType": 0,
"HtmlInfoTag": null,
"HtmlInfoTypeAttribute": null
},
{
"IdEntry": "dialog_parent_view",
"Hint": null,
"ClassName": "android.widget.FrameLayout",
"AutofillHints": null,
"IsFocused": false,
"InputType": 0,
"HtmlInfoTag": null,
"HtmlInfoTypeAttribute": null
},
{
"IdEntry": "keyboard_accessory",
"Hint": null,
"ClassName": "android.widget.LinearLayout",
"AutofillHints": null,
"IsFocused": false,
"InputType": 0,
"HtmlInfoTag": null,
"HtmlInfoTypeAttribute": null
},
{
"IdEntry": "accessory_bar_contents",
"Hint": null,
"ClassName": "android.widget.LinearLayout",
"AutofillHints": null,
"IsFocused": false,
"InputType": 0,
"HtmlInfoTag": null,
"HtmlInfoTypeAttribute": null
},
{
"IdEntry": "tabs",
"Hint": null,
"ClassName": "android.widget.HorizontalScrollView",
"AutofillHints": null,
"IsFocused": false,
"InputType": 0,
"HtmlInfoTag": null,
"HtmlInfoTypeAttribute": null
},
{
"IdEntry": "menu_anchor_stub",
"Hint": null,
"ClassName": "android.view.View",
"AutofillHints": null,
"IsFocused": false,
"InputType": 0,
"HtmlInfoTag": null,
"HtmlInfoTypeAttribute": null
},
{
"IdEntry": "navigation_popup_anchor_stub",
"Hint": null,
"ClassName": "android.view.View",
"AutofillHints": null,
"IsFocused": false,
"InputType": 0,
"HtmlInfoTag": null,
"HtmlInfoTypeAttribute": null
},
{
"IdEntry": "action_mode_bar_stub",
"Hint": null,
"ClassName": "android.view.View",
"AutofillHints": null,
"IsFocused": false,
"InputType": 0,
"HtmlInfoTag": null,
"HtmlInfoTypeAttribute": null
}
],
"PackageId": "com.vivaldi.browser",
"WebDomain": "m.imdb.com"
}

View File

@@ -2,7 +2,7 @@
<PropertyGroup>
<Flavor>NoNet</Flavor>
<xFlavor>Net</xFlavor>
</PropertyGroup>

View File

@@ -24,6 +24,7 @@ import com.jcraft.jsch.UserInfo;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
public class SftpStorage extends JavaFileStorageBase {
@@ -323,6 +324,8 @@ public class SftpStorage extends JavaFileStorageBase {
jsch = new JSch();
ConnectionInfo ci = splitStringToConnectionInfo(filename);
Log.d("KP2AJFS", "init SFTP");
String base_dir = getBaseDir();
jsch.setKnownHosts(base_dir + "/known_hosts");
@@ -340,7 +343,9 @@ public class SftpStorage extends JavaFileStorageBase {
}
Log.e("KP2AJFS[thread]", "getting session...");
Session session = jsch.getSession(ci.username, ci.host, ci.port);
Log.e("KP2AJFS", "creating SftpUserInfo");
UserInfo ui = new SftpUserInfo(ci.password,_appContext);
session.setUserInfo(ui);

View File

@@ -34,7 +34,6 @@ public class SftpUserInfo implements UserInfo {
builder.setContentText("SFTP prompt");
builder.setSmallIcon(R.drawable.ic_logo_green_foreground);
Handler h = new Handler() {
public void handleMessage(Message M) {
msg.copyFrom(M);
@@ -51,8 +50,12 @@ public class SftpUserInfo implements UserInfo {
intent.putExtra("keepass2android.sftp.prompt", text);
intent.setData((Uri.parse("suckit://"+SystemClock.elapsedRealtime())));
Log.e("KP2AJFS[thread]", "built after 2023-03-14");
int flags = 0;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) {
Log.e("KP2AJFS[thread]", "Setting mutable flag...");
flags |= PendingIntent.FLAG_MUTABLE;
}
PendingIntent contentIntent = PendingIntent.getActivity(_appContext, 0, intent, flags);

View File

@@ -21,7 +21,7 @@
<!-- Title for Latin keyboard -->
<string name="english_ime_name">Πληκτρολόγιο Keepass2Android</string>
<!-- Title for Latin keyboard settings activity / dialog -->
<string name="english_ime_settings">Ρυθμίσεις πληκτρολογίου Keepass2Android</string>
<string name="english_ime_settings">Ρυθμίσεις πληκτρολογίου Android</string>
<!-- Title for Latin keyboard input options dialog -->
<string name="english_ime_input_options">Επιλογές εισόδου</string>
<!-- Option to provide vibrate/haptic feedback on keypress -->
@@ -51,7 +51,7 @@
<!-- Dialog title for auto complete choices -->
<string name="auto_complete_dialog_title">Αυτόματη συμπλήρωση</string>
<!-- Option to enable text prediction in landscape -->
<string name="prediction_landscape">Αυξήστε το μέγεθος του πεδίου κειμένου</string>
<string name="prediction_landscape">Αύξηση μεγέθους του πεδίου κειμένου</string>
<!-- Description for text prediction -->
<string name="prediction_landscape_summary">Απόκρυψη υποδείξεων λέξεων στην οριζόντια προβολή</string>
<!-- Option to enable auto capitalization of sentences -->
@@ -77,7 +77,7 @@
<string name="prefs_settings_key">Εμφάνιση πλήκτρου ρυθμίσεων</string>
<!-- Array of the settings key mode values -->
<!-- Option to automatically decide to show/hide the settings key -->
<string name="settings_key_mode_auto_name">Αυτόματο</string>
<string name="settings_key_mode_auto_name">Αυτόματα</string>
<!-- Option to always show the settings key -->
<string name="settings_key_mode_always_show_name">Να εμφανίζεται πάντα</string>
<!-- Option to always hide the settings key -->
@@ -110,25 +110,25 @@
<!-- Tip to press ?123 to access numbers and symbols -->
<string name="tip_access_symbols">Πρόσβαση σε αριθμούς και σύμβολα</string>
<!-- Tip to long press on typed word to add to dictionary -->
<string name="tip_add_to_dictionary">Κρατήστε πατημένη τη λέξη στην άκρη αριστερά, για να την προσθέσετε στο λεξικό</string>
<string name="tip_add_to_dictionary">Παρατεταμένη επιλογή της λέξης στα αριστερά, την προσθέτει στο λεξικό</string>
<!-- Instruction to touch the bubble to continue -->
<string name="touch_to_continue">Αγγίξτε αυτή τη συμβουλή για να συνεχίσετε »</string>
<string name="touch_to_continue">Αγγίξτε αυτή την υπόδειξη για να συνεχίσετε »</string>
<!-- Instruction to touch the bubble to start typing -->
<string name="touch_to_finish">Αγγίξτε εδώ για να κλείσετε τη συμβουλή και να ξεκινήσετε την πληκτρολόγηση!</string>
<string name="touch_to_finish">Αγγίξτε εδώ για να κλείσετε την υπόδειξη και να ξεκινήσετε την πληκτρολόγηση!</string>
<!-- Tutorial tip 1 - The keyboard opens any time you touch a text field -->
<string name="tip_to_open_keyboard"><b>\"Το πληκτρολόγιο ανοίγει κάθε φορά που αγγίζετε ένα πεδίο κειμένου\"</b></string>
<string name="tip_to_open_keyboard"><b>Το πληκτρολόγιο ανοίγει κάθε φορά που αγγίζετε ένα πεδίο κειμένου</b></string>
<!-- Tutorial tip 2 - Touch and hold a key to view accents (examples) -->
<string name="tip_to_view_accents"><b>\"Αγγίξτε και κρατήστε κάποιο πλήκτρο για να προβάλετε τους τονισμένους χαρακτήρες\"\n\"(ø, ö, ô, ó κ.τ.λ.)\"</b></string>
<!-- Tutorial tip 3 - How to switch to number/symbol keyboard -->
<string name="tip_to_open_symbols"><b>\"Αλλαγή σε αριθμούς και σύμβολα με το πάτημα αυτού του πλήκτρου\"</b></string>
<string name="tip_to_open_symbols"><b>Αλλαγή σε αριθμούς και σύμβολα με το πάτημα αυτού του πλήκτρου</b></string>
<!-- Tutorial tip 4 - How to switch back to alphabet keyboard -->
<string name="tip_to_close_symbols"><b>\"Επιστρέψτε στα γράμματα αγγίζοντας ξανά αυτό το πλήκτρο\"</b></string>
<string name="tip_to_close_symbols"><b>Επιστρέψτε στα γράμματα αγγίζοντας ξανά αυτό το πλήκτρο</b></string>
<!-- Tutorial tip 5 - How to launch keyboard settings -->
<string name="tip_to_launch_settings"><b>\"Αγγίξτε και κρατήστε πατημένο αυτό το πληκτρολόγιο για να αλλάξετε τις ρυθμίσεις πληκτρολογίου, όπως η αυτόματη συμπλήρωση\"</b></string>
<string name="tip_to_launch_settings"><b>Αγγίξτε και κρατήστε πατημένο αυτό το πλήκτρο για να αλλάξετε τις ρυθμίσεις πληκτρολογίου, όπως η αυτόματη συμπλήρωση</b></string>
<!-- Tutorial tip 6 - Done with the tutorial -->
<string name="tip_to_start_typing"><b>\"Δοκιμάστε το!\"</b></string>
<string name="tip_to_start_typing"><b>Δοκιμάστε το!</b></string>
<!-- Label for soft enter key when it performs GO action. Must be short to fit on key! -->
<string name="label_go_key">Μετ.</string>
<string name="label_go_key">Μετάβαση</string>
<!-- Label for soft enter key when it performs NEXT action. Must be short to fit on key! -->
<string name="label_next_key">Επόμενο</string>
<!-- Label for soft enter key when it performs DONE action. Must be short to fit on key! -->

View File

@@ -21,7 +21,7 @@
<!-- Title for Latin keyboard -->
<string name="english_ime_name">== Keepass2Android 键盘 ==</string>
<!-- Title for Latin keyboard settings activity / dialog -->
<string name="english_ime_settings">USB 键盘设置</string>
<string name="english_ime_settings">键盘设置</string>
<!-- Title for Latin keyboard input options dialog -->
<string name="english_ime_input_options">输入选项</string>
<!-- Option to provide vibrate/haptic feedback on keypress -->
@@ -29,23 +29,23 @@
<!-- Option to play back sound on keypress in soft keyboard -->
<string name="sound_on_keypress">按键声音</string>
<!-- Option to pop up the character with a larger font above soft keyboard -->
<string name="popup_on_keypress">按键弹出放大</string>
<string name="popup_on_keypress">按键弹出显示</string>
<!-- Option to enable using nearby keys when correcting/predicting -->
<string name="hit_correction">智能纠错</string>
<!-- Description for hit_correction -->
<string name="hit_correction_summary">启用输入错误校正</string>
<!-- Option to enable using nearby keys when correcting/predicting in landscape-->
<string name="hit_correction_land">横屏输入错</string>
<string name="hit_correction_land">横屏输入</string>
<!-- Description for hit_correction in landscape -->
<string name="hit_correction_land_summary">启用输入错误校正</string>
<!-- Option to automatically correct word on hitting space -->
<string name="auto_correction">单词联想</string>
<string name="auto_correction">输入建议</string>
<!-- Description for auto_correction -->
<string name="auto_correction_summary">自动更正前一个单词</string>
<!-- Option to enable text prediction -->
<string name="prediction">单词联想</string>
<string name="prediction">输入建议</string>
<!-- Category title for text prediction -->
<string name="prediction_category"> 词语建议设置</string>
<string name="prediction_category">输入建议设置</string>
<!-- Description for text prediction -->
<string name="prediction_summary">在输入时启用自动补全</string>
<!-- Dialog title for auto complete choices -->
@@ -91,7 +91,7 @@
<!-- Option to enable bigram completion -->
<string name="bigram_suggestion">二元语法分词建议</string>
<!-- Description for auto completion -->
<string name="bigram_suggestion_summary">使用曾经使用过的词语改进建议</string>
<string name="bigram_suggestion_summary">使用前一个单词来改进建议</string>
<!-- Array of prediction modes -->
<string-array name="prediction_modes">
<item></item>

View File

@@ -530,7 +530,7 @@ public abstract class Kp2aFileProvider extends BaseFileProvider {
* parameters.
*/
private MatrixCursor doRetrieveFileInfo(Uri uri) {
Log.d(CLASSNAME, "retrieve file info "+uri.toString());
MatrixCursor matrixCursor = BaseFileProviderUtils.newBaseFileCursor();
String filename = extractFile(uri);

View File

@@ -43,7 +43,7 @@
</queries>
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="30" />
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="31" />
<permission android:description="@string/permission_desc2" android:icon="@drawable/ic_notify_locked" android:label="KP2A entry search" android:name="keepass2android.keepass2android_debug.permission.KP2aInternalSearch" android:protectionLevel="signature" />
<permission android:description="@string/permission_desc3" android:icon="@drawable/ic_launcher" android:label="KP2A choose autofill dataset" android:name="keepass2android.keepass2android_debug.permission.Kp2aChooseAutofill" android:protectionLevel="signature" />
<application
@@ -55,7 +55,7 @@
<uses-library
android:name="org.apache.http.legacy"
android:required="false"/>
<activity android:name="microsoft.identity.client.BrowserTabActivity">
<activity android:name="microsoft.identity.client.BrowserTabActivity" android:exported="true">
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
@@ -63,7 +63,7 @@
<data android:scheme="msal8374f801-0f55-407d-80cc-9a04fe86d9b2" android:host="auth" />
</intent-filter>
</activity>
<activity android:name="com.dropbox.core.android.AuthActivity" android:launchMode="singleTask" android:configChanges="orientation|keyboard">
<activity android:name="com.dropbox.core.android.AuthActivity" android:launchMode="singleTask" android:configChanges="orientation|keyboard" android:exported="true">
<intent-filter>
<data android:scheme="db-2gormiq7iq1jls1" />
<action android:name="android.intent.action.VIEW" />
@@ -83,13 +83,13 @@
<provider android:name="group.pals.android.lib.ui.filechooser.providers.history.HistoryProvider" android:authorities="keepass2android.keepass2android_debug.android-filechooser.history" android:exported="false" />
<activity android:name="group.pals.android.lib.ui.filechooser.FileChooserActivity" android:configChanges="keyboard|keyboardHidden|orientation|screenSize" android:screenOrientation="user" android:theme="@style/Afc.Theme.Light">
</activity>
<service android:name="keepass2android.softkeyboard.KP2AKeyboard" android:permission="android.permission.BIND_INPUT_METHOD">
<service android:name="keepass2android.softkeyboard.KP2AKeyboard" android:permission="android.permission.BIND_INPUT_METHOD" android:exported="true">
<intent-filter>
<action android:name="android.view.InputMethod" />
</intent-filter>
<meta-data android:name="android.view.im" android:resource="@xml/method" />
</service>
<activity android:name="keepass2android.softkeyboard.LatinIMESettings" android:label="@string/english_ime_settings">
<activity android:name="keepass2android.softkeyboard.LatinIMESettings" android:label="@string/english_ime_settings" android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
</intent-filter>
@@ -99,7 +99,8 @@
</intent-filter>
</activity>
<activity android:name="keepass2android.softkeyboard.InputLanguageSelection"
android:label="@string/language_selection_title">
android:label="@string/language_selection_title"
android:exported="true" >
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<action android:name="keepass2android.softkeyboard.INPUT_LANGUAGE_SELECTION"/>
@@ -107,7 +108,7 @@
</intent-filter>
</activity>
<activity android:configChanges="orientation|keyboard|keyboardHidden" android:label="@string/app_name" android:theme="@style/MyTheme_Blue" android:name="keepass2android.SelectCurrentDbActivity" android:windowSoftInputMode="adjustResize">
<activity android:configChanges="orientation|keyboard|keyboardHidden" android:label="@string/app_name" android:theme="@style/MyTheme_Blue" android:name="keepass2android.SelectCurrentDbActivity" android:windowSoftInputMode="adjustResize" android:exported="true">
<intent-filter android:label="@string/app_name">
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
@@ -252,13 +253,13 @@ The scheme=file is still there for old OS devices. It's also queried by apps lik
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.USE_CREDENTIALS" />
<uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />
<uses-permission android:name="android.permission.USE_CREDENTIALS" android:maxSdkVersion="22" />
<uses-permission android:name="android.permission.MANAGE_ACCOUNTS" android:maxSdkVersion="22" />
<uses-permission android:name="keepass2android.keepass2android_debug.permission.KP2aInternalFileBrowsing" />
<uses-permission android:name="android.permission.USE_FINGERPRINT" />
<uses-permission android:name="android.permission.USE_BIOMETRIC" />
<!-- Samsung Pass permission -->
<uses-permission android:name="com.samsung.android.providers.context.permission.WRITE_USE_APP_FEATURE_SURVEY" />
<!-- READ_PHONE_STATE seems to come from some library or so, not clear where. We don't want to have it, remove it: -->
<uses-permission android:name="android.permission.READ_PHONE_STATE" tools:node="remove" />
</manifest>

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:versionCode="191"
android:versionName="1.09e-r3"
android:versionCode="197"
android:versionName="1.09e-r7"
package="keepass2android.keepass2android"
xmlns:tools="http://schemas.android.com/tools"
android:installLocation="auto">
@@ -103,8 +103,8 @@
</intent-filter>
</activity>
<activity android:name="keepass2android.softkeyboard.InputLanguageSelection"
android:label="@string/language_selection_title"
android:exported="true">
android:label="@string/language_selection_title"
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<action android:name="keepass2android.softkeyboard.INPUT_LANGUAGE_SELECTION"/>
@@ -272,5 +272,5 @@ The scheme=file is still there for old OS devices. It's also queried by apps lik
<uses-permission android:name="android.permission.USE_BIOMETRIC" />
<!-- Samsung Pass permission -->
<uses-permission android:name="com.samsung.android.providers.context.permission.WRITE_USE_APP_FEATURE_SURVEY" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" tools:node="remove" />
</manifest>

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
android:versionCode="191"
android:versionName="1.09e-r3"
android:versionCode="197"
android:versionName="1.09e-r7"
package="keepass2android.keepass2android_nonet"
xmlns:tools="http://schemas.android.com/tools"
android:installLocation="auto">
@@ -246,5 +246,6 @@ The scheme=file is still there for old OS devices. It's also queried by apps lik
<uses-permission android:name="keepass2android.keepass2android_nonet.permission.KP2aInternalFileBrowsing" />
<uses-permission android:name="keepass2android.keepass2android_nonet.permission.KP2aInternalSearch" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" tools:node="remove" />
</manifest>

View File

@@ -689,6 +689,7 @@
<item>Fejlrettelse til nedbrud og uventede log-outs</item>
<item>Skift til ny SFTP-implementering, som understøtter moderne offentlige nøglealgoritmer såsom rsa-sha2-256</item>
<item>Markér adgangskoder som følsomme ved kopiering til udklipsholder (Android 13)</item>
<item>Autofill improvements</item>
</string-array>
<string-array name="ChangeLog_1_09d">
<item>Tilføjet understøttelse af visning, fjernelse og gendannelse af sikkerhedskopierede poster</item>

View File

@@ -529,7 +529,7 @@ Der Android Robot wird genutzt und wurde modifiziert basierend auf Arbeiten, die
<string name="filestoragename_onedrive2_appfolder">Ordner der Keepass2Android-App</string>
<string name="filestoragename_sftp">SFTP (SSH File Transfer)</string>
<string name="filestoragename_mega">MEGA</string>
<string name="filestoragehelp_mega">Bitte beachten: Keepass2Android muss die Liste aller Dateien des Mega-Konto herunterladen, um ordnungsgemäß zu funktionieren. Aus diesem Grund ist der Zugriff auf Konten mit vielen Dateien möglicherweise langsam.</string>
<string name="filestoragehelp_mega">Bitte beachte: Keepass2Android muss eineListe aller Dateien des Mega-Kontos herunterladen, um ordnungsgemäß zu funktionieren. Aus diesem Grund ist der Zugriff auf Konten mit vielen Dateien möglicherweise langsam.</string>
<string name="filestoragename_content">Android-Dateibrowser</string>
<string name="filestorage_setup_title">Dateizugriff initialisieren</string>
<string name="database_location">Speicherort der Datenbank</string>
@@ -688,6 +688,7 @@ Anbei einige Tipps, die bei der Diagnose des Problems helfen können:\n
<item>Fehlerbehebung, um Abstürze und unerwartetes Abmelden zu vermeiden</item>
<item>Wechsel auf eine neue SFTP-Implementierung, jetzt mit Unterstützung von modernen Public-Key-Algorithmen wie rsa-sha2-256</item>
<item>Passwörter werden beim Kopieren in die Zwischenablage als vertraulich markiert (Android 13)</item>
<item>Autofill improvements</item>
</string-array>
<string-array name="ChangeLog_1_09d">
<item>Unterstützung für das Ansehen, Entfernen und Wiederherstellen von Eintragssicherungen hinzugefügt</item>
@@ -1069,8 +1070,8 @@ Erstes öffentliches Release</string>
<string name="enable_fingerprint_hint">Keepass2Android hat biometrische Hardware erkannt. Soll Biometrisches Entsperren für diese Datenbank aktiviert werden?</string>
<string name="understand">Okay, verstanden</string>
<string name="dont_show_again">Nicht erneut anzeigen</string>
<string name="masterkey_infotext_head">Ist das Hauptpasswort bekannt?</string>
<string name="masterkey_infotext_main">Bitte beachten, dass die Datenbank ohne den Hauptschlüssel nicht geöffnet werden kann. Es gibt keine Möglichkeit, das Hauptpasswort „zurückzusetzen“.</string>
<string name="masterkey_infotext_head">Kennst du dein Master-Passwort?</string>
<string name="masterkey_infotext_main">Bitte beachte, dass du deine Datenbank ohne den Hauptschlüssel nicht öffnen kannst. Es gibt keine Möglichkeit, das Hauptpasswort „zurückzusetzen“.</string>
<string name="masterkey_infotext_fingerprint_note">Bitte auch bedenken, dass das Biometrische Entsperren über das Speichern des Hauptschlüssels im sicheren Speicher von Android funktioniert. Dieser Speicher kann von Android jederzeit gelöscht werden, z. B. wenn ein neuer Fingerabdruck in den Systemeinstellungen hinzugefügt wird. Daher sich nicht auf das biometrische Entsperren verlassen, sondern sich bitte das eigene Hauptpasswort merken!</string>
<string name="backup_infotext_head">Gibt es eine Sicherung der Datenbank?</string>
<string name="backup_infotext_main">Keepass2Android speichert die Passwörter in einer Datei an einem frei wählbarem Speicherort.Ist sichergestellt, dass die Datei auch dann noch verfügbar ist, wenn das Telefon verloren geht oder gestohlen wird, oder wenn die Datei zerstört oder gelöscht wird? Bitte sicherstellen, dass immer eine aktuelle Kopie an einem sichern Ort aufbewahrt wird!</string>

View File

@@ -301,6 +301,8 @@
<string name="NoDalVerification_summary">Απενεργοποιεί τον έλεγχο αν ταιριάζει ο τομέας και το πακέτο εφαρμογής</string>
<string name="InlineSuggestions_title">Ενσωμάτωση με πληκτρολόγιο</string>
<string name="InlineSuggestions_summary">Δείχνει τις προτάσεις αυτόματης συμπλήρωσης ως γραμμές μέσα στο πρηκτρολόγιο</string>
<string name="LogAutofillView_title">Προβολή αυτόματης συμπλήρωσης αρχείου καταγραφής</string>
<string name="LogAutofillView_summary">Εγγραφή λεπτομερειών σχετικά με την προβολή αυτόματης συμπλήρωσης στο αρχείο καταγραφής αποσφαλμάτωσης (αν η καταγραφή αποσφαλμάτωσης είναι ενεργοποιημένη). Αυτές οι λεπτομέρειες μπορούν να σταλούν στον προγραμματιστή αν η αυτόματη συμπλήρωση δε λειτουργεί όπως αναμενόταν.</string>
<string name="requires_android11">Απαιτείται Android 11 ή νεότερη έκδοση</string>
<string name="kp2a_findUrl">Εύρεση συνθηματικού</string>
<string name="excludeExpiredEntries">Εξαίρεση ληγμένων εγγραφών</string>
@@ -330,7 +332,7 @@
<string name="QuickUnlockHideLength_title">Απόκρυψη μήκους QuickUnlock</string>
<string name="QuickUnlockHideLength_summary">Αν ενεργοποιηθεί, αποκρύπτει το μήκος του κωδικού QuickUnlock στη σχετική οθόνη.</string>
<string name="QuickUnlockKeyFromDatabase_title">Κλειδί QuickUnlock από τη βάση δεδομένων</string>
<string name="QuickUnlockKeyFromDatabase_summary">Εάν η ενεργή βάση δεδομένων περιέχει μια καταχώρηση με τίτλο QuickUnlock στην ομάδα ρίζας της, ο κωδικός πρόσβασης αυτής της καταχώρησης χρησιμοποιείται ως κωδικός QuickUnlock.</string>
<string name="QuickUnlockKeyFromDatabase_summary">Εάν η ενεργή βάση δεδομένων περιέχει μια καταχώριση με τίτλο QuickUnlock στην ομάδα ρίζας της, ο κωδικός πρόσβασης αυτής της καταχώρισης χρησιμοποιείται ως κωδικός QuickUnlock.</string>
<string name="QuickUnlock_fail">Αποτυχία QuickUnlock: λανθασμένο συνθηματικό!</string>
<string name="SaveAttachmentDialog_title">Αποθήκευση συνημμένου</string>
<string name="SaveAttachmentDialog_text">Επιλέξτε πού θα αποθηκεύσετε το συνημμένο.</string>
@@ -427,7 +429,7 @@
<string name="AskOverwriteBinary_no">Μετονομασία</string>
<string name="AttachFailed">Απέτυχε η προσθήκη του συνημμένου αρχείου.</string>
<string name="RecycleBin">Κάδος ανακύκλωσης</string>
<string name="AskDeletePermanentlyEntry">Θέλετε να διαγράψετε οριστικά αυτή την καταχώριση; Πατήστε όχι για να ανακύκλωση.</string>
<string name="AskDeletePermanentlyEntry">Θέλετε να διαγράψετε οριστικά αυτή την καταχώριση; Πατήστε όχι για ανακύκλωση.</string>
<string name="AskDeletePermanentlyGroup">Θέλετε να διαγράψετε οριστικά αυτή την ομάδα; Πατήστε όχι για ανακύκλωση.</string>
<string name="AskDeletePermanentlyItems">Θέλετε να διαγράψετε οριστικά τα επιλεγμένα στοιχεία; Πατήστε όχι για ανακύκλωση.</string>
<string name="AskDeletePermanentlyEntryNoRecycle">Θέλετε να διαγράψετε οριστικά αυτή την καταχώριση;</string>
@@ -540,7 +542,7 @@
<string name="help_master_password">Η βάση δεδομένων είναι κρυπτογραφημένη με το συνθηματικό που εισάγετε εδώ. Επιλέξτε ένα ισχυρό συνθηματικό προκειμένου να διατηρείτε τη βάση δεδομένων ασφαλή! Συμβουλή: Συνθέστε μια-δυο φράσεις και χρησιμοποιήστε τα πρώτα γράμματα των λέξεων ως συνθηματικό. Συμπεριλάβετε σημεία στίξης.</string>
<string name="hint_master_password">Επιλέξτε κύριο συνθηματικό για την προστασία της βάσης δεδομένων:</string>
<string name="key_file">Αρχείο κλειδιού</string>
<string name="help_key_file">Το αρχείο κλειδιού είναι βασικά ένα συνθηματικό αποθηκευμένο σε ένα αρχείο. Τα αρχείο κλειδιού είναισυνήθως ισχυρότερα από τα κύρια συνθηματικά, γιατί το κλειδί μπορεί να είναι πιο σύνθετο, ωστόσο είναι ε΄πίσης δυσκολότερο να διατηρηθούν μυστικά. Αν αποθηκεύεις τη βάση δεδομένων στο σύννεφο, μην αποθηκεύσεις και το αρχείο κλειδί εκεί! Αυτό θα το έκανε εντελώς άχρηστο! Σημαντικό: Μην αλλάζετε τα περιεχόμενο του αρχείου κλειδιού αφού δημιουργηθεί η βάση δεδομένων!</string>
<string name="help_key_file">Το αρχείο κλειδιού είναι βασικά ένα συνθηματικό αποθηκευμένο σε ένα αρχείο. Τα αρχεία κλειδιού είναι συνήθως ισχυρότερα από τα κύρια συνθηματικά, γιατί το κλειδί μπορεί να είναι πιο σύνθετο, ωστόσο είναι επίσης δυσκολότερο να διατηρηθούν μυστικά. Αν αποθηκεύεις τη βάση δεδομένων στο σύννεφο, μην αποθηκεύσεις και το αρχείο κλειδιού εκεί! Αυτό θα το έκανε εντελώς άχρηστο! Σημαντικό: Μην αλλάζετε τα περιεχόμενο του αρχείου κλειδιού αφού δημιουργηθεί η βάση δεδομένων!</string>
<string name="hint_key_file">Επιλέξτε αν θέλετε να χρησιμοποιήσετε ένα αρχείο κλειδιού, εκτός από το κύριο συνθηματικό:</string>
<string name="use_key_file">Χρήση αρχείου κλειδιού</string>
<string name="error_adding_keyfile">Παρουσιάστηκε σφάλμα κατά την προσθήκη του αρχείου κλειδιού!</string>
@@ -570,9 +572,9 @@
<string name="TrayTotp_SettingsField_title">Όνομα πεδίου στις ρυθμίσεις TOTP</string>
<string name="TrayTotp_SettingsField_summary">Εισάγετε όνομα πεδίου από ρυθμίσεις TrayTotp.</string>
<string name="TrayTotp_prefs">TrayTotp</string>
<string name="DebugLog_prefs_prefs">Αρχείο καταχώρησης για αποσφαλματοποίηση</string>
<string name="DebugLog_title">Χρήση αρχείου καταχώρησης</string>
<string name="DebugLog_summary">Καταγραφή στοιχείων εφαρμογής σε τοπικό αρχείο καταχώρησης</string>
<string name="DebugLog_prefs_prefs">Αρχείο καταγραφών για αποσφαλμάτωση</string>
<string name="DebugLog_title">Χρήση αρχείου καταγραφών</string>
<string name="DebugLog_summary">Καταγραφή στοιχείων της εφαρμογής σε τοπικό αρχείο καταγραφών</string>
<string name="DebugLog_send">Αποστολή αρχείων καταγραφής εκσφαλμάτωσης...</string>
<string name="loading">Φόρτωση…</string>
<string name="plugins">Πρόσθετα</string>
@@ -682,6 +684,12 @@
<string name="EntryChannel_desc">Ειδοποίηση για απλοποιημένη πρόσβαση στην τρέχουσα καταχώριση.</string>
<string name="CloseDbAfterFailedAttempts">Κλείσιμο της βάσης δεδομένων μετά από 3 ανεπιτυχείς προσπάθειες βιομετρικού ξεκλειδώματος.</string>
<string name="WarnFingerprintInvalidated">Προσοχή! Ο βιομετρικός έλεγχος ταυτότητας μπορεί να ακυρωθεί από το Android, π.χ. μετά την προσθήκη ενός νέου δακτυλικού αποτυπώματος στις ρυθμίσεις της συσκευής σας. Βεβαιωθείτε ότι ξέρετε πάντα πώς να ξεκλειδώσετε με τον κύριο κωδικό πρόσβασης!</string>
<string-array name="ChangeLog_1_09e">
<item>Διόρθωση σφάλματος για απότομα κλεισίματα εφαρμογής και μη αναμενόμενες αποσυνδέσεις</item>
<item>Μετάβαση σε νέα υλοποίηση SFTP, υποστηρίζοντας σύγχρονους αλγόριθμους δημόσιου κλειδιού όπως rsa-sha2-256</item>
<item>Μαρκάρισμα κωδικών πρόσβασης ως ευαίσθητοι κατά την αντιγραφή στο πρόχειρο (Android 13)</item>
<item>Βελτιώσεις Autofill</item>
</string-array>
<string-array name="ChangeLog_1_09d">
<item>Υποστηρίζεται πλέον προβολή, διαγραφή και ανάκτηση των διαγραμμένων εγγραφών</item>
<item>Υλοποιήθηκε υποστήριξη για αποθήκευση στο νέφος MEGA </item>

View File

@@ -172,7 +172,9 @@
<string name="MaskedPassword">*****</string>
<string name="maskpass_title">Piilota salasana</string>
<string name="maskpass_summary">Piilota salasanat oletuksena</string>
<string name="masktotp_title">Peitä TOTP-kenttä</string>
<string name="masktotp_summary">Piilota TOTP-kenttä oletuksena</string>
<string name="NoAutofillDisabling_summary">Jos aktivoitu, sovellus ei näytä vaihtoehtoa poistaa automaattista täyttöä tiettyjen merkintöjen osalta.</string>
<string name="menu_about">Tietoja</string>
<string name="menu_change_key">Vaihda pääavain</string>
<string name="menu_copy_pass">Kopioi salasana</string>
@@ -285,6 +287,8 @@
<string name="please_note">Huomaa</string>
<string name="contributors">Kehittäjät ja avustajat</string>
<string name="regular_expression">Säännöllinen lauseke</string>
<string name="AlwaysMergeOnConflict_title">Yhdistä aina ristiriidan yhteydessä</string>
<string name="AlwaysMergeOnConflict_summary">Kun Keepass2Android havaitsee, että etätiedostoa on muokattu, yhdistetään paikalliset muutokset aina etämuutoksiin.</string>
<string name="TanExpiresOnUse_title">TAN käytön lopetus</string>
<string name="TanExpiresOnUse_summary">Merkitse TAN-merkinnät vanhentuneiksi käytön jälkeen</string>
<string name="ShowUsernameInList_title">Näytä käyttäjänimi</string>
@@ -323,6 +327,7 @@
<string name="QuickUnlockLength_summary">Pika-avauksessa käytettävien merkkien enimmäismäärä.</string>
<string name="QuickUnlockHideLength_title">Piilota pika-avauskoodin pituus</string>
<string name="QuickUnlockHideLength_summary">Jos käytössä, pika-avauskoodin pituutta ei näytetä pika-avausnäytössä.</string>
<string name="QuickUnlockKeyFromDatabase_title">QuickUnlock-avain tietokannan syötteestä</string>
<string name="QuickUnlock_fail">Pika-avaus epäonnistui: väärä salasana!</string>
<string name="SaveAttachmentDialog_title">Tallenna liite</string>
<string name="SaveAttachmentDialog_text">Valitse liitteen tallennuspaikka.</string>
@@ -946,7 +951,7 @@ Suojelee sinua Leikepöytään perustuvalta salasana sniffaukselta (Poista vanha
<item>Salasana + OTP salaus (Palautustila)</item>
<item>Salasana + Haastemenetelmä</item>
<item>Salasana + Haastemenetelmä (palautustila)</item>
<item>Salasana + Avaintiedosto + Haastemenetelmä Keepass XC:n kanssa</item>
<item>Salasana + Haastemenetelmä Keepass XC:n kanssa</item>
<item>Salasana + Avaintiedosto + Haastemenetelmä Keepass XC:n kanssa</item>
</string-array>
<string-array name="sftp_auth_modes">

View File

@@ -687,6 +687,7 @@ Voici quelques conseils qui pourraient aider à diagnostiquer le problème : \n
<item>Correction de bugs pour les plantages et les déconnexions inattendues</item>
<item>Passage à une nouvelle implémentation SFTP, prenant en charge les algorithmes à clé publique modernes tels que rsa-sha2-256</item>
<item>Marquer les mots de passe comme sensibles lors de la copie dans le presse-papiers (Android 13)</item>
<item>Autofill improvements</item>
</string-array>
<string-array name="ChangeLog_1_09d">
<item>Ajout du support pour la visualisation, la suppression et la restauration des sauvegardes d\'entrée</item>

View File

@@ -301,6 +301,8 @@
<string name="NoDalVerification_summary">Disabilita il controllo se i pacchetti di dominio e applicazione corrispondono</string>
<string name="InlineSuggestions_title">Integra con la tastiera</string>
<string name="InlineSuggestions_summary">Mostra i suggerimenti di completamento automatico come opzioni in linea sulla tastiera (se supportato dal metodo di inserimento)</string>
<string name="LogAutofillView_title">Visualizza log autocompilazione</string>
<string name="LogAutofillView_summary">Scrivi i dettagli sulla visualizzazione del riempimento automatico per il log di debug (se il log di debug è abilitato). Questi dettagli possono essere inviati allo sviluppatore se il riempimento automatico non funziona come previsto.</string>
<string name="requires_android11">Richiede Android 11 o versioni successive</string>
<string name="kp2a_findUrl">Trova password</string>
<string name="excludeExpiredEntries">Escludi voci scadute</string>
@@ -683,6 +685,12 @@ Ecco alcuni suggerimenti che ti potrebbero aiutare a diagnosticare il problema:\
<string name="EntryChannel_desc">Notifica per semplificare l\'accesso alla voce attualmente selezionata.</string>
<string name="CloseDbAfterFailedAttempts">Chiudi il database dopo tre tentativi di sblocco biometrici falliti.</string>
<string name="WarnFingerprintInvalidated">Attenzione! L\'autenticazione biometrica può essere invalidata da Android, ad es. dopo aver aggiunto una nuova impronta digitale nelle impostazioni del dispositivo. Assicurati di sapere sempre come sbloccare con la tua password principale!</string>
<string-array name="ChangeLog_1_09e">
<item>Correzione bug per crash e logout non previsti</item>
<item>Passa alla nuova implementazione SFTP, supportando moderni algoritmi a chiave pubblica come rsa-sha2-256</item>
<item>Contrassegna le password come sensibili quando si copiano negli appunti (Android 13)</item>
<item>Migliorie Riempimento automatico</item>
</string-array>
<string-array name="ChangeLog_1_09d">
<item>Aggiunto il supporto per la visualizzazione, la rimozione e il ripristino dei backup delle voci</item>
<item>Implementato supporto per l\'archiviazione su cloud MEGA</item>

View File

@@ -36,7 +36,7 @@
<string name="OfferSaveCredentials_title">アカウント情報の保存を提案</string>
<string name="ShowGroupInEntry_title">エントリー画面にグループ名を表示</string>
<string name="unknown_uri_scheme">申し訳ありません! Keepass2Android は、返された URI %1$s を処理できませんでした。開発者にお問い合わせください!</string>
<string name="Entry_singular">1 エントリー</string>
<string name="Entry_singular">1 件のエントリー</string>
<string name="Entry_plural">%1$d 件のエントリー</string>
<string name="IconSet_title">アイコンセット</string>
<string name="IconSet_install">さらに探す…</string>
@@ -301,6 +301,8 @@
<string name="NoDalVerification_summary">ドメインとアプリパッケージが一致するかどうかの確認を無効にします</string>
<string name="InlineSuggestions_title">キーボードとの統合</string>
<string name="InlineSuggestions_summary">自動入力のサジェストをキーボード内に表示します (対応する入力方法のみ)</string>
<string name="LogAutofillView_title">自動入力表示のログ</string>
<string name="LogAutofillView_summary">(デバッグログが有効な場合) 自動入力表示に関する詳細をデバッグログに書き込みます。自動入力が予想に反する動作をした場合、これらの詳細を開発者に送信することができます。</string>
<string name="requires_android11">Android 11 以上が必要</string>
<string name="kp2a_findUrl">パスワードを探す</string>
<string name="excludeExpiredEntries">期限切れのエントリーを除外する</string>
@@ -690,6 +692,7 @@
<item>クラッシュと突発的にログアウトするバグを修正</item>
<item>rsa-sha2-256 などの最新の公開鍵アルゴリズムをサポートする、新しい SFTP 実装に切り替え</item>
<item>パスワードをクリップボードにコピーしたとき、機密コンテンツとしてマークするよう変更 (Android 13)</item>
<item>自動入力の改善</item>
</string-array>
<string-array name="ChangeLog_1_09d">
<item>エントリーバックアップの表示、削除、および復元に対応</item>

View File

@@ -301,6 +301,8 @@
<string name="NoDalVerification_summary">Schakelt controle of domein en app pakket overeenkomen uit </string>
<string name="InlineSuggestions_title">Integreer met toetsenbord</string>
<string name="InlineSuggestions_summary">Toont de suggesties voor automatisch aanvullen als inline-opties in het toetsenbord (indien ondersteund door de invoermethode)</string>
<string name="LogAutofillView_title">Automatisch invullen loggen</string>
<string name="LogAutofillView_summary">Schrijf details over de autofill weergave naar debug log (als debug logging is ingeschakeld). Deze details kunnen naar de ontwikkelaar worden verzonden als het automatisch invullen niet werkt zoals verwacht.</string>
<string name="requires_android11">Vereist Android 11 of hoger</string>
<string name="kp2a_findUrl">Zoek wachtwoord</string>
<string name="excludeExpiredEntries">Verlopen items uitsluiten</string>
@@ -687,6 +689,12 @@
<string name="EntryChannel_desc">Melding voor vereenvoudigde toegang van het nu geselecteerde item.</string>
<string name="CloseDbAfterFailedAttempts">Sluit de database na drie mislukte biometrische ontgrendelpogingen.</string>
<string name="WarnFingerprintInvalidated">Waarschuwing! Biometrische authenticatie wordt uitgeschakeld door Android, bijv. na het toevoegen van een nieuwe vingerafdruk in de instellingen van jouw apparaat. Zorg ervoor dat je de database altijd kunt ontgrendelen met het hoofdwachtwoord!</string>
<string-array name="ChangeLog_1_09e">
<item>Bug fix op crashes en onverwachte log-outs</item>
<item>Schakel over naar nieuwe SFTP-implementatie ter ondersteuning van moderne publieke sleutel algoritmen zoals rsa-sha2-256</item>
<item>Wachtwoorden als gevoelig markeren bij het kopiëren naar klembord (Android 13)</item>
<item>Autofill verbeteringen</item>
</string-array>
<string-array name="ChangeLog_1_09d">
<item>Toegevoegde ondersteuning voor het bekijken, verwijderen en herstellen van invoer back-ups</item>
<item>Implementatie ondersteuning voor MEGA cloud opslag</item>

View File

@@ -690,6 +690,7 @@
<item>Naprawa błędów awarii i nieoczekiwanych wylogowań</item>
<item>Przełącz się na nową implementację SFTP, wspierając nowoczesne algorytmy klucza publicznego, takie jak rsa-sha2-256</item>
<item>Oznacz hasła jako wrażliwe podczas kopiowania do schowka (Android 13)</item>
<item>Autofill improvements</item>
</string-array>
<string-array name="ChangeLog_1_09d">
<item>Dodano wsparcie dla przeglądania, usuwania i przywracania kopii zapasowych wpisów</item>

View File

@@ -303,6 +303,8 @@
<string name="NoDalVerification_summary">Desativa a checagem se domínio e pacote do app correspondem.</string>
<string name="InlineSuggestions_title">Integrar com o teclado</string>
<string name="InlineSuggestions_summary">Mostra sugestões de Autopreenchimento como opção na linha no teclado (se suportado pelo método de entrada)</string>
<string name="LogAutofillView_title">Registrar exibição de preenchimento automático</string>
<string name="LogAutofillView_summary">Escreva detalhes sobre a exibição de preenchimento automático para registro de depuração (se o registro de depuração estiver habilitado). Esses detalhes podem ser enviados ao desenvolvedor se o preenchimento automático não funcionar conforme o esperado.</string>
<string name="requires_android11">Requer Android 11 ou posterior</string>
<string name="kp2a_findUrl">Keepass2Android: Buscar senha</string>
<string name="excludeExpiredEntries">Excluir entradas expiradas</string>
@@ -690,6 +692,7 @@
<item>Correção de bugs em falhas e logouts inesperados</item>
<item>Mudar para nova implementação SFTP, suportando algoritmos de chave pública modernos como rsa-sha2-256</item>
<item>Marcar senhas como confidenciais ao copiar para a área de transferência (Android 13)</item>
<item>Melhorias no preenchimento automático</item>
</string-array>
<string-array name="ChangeLog_1_09d">
<item>Adicionado suporte para visualização, remoção e restauração de backups de entrada</item>

View File

@@ -690,6 +690,7 @@
<item>Oprava chyby vedúcej k pádom a neočakávaným odhláseniam</item>
<item>Prepnutie na novú implementáciu SFTP, s podporou pre moderné algoritmy verejných kľúčov, ako je rsa-sha2-256</item>
<item>Označiť heslá ako citlivé údaje pri kopírovaní do schránky (Android 13)</item>
<item>Autofill improvements</item>
</string-array>
<string-array name="ChangeLog_1_09d">
<item>Pridaná podpora prehliadania, odstraňovania a obnovovania záloh záznamu</item>

View File

@@ -301,6 +301,8 @@
<string name="NoDalVerification_summary">Onemogoči preverjanje, ali se paket domen in aplikacije ujemata</string>
<string name="InlineSuggestions_title">Integracija s tipkovnico</string>
<string name="InlineSuggestions_summary">Prikaže predloge samodejnega izpolnjevanja kot vgrajene možnosti na tipkovnici (če to podpira način vnosa)</string>
<string name="LogAutofillView_title">Pregled podrobnosti samodejnega izpolnjevanja</string>
<string name="LogAutofillView_summary">Zapišite podrobnosti o pogledu samodejnega izpolnjevanja v dnevnik odpravljanja napak (če je omogočeno beleženje odpravljanja napak). Te podrobnosti lahko pošljete razvijalcu, če samodejno izpolnjevanje ne deluje po pričakovanjih.</string>
<string name="requires_android11">Zahteva Android 11 ali novejši</string>
<string name="kp2a_findUrl">Najdi geslo</string>
<string name="excludeExpiredEntries">Izključi potekle vnose</string>
@@ -690,6 +692,7 @@
<item>Popravek napak pri zrušitvah in nepričakovanih odjavah</item>
<item>Preklopite na novo izvedbo SFTP, ki podpira sodobne algoritme javnih ključev, kot je rsa-sha2-256</item>
<item>Označi gesla kot občutljiva pri kopiranju v odložišče (Android 13)</item>
<item>Izboljšave samodejnega izpolnjevanja</item>
</string-array>
<string-array name="ChangeLog_1_09d">
<item>Dodana podpora za ogled, odstranjevanje in obnavljanje varnostnih kopij vnosov</item>

View File

@@ -301,6 +301,8 @@
<string name="NoDalVerification_summary">Вимкнення перевірки, якщо збігаються домен і пакунок програми</string>
<string name="InlineSuggestions_title">Інтегрувати до клавіатури</string>
<string name="InlineSuggestions_summary">Показує пропозиції автозаповнення як вбудовану опцію в клавіатурі (якщо підтримується методом вводу)</string>
<string name="LogAutofillView_title">Журнал перегляду автозаповнення</string>
<string name="LogAutofillView_summary">Записувати подробиці про перегляд автозаповнення до журналу зневадження (якщо увімкнено журнал зневадження). Ці подробиці можна надсилати розробникам, якщо автозаповнення працює некоректно.</string>
<string name="requires_android11">Потрібна версія Android 11 або новіша</string>
<string name="kp2a_findUrl">Знайти пароль</string>
<string name="excludeExpiredEntries">Виключити прострочені елементи</string>
@@ -690,6 +692,7 @@
<item>Виправлено помилку зі збоями та несподіваними виходами</item>
<item>Перехід на нову реалізацію SFTP з підтримкою сучасних алгоритмів публічного ключа, як-от rsa-sha2-256</item>
<item>Позначати паролі як вразливі під час копіювання до буфера обміну (Android 13)</item>
<item>Вдосконалене автозаповнення</item>
</string-array>
<string-array name="ChangeLog_1_09d">
<item>Додано підтримку перегляду, видалення та відновлення резервних копій записів</item>

View File

@@ -301,6 +301,8 @@
<string name="NoDalVerification_summary">不檢查域名是否符合應用程式包裹</string>
<string name="InlineSuggestions_title">整合到鍵盤</string>
<string name="InlineSuggestions_summary">在鍵盤中內嵌自動填入建議選項 (如輸入法支援) </string>
<string name="LogAutofillView_title">記錄自動填入畫面</string>
<string name="LogAutofillView_summary">記下自動填入畫面的詳情到偵錯日誌(僅啟用時)。自動填入出錯時,可以發送這些詳情給開發者。</string>
<string name="requires_android11">需要 Android 11 以上版本</string>
<string name="kp2a_findUrl">查找密碼</string>
<string name="excludeExpiredEntries">排除過期的項目</string>
@@ -690,6 +692,7 @@
<item>修正當機和意外登出的錯誤</item>
<item>切換成新 SFTP 實作,支援現代公鑰演算法,如 rsa-sha2-256</item>
<item>複製密碼到剪貼簿時設為機密 (Android 13)</item>
<item>自動填入改進</item>
</string-array>
<string-array name="ChangeLog_1_09d">
<item>支援查看、移除和還原項目備份</item>

View File

@@ -301,6 +301,8 @@
<string name="NoDalVerification_summary">不检查域名和应用程序包是否匹配</string>
<string name="InlineSuggestions_title">与键盘集成</string>
<string name="InlineSuggestions_summary">将自动填充建议显示为键盘中的内联选项(如果输入法支持的话)</string>
<string name="LogAutofillView_title">记录自动填充视图</string>
<string name="LogAutofillView_summary">将自动填充视图的详情写入调试日志 (如果启用了调试日志)。 如果自动填充无法正常工作,这些细节可以发送给开发者。</string>
<string name="requires_android11">需要 Android 11 或更高版本</string>
<string name="kp2a_findUrl">找回密码</string>
<string name="excludeExpiredEntries">排除过期的条目</string>
@@ -689,6 +691,7 @@
<item>修复崩溃和意外注销的 bug</item>
<item>切换到新的 SFTP 实现,支持现代公钥算法,例如 rsa-sha2-256</item>
<item>复制到剪贴板时将密码标记为敏感 (Android 13)</item>
<item>自动填充改进</item>
</string-array>
<string-array name="ChangeLog_1_09d">
<item>新增查看、移除和恢复条目备份的功能</item>

View File

@@ -475,22 +475,26 @@ namespace keepass2android
builder.SetMessage(activity.GetString(Resource.String.AskReloadFile));
builder.SetPositiveButton(activity.GetString(Android.Resource.String.Yes),
bool buttonPressed = false;
builder.SetPositiveButton(activity.GetString(Android.Resource.String.Yes),
(dlgSender, dlgEvt) =>
{
{
buttonPressed = true;
CurrentDb.ReloadRequested = true;
activity.SetResult(KeePass.ExitReloadDb);
activity.Finish();
if (actionOnResult != null)
{
actionOnResult(true);
actionOnResult = null;
{
actionOnResult(true);
actionOnResult = null;
}
});
builder.SetNegativeButton(activity.GetString(Android.Resource.String.No), (dlgSender, dlgEvt) =>
{
if (actionOnResult != null)
{
buttonPressed = true;
if (actionOnResult != null)
{
actionOnResult(false);
actionOnResult = null;
@@ -501,10 +505,18 @@ namespace keepass2android
Dialog dialog = builder.Create();
dialog.SetOnDismissListener(new Util.DismissListener(() =>
{
if (actionOnResult != null)
actionOnResult(false);
}));
{
//dismiss can be called when we're calling activity.Finish() during button press.
//don't do anything then.
if (buttonPressed)
return;
if (actionOnResult != null)
{
actionOnResult(false);
actionOnResult = null;
}
}));
dialog.Show();
}

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003" InitialTargets="showFlavor">
<Target Name="showFlavor" AfterTargets="Build">
<Message Importance="high" Text="building flavor $(Flavor)">
<Message Importance="high" Text="building flavor $(Flavor) with Config $(Configuration)">
</Message>
</Target>
<Import Project="../build-properties.props" />

View File

@@ -142,7 +142,7 @@ namespace keepass2android.services.AutofillBase
{
foreach (AutofillFieldMetadata autofillFieldMetadata in autofillFieldMetadataCollection.GetFieldsForHint(hint))
{
FilledAutofillField<ViewNodeInputField> filledAutofillField;
FilledAutofillField filledAutofillField;
if (!filledAutofillFieldCollection.HintMap.TryGetValue(hint, out filledAutofillField) || (filledAutofillField == null))
{
continue;

View File

@@ -29,7 +29,7 @@ namespace keepass2android.services.AutofillBase
[JsonIgnore]
public AssistStructure.ViewNode ViewNode { get; set; }
public void FillFilledAutofillValue(FilledAutofillField<ViewNodeInputField> filledField)
public override void FillFilledAutofillValue(FilledAutofillField filledField)
{
AutofillValue autofillValue = ViewNode.AutofillValue;
if (autofillValue != null)
@@ -159,8 +159,12 @@ namespace keepass2android.services.AutofillBase
protected override AutofillTargetId Parse(bool forFill, bool isManualRequest, AutofillView<ViewNodeInputField> autofillView)
{
if (autofillView == null)
Kp2aLog.Log("Received null autofill view!");
var result = base.Parse(forFill, isManualRequest, autofillView);
Kp2aLog.Log("Parsing done");
if (forFill)
{
foreach (var p in FieldsMappedToHints)
@@ -168,8 +172,9 @@ namespace keepass2android.services.AutofillBase
}
else
{
ClientFormData = new FilledAutofillFieldCollection<ViewNodeInputField>();
foreach (var p in FieldsMappedToHints)
ClientFormData.Add(new FilledAutofillField<ViewNodeInputField>(p.Key, p.Value));
ClientFormData.Add(new FilledAutofillField(p.Key, p.Value));
}

View File

@@ -61,8 +61,8 @@ namespace keepass2android.services.Kp2aAutofill
foreach (string key in pwEntryOutput.OutputStrings.GetKeys())
{
FilledAutofillField<ViewNodeInputField> field =
new FilledAutofillField<ViewNodeInputField>
FilledAutofillField field =
new FilledAutofillField
{
AutofillHints = GetCanonicalHintsFromKp2aField(key).ToArray(),
TextValue = pwEntryOutput.OutputStrings.ReadSafe(key)
@@ -73,8 +73,8 @@ namespace keepass2android.services.Kp2aAutofill
if (IsCreditCard(pwEntry, context) && pwEntry.Expires)
{
DateTime expTime = pwEntry.ExpiryTime;
FilledAutofillField<ViewNodeInputField> field =
new FilledAutofillField<ViewNodeInputField>
FilledAutofillField field =
new FilledAutofillField
{
AutofillHints = new[] {View.AutofillHintCreditCardExpirationDate},
DateValue = (long) (1000 * TimeUtil.SerializeUnix(expTime))
@@ -82,7 +82,7 @@ namespace keepass2android.services.Kp2aAutofill
fieldCollection.Add(field);
field =
new FilledAutofillField<ViewNodeInputField>
new FilledAutofillField
{
AutofillHints = new[] {View.AutofillHintCreditCardExpirationDay},
TextValue = expTime.Day.ToString()
@@ -90,7 +90,7 @@ namespace keepass2android.services.Kp2aAutofill
fieldCollection.Add(field);
field =
new FilledAutofillField<ViewNodeInputField>
new FilledAutofillField
{
AutofillHints = new[] {View.AutofillHintCreditCardExpirationMonth},
TextValue = expTime.Month.ToString()
@@ -98,7 +98,7 @@ namespace keepass2android.services.Kp2aAutofill
fieldCollection.Add(field);
field =
new FilledAutofillField<ViewNodeInputField>
new FilledAutofillField
{
AutofillHints = new[] {View.AutofillHintCreditCardExpirationYear},
TextValue = expTime.Year.ToString()

View File

@@ -1,956 +0,0 @@
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using Newtonsoft.Json;
using Formatting = System.Xml.Formatting;
namespace Kp2aAutofillParser
{
public class W3cHints
{
// Supported W3C autofill tokens (https://html.spec.whatwg.org/multipage/forms.html#autofill)
public const string HONORIFIC_PREFIX = "honorific-prefix";
public const string NAME = "name";
public const string GIVEN_NAME = "given-name";
public const string ADDITIONAL_NAME = "additional-name";
public const string FAMILY_NAME = "family-name";
public const string HONORIFIC_SUFFIX = "honorific-suffix";
public const string USERNAME = "username";
public const string NEW_PASSWORD = "new-password";
public const string CURRENT_PASSWORD = "current-password";
public const string ORGANIZATION_TITLE = "organization-title";
public const string ORGANIZATION = "organization";
public const string STREET_ADDRESS = "street-address";
public const string ADDRESS_LINE1 = "address-line1";
public const string ADDRESS_LINE2 = "address-line2";
public const string ADDRESS_LINE3 = "address-line3";
public const string ADDRESS_LEVEL4 = "address-level4";
public const string ADDRESS_LEVEL3 = "address-level3";
public const string ADDRESS_LEVEL2 = "address-level2";
public const string ADDRESS_LEVEL1 = "address-level1";
public const string COUNTRY = "country";
public const string COUNTRY_NAME = "country-name";
public const string POSTAL_CODE = "postal-code";
public const string CC_NAME = "cc-name";
public const string CC_GIVEN_NAME = "cc-given-name";
public const string CC_ADDITIONAL_NAME = "cc-additional-name";
public const string CC_FAMILY_NAME = "cc-family-name";
public const string CC_NUMBER = "cc-number";
public const string CC_EXPIRATION = "cc-exp";
public const string CC_EXPIRATION_MONTH = "cc-exp-month";
public const string CC_EXPIRATION_YEAR = "cc-exp-year";
public const string CC_CSC = "cc-csc";
public const string CC_TYPE = "cc-type";
public const string TRANSACTION_CURRENCY = "transaction-currency";
public const string TRANSACTION_AMOUNT = "transaction-amount";
public const string LANGUAGE = "language";
public const string BDAY = "bday";
public const string BDAY_DAY = "bday-day";
public const string BDAY_MONTH = "bday-month";
public const string BDAY_YEAR = "bday-year";
public const string SEX = "sex";
public const string URL = "url";
public const string PHOTO = "photo";
// Optional W3C prefixes
public const string PREFIX_SECTION = "section-";
public const string SHIPPING = "shipping";
public const string BILLING = "billing";
// W3C prefixes below...
public const string PREFIX_HOME = "home";
public const string PREFIX_WORK = "work";
public const string PREFIX_FAX = "fax";
public const string PREFIX_PAGER = "pager";
// ... require those suffix
public const string TEL = "tel";
public const string TEL_COUNTRY_CODE = "tel-country-code";
public const string TEL_NATIONAL = "tel-national";
public const string TEL_AREA_CODE = "tel-area-code";
public const string TEL_LOCAL = "tel-local";
public const string TEL_LOCAL_PREFIX = "tel-local-prefix";
public const string TEL_LOCAL_SUFFIX = "tel-local-suffix";
public const string TEL_EXTENSION = "tel_extension";
public const string EMAIL = "email";
public const string IMPP = "impp";
private W3cHints()
{
}
public static bool isW3cSectionPrefix(string hint)
{
return hint.ToLower().StartsWith(W3cHints.PREFIX_SECTION);
}
public static bool isW3cAddressType(string hint)
{
switch (hint.ToLower())
{
case W3cHints.SHIPPING:
case W3cHints.BILLING:
return true;
}
return false;
}
public static bool isW3cTypePrefix(string hint)
{
switch (hint.ToLower())
{
case W3cHints.PREFIX_WORK:
case W3cHints.PREFIX_FAX:
case W3cHints.PREFIX_HOME:
case W3cHints.PREFIX_PAGER:
return true;
}
return false;
}
public static bool isW3cTypeHint(string hint)
{
switch (hint.ToLower())
{
case W3cHints.TEL:
case W3cHints.TEL_COUNTRY_CODE:
case W3cHints.TEL_NATIONAL:
case W3cHints.TEL_AREA_CODE:
case W3cHints.TEL_LOCAL:
case W3cHints.TEL_LOCAL_PREFIX:
case W3cHints.TEL_LOCAL_SUFFIX:
case W3cHints.TEL_EXTENSION:
case W3cHints.EMAIL:
case W3cHints.IMPP:
return true;
}
return false;
}
}
/// <summary>
/// FilledAutofillFieldCollection is the model that holds all of the data on a client app's page,
/// plus the dataset name associated with it.
/// </summary>
public class FilledAutofillFieldCollection<FieldT> where FieldT:InputField
{
public Dictionary<string, FilledAutofillField<FieldT>> HintMap { get; }
public string DatasetName { get; set; }
public FilledAutofillFieldCollection(Dictionary<string, FilledAutofillField<FieldT>> hintMap, string datasetName = "")
{
//recreate hint map making sure we compare case insensitive
HintMap = BuildHintMap();
foreach (var p in hintMap)
HintMap.Add(p.Key, p.Value);
DatasetName = datasetName;
}
public FilledAutofillFieldCollection() : this(BuildHintMap())
{ }
private static Dictionary<string, FilledAutofillField<FieldT>> BuildHintMap()
{
return new Dictionary<string, FilledAutofillField<FieldT>>(StringComparer.OrdinalIgnoreCase);
}
/// <summary>
/// Adds a filledAutofillField to the collection, indexed by all of its hints.
/// </summary>
/// <returns>The add.</returns>
/// <param name="filledAutofillField">Filled autofill field.</param>
public void Add(FilledAutofillField<FieldT> filledAutofillField)
{
foreach (string hint in filledAutofillField.AutofillHints)
{
if (AutofillHintsHelper.IsSupportedHint(hint))
{
HintMap.TryAdd(hint, filledAutofillField);
}
}
}
/// <summary>
/// Takes in a list of autofill hints (`autofillHints`), usually associated with a View or set of
/// Views. Returns whether any of the filled fields on the page have at least 1 of these
/// `autofillHint`s.
/// </summary>
/// <returns><c>true</c>, if with hints was helpsed, <c>false</c> otherwise.</returns>
/// <param name="autofillHints">Autofill hints.</param>
public bool HelpsWithHints(List<string> autofillHints)
{
for (int i = 0; i < autofillHints.Count; i++)
{
var autofillHint = autofillHints[i];
if (HintMap.ContainsKey(autofillHint) && !HintMap[autofillHint].IsNull())
{
return true;
}
}
return false;
}
}
public class AutofillHintsHelper
{
public const string AutofillHint2faAppOtp = "2faAppOTPCode";
public const string AutofillHintBirthDateDay = "birthDateDay";
public const string AutofillHintBirthDateFull = "birthDateFull";
public const string AutofillHintBirthDateMonth = "birthDateMonth";
public const string AutofillHintBirthDateYear = "birthDateYear";
public const string AutofillHintCreditCardExpirationDate = "creditCardExpirationDate";
public const string AutofillHintCreditCardExpirationDay = "creditCardExpirationDay";
public const string AutofillHintCreditCardExpirationMonth = "creditCardExpirationMonth";
public const string AutofillHintCreditCardExpirationYear = "creditCardExpirationYear";
public const string AutofillHintCreditCardNumber = "creditCardNumber";
public const string AutofillHintCreditCardSecurityCode = "creditCardSecurityCode";
public const string AutofillHintEmailAddress = "emailAddress";
public const string AutofillHintEmailOtp = "emailOTPCode";
public const string AutofillHintGender = "gender";
public const string AutofillHintName = "name";
public const string AutofillHintNewPassword = "newPassword";
public const string AutofillHintNewUsername = "newUsername";
public const string AutofillHintNotApplicable = "notApplicable";
public const string AutofillHintPassword = "password";
public const string AutofillHintPersonName = "personName";
public const string AutofillHintPersonNameFAMILY = "personFamilyName";
public const string AutofillHintPersonNameGIVEN = "personGivenName";
public const string AutofillHintPersonNameMIDDLE = "personMiddleName";
public const string AutofillHintPersonNameMIDDLE_INITIAL = "personMiddleInitial";
public const string AutofillHintPersonNamePREFIX = "personNamePrefix";
public const string AutofillHintPersonNameSUFFIX = "personNameSuffix";
public const string AutofillHintPhone = "phone";
public const string AutofillHintPhoneContryCode = "phoneCountryCode";
public const string AutofillHintPostalAddressAPT_NUMBER = "aptNumber";
public const string AutofillHintPostalAddressCOUNTRY = "addressCountry";
public const string AutofillHintPostalAddressDEPENDENT_LOCALITY = "dependentLocality";
public const string AutofillHintPostalAddressEXTENDED_ADDRESS = "extendedAddress";
public const string AutofillHintPostalAddressEXTENDED_POSTAL_CODE = "extendedPostalCode";
public const string AutofillHintPostalAddressLOCALITY = "addressLocality";
public const string AutofillHintPostalAddressREGION = "addressRegion";
public const string AutofillHintPostalAddressSTREET_ADDRESS = "streetAddress";
public const string AutofillHintPostalCode = "postalCode";
public const string AutofillHintPromoCode = "promoCode";
public const string AutofillHintSMS_OTP = "smsOTPCode";
public const string AutofillHintUPI_VPA = "upiVirtualPaymentAddress";
public const string AutofillHintUsername = "username";
public const string AutofillHintWifiPassword = "wifiPassword";
public const string AutofillHintPhoneNational = "phoneNational";
public const string AutofillHintPhoneNumber = "phoneNumber";
public const string AutofillHintPhoneNumberDevice = "phoneNumberDevice";
public const string AutofillHintPostalAddress = "postalAddress";
private static readonly HashSet<string> _allSupportedHints = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
{
AutofillHintCreditCardExpirationDate,
AutofillHintCreditCardExpirationDay,
AutofillHintCreditCardExpirationMonth,
AutofillHintCreditCardExpirationYear,
AutofillHintCreditCardNumber,
AutofillHintCreditCardSecurityCode,
AutofillHintEmailAddress,
AutofillHintPhone,
AutofillHintName,
AutofillHintPassword,
AutofillHintPostalAddress,
AutofillHintPostalCode,
AutofillHintUsername,
W3cHints.HONORIFIC_PREFIX,
W3cHints.NAME,
W3cHints.GIVEN_NAME,
W3cHints.ADDITIONAL_NAME,
W3cHints.FAMILY_NAME,
W3cHints.HONORIFIC_SUFFIX,
W3cHints.USERNAME,
W3cHints.NEW_PASSWORD,
W3cHints.CURRENT_PASSWORD,
W3cHints.ORGANIZATION_TITLE,
W3cHints.ORGANIZATION,
W3cHints.STREET_ADDRESS,
W3cHints.ADDRESS_LINE1,
W3cHints.ADDRESS_LINE2,
W3cHints.ADDRESS_LINE3,
W3cHints.ADDRESS_LEVEL4,
W3cHints.ADDRESS_LEVEL3,
W3cHints.ADDRESS_LEVEL2,
W3cHints.ADDRESS_LEVEL1,
W3cHints.COUNTRY,
W3cHints.COUNTRY_NAME,
W3cHints.POSTAL_CODE,
W3cHints.CC_NAME,
W3cHints.CC_GIVEN_NAME,
W3cHints.CC_ADDITIONAL_NAME,
W3cHints.CC_FAMILY_NAME,
W3cHints.CC_NUMBER,
W3cHints.CC_EXPIRATION,
W3cHints.CC_EXPIRATION_MONTH,
W3cHints.CC_EXPIRATION_YEAR,
W3cHints.CC_CSC,
W3cHints.CC_TYPE,
W3cHints.TRANSACTION_CURRENCY,
W3cHints.TRANSACTION_AMOUNT,
W3cHints.LANGUAGE,
W3cHints.BDAY,
W3cHints.BDAY_DAY,
W3cHints.BDAY_MONTH,
W3cHints.BDAY_YEAR,
W3cHints.SEX,
W3cHints.URL,
W3cHints.PHOTO,
W3cHints.TEL,
W3cHints.TEL_COUNTRY_CODE,
W3cHints.TEL_NATIONAL,
W3cHints.TEL_AREA_CODE,
W3cHints.TEL_LOCAL,
W3cHints.TEL_LOCAL_PREFIX,
W3cHints.TEL_LOCAL_SUFFIX,
W3cHints.TEL_EXTENSION,
W3cHints.EMAIL,
W3cHints.IMPP,
};
private static readonly List<HashSet<string>> partitionsOfCanonicalHints = new List<HashSet<string>>()
{
new HashSet<string>(StringComparer.OrdinalIgnoreCase)
{
AutofillHintEmailAddress,
AutofillHintPhone,
AutofillHintName,
AutofillHintPassword,
AutofillHintUsername,
W3cHints.HONORIFIC_PREFIX,
W3cHints.NAME,
W3cHints.GIVEN_NAME,
W3cHints.ADDITIONAL_NAME,
W3cHints.FAMILY_NAME,
W3cHints.HONORIFIC_SUFFIX,
W3cHints.ORGANIZATION_TITLE,
W3cHints.ORGANIZATION,
W3cHints.LANGUAGE,
W3cHints.BDAY,
W3cHints.BDAY_DAY,
W3cHints.BDAY_MONTH,
W3cHints.BDAY_YEAR,
W3cHints.SEX,
W3cHints.URL,
W3cHints.PHOTO,
W3cHints.TEL,
W3cHints.TEL_COUNTRY_CODE,
W3cHints.TEL_NATIONAL,
W3cHints.TEL_AREA_CODE,
W3cHints.TEL_LOCAL,
W3cHints.TEL_LOCAL_PREFIX,
W3cHints.TEL_LOCAL_SUFFIX,
W3cHints.TEL_EXTENSION,
W3cHints.IMPP,
},
new HashSet<string>(StringComparer.OrdinalIgnoreCase)
{
AutofillHintPostalAddress,
AutofillHintPostalCode,
W3cHints.STREET_ADDRESS,
W3cHints.ADDRESS_LINE1,
W3cHints.ADDRESS_LINE2,
W3cHints.ADDRESS_LINE3,
W3cHints.ADDRESS_LEVEL4,
W3cHints.ADDRESS_LEVEL3,
W3cHints.ADDRESS_LEVEL2,
W3cHints.ADDRESS_LEVEL1,
W3cHints.COUNTRY,
W3cHints.COUNTRY_NAME
},
new HashSet<string>(StringComparer.OrdinalIgnoreCase)
{
AutofillHintCreditCardExpirationDate,
AutofillHintCreditCardExpirationDay,
AutofillHintCreditCardExpirationMonth,
AutofillHintCreditCardExpirationYear,
AutofillHintCreditCardNumber,
AutofillHintCreditCardSecurityCode,
W3cHints.CC_NAME,
W3cHints.CC_GIVEN_NAME,
W3cHints.CC_ADDITIONAL_NAME,
W3cHints.CC_FAMILY_NAME,
W3cHints.CC_TYPE,
W3cHints.TRANSACTION_CURRENCY,
W3cHints.TRANSACTION_AMOUNT,
},
};
private static readonly Dictionary<string, string> hintToCanonicalReplacement = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase)
{
{W3cHints.EMAIL, AutofillHintEmailAddress},
{W3cHints.USERNAME, AutofillHintUsername},
{W3cHints.CURRENT_PASSWORD, AutofillHintPassword},
{W3cHints.NEW_PASSWORD, AutofillHintPassword},
{W3cHints.CC_EXPIRATION_MONTH, AutofillHintCreditCardExpirationMonth },
{W3cHints.CC_EXPIRATION_YEAR, AutofillHintCreditCardExpirationYear },
{W3cHints.CC_EXPIRATION, AutofillHintCreditCardExpirationDate },
{W3cHints.CC_NUMBER, AutofillHintCreditCardNumber },
{W3cHints.CC_CSC, AutofillHintCreditCardSecurityCode },
{W3cHints.POSTAL_CODE, AutofillHintPostalCode },
};
public static bool IsSupportedHint(string hint)
{
return _allSupportedHints.Contains(hint);
}
public static string[] FilterForSupportedHints(string[] hints)
{
if (hints == null)
return Array.Empty<string>();
var filteredHints = new string[hints.Length];
int i = 0;
foreach (var hint in hints)
{
if (IsSupportedHint(hint))
{
filteredHints[i++] = hint;
}
}
var finalFilteredHints = new string[i];
Array.Copy(filteredHints, 0, finalFilteredHints, 0, i);
return finalFilteredHints;
}
/// <summary>
/// transforms hints by replacing some W3cHints by their Android counterparts and transforming everything to lowercase
/// </summary>
public static List<string> ConvertToCanonicalHints(string[] supportedHints)
{
List<string> result = new List<string>();
foreach (string hint in supportedHints)
{
string canonicalHint;
if (!hintToCanonicalReplacement.TryGetValue(hint, out canonicalHint))
canonicalHint = hint;
result.Add(canonicalHint.ToLower());
}
return result;
}
public static int GetPartitionIndex(string hint)
{
for (int i = 0; i < partitionsOfCanonicalHints.Count; i++)
{
if (partitionsOfCanonicalHints[i].Contains(hint))
{
return i;
}
}
return -1;
}
public static FilledAutofillFieldCollection<FieldT> FilterForPartition<FieldT>(FilledAutofillFieldCollection<FieldT> autofillFields, int partitionIndex) where FieldT: InputField
{
FilledAutofillFieldCollection<FieldT> filteredCollection =
new FilledAutofillFieldCollection<FieldT> { DatasetName = autofillFields.DatasetName };
if (partitionIndex == -1)
return filteredCollection;
foreach (var field in autofillFields.HintMap.Values.Distinct())
{
foreach (var hint in field.AutofillHints)
{
if (GetPartitionIndex(hint) == partitionIndex)
{
filteredCollection.Add(field);
break;
}
}
}
return filteredCollection;
}
public static FilledAutofillFieldCollection<FieldT> FilterForPartition<FieldT>(FilledAutofillFieldCollection<FieldT> filledAutofillFieldCollection, List<string> autofillFieldsFocusedAutofillCanonicalHints) where FieldT: InputField
{
//only apply partition data if we have FocusedAutofillCanonicalHints. This may be empty on buggy Firefox.
if (autofillFieldsFocusedAutofillCanonicalHints.Any())
{
int partitionIndex = AutofillHintsHelper.GetPartitionIndex(autofillFieldsFocusedAutofillCanonicalHints.FirstOrDefault());
return AutofillHintsHelper.FilterForPartition(filledAutofillFieldCollection, partitionIndex);
}
return filledAutofillFieldCollection;
}
}
/// <summary>
/// This enum represents the Android.Text.InputTypes values. For testability, this is duplicated here.
/// </summary>
public enum InputTypes
{
ClassDatetime = 4,
ClassNumber = 2,
ClassPhone = 3,
ClassText = 1,
DatetimeVariationDate = 16,
DatetimeVariationNormal = 0,
DatetimeVariationTime = 32,
MaskClass = 15,
MaskFlags = 16773120,
MaskVariation = 4080,
Null = 0,
NumberFlagDecimal = 8192,
NumberFlagSigned = 4096,
NumberVariationNormal = 0,
NumberVariationPassword = 16,
TextFlagAutoComplete = 65536,
TextFlagAutoCorrect = 32768,
TextFlagCapCharacters = 4096,
TextFlagCapSentences = 16384,
TextFlagCapWords = 8192,
TextFlagEnableTextConversionSuggestions = 1048576,
TextFlagImeMultiLine = 262144,
TextFlagMultiLine = 131072,
TextFlagNoSuggestions = 524288,
TextVariationEmailAddress = 32,
TextVariationEmailSubject = 48,
TextVariationFilter = 176,
TextVariationLongMessage = 80,
TextVariationNormal = 0,
TextVariationPassword = 128,
TextVariationPersonName = 96,
TextVariationPhonetic = 192,
TextVariationPostalAddress = 112,
TextVariationShortMessage = 64,
TextVariationUri = 16,
TextVariationVisiblePassword = 144,
TextVariationWebEditText = 160,
TextVariationWebEmailAddress = 208,
TextVariationWebPassword = 224
}
public interface IKp2aDigitalAssetLinksDataSource
{
bool IsTrustedApp(string packageName);
bool IsTrustedLink(string domain, string targetPackage);
bool IsEnabled();
}
class TimeUtil
{
private static DateTime? m_dtUnixRoot = null;
public static DateTime ConvertUnixTime(double dtUnix)
{
try
{
if (!m_dtUnixRoot.HasValue)
m_dtUnixRoot = (new DateTime(1970, 1, 1, 0, 0, 0, 0,
DateTimeKind.Utc)).ToLocalTime();
return m_dtUnixRoot.Value.AddSeconds(dtUnix);
}
catch (Exception) { Debug.Assert(false); }
return DateTime.UtcNow;
}
}
public class FilledAutofillField<FieldT> where FieldT : InputField
{
private string[] _autofillHints;
public string TextValue { get; set; }
public long? DateValue { get; set; }
public bool? ToggleValue { get; set; }
public string ValueToString()
{
if (DateValue != null)
{
return TimeUtil.ConvertUnixTime((long)DateValue / 1000.0).ToLongDateString();
}
if (ToggleValue != null)
return ToggleValue.ToString();
return TextValue;
}
/// <summary>
/// returns the autofill hints for the filled field. These are always lowercased for simpler string comparison.
/// </summary>
public string[] AutofillHints
{
get
{
return _autofillHints;
}
set
{
_autofillHints = value;
for (int i = 0; i < _autofillHints.Length; i++)
_autofillHints[i] = _autofillHints[i].ToLower();
}
}
public FilledAutofillField()
{ }
public FilledAutofillField(FieldT inputField)
: this(inputField, inputField.AutofillHints)
{
}
public FilledAutofillField(FieldT inputField, string[] hints)
{
string[] rawHints = AutofillHintsHelper.FilterForSupportedHints(hints);
List<string> hintList = new List<string>();
string nextHint = null;
for (int i = 0; i < rawHints.Length; i++)
{
string hint = rawHints[i];
if (i < rawHints.Length - 1)
{
nextHint = rawHints[i + 1];
}
// First convert the compound W3C autofill hints
if (W3cHints.isW3cSectionPrefix(hint) && i < rawHints.Length - 1)
{
hint = rawHints[++i];
if (i < rawHints.Length - 1)
{
nextHint = rawHints[i + 1];
}
}
if (W3cHints.isW3cTypePrefix(hint) && nextHint != null && W3cHints.isW3cTypeHint(nextHint))
{
hint = nextHint;
i++;
}
if (W3cHints.isW3cAddressType(hint) && nextHint != null)
{
hint = nextHint;
i++;
}
// Then check if the "actual" hint is supported.
if (AutofillHintsHelper.IsSupportedHint(hint))
{
hintList.Add(hint);
}
else
{
}
}
AutofillHints = AutofillHintsHelper.ConvertToCanonicalHints(hintList.ToArray()).ToArray();
}
public bool IsNull()
{
return TextValue == null && DateValue == null && ToggleValue == null;
}
public override bool Equals(object obj)
{
if (this == obj) return true;
if (obj == null || GetType() != obj.GetType()) return false;
FilledAutofillField<FieldT> that = (FilledAutofillField<FieldT>)obj;
if (!TextValue?.Equals(that.TextValue) ?? that.TextValue != null)
return false;
if (DateValue != null ? !DateValue.Equals(that.DateValue) : that.DateValue != null)
return false;
return ToggleValue != null ? ToggleValue.Equals(that.ToggleValue) : that.ToggleValue == null;
}
public override int GetHashCode()
{
unchecked
{
var result = TextValue != null ? TextValue.GetHashCode() : 0;
result = 31 * result + (DateValue != null ? DateValue.GetHashCode() : 0);
result = 31 * result + (ToggleValue != null ? ToggleValue.GetHashCode() : 0);
return result;
}
}
}
/// <summary>
/// Base class for everything that is a input field which might (or might not) be autofilled.
/// For testability, this is independent from Android classes like ViewNode
/// </summary>
public abstract class InputField
{
public string IdEntry { get; set; }
public string Hint { get; set; }
public string ClassName { get; set; }
public string[] AutofillHints { get; set; }
public bool IsFocused { get; set; }
public InputTypes InputType { get; set; }
public string HtmlInfoTag { get; set; }
public string HtmlInfoTypeAttribute { get; set; }
}
public class AutofillView<TField> where TField : InputField
{
public List<TField> InputFields { get; set; } = new List<TField>();
public string PackageId { get; set; } = null;
public string WebDomain { get; set; } = null;
}
public interface ILogger
{
void Log(string x);
}
public class StructureParserBase<FieldT> where FieldT: InputField
{
private readonly ILogger _log;
private readonly IKp2aDigitalAssetLinksDataSource _digitalAssetLinksDataSource;
private readonly List<string> _autofillHintsForLogin = new List<string>
{
AutofillHintsHelper.AutofillHintPassword,
AutofillHintsHelper.AutofillHintUsername,
AutofillHintsHelper.AutofillHintEmailAddress
};
public string PackageId { get; set; }
public Dictionary<FieldT, string[]> FieldsMappedToHints = new Dictionary<FieldT, string[]>();
public StructureParserBase(ILogger logger, IKp2aDigitalAssetLinksDataSource digitalAssetLinksDataSource)
{
_log = logger;
_digitalAssetLinksDataSource = digitalAssetLinksDataSource;
}
public class AutofillTargetId
{
public string PackageName { get; set; }
public string PackageNameWithPseudoSchema
{
get { return AndroidAppScheme + PackageName; }
}
public const string AndroidAppScheme = "androidapp://";
public string WebDomain { get; set; }
/// <summary>
/// If PackageName and WebDomain are not compatible (by DAL or because PackageName is a trusted browser in which case we treat all domains as "compatible"
/// we need to issue a warning. If we would fill credentials for the package, a malicious website could try to get credentials for the app.
/// If we would fill credentials for the domain, a malicious app could get credentials for the domain.
/// </summary>
public bool IncompatiblePackageAndDomain { get; set; }
public string DomainOrPackage
{
get
{
return WebDomain ?? PackageNameWithPseudoSchema;
}
}
}
public AutofillTargetId ParseForFill(bool isManual, AutofillView<FieldT> autofillView)
{
return Parse(true, isManual, autofillView);
}
public AutofillTargetId ParseForSave(AutofillView<FieldT> autofillView)
{
return Parse(false, true, autofillView);
}
/// <summary>
/// Traverse AssistStructure and add ViewNode metadata to a flat list.
/// </summary>
/// <returns>The parse.</returns>
/// <param name="forFill">If set to <c>true</c> for fill.</param>
/// <param name="isManualRequest"></param>
protected virtual AutofillTargetId Parse(bool forFill, bool isManualRequest, AutofillView<FieldT> autofillView)
{
AutofillTargetId result = new AutofillTargetId()
{
PackageName = autofillView.PackageId,
WebDomain = autofillView.WebDomain
};
_log.Log("parsing autofillStructure...");
//TODO remove from production
_log.Log("will log the autofillStructure...");
string debugInfo = JsonConvert.SerializeObject(autofillView, Newtonsoft.Json.Formatting.Indented);
_log.Log("will log the autofillStructure... size is " + debugInfo.Length);
_log.Log("This is the autofillStructure: \n\n " + debugInfo);
//go through each input field and determine username/password fields.
//Depending on the target this can require more or less heuristics.
// * if there is a valid & supported autofill hint, we assume that all fields which should be filled do have an appropriate Autofill hint
// * if there is no such autofill hint, we use IsPassword to
HashSet<string> autofillHintsOfAllFields = autofillView.InputFields.Where(f => f.AutofillHints != null)
.SelectMany(f => f.AutofillHints).ToHashSet();
bool hasLoginAutofillHints = autofillHintsOfAllFields.Intersect(_autofillHintsForLogin).Any();
if (hasLoginAutofillHints)
{
foreach (var viewNode in autofillView.InputFields)
{
string[] viewHints = viewNode.AutofillHints;
if (viewHints == null)
continue;
if (viewHints.Intersect(_autofillHintsForLogin).Any())
{
FieldsMappedToHints.Add(viewNode, viewHints);
}
}
}
else
{
//determine password fields, first by type, then by hint:
List<FieldT> passwordFields = autofillView.InputFields.Where(f => IsEditText(f) && IsPassword(f)).ToList();
if (!passwordFields.Any())
{
passwordFields = autofillView.InputFields.Where(f => IsEditText(f) && HasPasswordHint(f)).ToList();
}
//determine username fields. Try by hint, if that fails use the one before the password
List<FieldT> usernameFields = autofillView.InputFields.Where(f => IsEditText(f) && HasUsernameHint(f)).ToList();
if (!usernameFields.Any())
{
foreach (var passwordField in passwordFields)
{
var lastInputBeforePassword = autofillView.InputFields
.TakeWhile(f => IsEditText(f) && f != passwordField && !passwordFields.Contains(f)).LastOrDefault();
if (lastInputBeforePassword != null)
usernameFields.Add(lastInputBeforePassword);
}
}
//for "heuristic determination" we demand that one of the filled fields is focused:
if (passwordFields.Concat(usernameFields).Any(f => f.IsFocused))
{
foreach (var uf in usernameFields)
FieldsMappedToHints.Add(uf, new string[] { AutofillHintsHelper.AutofillHintUsername });
foreach (var pf in passwordFields)
FieldsMappedToHints.Add(pf, new string[] { AutofillHintsHelper.AutofillHintPassword });
}
}
if (!string.IsNullOrEmpty(autofillView.WebDomain) && _digitalAssetLinksDataSource.IsEnabled())
{
result.IncompatiblePackageAndDomain = !_digitalAssetLinksDataSource.IsTrustedLink(autofillView.WebDomain, result.PackageName);
if (result.IncompatiblePackageAndDomain)
{
_log.Log($"DAL verification failed for {result.PackageName}/{result.WebDomain}");
}
}
else
{
result.IncompatiblePackageAndDomain = false;
}
return result;
}
private bool IsEditText(FieldT f)
{
return (f.ClassName == "android.widget.EditText"
|| f.ClassName == "android.widget.AutoCompleteTextView"
|| f.HtmlInfoTag == "input");
}
private static readonly HashSet<string> _passwordHints = new HashSet<string> { "password", "passwort"
/*, "passwordAuto", "pswd"*/ };
private static bool HasPasswordHint(InputField f)
{
return IsAny(f.IdEntry, _passwordHints) ||
IsAny(f.Hint, _passwordHints);
}
private static readonly HashSet<string> _usernameHints = new HashSet<string> { "email", "e-mail", "username" };
private static bool HasUsernameHint(InputField f)
{
return IsAny(f.IdEntry, _usernameHints) ||
IsAny(f.Hint, _usernameHints);
}
private static bool IsAny(string value, IEnumerable<string> terms)
{
if (string.IsNullOrWhiteSpace(value))
{
return false;
}
var lowerValue = value.ToLowerInvariant();
return terms.Any(t => lowerValue == t);
}
private static bool IsInputTypeClass(InputTypes inputType, InputTypes inputTypeClass)
{
if (!InputTypes.MaskClass.HasFlag(inputTypeClass))
throw new Exception("invalid inputTypeClass");
return (((int)inputType) & (int)InputTypes.MaskClass) == (int)(inputTypeClass);
}
private static bool IsInputTypeVariation(InputTypes inputType, InputTypes inputTypeVariation)
{
if (!InputTypes.MaskVariation.HasFlag(inputTypeVariation))
throw new Exception("invalid inputTypeVariation");
return (((int)inputType) & (int)InputTypes.MaskVariation) == (int)(inputTypeVariation);
}
private static bool IsPassword(InputField f)
{
InputTypes inputType = f.InputType;
return
(!f.IdEntry?.ToLowerInvariant().Contains("search") ?? true) &&
(!f.Hint?.ToLowerInvariant().Contains("search") ?? true) &&
(
(IsInputTypeClass(inputType, InputTypes.ClassText)
&&
(
IsInputTypeVariation(inputType, InputTypes.TextVariationPassword)
|| IsInputTypeVariation(inputType, InputTypes.TextVariationVisiblePassword)
|| IsInputTypeVariation(inputType, InputTypes.TextVariationWebPassword)
)
)
|| (f.AutofillHints != null && f.AutofillHints.First() == "passwordAuto")
|| (f.HtmlInfoTypeAttribute == "password")
);
}
}
}

View File

@@ -1,12 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.1</TargetFramework>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
</ItemGroup>
</Project>

View File

@@ -67,8 +67,8 @@ namespace keepass2android.view
private PwEntryView(GroupBaseActivity groupActivity, PwEntry pw, int pos):base(groupActivity)
{
_groupActivity = groupActivity;
View ev = Inflate(groupActivity, Resource.Layout.entry_list_entry, null);
View ev = Inflate(groupActivity, Resource.Layout.entry_list_entry, null);
_textView = (TextView)ev.FindViewById(Resource.Id.entry_text);
_textView.TextSize = PrefsUtil.GetListTextSize(groupActivity);
@@ -103,7 +103,11 @@ namespace keepass2android.view
private void PopulateView(View ev, PwEntry pw, int pos)
{
_entry = pw;
if (_groupBaseActivity.IsFinishing)
return;
_entry = pw;
_pos = pos;
ev.FindViewById(Resource.Id.icon).Visibility = ViewStates.Visible;
ev.FindViewById(Resource.Id.check_mark).Visibility = ViewStates.Invisible;

View File

@@ -77,10 +77,15 @@ namespace keepass2android.view
AddView(gv, lp);
}
private void PopulateView(View gv, PwGroup pw) {
private void PopulateView(View gv, PwGroup pw)
{
_pwGroup = pw;
ImageView iv = (ImageView) gv.FindViewById(Resource.Id.icon);
Kp2aLog.Log($"Populating group view {_groupBaseActivity.IsFinishing} {pw.Name}");
if (_groupBaseActivity.IsFinishing)
return;
ImageView iv = (ImageView) gv.FindViewById(Resource.Id.icon);
Database db = App.Kp2a.FindDatabaseForElement(pw);
db.DrawableFactory.AssignDrawableTo(iv, _groupBaseActivity, db.KpDatabase, pw.IconId, pw.CustomIconUuid, true);
gv.FindViewById(Resource.Id.icon).Visibility = ViewStates.Visible;