Compare commits
148 Commits
2818-feat-
...
security/a
Author | SHA1 | Date | |
---|---|---|---|
![]() |
62c361feb0 | ||
![]() |
0ee2495528 | ||
![]() |
7dc635a625 | ||
![]() |
e15112c3b4 | ||
![]() |
89a09ea142 | ||
![]() |
628c0d2c19 | ||
![]() |
584feabe44 | ||
![]() |
ae2cfde897 | ||
![]() |
42c66670b8 | ||
![]() |
288539b902 | ||
![]() |
61fd32f121 | ||
![]() |
43108ec4a6 | ||
![]() |
51089c6b98 | ||
![]() |
cf18fcf91c | ||
![]() |
da0513c768 | ||
![]() |
37f520cdbe | ||
![]() |
c98572bee0 | ||
![]() |
b1774ffc4b | ||
![]() |
57aaa0c4cd | ||
![]() |
b961ae1b33 | ||
![]() |
5e418e2b1b | ||
![]() |
6d22a213f3 | ||
![]() |
a76addc43f | ||
![]() |
1d96217713 | ||
![]() |
d2b8fdcfff | ||
![]() |
507b671448 | ||
![]() |
3118ffaeb5 | ||
![]() |
0abe29bd77 | ||
![]() |
f3a7831390 | ||
![]() |
37cd58f7ba | ||
![]() |
7dd80a8ef7 | ||
![]() |
c78636264b | ||
![]() |
035506a5a3 | ||
![]() |
4cf46ef062 | ||
![]() |
c7b8063171 | ||
![]() |
0a8b149c9a | ||
![]() |
9240a27791 | ||
![]() |
e90d5b903c | ||
![]() |
50b4a9f1b9 | ||
![]() |
9783c3b5fe | ||
![]() |
7a837e3237 | ||
![]() |
c8f6714373 | ||
![]() |
bc0313aa6a | ||
![]() |
0f98668bcd | ||
![]() |
8d1195ac96 | ||
![]() |
df731ac1b3 | ||
![]() |
bd784fa13d | ||
![]() |
a6bc5e657c | ||
![]() |
56c4cdb321 | ||
![]() |
42a4a83c7d | ||
![]() |
fe3933e154 | ||
![]() |
3efe130ee8 | ||
![]() |
5808857749 | ||
![]() |
a7397c3316 | ||
![]() |
d12f936898 | ||
![]() |
67f7d74bb9 | ||
![]() |
b0d0f06073 | ||
![]() |
67ee571c27 | ||
![]() |
a360695271 | ||
![]() |
149857a516 | ||
![]() |
fb8ffb802f | ||
![]() |
e957073457 | ||
![]() |
da86b0f50b | ||
![]() |
0aa78ffd66 | ||
![]() |
ce0087af99 | ||
![]() |
576bfeecfe | ||
![]() |
c0e2f34b79 | ||
![]() |
84d0c32610 | ||
![]() |
40184dbd55 | ||
![]() |
2d17bdde19 | ||
![]() |
e2babde1fa | ||
![]() |
e1f26fb045 | ||
![]() |
adbbfa0ac1 | ||
![]() |
37a013135e | ||
![]() |
acc6ea7f85 | ||
![]() |
62f012713a | ||
![]() |
0d726c1789 | ||
![]() |
f162e868b9 | ||
![]() |
0a1f95653f | ||
![]() |
27451825c6 | ||
![]() |
bdd6f1033e | ||
![]() |
c0413f9b74 | ||
![]() |
59d6fc8fdb | ||
![]() |
c500245647 | ||
![]() |
026a263f10 | ||
![]() |
839e6d3cb4 | ||
![]() |
735f4caf89 | ||
![]() |
11af71ef82 | ||
![]() |
e09577d17f | ||
![]() |
c1dbf171f5 | ||
![]() |
4ca4ec10be | ||
![]() |
77fded4964 | ||
![]() |
578491b1c7 | ||
![]() |
eee3ffd861 | ||
![]() |
89696d7f0d | ||
![]() |
e5d28f0979 | ||
![]() |
0e581a66c5 | ||
![]() |
a202c76bf0 | ||
![]() |
c9936ab76b | ||
![]() |
7ac6f7ed51 | ||
![]() |
ceb31c54b1 | ||
![]() |
42d8be593e | ||
![]() |
313adb6c3e | ||
![]() |
668ba4cdee | ||
![]() |
a36bfa7ff5 | ||
![]() |
26c37bcd2a | ||
![]() |
1980f05a7c | ||
![]() |
dbf10ba9fb | ||
![]() |
4be18d8373 | ||
![]() |
831b290d81 | ||
![]() |
9d4c15f7bc | ||
![]() |
4c4afa792d | ||
![]() |
8e256ac94d | ||
![]() |
65ff09f866 | ||
![]() |
8e9c2824cf | ||
![]() |
92b8ff5c8d | ||
![]() |
223c3bfb8e | ||
![]() |
b4e03a8374 | ||
![]() |
fb2df35d37 | ||
![]() |
50d6598b02 | ||
![]() |
90f04b76f4 | ||
![]() |
8b4314c394 | ||
![]() |
17241bc422 | ||
![]() |
c4a73bf107 | ||
![]() |
4ba40ba24f | ||
![]() |
e2711b709d | ||
![]() |
4764b15e75 | ||
![]() |
1b389ef12e | ||
![]() |
b32c2dbc7e | ||
![]() |
f06937dab3 | ||
![]() |
14efce62ff | ||
![]() |
3c8b530e2e | ||
![]() |
9939e07b7d | ||
![]() |
ecf416febc | ||
![]() |
1cb036941e | ||
![]() |
a53ff37e89 | ||
![]() |
dc3ee35c8b | ||
![]() |
e05fe94650 | ||
![]() |
b0cb0b06a2 | ||
![]() |
6d7b4810da | ||
![]() |
585b747612 | ||
![]() |
55887e1a89 | ||
![]() |
39a7a1298a | ||
![]() |
90059c5ae6 | ||
![]() |
ad63179484 | ||
![]() |
6eaba9d3a8 | ||
![]() |
11ce68902c | ||
![]() |
70ca059e0f |
29
.github/workflows/build.yml
vendored
29
.github/workflows/build.yml
vendored
@@ -78,7 +78,7 @@ jobs:
|
||||
|
||||
# - name: Build keepass2android (net)
|
||||
# run: |
|
||||
# make msbuild Flavor=Net
|
||||
# make dotnetbuild Flavor=Net
|
||||
|
||||
# - name: Build APK (net)
|
||||
# run: |
|
||||
@@ -96,7 +96,7 @@ jobs:
|
||||
|
||||
# - name: Build keepass2android (nonet)
|
||||
# run: |
|
||||
# make msbuild Flavor=NoNet
|
||||
# make dotnetbuild Flavor=NoNet
|
||||
|
||||
# - name: Build APK (nonet)
|
||||
# run: |
|
||||
@@ -212,7 +212,7 @@ jobs:
|
||||
|
||||
# - name: Build keepass2android (net)
|
||||
# run: |
|
||||
# make msbuild Flavor=Net
|
||||
# make dotnetbuild Flavor=Net
|
||||
|
||||
# - name: Build APK (net)
|
||||
# run: |
|
||||
@@ -230,7 +230,7 @@ jobs:
|
||||
|
||||
# - name: Build keepass2android (nonet)
|
||||
# run: |
|
||||
# make msbuild Flavor=NoNet
|
||||
# make dotnetbuild Flavor=NoNet
|
||||
|
||||
# - name: Build APK (nonet)
|
||||
# run: |
|
||||
@@ -279,7 +279,7 @@ jobs:
|
||||
with:
|
||||
minimum-size: 8GB
|
||||
|
||||
- name: Add msbuild to PATH
|
||||
- name: Add dotnetbuild to PATH
|
||||
uses: microsoft/setup-msbuild@v2
|
||||
# If we want to also have nmake, use this instead
|
||||
#uses: ilammy/msvc-dev-cmd@v1
|
||||
@@ -309,12 +309,20 @@ jobs:
|
||||
run: |
|
||||
make java
|
||||
|
||||
- name: Update dotnet workloads
|
||||
run: |
|
||||
dotnet workload update
|
||||
|
||||
- name: Select the manifest
|
||||
run: |
|
||||
make manifestlink Flavor=Net
|
||||
|
||||
- name: Install NuGet dependencies (net)
|
||||
run: make nuget Flavor=Net
|
||||
|
||||
- name: Build keepass2android (net)
|
||||
run: |
|
||||
make msbuild Flavor=Net
|
||||
make dotnetbuild Flavor=Net
|
||||
|
||||
- name: Build APK (net)
|
||||
run: |
|
||||
@@ -327,12 +335,17 @@ jobs:
|
||||
path: |
|
||||
src/keepass2android/bin/*/*-Signed.apk
|
||||
|
||||
- name: Select the manifest
|
||||
run: |
|
||||
make manifestlink Flavor=NoNet
|
||||
|
||||
- name: Install NuGet dependencies (nonet)
|
||||
run: make nuget Flavor=NoNet
|
||||
|
||||
- name: Build keepass2android (nonet)
|
||||
run: |
|
||||
make msbuild Flavor=NoNet
|
||||
make dotnetbuild Flavor=NoNet
|
||||
|
||||
- name: Test Autofill
|
||||
working-directory: ./src/Kp2aAutofillParser.Tests
|
||||
run: dotnet test
|
||||
@@ -348,5 +361,3 @@ jobs:
|
||||
path: |
|
||||
src/keepass2android/bin/*/*-Signed.apk
|
||||
|
||||
- name: Perform "make distclean"
|
||||
run: make distclean
|
||||
|
146
.github/workflows/release.yml
vendored
Normal file
146
.github/workflows/release.yml
vendored
Normal file
@@ -0,0 +1,146 @@
|
||||
name: Create keepass2android release
|
||||
env:
|
||||
NAME: 'Release'
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- "v1.*"
|
||||
jobs:
|
||||
|
||||
build-release:
|
||||
|
||||
runs-on: windows-2022
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
flavor: [Net, NoNet]
|
||||
target: [apk, apk_split]
|
||||
|
||||
steps:
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: true
|
||||
|
||||
- name: Extract key store
|
||||
env:
|
||||
KEYSTORE_BASE64: ${{ secrets.KEYSTORE_BASE64 }}
|
||||
KeyStore: "${{ github.workspace }}/kp2a.keystore"
|
||||
|
||||
shell: bash
|
||||
run: |
|
||||
echo $KeyStore
|
||||
echo $KEYSTORE_BASE64 | base64 --decode > $KeyStore
|
||||
|
||||
|
||||
|
||||
- name: Setup Gradle
|
||||
uses: gradle/actions/setup-gradle@v3
|
||||
|
||||
- name: Cache NuGet packages
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: ~/.nuget/packages
|
||||
key: ${{ runner.os }}-nuget-${{ hashFiles('src/**/*.csproj', 'src/**/packages.config') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-nuget-
|
||||
|
||||
# Workaround an issue when building on windows-2022. Error was
|
||||
# D8 : OpenJDK 64-Bit Server VM warning : INFO: os::commit_memory(0x00000000ae400000, 330301440, 0) failed; error='The paging file is too small for this operation to complete' (DOS error/errno=1455) [D:\a\keepass2android\keepass2android\src\keepass2android\keepass2android-app.csproj]
|
||||
# C:\Program Files\Microsoft Visual Studio\2022\Enterprise\MSBuild\Xamarin\Android\Xamarin.Android.D8.targets(81,5): error MSB6006: "java.exe" exited with code 1. [D:\a\keepass2android\keepass2android\src\keepass2android\keepass2android-app.csproj]
|
||||
- name: Configure Pagefile
|
||||
uses: al-cheb/configure-pagefile-action@a3b6ebd6b634da88790d9c58d4b37a7f4a7b8708 # v1.4
|
||||
with:
|
||||
minimum-size: 8GB
|
||||
|
||||
- name: Add msbuild/dotnet to PATH
|
||||
uses: microsoft/setup-msbuild@v2
|
||||
# If we want to also have nmake, use this instead
|
||||
#uses: ilammy/msvc-dev-cmd@v1
|
||||
|
||||
- name: Switch to JDK-17
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: '17'
|
||||
distribution: 'temurin'
|
||||
|
||||
- name: Display java version
|
||||
run: java -version
|
||||
|
||||
- name: Build native dependencies
|
||||
shell: cmd
|
||||
run: |
|
||||
make native
|
||||
|
||||
- name: Build java dependencies
|
||||
shell: cmd
|
||||
run: |
|
||||
make java
|
||||
|
||||
- name: List apks
|
||||
run: find . -type f -name "*.apk"
|
||||
shell: bash
|
||||
|
||||
- name: Update dotnet workloads
|
||||
run: |
|
||||
dotnet workload update
|
||||
|
||||
- name: List apks
|
||||
run: find . -type f -name "*.apk"
|
||||
shell: bash
|
||||
|
||||
|
||||
- name: Select the manifest
|
||||
run: |
|
||||
make manifestlink Flavor=${{ matrix.flavor }}
|
||||
|
||||
- name: List apks
|
||||
run: find . -type f -name "*.apk"
|
||||
shell: bash
|
||||
|
||||
|
||||
- name: Install NuGet dependencies
|
||||
run: make nuget Flavor=${{ matrix.flavor }}
|
||||
|
||||
- name: List apks
|
||||
run: find . -type f -name "*.apk"
|
||||
shell: bash
|
||||
|
||||
- name: Build APK (net)
|
||||
env:
|
||||
KeyStore: "${{ github.workspace }}/kp2a.keystore"
|
||||
MyAndroidSigningStorePass: ${{ secrets.KEY_STORE_PASSWORD }}
|
||||
MyAndroidSigningKeyPass: ${{ secrets.KEY_PASSWORD }}
|
||||
DropboxAppKey: ${{ secrets.DROPBOX_APP_KEY }}
|
||||
DropboxAppSecret: ${{ secrets.DROPBOX_APP_SECRET }}
|
||||
DropboxAppFolderAppKey: ${{ secrets.DROPBOX_APP_FOLDER_APP_KEY }}
|
||||
DropboxAppFolderAppSecret: ${{ secrets.DROPBOX_APP_FOLDER_APP_SECRET }}
|
||||
|
||||
run: |
|
||||
make ${{ matrix.target }} Configuration=Release Flavor=${{ matrix.flavor }}
|
||||
|
||||
- name: List apks
|
||||
run: find . -type f -name "*.apk"
|
||||
shell: bash
|
||||
|
||||
- name: Archive production artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: keepass2android_${{ matrix.target }}_${{ matrix.flavor }}
|
||||
# the first line is for "apk" target, the second line is for "apk_split" target
|
||||
path: |
|
||||
src/keepass2android-app/bin/Release/net8.0-android/publish/*.apk
|
||||
src/keepass2android-app/bin/Release/net8.0-android/*/publish/*.apk
|
||||
|
||||
- name: List apks
|
||||
run: find . -type f -name "*.apk"
|
||||
shell: bash
|
||||
|
||||
- name: Upload APK to GitHub Release
|
||||
uses: softprops/action-gh-release@v2
|
||||
if: github.ref_type == 'tag'
|
||||
with:
|
||||
files: |
|
||||
src/keepass2android-app/bin/Release/net8.0-android/publish/*.apk
|
||||
src/keepass2android-app/bin/Release/net8.0-android/*/publish/*.apk
|
2
.gitignore
vendored
2
.gitignore
vendored
@@ -64,7 +64,7 @@ Thumbs.db
|
||||
/src/java/android-filechooser/code/projectzip/project.zip
|
||||
/src/java/android-filechooser/code/unused.txt
|
||||
|
||||
/src/Kp2aBusinessLogic/Io/DropboxFileStorageKeys.cs
|
||||
/src/Kp2aBusinessLogic/Io/DropboxFileStorage.g.cs
|
||||
|
||||
/src/java/workspace/DriveTest
|
||||
|
||||
|
89
Makefile
89
Makefile
@@ -4,10 +4,10 @@
|
||||
# This Makefile can be used on both unix-like (use make) & windows (with GNU make)
|
||||
#
|
||||
# append the Configuration variable to 'make' call with value to use in '/p:Configuration='
|
||||
# of msbuild command.
|
||||
# of dotnetbuild command.
|
||||
#
|
||||
# append the Flavor variable to 'make' call with value to use in '/p:Flavor='
|
||||
# of msbuild command.
|
||||
# of dotnetbuild command.
|
||||
#
|
||||
# Example:
|
||||
# make Configuration=Release Flavor=NoNet
|
||||
@@ -18,7 +18,7 @@
|
||||
# - native: build the native libs
|
||||
# - java: build the java libs
|
||||
# - nuget: restore NuGet packages
|
||||
# - msbuild: build the project
|
||||
# - dotnetbuild: build the project
|
||||
# - apk: same as all
|
||||
# - manifestlink: creates a symlink (to be used in building) to the AndroidManifest corresponding to the selected Flavor
|
||||
#
|
||||
@@ -27,7 +27,7 @@
|
||||
# - clean_native: clean native lib
|
||||
# - clean_java: call clean target of java libs
|
||||
# - clean_nuget: cleanup the 'nuget restore'
|
||||
# - clean_msbuild: call clean target of msbuild
|
||||
# - clean_dotnet: call clean target of dotnetbuild
|
||||
#
|
||||
#
|
||||
#
|
||||
@@ -60,45 +60,23 @@ $(info MAKESHELL: $(MAKESHELL))
|
||||
$(info SHELL: $(SHELL))
|
||||
$(info )
|
||||
|
||||
# On linux use xabuild, on Windows use MSBuild.exe, otherwise (macos?) use msbuild.
|
||||
ifeq ($(detected_OS),Linux)
|
||||
MSBUILD_binary := xabuild
|
||||
MSBUILD := $(shell $(WHICH) $(MSBUILD_binary))
|
||||
DOTNET_binary := dotnet
|
||||
DOTNET := $(shell $(WHICH) $(DOTNET_binary))
|
||||
else ifeq ($(detected_OS),Windows)
|
||||
MSBUILD_binary := MSBuild.exe
|
||||
MSBUILD := $(shell $(WHICH) $(MSBUILD_binary) 2> nul)
|
||||
ifeq ($(MSBUILD),)
|
||||
# Additional heuristic to find MSBUILD_BINARY on Windows
|
||||
VSWHERE := "%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe"
|
||||
VSWHERE_CHECK := $(shell @echo off & $(VSWHERE) 2> nul || echo VSWHERE_NOT_FOUND)
|
||||
ifneq ($(VSWHERE_CHECK),VSWHERE_NOT_FOUND)
|
||||
MSBUILD := $(shell @echo off & $(VSWHERE) -latest -prerelease -products * -requires Microsoft.Component.MSBuild -find MSBuild\**\Bin\MSBuild.exe)
|
||||
VS_INSTALL_PATH := $(shell @echo off & $(VSWHERE) -property installationPath)
|
||||
endif
|
||||
endif
|
||||
DOTNET_binary := dotnet
|
||||
DOTNET := $(shell $(WHICH) $(DOTNET_binary) 2> nul)
|
||||
else
|
||||
MSBUILD_binary := msbuild
|
||||
MSBUILD := $(shell $(WHICH) $(MSBUILD_binary))
|
||||
DOTNET_binary := dotnet
|
||||
DOTNET := $(shell $(WHICH) $(DOTNET_binary))
|
||||
endif
|
||||
|
||||
ifeq ($(MSBUILD),)
|
||||
ifeq ($(DOTNET),)
|
||||
$(info )
|
||||
$(info '$(MSBUILD_binary)' binary could not be found. Check it is in your PATH.)
|
||||
ifeq ($(detected_OS),Windows)
|
||||
ifneq ($(VSWHERE_CHECK),VSWHERE_NOT_FOUND)
|
||||
$(info )
|
||||
$(info You may retry after running in the command prompt:)
|
||||
$(info )
|
||||
$(info "$(VS_INSTALL_PATH)\VC\Auxiliary\Build\vcvarsall.bat" x86_amd64)
|
||||
$(info )
|
||||
$(info If this doesn't work, install/find the location of vcvarsall.bat)
|
||||
$(info or install and add msbuild.exe to your PATH)
|
||||
$(info )
|
||||
endif
|
||||
endif
|
||||
$(info '$(DOTNET_binary)' binary could not be found. Check it is in your PATH.)
|
||||
$(error )
|
||||
endif
|
||||
$(info MSBUILD: $(MSBUILD))
|
||||
$(info DOTNET: $(DOTNET))
|
||||
$(info )
|
||||
|
||||
ifeq ($(ANDROID_SDK_ROOT),)
|
||||
@@ -117,7 +95,7 @@ endif
|
||||
$(info ANDROID_NDK_ROOT: $(ANDROID_NDK_ROOT))
|
||||
|
||||
ifneq ($(Configuration),)
|
||||
MSBUILD_PARAM = -p:Configuration="$(Configuration)"
|
||||
DOTNET_PARAM = -p:Configuration="$(Configuration)"
|
||||
else
|
||||
$(warning Configuration environment variable not set.)
|
||||
endif
|
||||
@@ -127,7 +105,7 @@ CREATE_MANIFEST_LINK :=
|
||||
|
||||
MANIFEST_FILE :=
|
||||
ifneq ($(Flavor),)
|
||||
MSBUILD_PARAM += -p:Flavor="$(Flavor)"
|
||||
DOTNET_PARAM += -p:Flavor="$(Flavor)"
|
||||
ifneq ($(Flavor),)
|
||||
ifeq ($(Flavor),Debug)
|
||||
MANIFEST_FILE := AndroidManifest_debug.xml
|
||||
@@ -152,7 +130,7 @@ else
|
||||
endif
|
||||
|
||||
ifneq ($(KeyStore),)
|
||||
MSBUILD_PARAM += -p:AndroidKeyStore=True -p:AndroidSigningKeyStore="$(KeyStore)" -p:AndroidSigningStorePass=env:MyAndroidSigningStorePass -p:AndroidSigningKeyPass=env:MyAndroidSigningKeyPass -p:AndroidSigningKeyAlias="kp2a"
|
||||
DOTNET_PARAM += -p:AndroidKeyStore=True -p:AndroidSigningKeyStore="$(KeyStore)" -p:AndroidSigningStorePass=env:MyAndroidSigningStorePass -p:AndroidSigningKeyPass=env:MyAndroidSigningKeyPass -p:AndroidSigningKeyAlias="kp2a"
|
||||
endif
|
||||
|
||||
ifeq ($(detected_OS),Windows)
|
||||
@@ -176,7 +154,7 @@ endif
|
||||
# Recursive wildcard: https://stackoverflow.com/a/18258352
|
||||
rwildcard=$(foreach d,$(wildcard $(1:=/*)),$(call rwildcard,$d,$2) $(filter $(subst *,%,$2),$d))
|
||||
|
||||
$(info MSBUILD_PARAM: $(MSBUILD_PARAM))
|
||||
$(info DOTNET_PARAM: $(DOTNET_PARAM))
|
||||
$(info nuget path: $(shell $(WHICH) nuget))
|
||||
$(info )
|
||||
|
||||
@@ -254,7 +232,7 @@ OUTPUT_PluginQR = src/java/Keepass2AndroidPluginSDK2/app/build/outputs/aar/Keepa
|
||||
.PHONY: native $(NATIVE_COMPONENTS) clean_native $(NATIVE_CLEAN_TARGETS) \
|
||||
java $(JAVA_COMPONENTS) clean_java $(JAVA_CLEAN_TARGETS) \
|
||||
nuget clean_nuget \
|
||||
msbuild clean_msbuild \
|
||||
dotnetbuild clean_dotnet \
|
||||
apk all clean
|
||||
|
||||
all: apk
|
||||
@@ -303,7 +281,7 @@ ifeq ($(shell $(WHICH) nuget),)
|
||||
endif
|
||||
$(RMFILE) stamp.nuget_*
|
||||
nuget restore src/KeePass.sln
|
||||
$(MSBUILD) src/KeePass.sln -t:restore $(MSBUILD_PARAM) -p:RestorePackagesConfig=true
|
||||
$(DOTNET) restore src/KeePass.sln $(DOTNET_PARAM) -p:RestorePackagesConfig=true
|
||||
@echo "" > stamp.nuget_$(Flavor)
|
||||
|
||||
manifestlink:
|
||||
@@ -312,20 +290,21 @@ manifestlink:
|
||||
$(CREATE_MANIFEST_LINK)
|
||||
|
||||
#####
|
||||
src/Kp2aBusinessLogic/Io/DropboxFileStorageKeys.cs:
|
||||
ifeq ($(detected_OS),Windows)
|
||||
$(CP) src\Kp2aBusinessLogic\Io\DropboxFileStorageKeysDummy.cs src\Kp2aBusinessLogic\Io\DropboxFileStorageKeys.cs
|
||||
else
|
||||
$(CP) src/Kp2aBusinessLogic/Io/DropboxFileStorageKeysDummy.cs $@
|
||||
endif
|
||||
|
||||
msbuild: manifestlink native java nuget src/Kp2aBusinessLogic/Io/DropboxFileStorageKeys.cs
|
||||
$(MSBUILD) src/KeePass.sln -target:keepass2android-app -p:AndroidSdkDirectory="$(ANDROID_SDK_ROOT)" -p:BuildProjectReferences=true $(MSBUILD_PARAM) -p:Platform="Any CPU" -m
|
||||
dotnetbuild: manifestlink native java nuget
|
||||
$(DOTNET) build src/KeePass.sln -target:keepass2android-app -p:AndroidSdkDirectory="$(ANDROID_SDK_ROOT)" -p:BuildProjectReferences=true $(DOTNET_PARAM) -p:Platform="Any CPU" -m
|
||||
|
||||
apk: msbuild
|
||||
$(MSBUILD) src/keepass2android-app/keepass2android-app.csproj -p:AndroidSdkDirectory="$(ANDROID_SDK_ROOT)" -t:SignAndroidPackage $(MSBUILD_PARAM) -p:Platform=AnyCPU -m
|
||||
apk: manifestlink native java nuget
|
||||
$(DOTNET) publish src/keepass2android-app/keepass2android-app.csproj -p:AndroidSdkDirectory="$(ANDROID_SDK_ROOT)" -t:SignAndroidPackage $(DOTNET_PARAM) -p:Platform=AnyCPU -m
|
||||
|
||||
build_all: msbuild
|
||||
apk_split: manifestlink native java nuget
|
||||
$(DOTNET) publish src/keepass2android-app/keepass2android-app.csproj -p:AndroidSdkDirectory="$(ANDROID_SDK_ROOT)" -t:SignAndroidPackage $(DOTNET_PARAM) -p:Platform=AnyCPU -m -p:RuntimeIdentifier=android-arm
|
||||
$(DOTNET) publish src/keepass2android-app/keepass2android-app.csproj -p:AndroidSdkDirectory="$(ANDROID_SDK_ROOT)" -t:SignAndroidPackage $(DOTNET_PARAM) -p:Platform=AnyCPU -m -p:RuntimeIdentifier=android-arm64
|
||||
$(DOTNET) publish src/keepass2android-app/keepass2android-app.csproj -p:AndroidSdkDirectory="$(ANDROID_SDK_ROOT)" -t:SignAndroidPackage $(DOTNET_PARAM) -p:Platform=AnyCPU -m -p:RuntimeIdentifier=android-x86
|
||||
$(DOTNET) publish src/keepass2android-app/keepass2android-app.csproj -p:AndroidSdkDirectory="$(ANDROID_SDK_ROOT)" -t:SignAndroidPackage $(DOTNET_PARAM) -p:Platform=AnyCPU -m -p:RuntimeIdentifier=android-x64
|
||||
src/build-scripts/rename-output-apks.sh src/keepass2android-app/bin/Release/net8.0-android/
|
||||
|
||||
build_all: dotnetbuild
|
||||
|
||||
##### Cleanup targets
|
||||
|
||||
@@ -369,10 +348,10 @@ else
|
||||
endif
|
||||
$(RMFILE) stamp.nuget_*
|
||||
|
||||
clean_msbuild:
|
||||
$(MSBUILD) src/KeePass.sln -target:clean $(MSBUILD_PARAM)
|
||||
clean_dotnet:
|
||||
$(DOTNET) clean src/KeePass.sln $(DOTNET_PARAM)
|
||||
|
||||
clean: clean_native clean_java clean_nuget clean_msbuild
|
||||
clean: clean_native clean_java clean_nuget clean_dotnet
|
||||
|
||||
distclean: clean
|
||||
ifneq ("$(wildcard ./allow_git_clean)","")
|
||||
|
@@ -11,10 +11,10 @@ Regular stable releases of Keepass2Android are available on [Google Play](https:
|
||||
Beta-releases can be obtained by opting in to the [Beta testing channel](https://play.google.com/apps/testing/keepass2android.keepass2android) or [Beta testing channel for Keepass2Android Offline](https://play.google.com/apps/testing/keepass2android.keepass2android_nonet).
|
||||
|
||||
# How can I contribute?
|
||||
* Help to translate Keepass2Android into your language or improve translations at [our Crowdin page](http://crowdin.net/project/keepass2android)
|
||||
* Help to translate Keepass2Android into your language or improve translations at [our Crowdin page](https://crowdin.net/project/keepass2android)
|
||||
* Add features by [creating a plugin](How-to-create-a-plug-in_.md) or creating a pull request. You might want to contact me before you start working so I can coordinate efforts.
|
||||
* [Become a GitHub sponsor to boost 🚀 development](https://github.com/sponsors/PhilippC)
|
||||
* [Make a donation](http://philipp.crocoll.net/donate.php)
|
||||
* [Make a donation](https://philipp.crocoll.net/donate.php)
|
||||
|
||||
# How do I learn more?
|
||||
Please see the [wiki](https://github.com/PhilippC/keepass2android/wiki/Documentation) for further information.
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2017 Dominik Reichl <dominik.reichl@t-online.de>
|
||||
Copyright (C) 2003-2025 Dominik Reichl <dominik.reichl@t-online.de>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -29,197 +29,226 @@ using KeePassLib.Utility;
|
||||
|
||||
namespace KeePassLib.Cryptography
|
||||
{
|
||||
/// <summary>
|
||||
/// Algorithms supported by <c>CryptoRandomStream</c>.
|
||||
/// </summary>
|
||||
public enum CrsAlgorithm
|
||||
{
|
||||
/// <summary>
|
||||
/// Not supported.
|
||||
/// </summary>
|
||||
Null = 0,
|
||||
/// <summary>
|
||||
/// Algorithms supported by <c>CryptoRandomStream</c>.
|
||||
/// </summary>
|
||||
public enum CrsAlgorithm
|
||||
{
|
||||
/// <summary>
|
||||
/// Not supported.
|
||||
/// </summary>
|
||||
Null = 0,
|
||||
|
||||
/// <summary>
|
||||
/// A variant of the ARCFour algorithm (RC4 incompatible).
|
||||
/// </summary>
|
||||
/// </summary>
|
||||
ArcFourVariant = 1,
|
||||
/// <summary>
|
||||
/// A variant of the ArcFour algorithm (RC4 incompatible).
|
||||
/// Insecure; for backward compatibility only.
|
||||
/// </summary>
|
||||
ArcFourVariant = 1,
|
||||
|
||||
/// <summary>
|
||||
/// Salsa20 stream cipher algorithm.
|
||||
/// </summary>
|
||||
Salsa20 = 2,
|
||||
/// <summary>
|
||||
/// Salsa20 stream cipher algorithm.
|
||||
/// </summary>
|
||||
Salsa20 = 2,
|
||||
|
||||
/// <summary>
|
||||
/// ChaCha20 stream cipher algorithm.
|
||||
/// </summary>
|
||||
ChaCha20 = 3,
|
||||
/// <summary>
|
||||
/// ChaCha20 stream cipher algorithm.
|
||||
/// </summary>
|
||||
ChaCha20 = 3,
|
||||
|
||||
Count = 4
|
||||
}
|
||||
Count = 4
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A random stream class. The class is initialized using random
|
||||
/// bytes provided by the caller. The produced stream has random
|
||||
/// properties, but for the same seed always the same stream
|
||||
/// is produced, i.e. this class can be used as stream cipher.
|
||||
/// </summary>
|
||||
public sealed class CryptoRandomStream : IDisposable
|
||||
{
|
||||
private readonly CrsAlgorithm m_crsAlgorithm;
|
||||
/// <summary>
|
||||
/// A random stream class. The class is initialized using random
|
||||
/// bytes provided by the caller. The produced stream has random
|
||||
/// properties, but for the same seed always the same stream
|
||||
/// is produced, i.e. this class can be used as stream cipher.
|
||||
/// </summary>
|
||||
public sealed class CryptoRandomStream : IDisposable
|
||||
{
|
||||
private readonly CrsAlgorithm m_alg;
|
||||
private bool m_bDisposed = false;
|
||||
|
||||
private byte[] m_pbState = null;
|
||||
private byte m_i = 0;
|
||||
private byte m_j = 0;
|
||||
private readonly byte[] m_pbKey = null;
|
||||
private readonly byte[] m_pbIV = null;
|
||||
|
||||
private Salsa20Cipher m_salsa20 = null;
|
||||
private ChaCha20Cipher m_chacha20 = null;
|
||||
private readonly ChaCha20Cipher m_chacha20 = null;
|
||||
private readonly Salsa20Cipher m_salsa20 = null;
|
||||
|
||||
/// <summary>
|
||||
/// Construct a new cryptographically secure random stream object.
|
||||
/// </summary>
|
||||
/// <param name="genAlgorithm">Algorithm to use.</param>
|
||||
/// <param name="pbKey">Initialization key. Must not be <c>null</c> and
|
||||
/// must contain at least 1 byte.</param>
|
||||
public CryptoRandomStream(CrsAlgorithm a, byte[] pbKey)
|
||||
{
|
||||
if(pbKey == null) { Debug.Assert(false); throw new ArgumentNullException("pbKey"); }
|
||||
/// <exception cref="System.ArgumentNullException">Thrown if the
|
||||
int cbKey = pbKey.Length;
|
||||
if(cbKey <= 0)
|
||||
{
|
||||
Debug.Assert(false); // Need at least one byte
|
||||
throw new ArgumentOutOfRangeException("pbKey");
|
||||
}
|
||||
/// <paramref name="pbKey" /> parameter is <c>null</c>.</exception>
|
||||
m_crsAlgorithm = a;
|
||||
/// <exception cref="System.ArgumentException">Thrown if the
|
||||
if(a == CrsAlgorithm.ChaCha20)
|
||||
{
|
||||
byte[] pbKey32 = new byte[32];
|
||||
byte[] pbIV12 = new byte[12];
|
||||
/// <paramref name="pbKey" /> parameter contains no bytes or the
|
||||
using(SHA512Managed h = new SHA512Managed())
|
||||
{
|
||||
byte[] pbHash = h.ComputeHash(pbKey);
|
||||
Array.Copy(pbHash, pbKey32, 32);
|
||||
Array.Copy(pbHash, 32, pbIV12, 0, 12);
|
||||
MemUtil.ZeroByteArray(pbHash);
|
||||
}
|
||||
/// algorithm is unknown.</exception>
|
||||
m_chacha20 = new ChaCha20Cipher(pbKey32, pbIV12, true);
|
||||
}
|
||||
else if(a == CrsAlgorithm.Salsa20)
|
||||
{
|
||||
byte[] pbKey32 = CryptoUtil.HashSha256(pbKey);
|
||||
byte[] pbIV8 = new byte[8] { 0xE8, 0x30, 0x09, 0x4B,
|
||||
0x97, 0x20, 0x5D, 0x2A }; // Unique constant
|
||||
private readonly byte[] m_pbState = null;
|
||||
private byte m_i = 0;
|
||||
private byte m_j = 0;
|
||||
|
||||
m_salsa20 = new Salsa20Cipher(pbKey32, pbIV8);
|
||||
}
|
||||
else if(a == CrsAlgorithm.ArcFourVariant)
|
||||
{
|
||||
// Fill the state linearly
|
||||
m_pbState = new byte[256];
|
||||
for(int w = 0; w < 256; ++w) m_pbState[w] = (byte)w;
|
||||
/// <summary>
|
||||
/// Construct a new cryptographically secure random stream object.
|
||||
/// </summary>
|
||||
/// <param name="a">Algorithm to use.</param>
|
||||
/// <param name="pbKey">Initialization key. Must not be <c>null</c>
|
||||
/// and must contain at least 1 byte.</param>
|
||||
public CryptoRandomStream(CrsAlgorithm a, byte[] pbKey)
|
||||
{
|
||||
if (pbKey == null) { Debug.Assert(false); throw new ArgumentNullException("pbKey"); }
|
||||
|
||||
unchecked
|
||||
{
|
||||
byte j = 0, t;
|
||||
int inxKey = 0;
|
||||
for(int w = 0; w < 256; ++w) // Key setup
|
||||
{
|
||||
j += (byte)(m_pbState[w] + pbKey[inxKey]);
|
||||
int cbKey = pbKey.Length;
|
||||
if (cbKey <= 0)
|
||||
{
|
||||
Debug.Assert(false); // Need at least one byte
|
||||
throw new ArgumentOutOfRangeException("pbKey");
|
||||
}
|
||||
|
||||
t = m_pbState[0]; // Swap entries
|
||||
m_pbState[0] = m_pbState[j];
|
||||
m_pbState[j] = t;
|
||||
m_alg = a;
|
||||
|
||||
++inxKey;
|
||||
if(inxKey >= cbKey) inxKey = 0;
|
||||
}
|
||||
}
|
||||
if (a == CrsAlgorithm.ChaCha20)
|
||||
{
|
||||
m_pbKey = new byte[32];
|
||||
m_pbIV = new byte[12];
|
||||
|
||||
GetRandomBytes(512); // Increases security, see cryptanalysis
|
||||
}
|
||||
else // Unknown algorithm
|
||||
{
|
||||
Debug.Assert(false);
|
||||
throw new ArgumentOutOfRangeException("a");
|
||||
}
|
||||
}
|
||||
using (SHA512Managed h = new SHA512Managed())
|
||||
{
|
||||
byte[] pbHash = h.ComputeHash(pbKey);
|
||||
Array.Copy(pbHash, m_pbKey, 32);
|
||||
Array.Copy(pbHash, 32, m_pbIV, 0, 12);
|
||||
MemUtil.ZeroByteArray(pbHash);
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
m_chacha20 = new ChaCha20Cipher(m_pbKey, m_pbIV, true);
|
||||
}
|
||||
else if (a == CrsAlgorithm.Salsa20)
|
||||
{
|
||||
m_pbKey = CryptoUtil.HashSha256(pbKey);
|
||||
m_pbIV = new byte[8] { 0xE8, 0x30, 0x09, 0x4B,
|
||||
0x97, 0x20, 0x5D, 0x2A }; // Unique constant
|
||||
|
||||
private void Dispose(bool disposing)
|
||||
{
|
||||
if(disposing)
|
||||
{
|
||||
if(m_crsAlgorithm == CrsAlgorithm.ChaCha20)
|
||||
m_chacha20.Dispose();
|
||||
else if(m_crsAlgorithm == CrsAlgorithm.Salsa20)
|
||||
m_salsa20.Dispose();
|
||||
else if(m_crsAlgorithm == CrsAlgorithm.ArcFourVariant)
|
||||
{
|
||||
MemUtil.ZeroByteArray(m_pbState);
|
||||
m_i = 0;
|
||||
m_j = 0;
|
||||
}
|
||||
else { Debug.Assert(false); }
|
||||
}
|
||||
}
|
||||
m_salsa20 = new Salsa20Cipher(m_pbKey, m_pbIV);
|
||||
}
|
||||
else if (a == CrsAlgorithm.ArcFourVariant)
|
||||
{
|
||||
// Fill the state linearly
|
||||
m_pbState = new byte[256];
|
||||
for (int w = 0; w < 256; ++w) m_pbState[w] = (byte)w;
|
||||
|
||||
/// <summary>
|
||||
/// Get <paramref name="uRequestedCount" /> random bytes.
|
||||
/// </summary>
|
||||
/// <param name="uRequestedCount">Number of random bytes to retrieve.</param>
|
||||
/// <returns>Returns <paramref name="uRequestedCount" /> random bytes.</returns>
|
||||
public byte[] GetRandomBytes(uint uRequestedCount)
|
||||
{
|
||||
if(uRequestedCount == 0) return MemUtil.EmptyByteArray;
|
||||
unchecked
|
||||
{
|
||||
byte j = 0, t;
|
||||
int inxKey = 0;
|
||||
for (int w = 0; w < 256; ++w) // Key setup
|
||||
{
|
||||
j += (byte)(m_pbState[w] + pbKey[inxKey]);
|
||||
|
||||
if(uRequestedCount > (uint)int.MaxValue)
|
||||
throw new ArgumentOutOfRangeException("uRequestedCount");
|
||||
int cb = (int)uRequestedCount;
|
||||
t = m_pbState[0]; // Swap entries
|
||||
m_pbState[0] = m_pbState[j];
|
||||
m_pbState[j] = t;
|
||||
|
||||
byte[] pbRet = new byte[cb];
|
||||
++inxKey;
|
||||
if (inxKey >= cbKey) inxKey = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if(m_crsAlgorithm == CrsAlgorithm.ChaCha20)
|
||||
m_chacha20.Encrypt(pbRet, 0, cb);
|
||||
else if(m_crsAlgorithm == CrsAlgorithm.Salsa20)
|
||||
m_salsa20.Encrypt(pbRet, 0, cb);
|
||||
else if(m_crsAlgorithm == CrsAlgorithm.ArcFourVariant)
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
for(int w = 0; w < cb; ++w)
|
||||
{
|
||||
++m_i;
|
||||
m_j += m_pbState[m_i];
|
||||
GetRandomBytes(512); // Increases security, see cryptanalysis
|
||||
}
|
||||
else // Unknown algorithm
|
||||
{
|
||||
Debug.Assert(false);
|
||||
throw new ArgumentOutOfRangeException("a");
|
||||
}
|
||||
}
|
||||
|
||||
byte t = m_pbState[m_i]; // Swap entries
|
||||
m_pbState[m_i] = m_pbState[m_j];
|
||||
m_pbState[m_j] = t;
|
||||
public void Dispose()
|
||||
{
|
||||
Dispose(true);
|
||||
GC.SuppressFinalize(this);
|
||||
}
|
||||
|
||||
t = (byte)(m_pbState[m_i] + m_pbState[m_j]);
|
||||
pbRet[w] = m_pbState[t];
|
||||
}
|
||||
}
|
||||
}
|
||||
else { Debug.Assert(false); }
|
||||
private void Dispose(bool disposing)
|
||||
{
|
||||
if (disposing)
|
||||
{
|
||||
if (m_alg == CrsAlgorithm.ChaCha20)
|
||||
m_chacha20.Dispose();
|
||||
else if (m_alg == CrsAlgorithm.Salsa20)
|
||||
m_salsa20.Dispose();
|
||||
else if (m_alg == CrsAlgorithm.ArcFourVariant)
|
||||
{
|
||||
MemUtil.ZeroByteArray(m_pbState);
|
||||
m_i = 0;
|
||||
m_j = 0;
|
||||
}
|
||||
else { Debug.Assert(false); }
|
||||
|
||||
return pbRet;
|
||||
}
|
||||
if (m_pbKey != null) MemUtil.ZeroByteArray(m_pbKey);
|
||||
if (m_pbIV != null) MemUtil.ZeroByteArray(m_pbIV);
|
||||
|
||||
public ulong GetRandomUInt64()
|
||||
{
|
||||
byte[] pb = GetRandomBytes(8);
|
||||
return MemUtil.BytesToUInt64(pb);
|
||||
}
|
||||
m_bDisposed = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get <paramref name="uRequestedCount" /> random bytes.
|
||||
/// </summary>
|
||||
/// <param name="uRequestedCount">Number of random bytes to retrieve.</param>
|
||||
/// <returns>Returns <paramref name="uRequestedCount" /> random bytes.</returns>
|
||||
public byte[] GetRandomBytes(uint uRequestedCount)
|
||||
{
|
||||
if (m_bDisposed) throw new ObjectDisposedException(null);
|
||||
|
||||
if (uRequestedCount == 0) return MemUtil.EmptyByteArray;
|
||||
if (uRequestedCount > (uint)int.MaxValue)
|
||||
throw new ArgumentOutOfRangeException("uRequestedCount");
|
||||
int cb = (int)uRequestedCount;
|
||||
|
||||
byte[] pbRet = new byte[cb];
|
||||
|
||||
if (m_alg == CrsAlgorithm.ChaCha20)
|
||||
m_chacha20.Encrypt(pbRet, 0, cb);
|
||||
else if (m_alg == CrsAlgorithm.Salsa20)
|
||||
m_salsa20.Encrypt(pbRet, 0, cb);
|
||||
else if (m_alg == CrsAlgorithm.ArcFourVariant)
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
for (int w = 0; w < cb; ++w)
|
||||
{
|
||||
++m_i;
|
||||
m_j += m_pbState[m_i];
|
||||
|
||||
byte t = m_pbState[m_i]; // Swap entries
|
||||
m_pbState[m_i] = m_pbState[m_j];
|
||||
m_pbState[m_j] = t;
|
||||
|
||||
t = (byte)(m_pbState[m_i] + m_pbState[m_j]);
|
||||
pbRet[w] = m_pbState[t];
|
||||
}
|
||||
}
|
||||
}
|
||||
else { Debug.Assert(false); }
|
||||
|
||||
return pbRet;
|
||||
}
|
||||
|
||||
public ulong GetRandomUInt64()
|
||||
{
|
||||
byte[] pb = GetRandomBytes(8);
|
||||
return MemUtil.BytesToUInt64(pb);
|
||||
}
|
||||
|
||||
internal ulong GetRandomUInt64(ulong uMaxExcl)
|
||||
{
|
||||
if (uMaxExcl == 0) { Debug.Assert(false); throw new ArgumentOutOfRangeException("uMaxExcl"); }
|
||||
|
||||
ulong uGen, uRem;
|
||||
do
|
||||
{
|
||||
uGen = GetRandomUInt64();
|
||||
uRem = uGen % uMaxExcl;
|
||||
}
|
||||
while ((uGen - uRem) > (ulong.MaxValue - (uMaxExcl - 1UL)));
|
||||
// This ensures that the last number of the block (i.e.
|
||||
// (uGen - uRem) + (uMaxExcl - 1)) is generatable;
|
||||
// for signed longs, overflow to negative number:
|
||||
// while((uGen - uRem) + (uMaxExcl - 1) < 0);
|
||||
|
||||
return uRem;
|
||||
}
|
||||
|
||||
#if CRSBENCHMARK
|
||||
public static string Benchmark()
|
||||
@@ -237,22 +266,21 @@ namespace KeePassLib.Cryptography
|
||||
return str;
|
||||
}
|
||||
|
||||
private static int BenchTime(CrsAlgorithm cra, int nRounds, int nDataSize)
|
||||
private static int BenchTime(CrsAlgorithm a, int nRounds, int cbData)
|
||||
{
|
||||
byte[] pbKey = new byte[4] { 0x00, 0x01, 0x02, 0x03 };
|
||||
|
||||
int nStart = Environment.TickCount;
|
||||
int tStart = Environment.TickCount;
|
||||
for(int i = 0; i < nRounds; ++i)
|
||||
{
|
||||
using(CryptoRandomStream c = new CryptoRandomStream(cra, pbKey))
|
||||
using(CryptoRandomStream crs = new CryptoRandomStream(a, pbKey))
|
||||
{
|
||||
c.GetRandomBytes((uint)nDataSize);
|
||||
crs.GetRandomBytes((uint)cbData);
|
||||
}
|
||||
}
|
||||
int nEnd = Environment.TickCount;
|
||||
|
||||
return (nEnd - nStart);
|
||||
return (Environment.TickCount - tStart);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,65 +0,0 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2017 Dominik Reichl <dominik.reichl@t-online.de>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Diagnostics;
|
||||
|
||||
using KeePassLib.Security;
|
||||
using KeePassLib.Utility;
|
||||
|
||||
namespace KeePassLib.Cryptography.PasswordGenerator
|
||||
{
|
||||
internal static class CharSetBasedGenerator
|
||||
{
|
||||
internal static PwgError Generate(out ProtectedString psOut,
|
||||
PwProfile pwProfile, CryptoRandomStream crsRandomSource)
|
||||
{
|
||||
psOut = ProtectedString.Empty;
|
||||
if(pwProfile.Length == 0) return PwgError.Success;
|
||||
|
||||
PwCharSet pcs = new PwCharSet(pwProfile.CharSet.ToString());
|
||||
char[] vGenerated = new char[pwProfile.Length];
|
||||
|
||||
PwGenerator.PrepareCharSet(pcs, pwProfile);
|
||||
|
||||
for(int nIndex = 0; nIndex < (int)pwProfile.Length; ++nIndex)
|
||||
{
|
||||
char ch = PwGenerator.GenerateCharacter(pwProfile, pcs,
|
||||
crsRandomSource);
|
||||
|
||||
if(ch == char.MinValue)
|
||||
{
|
||||
MemUtil.ZeroArray<char>(vGenerated);
|
||||
return PwgError.TooFewCharacters;
|
||||
}
|
||||
|
||||
vGenerated[nIndex] = ch;
|
||||
}
|
||||
|
||||
byte[] pbUtf8 = StrUtil.Utf8.GetBytes(vGenerated);
|
||||
psOut = new ProtectedString(true, pbUtf8);
|
||||
MemUtil.ZeroByteArray(pbUtf8);
|
||||
MemUtil.ZeroArray<char>(vGenerated);
|
||||
|
||||
return PwgError.Success;
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,173 +0,0 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2017 Dominik Reichl <dominik.reichl@t-online.de>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
*/
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Diagnostics;
|
||||
|
||||
using KeePassLib.Security;
|
||||
using KeePassLib.Utility;
|
||||
|
||||
namespace KeePassLib.Cryptography.PasswordGenerator
|
||||
{
|
||||
internal static class PatternBasedGenerator
|
||||
{
|
||||
internal static PwgError Generate(out ProtectedString psOut,
|
||||
PwProfile pwProfile, CryptoRandomStream crsRandomSource)
|
||||
{
|
||||
psOut = ProtectedString.Empty;
|
||||
LinkedList<char> vGenerated = new LinkedList<char>();
|
||||
PwCharSet pcsCurrent = new PwCharSet();
|
||||
PwCharSet pcsCustom = new PwCharSet();
|
||||
PwCharSet pcsUsed = new PwCharSet();
|
||||
bool bInCharSetDef = false;
|
||||
|
||||
string strPattern = ExpandPattern(pwProfile.Pattern);
|
||||
if(strPattern.Length == 0) return PwgError.Success;
|
||||
|
||||
CharStream csStream = new CharStream(strPattern);
|
||||
char ch = csStream.ReadChar();
|
||||
|
||||
while(ch != char.MinValue)
|
||||
{
|
||||
pcsCurrent.Clear();
|
||||
|
||||
bool bGenerateChar = false;
|
||||
|
||||
if(ch == '\\')
|
||||
{
|
||||
ch = csStream.ReadChar();
|
||||
if(ch == char.MinValue) // Backslash at the end
|
||||
{
|
||||
vGenerated.AddLast('\\');
|
||||
break;
|
||||
}
|
||||
|
||||
if(bInCharSetDef) pcsCustom.Add(ch);
|
||||
else
|
||||
{
|
||||
vGenerated.AddLast(ch);
|
||||
pcsUsed.Add(ch);
|
||||
}
|
||||
}
|
||||
else if(ch == '[')
|
||||
{
|
||||
pcsCustom.Clear();
|
||||
bInCharSetDef = true;
|
||||
}
|
||||
else if(ch == ']')
|
||||
{
|
||||
pcsCurrent.Add(pcsCustom.ToString());
|
||||
|
||||
bInCharSetDef = false;
|
||||
bGenerateChar = true;
|
||||
}
|
||||
else if(bInCharSetDef)
|
||||
{
|
||||
if(pcsCustom.AddCharSet(ch) == false)
|
||||
pcsCustom.Add(ch);
|
||||
}
|
||||
else if(pcsCurrent.AddCharSet(ch) == false)
|
||||
{
|
||||
vGenerated.AddLast(ch);
|
||||
pcsUsed.Add(ch);
|
||||
}
|
||||
else bGenerateChar = true;
|
||||
|
||||
if(bGenerateChar)
|
||||
{
|
||||
PwGenerator.PrepareCharSet(pcsCurrent, pwProfile);
|
||||
|
||||
if(pwProfile.NoRepeatingCharacters)
|
||||
pcsCurrent.Remove(pcsUsed.ToString());
|
||||
|
||||
char chGen = PwGenerator.GenerateCharacter(pwProfile,
|
||||
pcsCurrent, crsRandomSource);
|
||||
|
||||
if(chGen == char.MinValue) return PwgError.TooFewCharacters;
|
||||
|
||||
vGenerated.AddLast(chGen);
|
||||
pcsUsed.Add(chGen);
|
||||
}
|
||||
|
||||
ch = csStream.ReadChar();
|
||||
}
|
||||
|
||||
if(vGenerated.Count == 0) return PwgError.Success;
|
||||
|
||||
char[] vArray = new char[vGenerated.Count];
|
||||
vGenerated.CopyTo(vArray, 0);
|
||||
|
||||
if(pwProfile.PatternPermutePassword)
|
||||
PwGenerator.ShufflePassword(vArray, crsRandomSource);
|
||||
|
||||
byte[] pbUtf8 = StrUtil.Utf8.GetBytes(vArray);
|
||||
psOut = new ProtectedString(true, pbUtf8);
|
||||
MemUtil.ZeroByteArray(pbUtf8);
|
||||
MemUtil.ZeroArray<char>(vArray);
|
||||
vGenerated.Clear();
|
||||
|
||||
return PwgError.Success;
|
||||
}
|
||||
|
||||
private static string ExpandPattern(string strPattern)
|
||||
{
|
||||
Debug.Assert(strPattern != null); if(strPattern == null) return string.Empty;
|
||||
string str = strPattern;
|
||||
|
||||
while(true)
|
||||
{
|
||||
int nOpen = FindFirstUnescapedChar(str, '{');
|
||||
int nClose = FindFirstUnescapedChar(str, '}');
|
||||
|
||||
if((nOpen >= 0) && (nOpen < nClose))
|
||||
{
|
||||
string strCount = str.Substring(nOpen + 1, nClose - nOpen - 1);
|
||||
str = str.Remove(nOpen, nClose - nOpen + 1);
|
||||
|
||||
uint uRepeat;
|
||||
if(StrUtil.TryParseUInt(strCount, out uRepeat) && (nOpen >= 1))
|
||||
{
|
||||
if(uRepeat == 0)
|
||||
str = str.Remove(nOpen - 1, 1);
|
||||
else
|
||||
str = str.Insert(nOpen, new string(str[nOpen - 1], (int)uRepeat - 1));
|
||||
}
|
||||
}
|
||||
else break;
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
private static int FindFirstUnescapedChar(string str, char ch)
|
||||
{
|
||||
for(int i = 0; i < str.Length; ++i)
|
||||
{
|
||||
char chCur = str[i];
|
||||
|
||||
if(chCur == '\\') ++i; // Next is escaped, skip it
|
||||
else if(chCur == ch) return i;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2017 Dominik Reichl <dominik.reichl@t-online.de>
|
||||
Copyright (C) 2003-2025 Dominik Reichl <dominik.reichl@t-online.de>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -19,333 +19,311 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
|
||||
using KeePassLib.Utility;
|
||||
|
||||
namespace KeePassLib.Cryptography.PasswordGenerator
|
||||
{
|
||||
public sealed class PwCharSet
|
||||
{
|
||||
public const string UpperCase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
public const string LowerCase = "abcdefghijklmnopqrstuvwxyz";
|
||||
public const string Digits = "0123456789";
|
||||
public sealed class PwCharSet : IEquatable<PwCharSet>
|
||||
{
|
||||
public static readonly string UpperCase = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
public static readonly string LowerCase = "abcdefghijklmnopqrstuvwxyz";
|
||||
public static readonly string Digits = "0123456789";
|
||||
|
||||
public const string UpperConsonants = "BCDFGHJKLMNPQRSTVWXYZ";
|
||||
public const string LowerConsonants = "bcdfghjklmnpqrstvwxyz";
|
||||
public const string UpperVowels = "AEIOU";
|
||||
public const string LowerVowels = "aeiou";
|
||||
public static readonly string UpperConsonants = "BCDFGHJKLMNPQRSTVWXYZ";
|
||||
public static readonly string LowerConsonants = "bcdfghjklmnpqrstvwxyz";
|
||||
public static readonly string UpperVowels = "AEIOU";
|
||||
public static readonly string LowerVowels = "aeiou";
|
||||
|
||||
public const string Punctuation = @",.;:";
|
||||
public const string Brackets = @"[]{}()<>";
|
||||
public static readonly string Punctuation = ",.;:";
|
||||
public static readonly string Brackets = @"[]{}()<>";
|
||||
|
||||
public const string PrintableAsciiSpecial = "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~";
|
||||
public static readonly string Special = "!\"#$%&'*+,./:;=?@\\^`|~";
|
||||
public static readonly string PrintableAsciiSpecial = "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~";
|
||||
|
||||
public const string UpperHex = "0123456789ABCDEF";
|
||||
public const string LowerHex = "0123456789abcdef";
|
||||
public static readonly string UpperHex = "0123456789ABCDEF";
|
||||
public static readonly string LowerHex = "0123456789abcdef";
|
||||
|
||||
public const string Invalid = "\t\r\n";
|
||||
public const string LookAlike = @"O0l1I|";
|
||||
public static readonly string LookAlike = "O0Il1|";
|
||||
|
||||
internal const string MenuAccels = PwCharSet.LowerCase + PwCharSet.Digits;
|
||||
/// <summary>
|
||||
/// Latin-1 Supplement except U+00A0 (NBSP) and U+00AD (SHY).
|
||||
/// </summary>
|
||||
public static readonly string Latin1S =
|
||||
"\u00A1\u00A2\u00A3\u00A4\u00A5\u00A6\u00A7" +
|
||||
"\u00A8\u00A9\u00AA\u00AB\u00AC\u00AE\u00AF" +
|
||||
"\u00B0\u00B1\u00B2\u00B3\u00B4\u00B5\u00B6\u00B7" +
|
||||
"\u00B8\u00B9\u00BA\u00BB\u00BC\u00BD\u00BE\u00BF" +
|
||||
"\u00C0\u00C1\u00C2\u00C3\u00C4\u00C5\u00C6\u00C7" +
|
||||
"\u00C8\u00C9\u00CA\u00CB\u00CC\u00CD\u00CE\u00CF" +
|
||||
"\u00D0\u00D1\u00D2\u00D3\u00D4\u00D5\u00D6\u00D7" +
|
||||
"\u00D8\u00D9\u00DA\u00DB\u00DC\u00DD\u00DE\u00DF" +
|
||||
"\u00E0\u00E1\u00E2\u00E3\u00E4\u00E5\u00E6\u00E7" +
|
||||
"\u00E8\u00E9\u00EA\u00EB\u00EC\u00ED\u00EE\u00EF" +
|
||||
"\u00F0\u00F1\u00F2\u00F3\u00F4\u00F5\u00F6\u00F7" +
|
||||
"\u00F8\u00F9\u00FA\u00FB\u00FC\u00FD\u00FE\u00FF";
|
||||
|
||||
private const int CharTabSize = (0x10000 / 8);
|
||||
// internal static readonly string MenuAccels = PwCharSet.LowerCase + PwCharSet.Digits;
|
||||
|
||||
private List<char> m_vChars = new List<char>();
|
||||
private byte[] m_vTab = new byte[CharTabSize];
|
||||
[Obsolete]
|
||||
public static string SpecialChars { get { return PwCharSet.Special; } }
|
||||
[Obsolete]
|
||||
public static string HighAnsiChars { get { return PwCharSet.Latin1S; } }
|
||||
|
||||
private static string m_strHighAnsi = null;
|
||||
public static string HighAnsiChars
|
||||
{
|
||||
get
|
||||
{
|
||||
if(m_strHighAnsi == null) { new PwCharSet(); } // Create string
|
||||
Debug.Assert(m_strHighAnsi != null);
|
||||
return m_strHighAnsi;
|
||||
}
|
||||
}
|
||||
private readonly List<char> m_lChars = new List<char>();
|
||||
private readonly byte[] m_vTab = new byte[0x10000 / 8];
|
||||
|
||||
private static string m_strSpecial = null;
|
||||
public static string SpecialChars
|
||||
{
|
||||
get
|
||||
{
|
||||
if(m_strSpecial == null) { new PwCharSet(); } // Create string
|
||||
Debug.Assert(m_strSpecial != null);
|
||||
return m_strSpecial;
|
||||
}
|
||||
}
|
||||
/// <summary>
|
||||
/// Create a new, empty character set.
|
||||
/// </summary>
|
||||
public PwCharSet()
|
||||
{
|
||||
Debug.Assert(PwCharSet.Latin1S.Length == (16 * 6 - 2));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new, empty character set collection object.
|
||||
/// </summary>
|
||||
public PwCharSet()
|
||||
{
|
||||
Initialize(true);
|
||||
}
|
||||
public PwCharSet(string strCharSet)
|
||||
{
|
||||
Add(strCharSet);
|
||||
}
|
||||
|
||||
public PwCharSet(string strCharSet)
|
||||
{
|
||||
Initialize(true);
|
||||
Add(strCharSet);
|
||||
}
|
||||
/// <summary>
|
||||
/// Number of characters in this set.
|
||||
/// </summary>
|
||||
public uint Size
|
||||
{
|
||||
get { return (uint)m_lChars.Count; }
|
||||
}
|
||||
|
||||
private PwCharSet(bool bFullInitialize)
|
||||
{
|
||||
Initialize(bFullInitialize);
|
||||
}
|
||||
/// <summary>
|
||||
/// Get a character of the set using an index.
|
||||
/// </summary>
|
||||
/// <param name="uPos">Index of the character to get.</param>
|
||||
/// <returns>Character at the specified position. If the index is invalid,
|
||||
/// an <c>ArgumentOutOfRangeException</c> is thrown.</returns>
|
||||
public char this[uint uPos]
|
||||
{
|
||||
get
|
||||
{
|
||||
if (uPos >= (uint)m_lChars.Count)
|
||||
throw new ArgumentOutOfRangeException("uPos");
|
||||
|
||||
private void Initialize(bool bFullInitialize)
|
||||
{
|
||||
Clear();
|
||||
return m_lChars[(int)uPos];
|
||||
}
|
||||
}
|
||||
|
||||
if(!bFullInitialize) return;
|
||||
public bool Equals(PwCharSet other)
|
||||
{
|
||||
if (object.ReferenceEquals(other, this)) return true;
|
||||
if (object.ReferenceEquals(other, null)) return false;
|
||||
|
||||
if(m_strHighAnsi == null)
|
||||
{
|
||||
StringBuilder sbHighAnsi = new StringBuilder();
|
||||
// [U+0080, U+009F] are C1 control characters,
|
||||
// U+00A0 is non-breaking space
|
||||
for(char ch = '\u00A1'; ch <= '\u00AC'; ++ch)
|
||||
sbHighAnsi.Append(ch);
|
||||
// U+00AD is soft hyphen (format character)
|
||||
for(char ch = '\u00AE'; ch < '\u00FF'; ++ch)
|
||||
sbHighAnsi.Append(ch);
|
||||
sbHighAnsi.Append('\u00FF');
|
||||
if (m_lChars.Count != other.m_lChars.Count) return false;
|
||||
|
||||
m_strHighAnsi = sbHighAnsi.ToString();
|
||||
}
|
||||
return MemUtil.ArraysEqual(m_vTab, other.m_vTab);
|
||||
}
|
||||
|
||||
if(m_strSpecial == null)
|
||||
{
|
||||
PwCharSet pcs = new PwCharSet(false);
|
||||
pcs.AddRange('!', '/');
|
||||
pcs.AddRange(':', '@');
|
||||
pcs.AddRange('[', '`');
|
||||
pcs.Add(@"|~");
|
||||
pcs.Remove(@"-_ ");
|
||||
pcs.Remove(PwCharSet.Brackets);
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
return Equals(obj as PwCharSet);
|
||||
}
|
||||
|
||||
m_strSpecial = pcs.ToString();
|
||||
}
|
||||
}
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return (int)MemUtil.Hash32(m_vTab, 0, m_vTab.Length);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Number of characters in this set.
|
||||
/// </summary>
|
||||
public uint Size
|
||||
{
|
||||
get { return (uint)m_vChars.Count; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Remove all characters from this set.
|
||||
/// </summary>
|
||||
public void Clear()
|
||||
{
|
||||
m_lChars.Clear();
|
||||
Array.Clear(m_vTab, 0, m_vTab.Length);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get a character of the set using an index.
|
||||
/// </summary>
|
||||
/// <param name="uPos">Index of the character to get.</param>
|
||||
/// <returns>Character at the specified position. If the index is invalid,
|
||||
/// an <c>ArgumentOutOfRangeException</c> is thrown.</returns>
|
||||
public char this[uint uPos]
|
||||
{
|
||||
get
|
||||
{
|
||||
if(uPos >= (uint)m_vChars.Count)
|
||||
throw new ArgumentOutOfRangeException("uPos");
|
||||
public bool Contains(char ch)
|
||||
{
|
||||
return (((m_vTab[ch / 8] >> (ch % 8)) & 1) != char.MinValue);
|
||||
}
|
||||
|
||||
return m_vChars[(int)uPos];
|
||||
}
|
||||
}
|
||||
public bool Contains(string strCharacters)
|
||||
{
|
||||
Debug.Assert(strCharacters != null);
|
||||
if (strCharacters == null) throw new ArgumentNullException("strCharacters");
|
||||
|
||||
/// <summary>
|
||||
/// Remove all characters from this set.
|
||||
/// </summary>
|
||||
public void Clear()
|
||||
{
|
||||
m_vChars.Clear();
|
||||
Array.Clear(m_vTab, 0, m_vTab.Length);
|
||||
}
|
||||
foreach (char ch in strCharacters)
|
||||
{
|
||||
if (!Contains(ch)) return false;
|
||||
}
|
||||
|
||||
public bool Contains(char ch)
|
||||
{
|
||||
return (((m_vTab[ch / 8] >> (ch % 8)) & 1) != char.MinValue);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool Contains(string strCharacters)
|
||||
{
|
||||
Debug.Assert(strCharacters != null);
|
||||
if(strCharacters == null) throw new ArgumentNullException("strCharacters");
|
||||
/// <summary>
|
||||
/// Add characters to the set.
|
||||
/// </summary>
|
||||
/// <param name="ch">Character to add.</param>
|
||||
public void Add(char ch)
|
||||
{
|
||||
if (ch == char.MinValue) { Debug.Assert(false); return; }
|
||||
|
||||
foreach(char ch in strCharacters)
|
||||
{
|
||||
if(!Contains(ch)) return false;
|
||||
}
|
||||
if (!Contains(ch))
|
||||
{
|
||||
m_lChars.Add(ch);
|
||||
m_vTab[ch / 8] |= (byte)(1 << (ch % 8));
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
/// <summary>
|
||||
/// Add characters to the set.
|
||||
/// </summary>
|
||||
/// <param name="strCharSet">String containing characters to add.</param>
|
||||
public void Add(string strCharSet)
|
||||
{
|
||||
Debug.Assert(strCharSet != null);
|
||||
if (strCharSet == null) throw new ArgumentNullException("strCharSet");
|
||||
|
||||
/// <summary>
|
||||
/// Add characters to the set.
|
||||
/// </summary>
|
||||
/// <param name="ch">Character to add.</param>
|
||||
public void Add(char ch)
|
||||
{
|
||||
if(ch == char.MinValue) { Debug.Assert(false); return; }
|
||||
foreach (char ch in strCharSet)
|
||||
Add(ch);
|
||||
}
|
||||
|
||||
if(!Contains(ch))
|
||||
{
|
||||
m_vChars.Add(ch);
|
||||
m_vTab[ch / 8] |= (byte)(1 << (ch % 8));
|
||||
}
|
||||
}
|
||||
public void Add(string strCharSet1, string strCharSet2)
|
||||
{
|
||||
Add(strCharSet1);
|
||||
Add(strCharSet2);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add characters to the set.
|
||||
/// </summary>
|
||||
/// <param name="strCharSet">String containing characters to add.</param>
|
||||
public void Add(string strCharSet)
|
||||
{
|
||||
Debug.Assert(strCharSet != null);
|
||||
if(strCharSet == null) throw new ArgumentNullException("strCharSet");
|
||||
public void Add(string strCharSet1, string strCharSet2, string strCharSet3)
|
||||
{
|
||||
Add(strCharSet1);
|
||||
Add(strCharSet2);
|
||||
Add(strCharSet3);
|
||||
}
|
||||
|
||||
m_vChars.Capacity = m_vChars.Count + strCharSet.Length;
|
||||
public void AddRange(char chMin, char chMax)
|
||||
{
|
||||
for (char ch = chMin; ch < chMax; ++ch)
|
||||
Add(ch);
|
||||
|
||||
foreach(char ch in strCharSet)
|
||||
Add(ch);
|
||||
}
|
||||
Add(chMax);
|
||||
}
|
||||
|
||||
public void Add(string strCharSet1, string strCharSet2)
|
||||
{
|
||||
Add(strCharSet1);
|
||||
Add(strCharSet2);
|
||||
}
|
||||
public bool AddCharSet(char chCharSetIdentifier)
|
||||
{
|
||||
bool bResult = true;
|
||||
|
||||
public void Add(string strCharSet1, string strCharSet2, string strCharSet3)
|
||||
{
|
||||
Add(strCharSet1);
|
||||
Add(strCharSet2);
|
||||
Add(strCharSet3);
|
||||
}
|
||||
switch (chCharSetIdentifier)
|
||||
{
|
||||
case 'a': Add(PwCharSet.LowerCase, PwCharSet.Digits); break;
|
||||
case 'A':
|
||||
Add(PwCharSet.LowerCase, PwCharSet.UpperCase,
|
||||
PwCharSet.Digits); break;
|
||||
case 'U': Add(PwCharSet.UpperCase, PwCharSet.Digits); break;
|
||||
case 'c': Add(PwCharSet.LowerConsonants); break;
|
||||
case 'C':
|
||||
Add(PwCharSet.LowerConsonants,
|
||||
PwCharSet.UpperConsonants); break;
|
||||
case 'z': Add(PwCharSet.UpperConsonants); break;
|
||||
case 'd': Add(PwCharSet.Digits); break; // Digit
|
||||
case 'h': Add(PwCharSet.LowerHex); break;
|
||||
case 'H': Add(PwCharSet.UpperHex); break;
|
||||
case 'l': Add(PwCharSet.LowerCase); break;
|
||||
case 'L': Add(PwCharSet.LowerCase, PwCharSet.UpperCase); break;
|
||||
case 'u': Add(PwCharSet.UpperCase); break;
|
||||
case 'p': Add(PwCharSet.Punctuation); break;
|
||||
case 'b': Add(PwCharSet.Brackets); break;
|
||||
case 's': Add(PwCharSet.PrintableAsciiSpecial); break;
|
||||
case 'S':
|
||||
Add(PwCharSet.UpperCase, PwCharSet.LowerCase);
|
||||
Add(PwCharSet.Digits, PwCharSet.PrintableAsciiSpecial); break;
|
||||
case 'v': Add(PwCharSet.LowerVowels); break;
|
||||
case 'V': Add(PwCharSet.LowerVowels, PwCharSet.UpperVowels); break;
|
||||
case 'Z': Add(PwCharSet.UpperVowels); break;
|
||||
case 'x': Add(PwCharSet.Latin1S); break;
|
||||
default: bResult = false; break;
|
||||
}
|
||||
|
||||
public void AddRange(char chMin, char chMax)
|
||||
{
|
||||
m_vChars.Capacity = m_vChars.Count + (chMax - chMin) + 1;
|
||||
return bResult;
|
||||
}
|
||||
|
||||
for(char ch = chMin; ch < chMax; ++ch)
|
||||
Add(ch);
|
||||
public bool Remove(char ch)
|
||||
{
|
||||
m_vTab[ch / 8] &= (byte)(~(1 << (ch % 8)));
|
||||
return m_lChars.Remove(ch);
|
||||
}
|
||||
|
||||
Add(chMax);
|
||||
}
|
||||
public bool Remove(string strCharacters)
|
||||
{
|
||||
Debug.Assert(strCharacters != null);
|
||||
if (strCharacters == null) throw new ArgumentNullException("strCharacters");
|
||||
|
||||
public bool AddCharSet(char chCharSetIdentifier)
|
||||
{
|
||||
bool bResult = true;
|
||||
bool bResult = true;
|
||||
foreach (char ch in strCharacters)
|
||||
{
|
||||
if (!Remove(ch)) bResult = false;
|
||||
}
|
||||
|
||||
switch(chCharSetIdentifier)
|
||||
{
|
||||
case 'a': Add(PwCharSet.LowerCase, PwCharSet.Digits); break;
|
||||
case 'A': Add(PwCharSet.LowerCase, PwCharSet.UpperCase,
|
||||
PwCharSet.Digits); break;
|
||||
case 'U': Add(PwCharSet.UpperCase, PwCharSet.Digits); break;
|
||||
case 'c': Add(PwCharSet.LowerConsonants); break;
|
||||
case 'C': Add(PwCharSet.LowerConsonants,
|
||||
PwCharSet.UpperConsonants); break;
|
||||
case 'z': Add(PwCharSet.UpperConsonants); break;
|
||||
case 'd': Add(PwCharSet.Digits); break; // Digit
|
||||
case 'h': Add(PwCharSet.LowerHex); break;
|
||||
case 'H': Add(PwCharSet.UpperHex); break;
|
||||
case 'l': Add(PwCharSet.LowerCase); break;
|
||||
case 'L': Add(PwCharSet.LowerCase, PwCharSet.UpperCase); break;
|
||||
case 'u': Add(PwCharSet.UpperCase); break;
|
||||
case 'p': Add(PwCharSet.Punctuation); break;
|
||||
case 'b': Add(PwCharSet.Brackets); break;
|
||||
case 's': Add(PwCharSet.PrintableAsciiSpecial); break;
|
||||
case 'S': Add(PwCharSet.UpperCase, PwCharSet.LowerCase);
|
||||
Add(PwCharSet.Digits, PwCharSet.PrintableAsciiSpecial); break;
|
||||
case 'v': Add(PwCharSet.LowerVowels); break;
|
||||
case 'V': Add(PwCharSet.LowerVowels, PwCharSet.UpperVowels); break;
|
||||
case 'Z': Add(PwCharSet.UpperVowels); break;
|
||||
case 'x': Add(m_strHighAnsi); break;
|
||||
default: bResult = false; break;
|
||||
}
|
||||
return bResult;
|
||||
}
|
||||
|
||||
return bResult;
|
||||
}
|
||||
public bool RemoveIfAllExist(string strCharacters)
|
||||
{
|
||||
Debug.Assert(strCharacters != null);
|
||||
if (strCharacters == null) throw new ArgumentNullException("strCharacters");
|
||||
|
||||
public bool Remove(char ch)
|
||||
{
|
||||
m_vTab[ch / 8] &= (byte)(~(1 << (ch % 8)));
|
||||
return m_vChars.Remove(ch);
|
||||
}
|
||||
if (!Contains(strCharacters))
|
||||
return false;
|
||||
|
||||
public bool Remove(string strCharacters)
|
||||
{
|
||||
Debug.Assert(strCharacters != null);
|
||||
if(strCharacters == null) throw new ArgumentNullException("strCharacters");
|
||||
return Remove(strCharacters);
|
||||
}
|
||||
|
||||
bool bResult = true;
|
||||
foreach(char ch in strCharacters)
|
||||
{
|
||||
if(!Remove(ch)) bResult = false;
|
||||
}
|
||||
/// <summary>
|
||||
/// Convert the character set to a string containing all its characters.
|
||||
/// </summary>
|
||||
/// <returns>String containing all character set characters.</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder(m_lChars.Count);
|
||||
foreach (char ch in m_lChars)
|
||||
sb.Append(ch);
|
||||
|
||||
return bResult;
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public bool RemoveIfAllExist(string strCharacters)
|
||||
{
|
||||
Debug.Assert(strCharacters != null);
|
||||
if(strCharacters == null) throw new ArgumentNullException("strCharacters");
|
||||
public string PackAndRemoveCharRanges()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
if(!Contains(strCharacters))
|
||||
return false;
|
||||
sb.Append(RemoveIfAllExist(PwCharSet.UpperCase) ? 'U' : '_');
|
||||
sb.Append(RemoveIfAllExist(PwCharSet.LowerCase) ? 'L' : '_');
|
||||
sb.Append(RemoveIfAllExist(PwCharSet.Digits) ? 'D' : '_');
|
||||
sb.Append(RemoveIfAllExist(PwCharSet.Special) ? 'S' : '_');
|
||||
sb.Append(RemoveIfAllExist(PwCharSet.Punctuation) ? 'P' : '_');
|
||||
sb.Append(RemoveIfAllExist("-") ? 'm' : '_');
|
||||
sb.Append(RemoveIfAllExist("_") ? 'u' : '_');
|
||||
sb.Append(RemoveIfAllExist(" ") ? 's' : '_');
|
||||
sb.Append(RemoveIfAllExist(PwCharSet.Brackets) ? 'B' : '_');
|
||||
sb.Append(RemoveIfAllExist(PwCharSet.Latin1S) ? 'H' : '_');
|
||||
|
||||
return Remove(strCharacters);
|
||||
}
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Convert the character set to a string containing all its characters.
|
||||
/// </summary>
|
||||
/// <returns>String containing all character set characters.</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
foreach(char ch in m_vChars)
|
||||
sb.Append(ch);
|
||||
public void UnpackCharRanges(string strRanges)
|
||||
{
|
||||
if (strRanges == null) { Debug.Assert(false); return; }
|
||||
if (strRanges.Length < 10) { Debug.Assert(false); return; }
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public string PackAndRemoveCharRanges()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.Append(RemoveIfAllExist(PwCharSet.UpperCase) ? 'U' : '_');
|
||||
sb.Append(RemoveIfAllExist(PwCharSet.LowerCase) ? 'L' : '_');
|
||||
sb.Append(RemoveIfAllExist(PwCharSet.Digits) ? 'D' : '_');
|
||||
sb.Append(RemoveIfAllExist(m_strSpecial) ? 'S' : '_');
|
||||
sb.Append(RemoveIfAllExist(PwCharSet.Punctuation) ? 'P' : '_');
|
||||
sb.Append(RemoveIfAllExist(@"-") ? 'm' : '_');
|
||||
sb.Append(RemoveIfAllExist(@"_") ? 'u' : '_');
|
||||
sb.Append(RemoveIfAllExist(@" ") ? 's' : '_');
|
||||
sb.Append(RemoveIfAllExist(PwCharSet.Brackets) ? 'B' : '_');
|
||||
sb.Append(RemoveIfAllExist(m_strHighAnsi) ? 'H' : '_');
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
public void UnpackCharRanges(string strRanges)
|
||||
{
|
||||
if(strRanges == null) { Debug.Assert(false); return; }
|
||||
if(strRanges.Length < 10) { Debug.Assert(false); return; }
|
||||
|
||||
if(strRanges[0] != '_') Add(PwCharSet.UpperCase);
|
||||
if(strRanges[1] != '_') Add(PwCharSet.LowerCase);
|
||||
if(strRanges[2] != '_') Add(PwCharSet.Digits);
|
||||
if(strRanges[3] != '_') Add(m_strSpecial);
|
||||
if(strRanges[4] != '_') Add(PwCharSet.Punctuation);
|
||||
if(strRanges[5] != '_') Add('-');
|
||||
if(strRanges[6] != '_') Add('_');
|
||||
if(strRanges[7] != '_') Add(' ');
|
||||
if(strRanges[8] != '_') Add(PwCharSet.Brackets);
|
||||
if(strRanges[9] != '_') Add(m_strHighAnsi);
|
||||
}
|
||||
}
|
||||
if (strRanges[0] != '_') Add(PwCharSet.UpperCase);
|
||||
if (strRanges[1] != '_') Add(PwCharSet.LowerCase);
|
||||
if (strRanges[2] != '_') Add(PwCharSet.Digits);
|
||||
if (strRanges[3] != '_') Add(PwCharSet.Special);
|
||||
if (strRanges[4] != '_') Add(PwCharSet.Punctuation);
|
||||
if (strRanges[5] != '_') Add('-');
|
||||
if (strRanges[6] != '_') Add('_');
|
||||
if (strRanges[7] != '_') Add(' ');
|
||||
if (strRanges[8] != '_') Add(PwCharSet.Brackets);
|
||||
if (strRanges[9] != '_') Add(PwCharSet.Latin1S);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2016 Dominik Reichl <dominik.reichl@t-online.de>
|
||||
Copyright (C) 2003-2025 Dominik Reichl <dominik.reichl@t-online.de>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -20,133 +20,172 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
|
||||
#if !KeePassUAP
|
||||
using System.Security.Cryptography;
|
||||
#endif
|
||||
|
||||
using KeePassLib.Resources;
|
||||
using KeePassLib.Security;
|
||||
using KeePassLib.Utility;
|
||||
|
||||
namespace KeePassLib.Cryptography.PasswordGenerator
|
||||
{
|
||||
public enum PwgError
|
||||
{
|
||||
Success = 0,
|
||||
Unknown = 1,
|
||||
TooFewCharacters = 2,
|
||||
UnknownAlgorithm = 3
|
||||
}
|
||||
public enum PwgError
|
||||
{
|
||||
Success = 0,
|
||||
Unknown = 1,
|
||||
TooFewCharacters = 2,
|
||||
UnknownAlgorithm = 3,
|
||||
InvalidCharSet = 4,
|
||||
InvalidPattern = 5
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Utility functions for generating random passwords.
|
||||
/// </summary>
|
||||
public static class PwGenerator
|
||||
{
|
||||
public static PwgError Generate(out ProtectedString psOut,
|
||||
PwProfile pwProfile, byte[] pbUserEntropy,
|
||||
CustomPwGeneratorPool pwAlgorithmPool)
|
||||
{
|
||||
Debug.Assert(pwProfile != null);
|
||||
if (pwProfile == null) throw new ArgumentNullException("pwProfile");
|
||||
/// <summary>
|
||||
/// Password generator.
|
||||
/// </summary>
|
||||
public static class PwGenerator
|
||||
{
|
||||
|
||||
CryptoRandomStream crs = CreateCryptoStream(pbUserEntropy);
|
||||
PwgError e = PwgError.Unknown;
|
||||
private static CryptoRandomStream CreateRandomStream(byte[] pbAdditionalEntropy,
|
||||
out byte[] pbKey)
|
||||
{
|
||||
pbKey = CryptoRandom.Instance.GetRandomBytes(128);
|
||||
|
||||
if (pwProfile.GeneratorType == PasswordGeneratorType.CharSet)
|
||||
e = CharSetBasedGenerator.Generate(out psOut, pwProfile, crs);
|
||||
else if (pwProfile.GeneratorType == PasswordGeneratorType.Pattern)
|
||||
e = PatternBasedGenerator.Generate(out psOut, pwProfile, crs);
|
||||
else if (pwProfile.GeneratorType == PasswordGeneratorType.Custom)
|
||||
e = GenerateCustom(out psOut, pwProfile, crs, pwAlgorithmPool);
|
||||
else { Debug.Assert(false); psOut = ProtectedString.Empty; }
|
||||
// Mix in additional entropy
|
||||
Debug.Assert(pbKey.Length >= 64);
|
||||
if ((pbAdditionalEntropy != null) && (pbAdditionalEntropy.Length != 0))
|
||||
{
|
||||
using (SHA512Managed h = new SHA512Managed())
|
||||
{
|
||||
byte[] pbHash = h.ComputeHash(pbAdditionalEntropy);
|
||||
MemUtil.XorArray(pbHash, 0, pbKey, 0, pbHash.Length);
|
||||
MemUtil.ZeroByteArray(pbHash);
|
||||
}
|
||||
}
|
||||
|
||||
return e;
|
||||
}
|
||||
return new CryptoRandomStream(CrsAlgorithm.ChaCha20, pbKey);
|
||||
}
|
||||
|
||||
private static CryptoRandomStream CreateCryptoStream(byte[] pbAdditionalEntropy)
|
||||
{
|
||||
byte[] pbKey = CryptoRandom.Instance.GetRandomBytes(128);
|
||||
internal static char GenerateCharacter(PwCharSet pwCharSet,
|
||||
CryptoRandomStream crsRandomSource)
|
||||
{
|
||||
uint cc = pwCharSet.Size;
|
||||
if (cc == 0) return char.MinValue;
|
||||
|
||||
// Mix in additional entropy
|
||||
Debug.Assert(pbKey.Length >= 64);
|
||||
if ((pbAdditionalEntropy != null) && (pbAdditionalEntropy.Length > 0))
|
||||
{
|
||||
using (SHA512Managed h = new SHA512Managed())
|
||||
{
|
||||
byte[] pbHash = h.ComputeHash(pbAdditionalEntropy);
|
||||
MemUtil.XorArray(pbHash, 0, pbKey, 0, pbHash.Length);
|
||||
}
|
||||
}
|
||||
uint i = (uint)crsRandomSource.GetRandomUInt64(cc);
|
||||
return pwCharSet[i];
|
||||
}
|
||||
|
||||
return new CryptoRandomStream(CrsAlgorithm.ChaCha20, pbKey);
|
||||
}
|
||||
internal static bool PrepareCharSet(PwCharSet pwCharSet, PwProfile pwProfile)
|
||||
{
|
||||
uint cc = pwCharSet.Size;
|
||||
for (uint i = 0; i < cc; ++i)
|
||||
{
|
||||
char ch = pwCharSet[i];
|
||||
if ((ch == char.MinValue) || (ch == '\t') || (ch == '\r') ||
|
||||
(ch == '\n') || char.IsSurrogate(ch))
|
||||
return false;
|
||||
}
|
||||
|
||||
internal static char GenerateCharacter(PwProfile pwProfile,
|
||||
PwCharSet pwCharSet, CryptoRandomStream crsRandomSource)
|
||||
{
|
||||
if (pwCharSet.Size == 0) return char.MinValue;
|
||||
if (pwProfile.ExcludeLookAlike) pwCharSet.Remove(PwCharSet.LookAlike);
|
||||
|
||||
ulong uIndex = crsRandomSource.GetRandomUInt64();
|
||||
uIndex %= (ulong)pwCharSet.Size;
|
||||
if (!string.IsNullOrEmpty(pwProfile.ExcludeCharacters))
|
||||
pwCharSet.Remove(pwProfile.ExcludeCharacters);
|
||||
|
||||
char ch = pwCharSet[(uint)uIndex];
|
||||
return true;
|
||||
}
|
||||
|
||||
if (pwProfile.NoRepeatingCharacters)
|
||||
pwCharSet.Remove(ch);
|
||||
internal static void Shuffle(char[] v, CryptoRandomStream crsRandomSource)
|
||||
{
|
||||
if (v == null) { Debug.Assert(false); return; }
|
||||
if (crsRandomSource == null) { Debug.Assert(false); return; }
|
||||
|
||||
return ch;
|
||||
}
|
||||
for (int i = v.Length - 1; i >= 1; --i)
|
||||
{
|
||||
int j = (int)crsRandomSource.GetRandomUInt64((ulong)(i + 1));
|
||||
|
||||
internal static void PrepareCharSet(PwCharSet pwCharSet, PwProfile pwProfile)
|
||||
{
|
||||
pwCharSet.Remove(PwCharSet.Invalid);
|
||||
char t = v[i];
|
||||
v[i] = v[j];
|
||||
v[j] = t;
|
||||
}
|
||||
}
|
||||
|
||||
if (pwProfile.ExcludeLookAlike) pwCharSet.Remove(PwCharSet.LookAlike);
|
||||
private static PwgError GenerateCustom(out ProtectedString psOut,
|
||||
PwProfile pwProfile, CryptoRandomStream crs,
|
||||
CustomPwGeneratorPool pwAlgorithmPool)
|
||||
{
|
||||
psOut = ProtectedString.Empty;
|
||||
|
||||
if (pwProfile.ExcludeCharacters.Length > 0)
|
||||
pwCharSet.Remove(pwProfile.ExcludeCharacters);
|
||||
}
|
||||
Debug.Assert(pwProfile.GeneratorType == PasswordGeneratorType.Custom);
|
||||
if (pwAlgorithmPool == null) return PwgError.UnknownAlgorithm;
|
||||
|
||||
internal static void ShufflePassword(char[] pPassword,
|
||||
CryptoRandomStream crsRandomSource)
|
||||
{
|
||||
Debug.Assert(pPassword != null); if (pPassword == null) return;
|
||||
Debug.Assert(crsRandomSource != null); if (crsRandomSource == null) return;
|
||||
string strID = pwProfile.CustomAlgorithmUuid;
|
||||
if (string.IsNullOrEmpty(strID)) return PwgError.UnknownAlgorithm;
|
||||
|
||||
if (pPassword.Length <= 1) return; // Nothing to shuffle
|
||||
byte[] pbUuid = Convert.FromBase64String(strID);
|
||||
PwUuid uuid = new PwUuid(pbUuid);
|
||||
CustomPwGenerator pwg = pwAlgorithmPool.Find(uuid);
|
||||
if (pwg == null) { Debug.Assert(false); return PwgError.UnknownAlgorithm; }
|
||||
|
||||
for (int nSelect = 0; nSelect < pPassword.Length; ++nSelect)
|
||||
{
|
||||
ulong uRandomIndex = crsRandomSource.GetRandomUInt64();
|
||||
uRandomIndex %= (ulong)(pPassword.Length - nSelect);
|
||||
ProtectedString pwd = pwg.Generate(pwProfile.CloneDeep(), crs);
|
||||
if (pwd == null) return PwgError.Unknown;
|
||||
|
||||
char chTemp = pPassword[nSelect];
|
||||
pPassword[nSelect] = pPassword[nSelect + (int)uRandomIndex];
|
||||
pPassword[nSelect + (int)uRandomIndex] = chTemp;
|
||||
}
|
||||
}
|
||||
psOut = pwd;
|
||||
return PwgError.Success;
|
||||
}
|
||||
|
||||
private static PwgError GenerateCustom(out ProtectedString psOut,
|
||||
PwProfile pwProfile, CryptoRandomStream crs,
|
||||
CustomPwGeneratorPool pwAlgorithmPool)
|
||||
{
|
||||
psOut = ProtectedString.Empty;
|
||||
internal static string ErrorToString(PwgError e, bool bHeader)
|
||||
{
|
||||
if (e == PwgError.Success) { Debug.Assert(false); return string.Empty; }
|
||||
if ((e == PwgError.Unknown) && bHeader) return KLRes.PwGenFailed;
|
||||
|
||||
Debug.Assert(pwProfile.GeneratorType == PasswordGeneratorType.Custom);
|
||||
if (pwAlgorithmPool == null) return PwgError.UnknownAlgorithm;
|
||||
string str = KLRes.UnknownError;
|
||||
switch (e)
|
||||
{
|
||||
// case PwgError.Success:
|
||||
// break;
|
||||
|
||||
string strID = pwProfile.CustomAlgorithmUuid;
|
||||
if (string.IsNullOrEmpty(strID)) { Debug.Assert(false); return PwgError.UnknownAlgorithm; }
|
||||
case PwgError.Unknown:
|
||||
break;
|
||||
|
||||
byte[] pbUuid = Convert.FromBase64String(strID);
|
||||
PwUuid uuid = new PwUuid(pbUuid);
|
||||
CustomPwGenerator pwg = pwAlgorithmPool.Find(uuid);
|
||||
if (pwg == null) { Debug.Assert(false); return PwgError.UnknownAlgorithm; }
|
||||
case PwgError.TooFewCharacters:
|
||||
str = KLRes.CharSetTooFewChars;
|
||||
break;
|
||||
|
||||
ProtectedString pwd = pwg.Generate(pwProfile.CloneDeep(), crs);
|
||||
if (pwd == null) return PwgError.Unknown;
|
||||
case PwgError.UnknownAlgorithm:
|
||||
str = KLRes.AlgorithmUnknown;
|
||||
break;
|
||||
|
||||
psOut = pwd;
|
||||
return PwgError.Success;
|
||||
}
|
||||
}
|
||||
case PwgError.InvalidCharSet:
|
||||
str = KLRes.CharSetInvalid;
|
||||
break;
|
||||
|
||||
case PwgError.InvalidPattern:
|
||||
str = KLRes.PatternInvalid;
|
||||
break;
|
||||
|
||||
default:
|
||||
Debug.Assert(false);
|
||||
break;
|
||||
}
|
||||
|
||||
if (bHeader)
|
||||
str = KLRes.PwGenFailed + MessageService.NewParagraph + str;
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
internal static string ErrorToString(Exception ex, bool bHeader)
|
||||
{
|
||||
string str = ((ex == null) ? KLRes.UnknownError :
|
||||
StrUtil.FormatException(ex));
|
||||
|
||||
if (bHeader)
|
||||
str = KLRes.PwGenFailed + MessageService.NewParagraph + str;
|
||||
|
||||
return str;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
KeePass Password Safe - The Open-Source Password Manager
|
||||
Copyright (C) 2003-2017 Dominik Reichl <dominik.reichl@t-online.de>
|
||||
Copyright (C) 2003-2025 Dominik Reichl <dominik.reichl@t-online.de>
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -19,114 +19,115 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text;
|
||||
using System.Diagnostics;
|
||||
using System.Text;
|
||||
|
||||
using KeePassLib.Utility;
|
||||
|
||||
namespace KeePassLib.Cryptography
|
||||
{
|
||||
public static class PopularPasswords
|
||||
{
|
||||
private static Dictionary<int, Dictionary<string, bool>> m_dicts =
|
||||
new Dictionary<int, Dictionary<string, bool>>();
|
||||
public static class PopularPasswords
|
||||
{
|
||||
private static readonly Dictionary<int, Dictionary<char[], bool>> g_dicts =
|
||||
new Dictionary<int, Dictionary<char[], bool>>();
|
||||
|
||||
internal static int MaxLength
|
||||
{
|
||||
get
|
||||
{
|
||||
int iMaxLen = 0;
|
||||
foreach(int iLen in m_dicts.Keys)
|
||||
{
|
||||
if(iLen > iMaxLen) iMaxLen = iLen;
|
||||
}
|
||||
internal static int MaxLength
|
||||
{
|
||||
get
|
||||
{
|
||||
Debug.Assert(g_dicts.Count > 0); // Should be initialized
|
||||
|
||||
return iMaxLen;
|
||||
}
|
||||
}
|
||||
int iMaxLen = 0;
|
||||
foreach (int iLen in g_dicts.Keys)
|
||||
{
|
||||
if (iLen > iMaxLen) iMaxLen = iLen;
|
||||
}
|
||||
|
||||
internal static bool ContainsLength(int nLength)
|
||||
{
|
||||
Dictionary<string, bool> dDummy;
|
||||
return m_dicts.TryGetValue(nLength, out dDummy);
|
||||
}
|
||||
return iMaxLen;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool IsPopularPassword(char[] vPassword)
|
||||
{
|
||||
ulong uDummy;
|
||||
return IsPopularPassword(vPassword, out uDummy);
|
||||
}
|
||||
internal static bool ContainsLength(int nLength)
|
||||
{
|
||||
Dictionary<char[], bool> dDummy;
|
||||
return g_dicts.TryGetValue(nLength, out dDummy);
|
||||
}
|
||||
|
||||
public static bool IsPopularPassword(char[] vPassword, out ulong uDictSize)
|
||||
{
|
||||
if(vPassword == null) throw new ArgumentNullException("vPassword");
|
||||
if(vPassword.Length == 0) { uDictSize = 0; return false; }
|
||||
public static bool IsPopularPassword(char[] vPassword)
|
||||
{
|
||||
ulong uDummy;
|
||||
return IsPopularPassword(vPassword, out uDummy);
|
||||
}
|
||||
|
||||
string str = new string(vPassword);
|
||||
public static bool IsPopularPassword(char[] vPassword, out ulong uDictSize)
|
||||
{
|
||||
if (vPassword == null) throw new ArgumentNullException("vPassword");
|
||||
if (vPassword.Length == 0) { uDictSize = 0; return false; }
|
||||
|
||||
try { return IsPopularPasswordPriv(str, out uDictSize); }
|
||||
catch(Exception) { Debug.Assert(false); }
|
||||
#if DEBUG
|
||||
Array.ForEach(vPassword, ch => Debug.Assert(ch == char.ToLower(ch)));
|
||||
#endif
|
||||
|
||||
uDictSize = 0;
|
||||
return false;
|
||||
}
|
||||
try { return IsPopularPasswordPriv(vPassword, out uDictSize); }
|
||||
catch (Exception) { Debug.Assert(false); }
|
||||
|
||||
private static bool IsPopularPasswordPriv(string str, out ulong uDictSize)
|
||||
{
|
||||
Debug.Assert(m_dicts.Count > 0); // Should be initialized with data
|
||||
uDictSize = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
Dictionary<string, bool> d;
|
||||
if(!m_dicts.TryGetValue(str.Length, out d))
|
||||
{
|
||||
uDictSize = 0;
|
||||
return false;
|
||||
}
|
||||
private static bool IsPopularPasswordPriv(char[] vPassword, out ulong uDictSize)
|
||||
{
|
||||
Debug.Assert(g_dicts.Count > 0); // Should be initialized with data
|
||||
|
||||
uDictSize = (ulong)d.Count;
|
||||
return d.ContainsKey(str);
|
||||
}
|
||||
Dictionary<char[], bool> d;
|
||||
if (!g_dicts.TryGetValue(vPassword.Length, out d))
|
||||
{
|
||||
uDictSize = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void Add(byte[] pbData, bool bGZipped)
|
||||
{
|
||||
try
|
||||
{
|
||||
if(bGZipped)
|
||||
pbData = MemUtil.Decompress(pbData);
|
||||
uDictSize = (ulong)d.Count;
|
||||
return d.ContainsKey(vPassword);
|
||||
}
|
||||
|
||||
string strData = StrUtil.Utf8.GetString(pbData, 0, pbData.Length);
|
||||
if(string.IsNullOrEmpty(strData)) { Debug.Assert(false); return; }
|
||||
public static void Add(byte[] pbData, bool bGZipped)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (bGZipped)
|
||||
pbData = MemUtil.Decompress(pbData);
|
||||
|
||||
if(!char.IsWhiteSpace(strData[strData.Length - 1]))
|
||||
strData += "\n";
|
||||
string strData = StrUtil.Utf8.GetString(pbData, 0, pbData.Length);
|
||||
if (string.IsNullOrEmpty(strData)) { Debug.Assert(false); return; }
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for(int i = 0; i < strData.Length; ++i)
|
||||
{
|
||||
char ch = strData[i];
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i <= strData.Length; ++i)
|
||||
{
|
||||
char ch = ((i == strData.Length) ? ' ' : strData[i]);
|
||||
|
||||
if(char.IsWhiteSpace(ch))
|
||||
{
|
||||
int cc = sb.Length;
|
||||
if(cc > 0)
|
||||
{
|
||||
string strWord = sb.ToString();
|
||||
Debug.Assert(strWord.Length == cc);
|
||||
if (char.IsWhiteSpace(ch))
|
||||
{
|
||||
int cc = sb.Length;
|
||||
if (cc > 0)
|
||||
{
|
||||
char[] vWord = new char[cc];
|
||||
sb.CopyTo(0, vWord, 0, cc);
|
||||
|
||||
Dictionary<string, bool> d;
|
||||
if(!m_dicts.TryGetValue(cc, out d))
|
||||
{
|
||||
d = new Dictionary<string, bool>();
|
||||
m_dicts[cc] = d;
|
||||
}
|
||||
Dictionary<char[], bool> d;
|
||||
if (!g_dicts.TryGetValue(cc, out d))
|
||||
{
|
||||
d = new Dictionary<char[], bool>(MemUtil.ArrayHelperExOfChar);
|
||||
g_dicts[cc] = d;
|
||||
}
|
||||
|
||||
d[strWord] = true;
|
||||
sb.Remove(0, cc);
|
||||
}
|
||||
}
|
||||
else sb.Append(char.ToLower(ch));
|
||||
}
|
||||
}
|
||||
catch(Exception) { Debug.Assert(false); }
|
||||
}
|
||||
}
|
||||
d[vWord] = true;
|
||||
sb.Remove(0, cc);
|
||||
}
|
||||
}
|
||||
else sb.Append(char.ToLower(ch));
|
||||
}
|
||||
}
|
||||
catch (Exception) { Debug.Assert(false); }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -46,4 +46,12 @@ namespace KeePassLib.Delegates
|
||||
public delegate void VoidDelegate();
|
||||
|
||||
public delegate string StrPwEntryDelegate(string str, PwEntry pe);
|
||||
|
||||
public delegate TResult GFunc<TResult>();
|
||||
public delegate TResult GFunc<T, TResult>(T o);
|
||||
public delegate TResult GFunc<T1, T2, TResult>(T1 o1, T2 o2);
|
||||
public delegate TResult GFunc<T1, T2, T3, TResult>(T1 o1, T2 o2, T3 o3);
|
||||
public delegate TResult GFunc<T1, T2, T3, T4, TResult>(T1 o1, T2 o2, T3 o3, T4 o4);
|
||||
public delegate TResult GFunc<T1, T2, T3, T4, T5, TResult>(T1 o1, T2 o2, T3 o3, T4 o4, T5 o5);
|
||||
public delegate TResult GFunc<T1, T2, T3, T4, T5, T6, TResult>(T1 o1, T2 o2, T3 o3, T4 o4, T5 o5, T6 o6);
|
||||
}
|
||||
|
@@ -116,12 +116,23 @@ namespace keepass2android
|
||||
|
||||
Intent sendIntent = new Intent();
|
||||
sendIntent.SetAction(Intent.ActionSend);
|
||||
sendIntent.PutExtra(Intent.ExtraText, File.ReadAllText(LogFilename));
|
||||
string logText = File.ReadAllText(LogFilename);
|
||||
|
||||
sendIntent.PutExtra(Intent.ExtraText, logText);
|
||||
sendIntent.PutExtra(Intent.ExtraEmail, "crocoapps@gmail.com");
|
||||
sendIntent.PutExtra(Intent.ExtraSubject, "Keepass2Android log");
|
||||
sendIntent.SetType("text/plain");
|
||||
ctx.StartActivity(Intent.CreateChooser(sendIntent, "Send log to..."));
|
||||
}
|
||||
try
|
||||
{
|
||||
ctx.StartActivity(Intent.CreateChooser(sendIntent, "Send log to..."));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Toast.MakeText(ctx, $"Error sending log of length {logText.Length} bytes: " + e.Message, ToastLength.Long)?.Show();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static void LogTask(object task, string activityName)
|
||||
{
|
||||
|
@@ -83,6 +83,7 @@ namespace KeePassLib.Serialization
|
||||
if (m_bUsedOnce)
|
||||
throw new InvalidOperationException("Do not reuse KdbxFile objects!");
|
||||
m_bUsedOnce = true;
|
||||
Kp2aLog.Log("Starting to load KDBX file...");
|
||||
|
||||
#if KDBX_BENCHMARK
|
||||
Stopwatch swTime = Stopwatch.StartNew();
|
||||
@@ -257,7 +258,8 @@ namespace KeePassLib.Serialization
|
||||
MessageService.ShowInfo("Loading KDBX took " +
|
||||
swTime.ElapsedMilliseconds.ToString() + " ms.");
|
||||
#endif
|
||||
}
|
||||
Kp2aLog.Log("Finished loading KDBX file.");
|
||||
}
|
||||
|
||||
private void CommonCleanUpRead(List<Stream> lStreams, HashingStreamEx sHashing)
|
||||
{
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -95,7 +95,7 @@ namespace Kp2aAutofillParserTest
|
||||
StructureParserBase<TestInputField> parser =
|
||||
new StructureParserBase<TestInputField>(new TestLogger(), new TestDalSourceTrustAll());
|
||||
|
||||
var result = parser.ParseForFill(false, autofillView);
|
||||
var result = parser.ParseForFill(autofillView);
|
||||
if (expectedPackageName != null)
|
||||
Assert.Equal(expectedPackageName, result.PackageName);
|
||||
if (expectedWebDomain != null)
|
||||
|
@@ -58,7 +58,8 @@
|
||||
"IsFocused": false,
|
||||
"InputType": 97,
|
||||
"HtmlInfoTag": null,
|
||||
"HtmlInfoTypeAttribute": null
|
||||
"HtmlInfoTypeAttribute": null,
|
||||
"ExpectedAssignedHints": [ "username" ]
|
||||
},
|
||||
{
|
||||
"IdEntry": "password_text_input_layout",
|
||||
@@ -81,6 +82,7 @@
|
||||
"InputType": 129,
|
||||
"HtmlInfoTag": null,
|
||||
"HtmlInfoTypeAttribute": null,
|
||||
"ExpectedAssignedHints": [ "password" ]
|
||||
|
||||
},
|
||||
{
|
||||
|
@@ -476,8 +476,16 @@ namespace Kp2aAutofillParser
|
||||
|
||||
foreach (var field in autofillFields.HintMap.Values.Distinct())
|
||||
{
|
||||
if (field == null || field.AutofillHints == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
foreach (var hint in field.AutofillHints)
|
||||
{
|
||||
if (hint == null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
if (GetPartitionIndex(hint) == partitionIndex)
|
||||
{
|
||||
filteredCollection.Add(field);
|
||||
@@ -793,14 +801,14 @@ namespace Kp2aAutofillParser
|
||||
}
|
||||
}
|
||||
|
||||
public AutofillTargetId ParseForFill(bool isManual, AutofillView<FieldT> autofillView)
|
||||
public AutofillTargetId ParseForFill(AutofillView<FieldT> autofillView)
|
||||
{
|
||||
return Parse(true, isManual, autofillView);
|
||||
return Parse(true, autofillView);
|
||||
}
|
||||
|
||||
public AutofillTargetId ParseForSave(AutofillView<FieldT> autofillView)
|
||||
{
|
||||
return Parse(false, true, autofillView);
|
||||
return Parse(false, autofillView);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -808,8 +816,7 @@ namespace Kp2aAutofillParser
|
||||
/// </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)
|
||||
protected virtual AutofillTargetId Parse(bool forFill, AutofillView<FieldT> autofillView)
|
||||
{
|
||||
AutofillTargetId result = new AutofillTargetId()
|
||||
{
|
||||
@@ -876,8 +883,9 @@ namespace Kp2aAutofillParser
|
||||
|
||||
}
|
||||
|
||||
//for "heuristic determination" we demand that one of the filled fields is focused:
|
||||
if (passwordFields.Concat(usernameFields).Any(f => f.IsFocused))
|
||||
//for "heuristic determination" we demand that there is a password field or one of the username fields is focused:
|
||||
//Note that "IsFocused" might be false even when tapping the field. It might require long-press to autofill.
|
||||
if (passwordFields.Any() || usernameFields.Any(f => f.IsFocused))
|
||||
{
|
||||
foreach (var uf in usernameFields)
|
||||
AddFieldToHintMap(uf, new string[] { AutofillHintsHelper.AutofillHintUsername });
|
||||
|
@@ -29,6 +29,14 @@ namespace keepass2android
|
||||
|
||||
}
|
||||
|
||||
|
||||
public enum MessageSeverity
|
||||
{
|
||||
Info,
|
||||
Warning,
|
||||
Error
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Interface through which Activities and the logic layer can access some app specific functionalities and Application static data
|
||||
/// </summary>
|
||||
@@ -102,10 +110,13 @@ namespace keepass2android
|
||||
Context ctx,
|
||||
string messageSuffix = "");
|
||||
|
||||
/// <summary>
|
||||
/// Returns a Handler object which can run tasks on the UI thread
|
||||
/// </summary>
|
||||
Handler UiThreadHandler { get; }
|
||||
void ShowMessage(Context ctx, int resourceId, MessageSeverity severity);
|
||||
void ShowMessage(Context ctx, string text, MessageSeverity severity);
|
||||
|
||||
/// <summary>
|
||||
/// Returns a Handler object which can run tasks on the UI thread
|
||||
/// </summary>
|
||||
Handler UiThreadHandler { get; }
|
||||
|
||||
IProgressDialog CreateProgressDialog(Context ctx);
|
||||
|
||||
|
@@ -13,7 +13,7 @@ using Android.Content.PM;
|
||||
using Android.OS;
|
||||
using Android.Preferences;
|
||||
using Java.IO;
|
||||
|
||||
using KeePass.Util;
|
||||
using KeePassLib.Serialization;
|
||||
using KeePassLib.Utility;
|
||||
using File = System.IO.File;
|
||||
@@ -121,7 +121,7 @@ namespace keepass2android.Io
|
||||
var response = ex.Response as HttpWebResponse;
|
||||
if ((response != null) && (response.StatusCode == HttpStatusCode.NotFound))
|
||||
{
|
||||
throw new FileNotFoundException(ex.Message, ioc.Path, ex);
|
||||
throw new FileNotFoundException(ExceptionUtil.GetErrorMessage(ex), ioc.Path, ex);
|
||||
}
|
||||
if (ex.Status == WebExceptionStatus.TrustFailure)
|
||||
{
|
||||
|
@@ -1,13 +0,0 @@
|
||||
namespace keepass2android.Io
|
||||
{
|
||||
public partial class DropboxFileStorage
|
||||
{
|
||||
private const string AppKey = "dummy";
|
||||
private const string AppSecret = "dummy";
|
||||
}
|
||||
public partial class DropboxAppFolderFileStorage
|
||||
{
|
||||
private const string AppKey = "dummy";
|
||||
private const string AppSecret = "dummy";
|
||||
}
|
||||
}
|
27
src/Kp2aBusinessLogic/Io/GenerateSecrets.targets
Normal file
27
src/Kp2aBusinessLogic/Io/GenerateSecrets.targets
Normal file
@@ -0,0 +1,27 @@
|
||||
<Project>
|
||||
<Target Name="GenerateDropboxSecrets" BeforeTargets="BeforeCompile"
|
||||
Inputs="@(DropboxSecretLines)"
|
||||
Outputs="DropboxFileStorage.g.cs">
|
||||
|
||||
<WriteLinesToFile
|
||||
File="Io/DropboxFileStorage.g.cs"
|
||||
Lines="@(DropboxSecretLines->'%(Text)')"
|
||||
Overwrite="true"
|
||||
/>
|
||||
</Target>
|
||||
|
||||
<ItemGroup>
|
||||
<DropboxSecretLines Include="GeneratedDropboxSecrets">
|
||||
<Text>namespace keepass2android.Io {
|
||||
public partial class DropboxFileStorage {
|
||||
private const string AppKey = "$(DropboxAppKey)";
|
||||
private const string AppSecret = "$(DropboxAppSecret)";
|
||||
}
|
||||
public partial class DropboxAppFolderFileStorage {
|
||||
private const string AppKey = "$(DropboxAppFolderAppKey)";
|
||||
private const string AppSecret = "$(DropboxAppFolderAppSecret)";
|
||||
}
|
||||
}</Text>
|
||||
</DropboxSecretLines>
|
||||
</ItemGroup>
|
||||
</Project>
|
@@ -13,6 +13,7 @@ using Keepass2android.Javafilestorage;
|
||||
#endif
|
||||
using Exception = System.Exception;
|
||||
using FileNotFoundException = Java.IO.FileNotFoundException;
|
||||
using KeePass.Util;
|
||||
|
||||
namespace keepass2android.Io
|
||||
{
|
||||
@@ -42,7 +43,7 @@ namespace keepass2android.Io
|
||||
}
|
||||
catch (FileNotFoundException e)
|
||||
{
|
||||
throw new System.IO.FileNotFoundException(e.Message, e);
|
||||
throw new System.IO.FileNotFoundException(ExceptionUtil.GetErrorMessage(e), e);
|
||||
}
|
||||
catch (Java.Lang.Exception e)
|
||||
{
|
||||
@@ -195,7 +196,7 @@ namespace keepass2android.Io
|
||||
}
|
||||
catch (FileNotFoundException e)
|
||||
{
|
||||
throw new System.IO.FileNotFoundException(e.Message, e);
|
||||
throw new System.IO.FileNotFoundException(ExceptionUtil.GetErrorMessage(e), e);
|
||||
}
|
||||
catch (Java.Lang.Exception e)
|
||||
{
|
||||
@@ -214,7 +215,7 @@ namespace keepass2android.Io
|
||||
}
|
||||
catch (FileNotFoundException e)
|
||||
{
|
||||
throw new System.IO.FileNotFoundException(e.Message, e);
|
||||
throw new System.IO.FileNotFoundException(ExceptionUtil.GetErrorMessage(e), e);
|
||||
}
|
||||
catch (Java.Lang.Exception e)
|
||||
{
|
||||
@@ -244,7 +245,7 @@ namespace keepass2android.Io
|
||||
}
|
||||
catch (FileNotFoundException e)
|
||||
{
|
||||
throw new System.IO.FileNotFoundException(e.Message, e);
|
||||
throw new System.IO.FileNotFoundException(ExceptionUtil.GetErrorMessage(e), e);
|
||||
}
|
||||
catch (Java.Lang.Exception e)
|
||||
{
|
||||
|
@@ -8,6 +8,7 @@ using Android.Content;
|
||||
using Android.OS;
|
||||
using FluentFTP;
|
||||
using FluentFTP.Exceptions;
|
||||
using KeePass.Util;
|
||||
using KeePassLib;
|
||||
using KeePassLib.Serialization;
|
||||
using KeePassLib.Utility;
|
||||
@@ -127,7 +128,7 @@ namespace keepass2android.Io
|
||||
var ftpEx = (FtpCommandException) exception;
|
||||
|
||||
if (ftpEx.CompletionCode == "550")
|
||||
throw new FileNotFoundException(exception.Message, exception);
|
||||
throw new FileNotFoundException(ExceptionUtil.GetErrorMessage(exception), exception);
|
||||
}
|
||||
|
||||
return exception;
|
||||
|
@@ -3,6 +3,7 @@ using System.Reflection;
|
||||
using System.Text;
|
||||
using Android.Content;
|
||||
using Android.Util;
|
||||
using KeePass.Util;
|
||||
using keepass2android.Io.ItemLocation;
|
||||
using KeePassLib.Serialization;
|
||||
using KeePassLib.Utility;
|
||||
@@ -522,10 +523,10 @@ namespace keepass2android.Io
|
||||
{
|
||||
|
||||
if (e.IsMatch(GraphErrorCode.ItemNotFound.ToString()))
|
||||
return new FileNotFoundException(e.Message);
|
||||
return new FileNotFoundException(ExceptionUtil.GetErrorMessage(e));
|
||||
if (e.Message.Contains("\n\n404 : ")
|
||||
) //hacky solution to check for not found. errorCode was null in my tests so I had to find a workaround.
|
||||
return new FileNotFoundException(e.Message);
|
||||
return new FileNotFoundException(ExceptionUtil.GetErrorMessage(e));
|
||||
return e;
|
||||
}
|
||||
|
||||
|
@@ -16,20 +16,32 @@ namespace keepass2android.Io
|
||||
/// </summary>
|
||||
public class OneDriveFileStorage: IFileStorage
|
||||
{
|
||||
|
||||
public IEnumerable<string> SupportedProtocols
|
||||
public OneDriveFileStorage(IKp2aApp app)
|
||||
{
|
||||
_app = app;
|
||||
}
|
||||
|
||||
private readonly IKp2aApp _app;
|
||||
|
||||
public IEnumerable<string> SupportedProtocols
|
||||
{
|
||||
get
|
||||
{
|
||||
yield return "skydrive";
|
||||
yield return "onedrive";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private Exception GetDeprecatedMessage()
|
||||
string GetDeprecatedMessage()
|
||||
{
|
||||
return
|
||||
"You have opened your file through a deprecated Microsoft API. Please select Change database, Open Database and then select OneDrive again.";
|
||||
}
|
||||
|
||||
private Exception GetDeprecatedException()
|
||||
{
|
||||
return new Exception(
|
||||
"You have opened your file through a deprecated Microsoft API. Please select Change database, Open Database and then select One Drive again.");
|
||||
GetDeprecatedMessage());
|
||||
}
|
||||
|
||||
public bool UserShouldBackup
|
||||
@@ -39,133 +51,132 @@ namespace keepass2android.Io
|
||||
|
||||
public void Delete(IOConnectionInfo ioc)
|
||||
{
|
||||
throw GetDeprecatedMessage();
|
||||
throw GetDeprecatedException();
|
||||
}
|
||||
|
||||
public bool CheckForFileChangeFast(IOConnectionInfo ioc, string previousFileVersion)
|
||||
{
|
||||
throw GetDeprecatedMessage();
|
||||
throw GetDeprecatedException();
|
||||
}
|
||||
|
||||
public string GetCurrentFileVersionFast(IOConnectionInfo ioc)
|
||||
{
|
||||
throw GetDeprecatedMessage();
|
||||
throw GetDeprecatedException();
|
||||
}
|
||||
|
||||
public Stream OpenFileForRead(IOConnectionInfo ioc)
|
||||
{
|
||||
throw GetDeprecatedMessage();
|
||||
throw GetDeprecatedException();
|
||||
}
|
||||
|
||||
public IWriteTransaction OpenWriteTransaction(IOConnectionInfo ioc, bool useFileTransaction)
|
||||
{
|
||||
throw GetDeprecatedMessage();
|
||||
throw GetDeprecatedException();
|
||||
}
|
||||
|
||||
public string GetFilenameWithoutPathAndExt(IOConnectionInfo ioc)
|
||||
{
|
||||
throw GetDeprecatedMessage();
|
||||
throw GetDeprecatedException();
|
||||
}
|
||||
|
||||
public string GetFileExtension(IOConnectionInfo ioc)
|
||||
{
|
||||
throw GetDeprecatedMessage();
|
||||
throw GetDeprecatedException();
|
||||
}
|
||||
|
||||
public bool RequiresCredentials(IOConnectionInfo ioc)
|
||||
{
|
||||
throw GetDeprecatedMessage();
|
||||
return false;
|
||||
}
|
||||
|
||||
public void CreateDirectory(IOConnectionInfo ioc, string newDirName)
|
||||
{
|
||||
throw GetDeprecatedMessage();
|
||||
throw GetDeprecatedException();
|
||||
}
|
||||
|
||||
public IEnumerable<FileDescription> ListContents(IOConnectionInfo ioc)
|
||||
{
|
||||
throw GetDeprecatedMessage();
|
||||
throw GetDeprecatedException();
|
||||
}
|
||||
|
||||
public FileDescription GetFileDescription(IOConnectionInfo ioc)
|
||||
{
|
||||
throw GetDeprecatedMessage();
|
||||
throw GetDeprecatedException();
|
||||
}
|
||||
|
||||
public bool RequiresSetup(IOConnectionInfo ioConnection)
|
||||
{
|
||||
throw GetDeprecatedMessage();
|
||||
return false;
|
||||
}
|
||||
|
||||
public string IocToPath(IOConnectionInfo ioc)
|
||||
{
|
||||
throw GetDeprecatedMessage();
|
||||
throw GetDeprecatedException();
|
||||
}
|
||||
|
||||
public void StartSelectFile(IFileStorageSetupInitiatorActivity activity, bool isForSave, int requestCode, string protocolId)
|
||||
{
|
||||
throw GetDeprecatedMessage();
|
||||
|
||||
}
|
||||
|
||||
public void PrepareFileUsage(IFileStorageSetupInitiatorActivity activity, IOConnectionInfo ioc, int requestCode,
|
||||
bool alwaysReturnSuccess)
|
||||
{
|
||||
throw GetDeprecatedMessage();
|
||||
_app.ShowMessage(activity.Activity, GetDeprecatedMessage(), MessageSeverity.Error);
|
||||
|
||||
}
|
||||
|
||||
public void PrepareFileUsage(Context ctx, IOConnectionInfo ioc)
|
||||
{
|
||||
throw GetDeprecatedMessage();
|
||||
|
||||
}
|
||||
|
||||
public void OnCreate(IFileStorageSetupActivity activity, Bundle savedInstanceState)
|
||||
{
|
||||
throw GetDeprecatedMessage();
|
||||
|
||||
}
|
||||
|
||||
public void OnResume(IFileStorageSetupActivity activity)
|
||||
{
|
||||
throw GetDeprecatedMessage();
|
||||
|
||||
}
|
||||
|
||||
public void OnStart(IFileStorageSetupActivity activity)
|
||||
{
|
||||
throw GetDeprecatedMessage();
|
||||
}
|
||||
|
||||
public void OnActivityResult(IFileStorageSetupActivity activity, int requestCode, int resultCode, Intent data)
|
||||
{
|
||||
throw GetDeprecatedMessage();
|
||||
}
|
||||
|
||||
public string GetDisplayName(IOConnectionInfo ioc)
|
||||
{
|
||||
throw GetDeprecatedMessage();
|
||||
return "File using deprecated Microsoft API. Please update.";
|
||||
}
|
||||
|
||||
public string CreateFilePath(string parent, string newFilename)
|
||||
{
|
||||
throw GetDeprecatedMessage();
|
||||
throw GetDeprecatedException();
|
||||
}
|
||||
|
||||
public IOConnectionInfo GetParentPath(IOConnectionInfo ioc)
|
||||
{
|
||||
throw GetDeprecatedMessage();
|
||||
throw GetDeprecatedException();
|
||||
}
|
||||
|
||||
public IOConnectionInfo GetFilePath(IOConnectionInfo folderPath, string filename)
|
||||
{
|
||||
throw GetDeprecatedMessage();
|
||||
throw GetDeprecatedException();
|
||||
}
|
||||
|
||||
public bool IsPermanentLocation(IOConnectionInfo ioc)
|
||||
{
|
||||
throw GetDeprecatedMessage();
|
||||
throw GetDeprecatedException();
|
||||
}
|
||||
|
||||
public bool IsReadOnly(IOConnectionInfo ioc, OptionalOut<UiStringKey> reason = null)
|
||||
{
|
||||
throw GetDeprecatedMessage();
|
||||
throw GetDeprecatedException();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -4,30 +4,43 @@
|
||||
<SupportedOSPlatformVersion>21</SupportedOSPlatformVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<DefineConstants Condition="'$(Flavor)'=='NoNet'">NO_QR_SCANNER;EXCLUDE_JAVAFILESTORAGE;NoNet</DefineConstants>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Folder Include="Resources\" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<PackageReference Include="FluentFTP" Version="51.1.0" />
|
||||
<PackageReference Include="MegaApiClient" Version="1.10.4" />
|
||||
<PackageReference Include="Microsoft.Graph" Version="5.68.0" />
|
||||
<PackageReference Include="Microsoft.Identity.Client" Version="4.67.1" />
|
||||
<PackageReference Include="FluentFTP" Version="51.1.0" Condition="'$(Flavor)'!='NoNet'"/>
|
||||
<PackageReference Include="MegaApiClient" Version="1.10.4" Condition="'$(Flavor)'!='NoNet'"/>
|
||||
<PackageReference Include="Microsoft.Graph" Version="5.68.0" Condition="'$(Flavor)'!='NoNet'"/>
|
||||
<PackageReference Include="Microsoft.Identity.Client" Version="4.67.1" Condition="'$(Flavor)'!='NoNet'"/>
|
||||
<PackageReference Include="Xamarin.AndroidX.Browser" Version="1.8.0" />
|
||||
<PackageReference Include="Xamarin.AndroidX.Core" Version="1.13.1.5" />
|
||||
<PackageReference Include="Xamarin.Google.Android.Material" Version="1.11.0.3" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\AndroidFileChooserBinding\AndroidFileChooserBinding.csproj" />
|
||||
<ProjectReference Include="..\JavaFileStorageBindings\JavaFileStorageBindings.csproj" />
|
||||
<ProjectReference Include="..\JavaFileStorageBindings\JavaFileStorageBindings.csproj" Condition="'$(Flavor)'!='NoNet'" />
|
||||
<ProjectReference Include="..\KeePassLib2Android\KeePassLib2Android.csproj" />
|
||||
<ProjectReference Include="..\KP2AKdbLibraryBinding\KP2AKdbLibraryBinding.csproj" />
|
||||
<ProjectReference Include="..\TwofishCipher\TwofishCipher.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Remove="Io/DropboxFileStorageKeysDummy.cs" />
|
||||
<Compile Remove="Io/DropboxFileStorageKeysDummy.cs" />
|
||||
<Content Remove="Io/DropboxFileStorageKeysDummy.cs" />
|
||||
|
||||
</ItemGroup>
|
||||
<ItemGroup Condition="'$(Flavor)'=='NoNet'">
|
||||
<None Remove="Io/OneDrive2FileStorage.cs" />
|
||||
<Compile Remove="Io/OneDrive2FileStorage.cs" />
|
||||
<Content Remove="Io/OneDrive2FileStorage.cs" />
|
||||
<None Remove="Io/MegaFileStorage.cs" />
|
||||
<Compile Remove="Io/MegaFileStorage.cs" />
|
||||
<Content Remove="Io/MegaFileStorage.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<Import Project="Io/GenerateSecrets.targets" />
|
||||
<ItemGroup>
|
||||
<Compile Include="Io/DropboxFileStorage.g.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
</Project>
|
@@ -4,6 +4,7 @@ using Android.Content;
|
||||
using Android.OS;
|
||||
using Android.Widget;
|
||||
using Java.Net;
|
||||
using KeePass.Util;
|
||||
using KeePassLib.Serialization;
|
||||
using keepass2android.Io;
|
||||
|
||||
@@ -94,15 +95,12 @@ namespace keepass2android
|
||||
}
|
||||
if ((resultCode == Result.Canceled) && (data != null) && (data.HasExtra("EXTRA_ERROR_MESSAGE")))
|
||||
{
|
||||
ShowToast(data.GetStringExtra("EXTRA_ERROR_MESSAGE"));
|
||||
ShowErrorToast(data.GetStringExtra("EXTRA_ERROR_MESSAGE"));
|
||||
}
|
||||
|
||||
if (resultCode == Result.Ok)
|
||||
{
|
||||
Kp2aLog.Log("FileSelection returned "+data.DataString);
|
||||
//TODO: don't try to extract filename if content URI
|
||||
string filename = IntentToFilename(data);
|
||||
Kp2aLog.Log("FileSelection returned filename " + filename);
|
||||
if (filename != null)
|
||||
{
|
||||
if (filename.StartsWith("file://"))
|
||||
@@ -150,7 +148,7 @@ namespace keepass2android
|
||||
|
||||
protected abstract void StartFileChooser(string path, int requestCode, bool isForSave);
|
||||
|
||||
protected abstract void ShowToast(string text);
|
||||
protected abstract void ShowErrorToast(string text);
|
||||
|
||||
protected abstract void ShowInvalidSchemeMessage(string dataString);
|
||||
|
||||
@@ -208,7 +206,7 @@ namespace keepass2android
|
||||
{
|
||||
return () =>
|
||||
{
|
||||
ShowToast(_app.GetResourceString(UiStringKey.ErrorOcurred) + " " + e.Message);
|
||||
ShowErrorToast(_app.GetResourceString(UiStringKey.ErrorOcurred) + " " + ExceptionUtil.GetErrorMessage(e));
|
||||
ReturnCancel();
|
||||
};
|
||||
}
|
||||
|
32
src/Kp2aBusinessLogic/Utils/ExceptionUtil.cs
Normal file
32
src/Kp2aBusinessLogic/Utils/ExceptionUtil.cs
Normal file
@@ -0,0 +1,32 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
|
||||
namespace KeePass.Util
|
||||
{
|
||||
public class ExceptionUtil
|
||||
{
|
||||
|
||||
public static string GetErrorMessage(Exception e)
|
||||
{
|
||||
string errorMessage = e.Message;
|
||||
if (e is Java.Lang.Exception javaException)
|
||||
{
|
||||
try
|
||||
{
|
||||
errorMessage = javaException.LocalizedMessage ?? javaException.Message ?? errorMessage;
|
||||
}
|
||||
finally
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return errorMessage;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
@@ -5,6 +5,7 @@ using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using Android.App;
|
||||
using Android.Content;
|
||||
using KeePass.Util;
|
||||
using KeePassLib.Cryptography;
|
||||
using KeePassLib.Serialization;
|
||||
using KeePassLib.Utility;
|
||||
@@ -65,7 +66,7 @@ namespace keepass2android
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Finish(false, e.Message);
|
||||
Finish(false, ExceptionUtil.GetErrorMessage(e));
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -90,9 +90,12 @@ namespace keepass2android
|
||||
PwDatabase pwDatabase = new PwDatabase();
|
||||
|
||||
IFileStorage fileStorage = _app.GetFileStorage(iocInfo);
|
||||
Stream s = databaseData ?? fileStorage.OpenFileForRead(iocInfo);
|
||||
var fileVersion = _app.GetFileStorage(iocInfo).GetCurrentFileVersionFast(iocInfo);
|
||||
PopulateDatabaseFromStream(pwDatabase, s, iocInfo, compositeKey, status, databaseFormat);
|
||||
Kp2aLog.Log("LoadData: Retrieving stream");
|
||||
Stream s = databaseData ?? fileStorage.OpenFileForRead(iocInfo);
|
||||
Kp2aLog.Log("LoadData: GetCurrentFileVersion");
|
||||
var fileVersion = _app.GetFileStorage(iocInfo).GetCurrentFileVersionFast(iocInfo);
|
||||
Kp2aLog.Log("LoadData: PopulateDatabaseFromStream");
|
||||
PopulateDatabaseFromStream(pwDatabase, s, iocInfo, compositeKey, status, databaseFormat);
|
||||
LastFileVersion = fileVersion;
|
||||
|
||||
status.UpdateSubMessage("");
|
||||
|
@@ -10,6 +10,7 @@ using Com.Keepassdroid.Database.Exception;
|
||||
#endif
|
||||
using Com.Keepassdroid.Database.Save;
|
||||
using Java.Util;
|
||||
using KeePass.Util;
|
||||
using KeePassLib;
|
||||
using KeePassLib.Cryptography;
|
||||
using KeePassLib.Cryptography.Cipher;
|
||||
@@ -82,15 +83,14 @@ namespace keepass2android
|
||||
catch (Java.IO.FileNotFoundException e)
|
||||
{
|
||||
throw new FileNotFoundException(
|
||||
e.Message, e);
|
||||
ExceptionUtil.GetErrorMessage(e), e);
|
||||
}
|
||||
catch (Java.Lang.Exception e)
|
||||
{
|
||||
if (e.Message == "Invalid key!")
|
||||
throw new InvalidCompositeKeyException();
|
||||
throw new Exception(e.LocalizedMessage ??
|
||||
e.Message ??
|
||||
e.GetType().Name, e);
|
||||
throw new Exception(ExceptionUtil.GetErrorMessage(e) ??
|
||||
e.GetType().Name, e);
|
||||
}
|
||||
|
||||
HashOfLastStream = hashingStream.Hash;
|
||||
|
@@ -6,6 +6,7 @@ using Android.App;
|
||||
using Android.Content;
|
||||
using KeePassLib.Serialization;
|
||||
using keepass2android.Io;
|
||||
using KeePass.Util;
|
||||
|
||||
namespace keepass2android
|
||||
{
|
||||
@@ -109,7 +110,7 @@ namespace keepass2android
|
||||
catch (Exception e)
|
||||
{
|
||||
Kp2aLog.LogUnexpectedError(e);
|
||||
Finish(false, e.Message);
|
||||
Finish(false, ExceptionUtil.GetErrorMessage(e));
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -21,6 +21,7 @@ using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Android.App;
|
||||
using KeePass.Util;
|
||||
using keepass2android.database.edit;
|
||||
using KeePassLib;
|
||||
using KeePassLib.Keys;
|
||||
@@ -103,10 +104,10 @@ namespace keepass2android
|
||||
}
|
||||
catch (AggregateException e)
|
||||
{
|
||||
string message = e.Message;
|
||||
string message = ExceptionUtil.GetErrorMessage(e);
|
||||
foreach (var innerException in e.InnerExceptions)
|
||||
{
|
||||
message = innerException.Message;
|
||||
message = ExceptionUtil.GetErrorMessage(innerException);
|
||||
// Override the message shown with the last (hopefully most recent) inner exception
|
||||
Kp2aLog.LogUnexpectedError(innerException);
|
||||
}
|
||||
@@ -116,14 +117,14 @@ namespace keepass2android
|
||||
catch (DuplicateUuidsException e)
|
||||
{
|
||||
Kp2aLog.Log(e.ToString());
|
||||
Finish(false, _app.GetResourceString(UiStringKey.DuplicateUuidsError) + " " + e.Message + _app.GetResourceString(UiStringKey.DuplicateUuidsErrorAdditional), false, Exception);
|
||||
Finish(false, _app.GetResourceString(UiStringKey.DuplicateUuidsError) + " " + ExceptionUtil.GetErrorMessage(e) + _app.GetResourceString(UiStringKey.DuplicateUuidsErrorAdditional), false, Exception);
|
||||
return;
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
if (!(e is InvalidCompositeKeyException))
|
||||
Kp2aLog.LogUnexpectedError(e);
|
||||
Finish(false, _app.GetResourceString(UiStringKey.ErrorOcurred) + " " + (e.Message ?? (e is FileNotFoundException ? _app.GetResourceString(UiStringKey.FileNotFound) : "")), false, Exception);
|
||||
Finish(false, _app.GetResourceString(UiStringKey.ErrorOcurred) + " " + (ExceptionUtil.GetErrorMessage(e) ?? (e is FileNotFoundException ? _app.GetResourceString(UiStringKey.FileNotFound) : "")), false, Exception);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -137,6 +138,7 @@ namespace keepass2android
|
||||
|
||||
Database TryLoad(MemoryStream databaseStream)
|
||||
{
|
||||
Kp2aLog.Log("LoadDb: Copying database in memory");
|
||||
//create a copy of the stream so we can try again if we get an exception which indicates we should change parameters
|
||||
//This is not optimal in terms of (short-time) memory usage but is hard to avoid because the Keepass library closes streams also in case of errors.
|
||||
//Alternatives would involve increased traffic (if file is on remote) and slower loading times, so this seems to be the best choice.
|
||||
@@ -145,8 +147,9 @@ namespace keepass2android
|
||||
workingCopy.Seek(0, SeekOrigin.Begin);
|
||||
//reset stream if we need to reuse it later:
|
||||
databaseStream.Seek(0, SeekOrigin.Begin);
|
||||
//now let's go:
|
||||
try
|
||||
Kp2aLog.Log("LoadDb: Ready to start loading");
|
||||
//now let's go:
|
||||
try
|
||||
{
|
||||
Database newDb = _app.LoadDatabase(_ioc, workingCopy, _compositeKey, StatusLogger, _format, _makeCurrent);
|
||||
Kp2aLog.Log("LoadDB OK");
|
||||
|
@@ -130,24 +130,24 @@ namespace keepass2android
|
||||
if ( !String.IsNullOrEmpty(message) ) {
|
||||
Kp2aLog.Log("OnFinish message: " + message);
|
||||
if (makeDialog && ctx != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(ctx);
|
||||
|
||||
builder.SetMessage(message)
|
||||
.SetPositiveButton(Android.Resource.String.Ok, (sender, args) => ((Dialog)sender).Dismiss())
|
||||
.Show();
|
||||
{
|
||||
try
|
||||
{
|
||||
MaterialAlertDialogBuilder builder = new MaterialAlertDialogBuilder(ctx);
|
||||
|
||||
builder.SetMessage(message)
|
||||
.SetPositiveButton(Android.Resource.String.Ok, (sender, args) => ((Dialog)sender).Dismiss())
|
||||
.Show();
|
||||
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
Toast.MakeText(ctx, message, ToastLength.Long).Show();
|
||||
}
|
||||
}
|
||||
{
|
||||
Toast.MakeText(ctx, message, ToastLength.Long).Show();
|
||||
}
|
||||
}
|
||||
else
|
||||
Toast.MakeText(ctx ?? Application.Context, message, ToastLength.Long).Show();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -29,6 +29,7 @@ using KeePassLib.Utility;
|
||||
using keepass2android.Io;
|
||||
using Debug = System.Diagnostics.Debug;
|
||||
using Exception = System.Exception;
|
||||
using KeePass.Util;
|
||||
|
||||
namespace keepass2android
|
||||
{
|
||||
@@ -187,7 +188,7 @@ namespace keepass2android
|
||||
}
|
||||
*/
|
||||
Kp2aLog.LogUnexpectedError(e);
|
||||
Finish(false, e.Message);
|
||||
Finish(false, ExceptionUtil.GetErrorMessage(e));
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -222,8 +223,8 @@ namespace keepass2android
|
||||
catch (Exception e)
|
||||
{
|
||||
Kp2aLog.LogUnexpectedError(e);
|
||||
Kp2aLog.Log("Error in worker thread of SaveDb: " + e);
|
||||
Finish(false, e.Message);
|
||||
Kp2aLog.Log("Error in worker thread of SaveDb: " + ExceptionUtil.GetErrorMessage(e));
|
||||
Finish(false, ExceptionUtil.GetErrorMessage(e));
|
||||
}
|
||||
|
||||
});
|
||||
@@ -233,7 +234,7 @@ namespace keepass2android
|
||||
{
|
||||
Kp2aLog.LogUnexpectedError(e);
|
||||
Kp2aLog.Log("Error starting worker thread of SaveDb: "+e);
|
||||
Finish(false, e.Message);
|
||||
Finish(false, ExceptionUtil.GetErrorMessage(e));
|
||||
}
|
||||
|
||||
}
|
||||
|
25
src/build-scripts/build-java.sh
Executable file
25
src/build-scripts/build-java.sh
Executable file
@@ -0,0 +1,25 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
#unset ANDROID_NDK_HOME ANDROID_NDK
|
||||
|
||||
pushd ../java/
|
||||
|
||||
pushd JavaFileStorageTest-AS
|
||||
./gradlew assemble
|
||||
popd
|
||||
|
||||
pushd KP2ASoftkeyboard_AS
|
||||
./gradlew assemble
|
||||
popd
|
||||
|
||||
pushd Keepass2AndroidPluginSDK2
|
||||
./gradlew assemble
|
||||
popd
|
||||
|
||||
pushd KP2AKdbLibrary
|
||||
./gradlew assemble
|
||||
popd
|
||||
|
||||
popd
|
6
src/build-scripts/build-native.sh
Executable file
6
src/build-scripts/build-native.sh
Executable file
@@ -0,0 +1,6 @@
|
||||
#!/bin/bash
|
||||
set -e
|
||||
|
||||
pushd ../java/argon2
|
||||
ndk-build
|
||||
popd
|
28
src/build-scripts/linux-build.md
Normal file
28
src/build-scripts/linux-build.md
Normal file
@@ -0,0 +1,28 @@
|
||||
## Setup build environment
|
||||
* install Android SDK
|
||||
* install Android NDK
|
||||
* install dotnet8
|
||||
|
||||
```
|
||||
|
||||
#from https://dotnet.microsoft.com/en-us/download/dotnet/thank-you/sdk-8.0.407-linux-x64-binaries
|
||||
wget https://download.visualstudio.microsoft.com/download/pr/9d07577e-f7bc-4d60-838d-f79c50b5c11a/459ef339396783db369e0432d6dc3d7e/dotnet-sdk-8.0.407-linux-x64.tar.gz
|
||||
mkdir -p $HOME/dotnet && tar zxf dotnet-sdk-8.0.407-linux-x64.tar.gz -C $HOME/dotnet
|
||||
export DOTNET_ROOT=$HOME/dotnet
|
||||
export PATH=$PATH:$HOME/dotnet
|
||||
|
||||
```
|
||||
|
||||
## Build Keepass2Android
|
||||
|
||||
```
|
||||
git clone --recurse-submodules https://github.com/PhilippC/keepass2android.git
|
||||
cd keepass2android/src/build-scripts
|
||||
./build-java.sh && ./build-native.sh
|
||||
cd ..
|
||||
cd keepass2android-app
|
||||
ln -s Manifests/AndroidManifest_debug.xml AndroidManifest.xml
|
||||
dotnet workload restore
|
||||
dotnet restore
|
||||
dotnet build
|
||||
```
|
22
src/build-scripts/rename-output-apks.sh
Normal file
22
src/build-scripts/rename-output-apks.sh
Normal file
@@ -0,0 +1,22 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
BASE_DIR="${1}"
|
||||
|
||||
for arch_dir in "$BASE_DIR"/android-*/; do
|
||||
arch=$(basename "$arch_dir")
|
||||
arch=${arch#android-}
|
||||
APK_DIR="${arch_dir}publish"
|
||||
if [[ -d "$APK_DIR" ]]; then
|
||||
apk_path=$(find "$APK_DIR" -maxdepth 1 -type f -name "*.apk" | head -n1)
|
||||
if [[ -n "$apk_path" ]]; then
|
||||
base=$(basename "$apk_path" .apk)
|
||||
new_path="$APK_DIR/${base}-${arch}.apk"
|
||||
mv "$apk_path" "$new_path"
|
||||
echo "Renamed $apk_path to $new_path"
|
||||
else
|
||||
echo "No APK found in $APK_DIR"
|
||||
fi
|
||||
else
|
||||
echo "Directory $APK_DIR does not exist"
|
||||
fi
|
||||
done
|
@@ -6,8 +6,7 @@
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
android:supportsRtl="true"
|
||||
android:theme="@style/AppTheme">
|
||||
android:supportsRtl="true">
|
||||
<activity android:name="com.crocoapps.javafilestoragetest2.MainActivity"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
|
@@ -56,15 +56,15 @@
|
||||
<string name="afc_title_sort_by">Ordina per…</string>
|
||||
<string name="afc_yesterday">Ieri</string>
|
||||
<plurals name="afc_title_choose_directories">
|
||||
<item quantity="one">Scegli la cartella…</item>
|
||||
<item quantity="other">Scegli le cartelle…</item>
|
||||
<item quantity="one">Scegli cartella...</item>
|
||||
<item quantity="other">Scegli le cartelle...</item>
|
||||
</plurals>
|
||||
<plurals name="afc_title_choose_files">
|
||||
<item quantity="one">Scegli il file…</item>
|
||||
<item quantity="other">Scegli i file…</item>
|
||||
<item quantity="one">Scegli il file</item>
|
||||
<item quantity="other">Scegli i file</item>
|
||||
</plurals>
|
||||
<plurals name="afc_title_choose_files_directories">
|
||||
<item quantity="one">Scegli file/ cartella…</item>
|
||||
<item quantity="other">Scegli file/ cartelle…</item>
|
||||
<item quantity="one">Scegli file/cartella</item>
|
||||
<item quantity="other">Scegli file/cartelle</item>
|
||||
</plurals>
|
||||
</resources>
|
||||
|
@@ -55,4 +55,19 @@
|
||||
<string name="afc_title_size">Dimensiune</string>
|
||||
<string name="afc_title_sort_by">Sortează după…</string>
|
||||
<string name="afc_yesterday">Ieri</string>
|
||||
<plurals name="afc_title_choose_directories">
|
||||
<item quantity="one">Alege dosarul…</item>
|
||||
<item quantity="few">Alege dosarele…</item>
|
||||
<item quantity="other">Alege dosarele…</item>
|
||||
</plurals>
|
||||
<plurals name="afc_title_choose_files">
|
||||
<item quantity="one">Alege fișierul…</item>
|
||||
<item quantity="few">Alege fișierele…</item>
|
||||
<item quantity="other">Alege fișierele…</item>
|
||||
</plurals>
|
||||
<plurals name="afc_title_choose_files_directories">
|
||||
<item quantity="one">Alege fișierul/dosarul…</item>
|
||||
<item quantity="few">Alege fișierele/dosarele…</item>
|
||||
<item quantity="other">Alege fișierele/dosarele…</item>
|
||||
</plurals>
|
||||
</resources>
|
||||
|
@@ -59,7 +59,7 @@ namespace keepass2android
|
||||
}
|
||||
catch (ActivityNotFoundException)
|
||||
{
|
||||
Toast.MakeText(Context, Resource.String.no_url_handler, ToastLength.Long).Show();
|
||||
App.Kp2a.ShowMessage(Context, Resource.String.no_url_handler, MessageSeverity.Error);
|
||||
}
|
||||
|
||||
};
|
||||
@@ -71,7 +71,7 @@ namespace keepass2android
|
||||
}
|
||||
catch (ActivityNotFoundException)
|
||||
{
|
||||
Toast.MakeText(Context, Resource.String.no_url_handler, ToastLength.Long).Show();
|
||||
App.Kp2a.ShowMessage(Context, Resource.String.no_url_handler, MessageSeverity.Error);
|
||||
}
|
||||
};
|
||||
FindViewById(Resource.Id.translate).Click += delegate
|
||||
@@ -82,7 +82,7 @@ namespace keepass2android
|
||||
}
|
||||
catch (ActivityNotFoundException)
|
||||
{
|
||||
Toast.MakeText(Context, Resource.String.no_url_handler, ToastLength.Long).Show();
|
||||
App.Kp2a.ShowMessage(Context, Resource.String.no_url_handler, MessageSeverity.Error);
|
||||
}
|
||||
}; FindViewById(Resource.Id.donate).Click += delegate
|
||||
{
|
||||
|
@@ -14,7 +14,7 @@ using keepass2android;
|
||||
|
||||
namespace keepass2android
|
||||
{
|
||||
[Activity(Label = AppNames.AppName)]
|
||||
[Activity(Label = AppNames.AppName, Theme = "@style/Kp2aTheme_BlueNoActionBar")]
|
||||
public class AppKilledInfo : Activity, IDialogInterfaceOnDismissListener
|
||||
{
|
||||
protected override void OnCreate(Bundle bundle)
|
||||
|
10183
src/keepass2android-app/Assets/MostPopularPasswords.txt
Normal file
10183
src/keepass2android-app/Assets/MostPopularPasswords.txt
Normal file
File diff suppressed because it is too large
Load Diff
@@ -183,7 +183,7 @@ namespace keepass2android
|
||||
// Verify that a password or keyfile is set
|
||||
if (password.Length == 0 && !keyfileCheckbox.Checked)
|
||||
{
|
||||
Toast.MakeText(this, Resource.String.error_nopass, ToastLength.Long).Show();
|
||||
App.Kp2a.ShowMessage(this, Resource.String.error_nopass, MessageSeverity.Error);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -207,7 +207,7 @@ namespace keepass2android
|
||||
}
|
||||
catch (Exception)
|
||||
{
|
||||
Toast.MakeText(this, Resource.String.error_adding_keyfile, ToastLength.Long).Show();
|
||||
App.Kp2a.ShowMessage(this, Resource.String.error_adding_keyfile, MessageSeverity.Error);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -235,7 +235,7 @@ namespace keepass2android
|
||||
if (! pass.Equals(confpass))
|
||||
{
|
||||
// Passwords do not match
|
||||
Toast.MakeText(this, Resource.String.error_pass_match, ToastLength.Long).Show();
|
||||
App.Kp2a.ShowMessage(this, Resource.String.error_pass_match, MessageSeverity.Error);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
|
@@ -28,7 +28,7 @@ namespace keepass2android
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Finish(false, e.Message);
|
||||
Finish(false, Util.GetErrorMessage(e));
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -19,7 +19,7 @@ using keepass2android.services.AutofillBase;
|
||||
|
||||
namespace keepass2android
|
||||
{
|
||||
[Activity(Label = "DisableAutofillForQueryActivity")]
|
||||
[Activity(Label = "DisableAutofillForQueryActivity", Theme = "@style/Kp2aTheme_ActionBar")]
|
||||
public class DisableAutofillForQueryActivity : Activity
|
||||
{
|
||||
public IAutofillIntentBuilder IntentBuilder = new Kp2aAutofillIntentBuilder();
|
||||
@@ -41,7 +41,7 @@ namespace keepass2android
|
||||
string requestedUrl = Intent.GetStringExtra(ChooseForAutofillActivityBase.ExtraQueryString);
|
||||
if (requestedUrl == null)
|
||||
{
|
||||
Toast.MakeText(this, "Cannot execute query for null.", ToastLength.Long).Show();
|
||||
App.Kp2a.ShowMessage(this, "Cannot execute query for null.", MessageSeverity.Error);
|
||||
RestartApp();
|
||||
return;
|
||||
}
|
||||
@@ -63,8 +63,6 @@ namespace keepass2android
|
||||
|
||||
prefs.Edit().PutStringSet("AutoFillDisabledQueries", disabledValues).Commit();
|
||||
|
||||
bool isManual = Intent.GetBooleanExtra(ChooseForAutofillActivityBase.ExtraIsManualRequest, false);
|
||||
|
||||
Intent reply = new Intent();
|
||||
FillResponse.Builder builder = new FillResponse.Builder();
|
||||
AssistStructure structure = (AssistStructure)Intent.GetParcelableExtra(AutofillManager.ExtraAssistStructure);
|
||||
@@ -77,7 +75,7 @@ namespace keepass2android
|
||||
StructureParser parser = new StructureParser(this, structure);
|
||||
try
|
||||
{
|
||||
parser.ParseForFill(isManual);
|
||||
parser.ParseForFill();
|
||||
|
||||
}
|
||||
catch (Java.Lang.SecurityException e)
|
||||
|
@@ -78,7 +78,7 @@ namespace keepass2android
|
||||
var task = new EntryActivity.WriteBinaryTask(_activity, App.Kp2a, new ActionOnFinish(_activity, (success, message, activity) =>
|
||||
{
|
||||
if (!success)
|
||||
Toast.MakeText(activity, message, ToastLength.Long).Show();
|
||||
App.Kp2a.ShowMessage(activity, message, MessageSeverity.Error);
|
||||
}
|
||||
), ((EntryActivity)_activity).Entry.Binaries.Get(_binaryToSave), ioc);
|
||||
ProgressTask pt = new ProgressTask(App.Kp2a, _activity, task);
|
||||
@@ -107,8 +107,8 @@ namespace keepass2android
|
||||
|
||||
public const int requestCodeBinaryFilename = 42376;
|
||||
public const int requestCodeSelFileStorageForWriteAttachment = 42377;
|
||||
|
||||
|
||||
protected override View? SnackbarAnchorView => FindViewById(Resource.Id.main_content);
|
||||
|
||||
public static void Launch(Activity act, PwEntry pw, int pos, AppTask appTask, ActivityFlags? flags = null, int historyIndex=-1)
|
||||
{
|
||||
@@ -767,9 +767,9 @@ namespace keepass2android
|
||||
|
||||
if (parent == null || (parent.Exists() && !parent.IsDirectory))
|
||||
{
|
||||
Toast.MakeText(this,
|
||||
App.Kp2a.ShowMessage(this,
|
||||
Resource.String.error_invalid_path,
|
||||
ToastLength.Long).Show();
|
||||
MessageSeverity.Error);
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -778,9 +778,9 @@ namespace keepass2android
|
||||
// Create parent directory
|
||||
if (!parent.Mkdirs())
|
||||
{
|
||||
Toast.MakeText(this,
|
||||
App.Kp2a.ShowMessage(this,
|
||||
Resource.String.error_could_not_create_parent,
|
||||
ToastLength.Long).Show();
|
||||
MessageSeverity.Error);
|
||||
return null;
|
||||
|
||||
}
|
||||
@@ -794,18 +794,18 @@ namespace keepass2android
|
||||
}
|
||||
catch (Exception exWrite)
|
||||
{
|
||||
Toast.MakeText(this,
|
||||
App.Kp2a.ShowMessage(this,
|
||||
GetString(Resource.String.SaveAttachment_Failed, new Java.Lang.Object[] {filename})
|
||||
+ exWrite.Message, ToastLength.Long).Show();
|
||||
+ Util.GetErrorMessage(exWrite), MessageSeverity.Error);
|
||||
return null;
|
||||
}
|
||||
finally
|
||||
{
|
||||
MemUtil.ZeroByteArray(pbData);
|
||||
}
|
||||
Toast.MakeText(this,
|
||||
App.Kp2a.ShowMessage(this,
|
||||
GetString(Resource.String.SaveAttachment_doneMessage, new Java.Lang.Object[] {filename}),
|
||||
ToastLength.Short).Show();
|
||||
MessageSeverity.Info);
|
||||
return Uri.Parse("content://" + AttachmentContentProvider.Authority + "/"
|
||||
+ filename);
|
||||
}
|
||||
@@ -838,7 +838,7 @@ namespace keepass2android
|
||||
catch (ActivityNotFoundException)
|
||||
{
|
||||
//ignore
|
||||
Toast.MakeText(this, "Couldn't open file", ToastLength.Short).Show();
|
||||
App.Kp2a.ShowMessage(this, "Couldn't open file", MessageSeverity.Error);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1305,7 +1305,7 @@ namespace keepass2android
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Finish(false, ex.Message);
|
||||
Finish(false, Util.GetErrorMessage(ex));
|
||||
}
|
||||
|
||||
|
||||
@@ -1546,10 +1546,10 @@ namespace keepass2android
|
||||
string url = _stringViews[urlFieldKey].Text;
|
||||
if (url == null) return false;
|
||||
|
||||
// Default http:// if no protocol specified
|
||||
// Default https:// if no protocol specified
|
||||
if ((!url.Contains(":") || (url.StartsWith("www."))))
|
||||
{
|
||||
url = "http://" + url;
|
||||
url = "https://" + url;
|
||||
}
|
||||
|
||||
try
|
||||
@@ -1558,7 +1558,7 @@ namespace keepass2android
|
||||
}
|
||||
catch (ActivityNotFoundException)
|
||||
{
|
||||
Toast.MakeText(this, Resource.String.no_url_handler, ToastLength.Long).Show();
|
||||
App.Kp2a.ShowMessage(this, Resource.String.no_url_handler, MessageSeverity.Error);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
@@ -37,8 +37,10 @@ using System.Net;
|
||||
using System.Text;
|
||||
using Android.Content.Res;
|
||||
using Android.Database;
|
||||
#if !NO_QR_SCANNER
|
||||
using Android.Gms.Common;
|
||||
using Android.Gms.Tasks;
|
||||
#endif
|
||||
using Android.Graphics;
|
||||
using Android.Graphics.Drawables;
|
||||
using Android.Runtime;
|
||||
@@ -55,19 +57,20 @@ using Object = Java.Lang.Object;
|
||||
using Uri = Android.Net.Uri;
|
||||
using Resource = keepass2android.Resource;
|
||||
using Google.Android.Material.TextField;
|
||||
#if !NO_QR_SCANNER
|
||||
using Xamarin.Google.MLKit.Vision.Barcode.Common;
|
||||
using Xamarin.Google.MLKit.Vision.CodeScanner;
|
||||
#endif
|
||||
using Console = System.Console;
|
||||
using Task = Android.Gms.Tasks.Task;
|
||||
|
||||
namespace keepass2android
|
||||
{
|
||||
[Activity(Label = "@string/app_name", ConfigurationChanges = ConfigChanges.Orientation | ConfigChanges.Keyboard | ConfigChanges.KeyboardHidden, Theme = "@style/Kp2aTheme_ActionBar")]
|
||||
public class EntryEditActivity : LockCloseActivity {
|
||||
|
||||
|
||||
|
||||
public const String KeyEntry = "entry";
|
||||
protected override View? SnackbarAnchorView => FindViewById(Resource.Id.main_content);
|
||||
|
||||
public const String KeyEntry = "entry";
|
||||
public const String KeyParent = "parent";
|
||||
public const String KeyTemplateUuid = "KeyTemplateUuid";
|
||||
|
||||
@@ -331,13 +334,18 @@ namespace keepass2android
|
||||
|
||||
}
|
||||
|
||||
protected override void OnStart()
|
||||
private bool hasRequestedKeyboardActivation = false;
|
||||
protected override void OnStart()
|
||||
{
|
||||
base.OnStart();
|
||||
if (PreferenceManager.GetDefaultSharedPreferences(this)
|
||||
.GetBoolean(GetString(Resource.String.UseKp2aKeyboardInKp2a_key), false))
|
||||
.GetBoolean(GetString(Resource.String.UseKp2aKeyboardInKp2a_key), false)
|
||||
&& (!hasRequestedKeyboardActivation))
|
||||
{
|
||||
CopyToClipboardService.ActivateKeyboard(this);
|
||||
//only try this once. if the user clicks cancel, we don't want to ask again
|
||||
// (it may happen that the activity is restarted because of the NewTask flag immediately after the dialog)
|
||||
hasRequestedKeyboardActivation = true;
|
||||
CopyToClipboardService.ActivateKeyboard(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -715,7 +723,7 @@ namespace keepass2android
|
||||
}
|
||||
catch(Exception exAttach)
|
||||
{
|
||||
Toast.MakeText(this, GetString(Resource.String.AttachFailed)+" "+exAttach.Message, ToastLength.Long).Show();
|
||||
App.Kp2a.ShowMessage(this, GetString(Resource.String.AttachFailed)+" "+ Util.GetErrorMessage(exAttach), MessageSeverity.Error);
|
||||
}
|
||||
State.EntryModified = true;
|
||||
PopulateBinaries();
|
||||
@@ -833,7 +841,7 @@ namespace keepass2android
|
||||
string s = Util.GetFilenameFromInternalFileChooser(data, this);
|
||||
if (s == null)
|
||||
{
|
||||
Toast.MakeText(this, "No URI retrieved.", ToastLength.Short).Show();
|
||||
App.Kp2a.ShowMessage(this, "No URI retrieved.", MessageSeverity.Error);
|
||||
return;
|
||||
}
|
||||
uri = Uri.Parse(s);
|
||||
@@ -1139,7 +1147,7 @@ namespace keepass2android
|
||||
}
|
||||
else
|
||||
{
|
||||
Toast.MakeText(this, "did not find target field", ToastLength.Long).Show();
|
||||
App.Kp2a.ShowMessage(this, "did not find target field", MessageSeverity.Error);
|
||||
}
|
||||
|
||||
|
||||
@@ -1153,12 +1161,15 @@ namespace keepass2android
|
||||
{
|
||||
dlgView.FindViewById(Resource.Id.totp_custom_settings_group).Visibility = args.IsChecked ? ViewStates.Visible : ViewStates.Gone;
|
||||
};
|
||||
|
||||
dlgView.FindViewById<Button>(Resource.Id.totp_scan).Click += async (object o, EventArgs args) =>
|
||||
#if NO_QR_SCANNER
|
||||
dlgView.FindViewById<Button>(Resource.Id.totp_scan).Visibility = ViewStates.Gone;
|
||||
#else
|
||||
dlgView.FindViewById<Button>(Resource.Id.totp_scan).Click += async (object o, EventArgs args) =>
|
||||
{
|
||||
if (GoogleApiAvailability.Instance.IsGooglePlayServicesAvailable(this) != ConnectionResult.Success)
|
||||
{
|
||||
Toast.MakeText(this, Resource.String.qr_scanning_error_no_google_play_services, ToastLength.Long);
|
||||
App.Kp2a.ShowMessage(this, Resource.String.qr_scanning_error_no_google_play_services,
|
||||
MessageSeverity.Error);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1178,16 +1189,17 @@ namespace keepass2android
|
||||
}
|
||||
else
|
||||
{
|
||||
Toast.MakeText(this, "Scanned code should contain an otpauth:// text.", ToastLength.Long).Show();
|
||||
App.Kp2a.ShowMessage(this, "Scanned code should contain an otpauth:// text.", MessageSeverity.Warning);
|
||||
}
|
||||
}))
|
||||
.AddOnFailureListener(new FailureListener((e) =>
|
||||
{
|
||||
Console.WriteLine($"Scan failed: {e.Message}");
|
||||
Console.WriteLine($"Scan failed: {Util.GetErrorMessage(e)}");
|
||||
}));
|
||||
|
||||
|
||||
};
|
||||
#endif
|
||||
|
||||
//copy values from entry into dialog
|
||||
View ees = (View)sender.Parent;
|
||||
@@ -1503,7 +1515,7 @@ namespace keepass2android
|
||||
// Require title
|
||||
String title = Util.GetEditText(this, Resource.Id.entry_title);
|
||||
if ( title.Length == 0 ) {
|
||||
Toast.MakeText(this, Resource.String.error_title_required, ToastLength.Long).Show();
|
||||
App.Kp2a.ShowMessage(this, Resource.String.error_title_required, MessageSeverity.Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1513,7 +1525,7 @@ namespace keepass2android
|
||||
DateTime newExpiry = new DateTime();
|
||||
if ((State.Entry.Expires) && (!DateTime.TryParse( Util.GetEditText(this,Resource.Id.entry_expires), out newExpiry)))
|
||||
{
|
||||
Toast.MakeText(this, Resource.String.error_invalid_expiry_date, ToastLength.Long).Show();
|
||||
App.Kp2a.ShowMessage(this, Resource.String.error_invalid_expiry_date, MessageSeverity.Error);
|
||||
return false;
|
||||
}
|
||||
State.Entry.ExpiryTime = newExpiry.ToUniversalTime();
|
||||
@@ -1527,13 +1539,13 @@ namespace keepass2android
|
||||
string key = keyView.Text;
|
||||
|
||||
if (String.IsNullOrEmpty(key)) {
|
||||
Toast.MakeText(this, Resource.String.error_string_key, ToastLength.Long).Show();
|
||||
App.Kp2a.ShowMessage(this, Resource.String.error_string_key, MessageSeverity.Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (allKeys.Contains(key))
|
||||
{
|
||||
Toast.MakeText(this, GetString(Resource.String.error_string_duplicate_key, new Object[]{key}), ToastLength.Long).Show();
|
||||
App.Kp2a.ShowMessage(this, GetString(Resource.String.error_string_duplicate_key, new Object[]{key}), MessageSeverity.Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -1566,6 +1578,7 @@ namespace keepass2android
|
||||
|
||||
}
|
||||
}
|
||||
#if !NO_QR_SCANNER
|
||||
public class SuccessListener : Object, IOnSuccessListener
|
||||
{
|
||||
private readonly Action<Barcode> _onSuccess;
|
||||
@@ -1595,8 +1608,9 @@ namespace keepass2android
|
||||
_onFailure?.Invoke(e);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
public class DefaultEdit : EditModeBase
|
||||
public class DefaultEdit : EditModeBase
|
||||
{
|
||||
|
||||
}
|
||||
|
@@ -29,9 +29,9 @@ namespace keepass2android
|
||||
var exportDb = new ExportDatabaseActivity.ExportDb(_activity, App.Kp2a, new ActionOnFinish(_activity, (success, message, activity) =>
|
||||
{
|
||||
if (!success)
|
||||
Toast.MakeText(activity, message, ToastLength.Long).Show();
|
||||
App.Kp2a.ShowMessage(activity, message, MessageSeverity.Error);
|
||||
else
|
||||
Toast.MakeText(activity, _activity.GetString(Resource.String.export_database_successful), ToastLength.Long).Show();
|
||||
App.Kp2a.ShowMessage(activity, _activity.GetString(Resource.String.export_database_successful), MessageSeverity.Info);
|
||||
activity.Finish();
|
||||
}
|
||||
), _ffp, ioc);
|
||||
@@ -140,7 +140,7 @@ namespace keepass2android
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Finish(false, ex.Message);
|
||||
Finish(false, Util.GetErrorMessage(ex));
|
||||
}
|
||||
|
||||
|
||||
|
@@ -107,7 +107,7 @@ namespace keepass2android
|
||||
{
|
||||
if (!success)
|
||||
{
|
||||
Toast.MakeText(activity, messageOrFilename, ToastLength.Long).Show();
|
||||
App.Kp2a.ShowMessage(activity, messageOrFilename, MessageSeverity.Error);
|
||||
return;
|
||||
}
|
||||
SaveFile(new IOConnectionInfo { Path = FileSelectHelper.ConvertFilenameToIocPath(messageOrFilename) });
|
||||
|
@@ -115,6 +115,7 @@ namespace keepass2android
|
||||
string keyContent = keyContentTxt.Text;
|
||||
|
||||
string toastMsg = null;
|
||||
MessageSeverity severity = MessageSeverity.Info;
|
||||
if (!string.IsNullOrEmpty(keyName) && !string.IsNullOrEmpty(keyContent))
|
||||
{
|
||||
try
|
||||
@@ -127,8 +128,10 @@ namespace keepass2android
|
||||
catch (Exception e)
|
||||
{
|
||||
toastMsg = ctx.GetString(Resource.String.private_key_save_failed,
|
||||
new Java.Lang.Object[] { e.Message });
|
||||
}
|
||||
new Java.Lang.Object[] { Util.GetErrorMessage(e)});
|
||||
severity = MessageSeverity.Error;
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -136,7 +139,7 @@ namespace keepass2android
|
||||
}
|
||||
|
||||
if (toastMsg!= null) {
|
||||
Toast.MakeText(_activity, toastMsg, ToastLength.Long).Show();
|
||||
App.Kp2a.ShowMessage(_activity, toastMsg, severity);
|
||||
}
|
||||
|
||||
UpdatePrivateKeyNames(keyNamesAdapter, fileStorage, ctx);
|
||||
@@ -153,7 +156,7 @@ namespace keepass2android
|
||||
|
||||
int msgId = deleted ? Resource.String.private_key_delete : Resource.String.private_key_delete_failed;
|
||||
string msg = ctx.GetString(msgId, new Java.Lang.Object[] { keyName });
|
||||
Toast.MakeText(_activity, msg, ToastLength.Long).Show();
|
||||
App.Kp2a.ShowMessage(_activity, msg, deleted ? MessageSeverity.Info :MessageSeverity.Error);
|
||||
|
||||
UpdatePrivateKeyNames(keyNamesAdapter, fileStorage, ctx);
|
||||
keySpinner.SetSelection(SftpKeySpinnerCreateNewIdx);
|
||||
@@ -581,9 +584,9 @@ namespace keepass2android
|
||||
// Make sure file name exists
|
||||
if (filename.Length == 0)
|
||||
{
|
||||
Toast.MakeText(_activity,
|
||||
App.Kp2a.ShowMessage(_activity,
|
||||
Resource.String.error_filename_required,
|
||||
ToastLength.Long).Show();
|
||||
MessageSeverity.Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -604,9 +607,9 @@ namespace keepass2android
|
||||
}
|
||||
catch (NoFileStorageFoundException)
|
||||
{
|
||||
Toast.MakeText(_activity,
|
||||
App.Kp2a.ShowMessage(_activity,
|
||||
"Unexpected scheme in "+filename,
|
||||
ToastLength.Long).Show();
|
||||
MessageSeverity.Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -620,9 +623,9 @@ namespace keepass2android
|
||||
|
||||
if (parent == null || (parent.Exists() && !parent.IsDirectory))
|
||||
{
|
||||
Toast.MakeText(_activity,
|
||||
App.Kp2a.ShowMessage(_activity,
|
||||
Resource.String.error_invalid_path,
|
||||
ToastLength.Long).Show();
|
||||
MessageSeverity.Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -631,9 +634,9 @@ namespace keepass2android
|
||||
// Create parent dircetory
|
||||
if (!parent.Mkdirs())
|
||||
{
|
||||
Toast.MakeText(_activity,
|
||||
App.Kp2a.ShowMessage(_activity,
|
||||
Resource.String.error_could_not_create_parent,
|
||||
ToastLength.Long).Show();
|
||||
MessageSeverity.Error);
|
||||
return false;
|
||||
|
||||
}
|
||||
@@ -643,11 +646,11 @@ namespace keepass2android
|
||||
}
|
||||
catch (Java.IO.IOException ex)
|
||||
{
|
||||
Toast.MakeText(
|
||||
App.Kp2a.ShowMessage(
|
||||
_activity,
|
||||
_activity.GetText(Resource.String.error_file_not_create) + " "
|
||||
+ ex.LocalizedMessage,
|
||||
ToastLength.Long).Show();
|
||||
MessageSeverity.Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -700,7 +703,7 @@ namespace keepass2android
|
||||
_activity.StartActivityForResult(i, _requestCode);
|
||||
|
||||
#else
|
||||
Toast.MakeText(LocaleManager.LocalizedAppContext, "File chooser is excluded!", ToastLength.Long).Show();
|
||||
App.Kp2a.ShowMessage(LocaleManager.LocalizedAppContext, "File chooser is excluded!", MessageSeverity.Error);
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
@@ -782,7 +785,7 @@ namespace keepass2android
|
||||
{
|
||||
if (!success)
|
||||
{
|
||||
Toast.MakeText(newActivity, messageOrFilename, ToastLength.Long).Show();
|
||||
App.Kp2a.ShowMessage(newActivity, messageOrFilename, MessageSeverity.Error);
|
||||
return;
|
||||
}
|
||||
var ioc = new IOConnectionInfo { Path = ConvertFilenameToIocPath(messageOrFilename) };
|
||||
|
@@ -251,7 +251,7 @@ namespace keepass2android
|
||||
catch (Exception e)
|
||||
{
|
||||
CheckCurrentRadioButton();
|
||||
Toast.MakeText(this, e.ToString(), ToastLength.Long).Show();
|
||||
App.Kp2a.ShowMessage(this, e.ToString(), MessageSeverity.Error);
|
||||
FindViewById(Resource.Id.radio_buttons).Visibility = ViewStates.Visible;
|
||||
FindViewById(Resource.Id.fingerprint_auth_container).Visibility = ViewStates.Gone;
|
||||
}
|
||||
|
@@ -23,6 +23,7 @@ using Android.App;
|
||||
using Android.App.Admin;
|
||||
using Android.Content;
|
||||
using Android.Content.PM;
|
||||
using Android.Content.Res;
|
||||
using Android.Graphics;
|
||||
using Android.OS;
|
||||
using Android.Preferences;
|
||||
@@ -66,10 +67,15 @@ namespace keepass2android
|
||||
Resource.Id.cb_exclude_lookalike
|
||||
};
|
||||
|
||||
|
||||
|
||||
PasswordFont _passwordFont = new PasswordFont();
|
||||
|
||||
private static object _popularPasswordsLock = new object();
|
||||
private static bool _popularPasswordsInitialized = false;
|
||||
|
||||
private ActivityDesign _design;
|
||||
|
||||
private ActivityDesign _design;
|
||||
public GeneratePasswordActivity()
|
||||
{
|
||||
_design = new ActivityDesign(this);
|
||||
@@ -302,6 +308,10 @@ namespace keepass2android
|
||||
|
||||
|
||||
EditText txtPasswordToSet = (EditText) FindViewById(Resource.Id.password_edit);
|
||||
txtPasswordToSet.TextChanged += (sender, args) =>
|
||||
{
|
||||
Task.Run(() => UpdatePasswordStrengthEstimate(txtPasswordToSet.Text));
|
||||
};
|
||||
|
||||
_passwordFont.ApplyTo(txtPasswordToSet);
|
||||
|
||||
@@ -467,51 +477,76 @@ namespace keepass2android
|
||||
return;
|
||||
|
||||
String password = "";
|
||||
uint passwordBits = 0;
|
||||
|
||||
|
||||
Task.Run(() =>
|
||||
{
|
||||
password = GeneratePassword();
|
||||
passwordBits = QualityEstimation.EstimatePasswordBits(password.ToCharArray());
|
||||
RunOnUiThread(() =>
|
||||
{
|
||||
EditText txtPassword = (EditText)FindViewById(Resource.Id.password_edit);
|
||||
txtPassword.Text = password;
|
||||
|
||||
var progressBar = FindViewById<ProgressBar>(Resource.Id.pb_password_strength);
|
||||
|
||||
progressBar.Progress = (int)passwordBits;
|
||||
progressBar.Max = 128;
|
||||
|
||||
Color color = new Color(196, 63, 49);
|
||||
if (passwordBits > 40)
|
||||
{
|
||||
color = new Color(219, 152, 55);
|
||||
}
|
||||
|
||||
if (passwordBits > 64)
|
||||
{
|
||||
color = new Color(96, 138, 38);
|
||||
}
|
||||
|
||||
if (passwordBits > 100)
|
||||
{
|
||||
color = new Color(31, 128, 31);
|
||||
}
|
||||
|
||||
progressBar.ProgressDrawable.SetColorFilter(new PorterDuffColorFilter(color,
|
||||
PorterDuff.Mode.SrcIn));
|
||||
|
||||
FindViewById<TextView>(Resource.Id.tv_password_strength).Text = " " + passwordBits + " bits";
|
||||
|
||||
|
||||
|
||||
UpdateProfileSpinnerSelection();
|
||||
});
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private void UpdatePasswordStrengthEstimate(string password)
|
||||
{
|
||||
lock (_popularPasswordsLock)
|
||||
{
|
||||
if (!_popularPasswordsInitialized)
|
||||
{
|
||||
|
||||
using (StreamReader sr = new StreamReader(Assets.Open("MostPopularPasswords.txt")))
|
||||
{
|
||||
var bytes = default(byte[]);
|
||||
using (var memstream = new MemoryStream())
|
||||
{
|
||||
sr.BaseStream.CopyTo(memstream);
|
||||
bytes = memstream.ToArray();
|
||||
}
|
||||
PopularPasswords.Add(bytes, false);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
uint passwordBits = QualityEstimation.EstimatePasswordBits(password.ToCharArray());
|
||||
|
||||
|
||||
|
||||
|
||||
RunOnUiThread(() =>
|
||||
{
|
||||
var progressBar = FindViewById<ProgressBar>(Resource.Id.pb_password_strength);
|
||||
|
||||
progressBar.Progress = (int)passwordBits;
|
||||
progressBar.Max = 128;
|
||||
|
||||
Color color = new Color(196, 63, 49);
|
||||
if (passwordBits > 40)
|
||||
{
|
||||
color = new Color(219, 152, 55);
|
||||
}
|
||||
|
||||
if (passwordBits > 64)
|
||||
{
|
||||
color = new Color(96, 138, 38);
|
||||
}
|
||||
|
||||
if (passwordBits > 100)
|
||||
{
|
||||
color = new Color(31, 128, 31);
|
||||
}
|
||||
|
||||
progressBar.ProgressDrawable.SetColorFilter(new PorterDuffColorFilter(color,
|
||||
PorterDuff.Mode.SrcIn));
|
||||
|
||||
FindViewById<TextView>(Resource.Id.tv_password_strength).Text = " " + passwordBits + " bits";
|
||||
});
|
||||
}
|
||||
|
||||
private void UpdateProfileSpinnerSelection()
|
||||
{
|
||||
int? lastUsedIndex = _profiles.TryFindLastUsedProfileIndex();
|
||||
@@ -543,7 +578,7 @@ namespace keepass2android
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Toast.MakeText(this, e.Message, ToastLength.Long).Show();
|
||||
App.Kp2a.ShowMessage(this, Util.GetErrorMessage(e), MessageSeverity.Error);
|
||||
}
|
||||
|
||||
return password;
|
||||
|
@@ -56,6 +56,8 @@ namespace keepass2android
|
||||
|
||||
public const int RequestCodeActivateRealSearch = 12366;
|
||||
|
||||
protected override View? SnackbarAnchorView => FindViewById(Resource.Id.main_content);
|
||||
|
||||
static readonly Dictionary<int /*resource id*/, int /*prio*/> bottomBarElementsPriority = new Dictionary<int, int>()
|
||||
{
|
||||
{ Resource.Id.cancel_insert_element, 20 },
|
||||
@@ -892,9 +894,14 @@ namespace keepass2android
|
||||
RegisterInfoTextDisplay(
|
||||
"DbReadOnly"); //this ensures that we don't show the general info texts too soon
|
||||
|
||||
FindViewById<TextView>(Resource.Id.dbreadonly_infotext_text).Text =
|
||||
(GetString(Resource.String.FileReadOnlyMessagePre) + " " +
|
||||
App.Kp2a.GetResourceString(reason.Result));
|
||||
var infotext_view = FindViewById<TextView>(Resource.Id.dbreadonly_infotext_text);
|
||||
if (infotext_view != null)
|
||||
{
|
||||
infotext_view.Text =
|
||||
(GetString(Resource.String.FileReadOnlyMessagePre) + " " +
|
||||
App.Kp2a.GetResourceString(reason.Result));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
UpdateBottomBarElementVisibility(Resource.Id.dbreadonly_infotext, canShow);
|
||||
@@ -927,7 +934,7 @@ namespace keepass2android
|
||||
{
|
||||
((GroupBaseActivity)activity)?.StopMovingElements();
|
||||
if (!String.IsNullOrEmpty(message))
|
||||
Toast.MakeText(activity, message, ToastLength.Long).Show();
|
||||
App.Kp2a.ShowMessage(activity, message, MessageSeverity.Error);
|
||||
}));
|
||||
var progressTask = new ProgressTask(App.Kp2a, this, moveElement);
|
||||
progressTask.Run();
|
||||
@@ -1328,7 +1335,7 @@ namespace keepass2android
|
||||
{
|
||||
Handler.Post(() =>
|
||||
{
|
||||
Toast.MakeText(ActiveActivity ?? LocaleManager.LocalizedAppContext, "Unrecoverable error: " + Message, ToastLength.Long).Show();
|
||||
App.Kp2a.ShowMessage(ActiveActivity ?? LocaleManager.LocalizedAppContext, "Unrecoverable error: " + Message, MessageSeverity.Error);
|
||||
});
|
||||
|
||||
App.Kp2a.Lock(false);
|
||||
|
@@ -111,9 +111,10 @@ namespace keepass2android
|
||||
SetResult (Result.Ok, intent);
|
||||
|
||||
Finish ();
|
||||
} else {
|
||||
Toast.MakeText (this, Resource.String.error_no_name, ToastLength.Long).Show ();
|
||||
}
|
||||
} else
|
||||
{
|
||||
App.Kp2a.ShowMessage(this, Resource.String.error_no_name, MessageSeverity.Error);
|
||||
}
|
||||
};
|
||||
|
||||
if (Intent.HasExtra(KeyGroupUuid))
|
||||
|
@@ -316,7 +316,7 @@ namespace keepass2android
|
||||
try { ck.AddUserKey(new KcpKeyFile(strAbs)); }
|
||||
catch (InvalidOperationException)
|
||||
{
|
||||
Toast.MakeText(LocaleManager.LocalizedAppContext,Resource.String.error_adding_keyfile,ToastLength.Long).Show();
|
||||
App.Kp2a.ShowMessage(LocaleManager.LocalizedAppContext,Resource.String.error_adding_keyfile, MessageSeverity.Error);
|
||||
return false;
|
||||
}
|
||||
catch (Exception) { throw; }
|
||||
|
@@ -146,7 +146,16 @@ namespace KeeChallenge
|
||||
{
|
||||
using (CryptoStream csDecrypt = (CryptoStream)aes.DecryptStream(msDecrypt, key, inf.IV))
|
||||
{
|
||||
csDecrypt.Read(secret, 0, secret.Length);
|
||||
//read the secret from the stream
|
||||
int totalBytesRead = 0;
|
||||
|
||||
int bytesRead = csDecrypt.Read(secret, totalBytesRead, secret.Length - totalBytesRead);
|
||||
while (bytesRead > 0 && totalBytesRead < secret.Length)
|
||||
{
|
||||
totalBytesRead += bytesRead;
|
||||
bytesRead = csDecrypt.Read(secret, totalBytesRead, secret.Length - totalBytesRead);
|
||||
}
|
||||
|
||||
csDecrypt.Close();
|
||||
}
|
||||
msDecrypt.Close();
|
||||
|
@@ -21,8 +21,10 @@ using Android.App;
|
||||
using Android.Content;
|
||||
using Android.Content.PM;
|
||||
using Android.Runtime;
|
||||
using Android.Views;
|
||||
using Google.Android.Material.Dialog;
|
||||
using keepass2android;
|
||||
using keepass2android.Utils;
|
||||
|
||||
namespace keepass2android
|
||||
{
|
||||
@@ -76,19 +78,34 @@ namespace keepass2android
|
||||
base.OnPause();
|
||||
|
||||
TimeoutHelper.Pause(this);
|
||||
}
|
||||
App.Kp2a.MessagePresenter = new NonePresenter();
|
||||
}
|
||||
|
||||
protected override void OnDestroy()
|
||||
{
|
||||
base.OnDestroy();
|
||||
GC.Collect();
|
||||
}
|
||||
|
||||
protected override void OnResume() {
|
||||
base.OnResume();
|
||||
|
||||
TimeoutHelper.Resume(this);
|
||||
}
|
||||
|
||||
protected override void OnResume()
|
||||
{
|
||||
base.OnResume();
|
||||
|
||||
TimeoutHelper.Resume(this);
|
||||
var snackbarAnchorView = SnackbarAnchorView;
|
||||
if (snackbarAnchorView != null)
|
||||
{
|
||||
App.Kp2a.MessagePresenter = new ChainedSnackbarPresenter(snackbarAnchorView);
|
||||
}
|
||||
else
|
||||
{
|
||||
App.Kp2a.MessagePresenter = new ToastPresenter();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
protected virtual View? SnackbarAnchorView => null;
|
||||
|
||||
|
||||
public const int RequestCodeChallengeYubikey = 793;
|
||||
|
||||
|
@@ -1,10 +1,10 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:versionCode="204"
|
||||
android:versionName="1.12-r3"
|
||||
package="keepass2android.keepass2android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:installLocation="auto">
|
||||
android:versionCode="218"
|
||||
android:versionName="1.12-r9d"
|
||||
package="keepass2android.keepass2android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:installLocation="auto">
|
||||
|
||||
|
||||
<queries>
|
||||
@@ -46,13 +46,11 @@
|
||||
|
||||
<permission android:description="@string/permission_desc2" android:icon="@drawable/ic_launcher" android:label="KP2A entry search" android:name="keepass2android.keepass2android.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.permission.Kp2aChooseAutofill" android:protectionLevel="signature" />
|
||||
|
||||
<application android:label="keepass2android"
|
||||
android:icon="@mipmap/ic_launcher_online"
|
||||
android:roundIcon="@mipmap/ic_launcher_online_round"
|
||||
android:networkSecurityConfig="@xml/network_security_config"
|
||||
|
||||
>
|
||||
android:icon="@mipmap/ic_launcher_online"
|
||||
android:roundIcon="@mipmap/ic_launcher_online_round"
|
||||
android:networkSecurityConfig="@xml/network_security_config"
|
||||
>
|
||||
|
||||
<meta-data
|
||||
android:name="com.google.mlkit.vision.DEPENDENCIES"
|
||||
@@ -107,16 +105,15 @@
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:name="keepass2android.softkeyboard.InputLanguageSelection"
|
||||
|
||||
android:exported="true">
|
||||
<!-- android:label="@string/language_selection_title" TODO -->
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<action android:name="keepass2android.softkeyboard.INPUT_LANGUAGE_SELECTION"/>
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:configChanges="orientation|keyboard|keyboardHidden" android:label="@string/app_name" android:theme="@style/Kp2aTheme_BlueNoActionBar" android:name="keepass2android.SelectCurrentDbActivity" android:windowSoftInputMode="adjustResize" android:exported="true">
|
||||
<activity android:configChanges="orientation|keyboard|keyboardHidden" android:label="@string/app_name" android:theme="@style/Kp2aTheme_BlueNoActionBar" 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" />
|
||||
|
@@ -1,24 +1,27 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:versionCode="200"
|
||||
android:versionName="1.11-r0"
|
||||
package="keepass2android.keepass2android_nonet"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:installLocation="auto">
|
||||
|
||||
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:versionCode="218"
|
||||
android:versionName="1.12-r9d"
|
||||
package="keepass2android.keepass2android_nonet"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:installLocation="auto">
|
||||
|
||||
|
||||
<queries>
|
||||
<!-- Specific intents and packages we query for (required since Android 11) -->
|
||||
<package android:name="keepass2android.plugin.keyboardswap2" />
|
||||
<package android:name="keepass2android.AncientIconSet" />
|
||||
<package android:name="com.dropbox.android" />
|
||||
<package android:name="keepass2android.plugin.qr" />
|
||||
<package android:name="it.andreacioni.kp2a.plugin.keelink" />
|
||||
<package android:name="com.inputstick.apps.kp2aplugin" />
|
||||
<package android:name="com.dropbox.android" />
|
||||
|
||||
<intent>
|
||||
<action android:name="android.intent.action.OPEN_DOCUMENT" />
|
||||
<data android:mimeType="*/*" />
|
||||
</intent>
|
||||
|
||||
<intent>
|
||||
<action android:name="android.intent.action.OPEN_DOCUMENT" />
|
||||
<data android:mimeType="*/*" />
|
||||
</intent>
|
||||
|
||||
<intent>
|
||||
<action android:name="android.intent.action.GET_DOCUMENT" />
|
||||
<data android:mimeType="*/*" />
|
||||
</intent>
|
||||
@@ -36,59 +39,57 @@
|
||||
</intent>
|
||||
|
||||
<intent>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
</intent>
|
||||
</queries>
|
||||
|
||||
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="34" />
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
</intent>
|
||||
</queries>
|
||||
<uses-sdk android:minSdkVersion="21" android:targetSdkVersion="34" />
|
||||
|
||||
<permission android:description="@string/permission_desc2" android:icon="@drawable/ic_launcher_offline" android:label="KP2A entry search" android:name="keepass2android.keepass2android_nonet.permission.KP2aInternalSearch" android:protectionLevel="signature" />
|
||||
<permission android:description="@string/permission_desc3" android:icon="@drawable/ic_launcher_offline" android:label="KP2A choose autofill dataset" android:name="keepass2android.keepass2android_nonet.permission.Kp2aChooseAutofill" android:protectionLevel="signature" />
|
||||
<application
|
||||
android:label="keepass2android"
|
||||
android:icon="@mipmap/ic_launcher_offline"
|
||||
android:networkSecurityConfig="@xml/network_security_config"
|
||||
>
|
||||
<application android:label="keepass2android"
|
||||
android:icon="@mipmap/ic_launcher_offline"
|
||||
android:roundIcon="@mipmap/ic_launcher_offline_round"
|
||||
android:networkSecurityConfig="@xml/network_security_config"
|
||||
>
|
||||
|
||||
<meta-data
|
||||
android:name="com.google.mlkit.vision.DEPENDENCIES"
|
||||
android:value="barcode_ui"/>
|
||||
|
||||
<uses-library
|
||||
<uses-library
|
||||
android:name="org.apache.http.legacy"
|
||||
android:required="false"/>
|
||||
|
||||
<provider android:name="group.pals.android.lib.ui.filechooser.providers.localfile.LocalFileProvider" android:authorities="keepass2android.keepass2android_nonet.android-filechooser.localfile" android:exported="false" />
|
||||
<provider android:name="group.pals.android.lib.ui.filechooser.providers.history.HistoryProvider" android:authorities="keepass2android.keepass2android_nonet.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>
|
||||
|
||||
<provider android:name="group.pals.android.lib.ui.filechooser.providers.localfile.LocalFileProvider" android:authorities="keepass2android.keepass2android_nonet.android-filechooser.localfile" android:exported="false" />
|
||||
<provider android:name="group.pals.android.lib.ui.filechooser.providers.history.HistoryProvider" android:authorities="keepass2android.keepass2android_nonet.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" 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" android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="keepass2android.softkeyboard.LatinIMESettings" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:name="keepass2android.softkeyboard.InputLanguageSelection"
|
||||
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"/>
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity android:configChanges="orientation|keyboard|keyboardHidden" android:label="@string/app_name" android:theme="@style/Kp2aTheme_BlueNoActionBar" android:name="keepass2android.SelectCurrentDbActivity" android:windowSoftInputMode="adjustResize"
|
||||
android:exported="true">
|
||||
<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" android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="keepass2android.softkeyboard.LatinIMESettings" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:name="keepass2android.softkeyboard.InputLanguageSelection"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN"/>
|
||||
<action android:name="keepass2android.softkeyboard.INPUT_LANGUAGE_SELECTION"/>
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<activity android:configChanges="orientation|keyboard|keyboardHidden" android:label="@string/app_name" android:theme="@style/Kp2aTheme_BlueNoActionBar" 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" />
|
||||
@@ -98,11 +99,11 @@
|
||||
<data android:host="*" />
|
||||
</intent-filter>
|
||||
|
||||
<intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="kp2a.action.SelectCurrentDbActivity" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
|
||||
|
||||
<intent-filter android:label="@string/app_name">
|
||||
<action android:name="android.intent.action.SEND" />
|
||||
<action android:name="android.intent.action.SEND_MULTIPLE" />
|
||||
@@ -112,7 +113,7 @@
|
||||
<data android:mimeType="application/*" />
|
||||
</intent-filter>
|
||||
|
||||
<!-- intent filter for opening database files
|
||||
<!-- intent filter for opening database files
|
||||
Note that this stopped working nicely with Android 7, see e.g. https://stackoverflow.com/a/26635162/292233
|
||||
KP2A was using
|
||||
<data android:scheme="content" />
|
||||
@@ -126,7 +127,7 @@ The scheme=file is still there for old OS devices. It's also queried by apps lik
|
||||
-->
|
||||
|
||||
|
||||
<!-- This intent filter is for apps which use content with a URI containing the extension but no specific mimeType, e.g. ASTRO file manager -->
|
||||
<!-- This intent filter is for apps which use content with a URI containing the extension but no specific mimeType, e.g. ASTRO file manager -->
|
||||
|
||||
<intent-filter android:label="@string/app_name">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
@@ -168,7 +169,7 @@ The scheme=file is still there for old OS devices. It's also queried by apps lik
|
||||
</intent-filter>
|
||||
|
||||
<!-- This intent filter is for apps which use content with a URI not containing the extension but at least specify mimeType=application/octet-stream, e.g. GoogleDrive or FolderSync -->
|
||||
<intent-filter android:label="@string/app_name">
|
||||
<intent-filter android:label="@string/app_name">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
@@ -218,24 +219,15 @@ The scheme=file is still there for old OS devices. It's also queried by apps lik
|
||||
<data android:pathPattern=".*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\..*\\.kdb" />
|
||||
</intent-filter>
|
||||
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW"/>
|
||||
<category android:name="android.intent.category.BROWSABLE"/>
|
||||
<data
|
||||
android:scheme="https"
|
||||
android:host="my.yubico.com"
|
||||
android:pathPrefix="/neo"/>
|
||||
<intent-filter android:label="@string/kp2a_findUrl">
|
||||
<action android:name="android.intent.action.SEND" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<data android:mimeType="text/plain" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="keepass2android.ACTION_START_WITH_TASK" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
|
||||
<intent-filter android:label="@string/kp2a_findUrl">
|
||||
<action android:name="android.intent.action.SEND" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<data android:mimeType="text/plain" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="keepass2android.ACTION_START_WITH_TASK" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
@@ -244,24 +236,28 @@ The scheme=file is still there for old OS devices. It's also queried by apps lik
|
||||
<data android:host="totp"/>
|
||||
<data android:host="hotp"/>
|
||||
</intent-filter>
|
||||
</activity>
|
||||
<uses-library android:required="false" android:name="com.sec.android.app.multiwindow" />
|
||||
<meta-data android:name="com.sec.android.support.multiwindow" android:value="true" />
|
||||
<meta-data android:name="com.sec.android.multiwindow.DEFAULT_SIZE_W" android:value="632.0dip" />
|
||||
<meta-data android:name="com.sec.android.multiwindow.DEFAULT_SIZE_H" android:value="598.0dip" />
|
||||
<meta-data android:name="com.sec.android.multiwindow.MINIMUM_SIZE_W" android:value="426.0dip" />
|
||||
<meta-data android:name="com.sec.android.multiwindow.MINIMUM_SIZE_H" android:value="360.0dip" />
|
||||
</application>
|
||||
<uses-permission android:name="android.permission.VIBRATE" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.USE_FINGERPRINT" />
|
||||
<uses-permission android:name="android.permission.USE_BIOMETRIC" />
|
||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
||||
|
||||
<uses-feature android:name="android.hardware.camera" android:required="false" />
|
||||
|
||||
</activity>
|
||||
<uses-library android:required="false" android:name="com.sec.android.app.multiwindow" />
|
||||
<meta-data android:name="com.sec.android.support.multiwindow" android:value="true" />
|
||||
<meta-data android:name="com.sec.android.multiwindow.DEFAULT_SIZE_W" android:value="632.0dip" />
|
||||
<meta-data android:name="com.sec.android.multiwindow.DEFAULT_SIZE_H" android:value="598.0dip" />
|
||||
<meta-data android:name="com.sec.android.multiwindow.MINIMUM_SIZE_W" android:value="426.0dip" />
|
||||
<meta-data android:name="com.sec.android.multiwindow.MINIMUM_SIZE_H" android:value="360.0dip" />
|
||||
</application>
|
||||
<uses-permission android:name="android.permission.VIBRATE" />
|
||||
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
|
||||
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE" />
|
||||
<uses-permission android:name="keepass2android.keepass2android_nonet.permission.KP2aInternalFileBrowsing" />
|
||||
<uses-permission android:name="keepass2android.keepass2android_nonet.permission.KP2aInternalSearch" />
|
||||
<uses-permission android:name="android.permission.USE_FINGERPRINT" />
|
||||
<uses-permission android:name="android.permission.USE_BIOMETRIC" />
|
||||
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
||||
|
||||
<uses-feature android:name="android.hardware.camera" android:required="false" />
|
||||
|
||||
<!-- 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>
|
||||
|
@@ -145,7 +145,7 @@ namespace keepass2android
|
||||
catch (Exception e)
|
||||
{
|
||||
Kp2aLog.LogUnexpectedError(e);
|
||||
Toast.MakeText(this, "No Yubikey OTP found!", ToastLength.Long).Show();
|
||||
App.Kp2a.ShowMessage(this, "No Yubikey OTP found!", MessageSeverity.Error);
|
||||
Finish();
|
||||
return;
|
||||
}
|
||||
|
@@ -131,7 +131,8 @@ namespace keepass2android
|
||||
ISharedPreferences _prefs;
|
||||
|
||||
private bool _starting;
|
||||
private OtpInfo _otpInfo;
|
||||
private bool _resumeCompleted;
|
||||
private OtpInfo _otpInfo;
|
||||
private IOConnectionInfo _otpAuxIoc;
|
||||
private ChallengeInfo _chalInfo;
|
||||
private byte[] _challengeSecret;
|
||||
@@ -309,7 +310,7 @@ namespace keepass2android
|
||||
catch (Exception e)
|
||||
{
|
||||
Kp2aLog.Log(e.ToString());
|
||||
Toast.MakeText(this, "Error: " + e.Message, ToastLength.Long).Show();
|
||||
App.Kp2a.ShowMessage(this, "Error: " + Util.GetErrorMessage(e), MessageSeverity.Error);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -328,8 +329,7 @@ namespace keepass2android
|
||||
ChallengeInfo temp = _challengeProv.Encrypt(_challengeSecret);
|
||||
if (!temp.Save(_otpAuxIoc))
|
||||
{
|
||||
Toast.MakeText(this, Resource.String.ErrorUpdatingChalAuxFile, ToastLength.Long)
|
||||
.Show();
|
||||
App.Kp2a.ShowMessage(this, Resource.String.ErrorUpdatingChalAuxFile, MessageSeverity.Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -348,7 +348,7 @@ namespace keepass2android
|
||||
}
|
||||
else
|
||||
{
|
||||
Toast.MakeText(this, Resource.String.bad_resp, ToastLength.Long).Show();
|
||||
App.Kp2a.ShowMessage(this, Resource.String.bad_resp, MessageSeverity.Error);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -420,8 +420,14 @@ namespace keepass2android
|
||||
try
|
||||
{
|
||||
var iocAux = GetDefaultAuxLocation();
|
||||
LoadFile(iocAux);
|
||||
}
|
||||
LoadFile(iocAux);
|
||||
|
||||
if (Activity._chalInfo == null)
|
||||
{
|
||||
throw new Java.Lang.Exception("Failed to load challenge aux file");
|
||||
}
|
||||
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
//this can happen e.g. if the file storage does not support GetParentPath
|
||||
@@ -458,7 +464,7 @@ namespace keepass2android
|
||||
}
|
||||
else
|
||||
{
|
||||
Toast.MakeText(Activity,GetErrorMessage(), ToastLength.Long).Show();
|
||||
App.Kp2a.ShowMessage(Activity,GetErrorMessage(), MessageSeverity.Error);
|
||||
}
|
||||
return;
|
||||
|
||||
@@ -801,8 +807,6 @@ namespace keepass2android
|
||||
|
||||
_password = i.GetStringExtra(KeyPassword) ?? "";
|
||||
if (!KeyProviderTypes.Any())
|
||||
|
||||
|
||||
{
|
||||
SetKeyProviderFromString(LoadKeyProviderStringForIoc(_ioConnection.Path));
|
||||
}
|
||||
@@ -957,7 +961,7 @@ namespace keepass2android
|
||||
{
|
||||
btn.SetImageResource(Resource.Drawable.baseline_fingerprint_24);
|
||||
}, 1300);
|
||||
Toast.MakeText(this, message, ToastLength.Long).Show();
|
||||
App.Kp2a.ShowMessage(this, message, MessageSeverity.Error);
|
||||
}
|
||||
|
||||
public void OnBiometricAttemptFailed(string message)
|
||||
@@ -996,8 +1000,12 @@ namespace keepass2android
|
||||
|
||||
btn.PostDelayed(() =>
|
||||
{
|
||||
//fire
|
||||
OnOk(true);
|
||||
//fire if everything else is ready
|
||||
if (FindViewById(Resource.Id.pass_ok).Enabled)
|
||||
{
|
||||
OnOk(true);
|
||||
}
|
||||
|
||||
FindViewById<EditText>(Resource.Id.password_edit).Enabled = true;
|
||||
}, 500);
|
||||
|
||||
@@ -1036,7 +1044,7 @@ namespace keepass2android
|
||||
if (_appnameclickCount == 6)
|
||||
{
|
||||
Kp2aLog.LogUnexpectedError(new Exception("some blabla"));
|
||||
Toast.MakeText(this, "Once again and the app will crash.", ToastLength.Long).Show();
|
||||
App.Kp2a.ShowMessage(this, "Once again and the app will crash.", MessageSeverity.Warning);
|
||||
}
|
||||
|
||||
if (_appnameclickCount == 7)
|
||||
@@ -1123,7 +1131,7 @@ namespace keepass2android
|
||||
//For security reasons: discard the OTP (otherwise the user might not select a database now and forget
|
||||
//about the OTP, but it would still be stored in the Intents and later be passed to PasswordActivity again.
|
||||
|
||||
Toast.MakeText(this, GetString(Resource.String.otp_discarded_because_no_db), ToastLength.Long).Show();
|
||||
App.Kp2a.ShowMessage(this, GetString(Resource.String.otp_discarded_because_no_db), MessageSeverity.Warning);
|
||||
GoToFileSelectActivity();
|
||||
return false;
|
||||
}
|
||||
@@ -1251,7 +1259,7 @@ namespace keepass2android
|
||||
case 6:
|
||||
KeyProviderTypes.Add(KeyProviders.ChallengeXC);
|
||||
break;
|
||||
case 7:
|
||||
case 7:
|
||||
//don't set to "" to prevent losing the filename. (ItemSelected is also called during recreation!)
|
||||
Kp2aLog.Log("key file length before: " + _keyFile?.Length);
|
||||
_keyFile = (FindViewById(Resource.Id.label_keyfilename).Tag ?? "").ToString();
|
||||
@@ -1400,7 +1408,7 @@ namespace keepass2android
|
||||
string errorMessage;
|
||||
if (!CreateCompositeKey(out compositeKey, out errorMessage)) return (() =>
|
||||
{
|
||||
Toast.MakeText(this, errorMessage, ToastLength.Long).Show();
|
||||
App.Kp2a.ShowMessage(this, errorMessage, MessageSeverity.Warning);
|
||||
_performingLoad = false;
|
||||
});
|
||||
return () => { PerformLoadDatabaseWithCompositeKey(compositeKey); };
|
||||
@@ -1415,6 +1423,8 @@ namespace keepass2android
|
||||
if (cbQuickUnlock == null)
|
||||
throw new NullPointerException("cpQuickUnlock");
|
||||
App.Kp2a.SetQuickUnlockEnabled(cbQuickUnlock.Checked);
|
||||
App.Kp2a.ScreenLockWasEnabledWhenOpeningDatabase =
|
||||
(((KeyguardManager)GetSystemService(Context.KeyguardService)!)!).IsDeviceSecure;
|
||||
|
||||
if ((_loadDbFileTask != null) && (App.Kp2a.OfflineMode != _loadDbTaskOffline))
|
||||
{
|
||||
@@ -1481,7 +1491,7 @@ namespace keepass2android
|
||||
catch (Exception e)
|
||||
{
|
||||
Kp2aLog.LogUnexpectedError(e);
|
||||
errorMessage = e.Message;
|
||||
errorMessage = Util.GetErrorMessage(e);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -1566,15 +1576,21 @@ namespace keepass2android
|
||||
|
||||
base.OnPause();
|
||||
}
|
||||
protected override void OnStart()
|
||||
|
||||
private bool hasRequestedKeyboardActivation = false;
|
||||
|
||||
|
||||
protected override void OnStart()
|
||||
{
|
||||
base.OnStart();
|
||||
_starting = true;
|
||||
|
||||
if (PreferenceManager.GetDefaultSharedPreferences(this)
|
||||
.GetBoolean(GetString(Resource.String.UseKp2aKeyboardInKp2a_key), false))
|
||||
{
|
||||
CopyToClipboardService.ActivateKeyboard(this);
|
||||
.GetBoolean(GetString(Resource.String.UseKp2aKeyboardInKp2a_key), false)
|
||||
&& !hasRequestedKeyboardActivation)
|
||||
{
|
||||
hasRequestedKeyboardActivation = true;
|
||||
CopyToClipboardService.ActivateKeyboard(this);
|
||||
}
|
||||
|
||||
DonateReminder.ShowDonateReminderIfAppropriate(this);
|
||||
@@ -1639,60 +1655,65 @@ namespace keepass2android
|
||||
if (intent != null)
|
||||
{
|
||||
if (intent.HasExtra(Intents.OtpExtraKey))
|
||||
{
|
||||
string otp = intent.GetStringExtra(Intents.OtpExtraKey);
|
||||
_keepPasswordInOnResume = true;
|
||||
if (KeyProviderTypes.Contains(KeyProviders.Otp))
|
||||
{
|
||||
string otp = intent.GetStringExtra(Intents.OtpExtraKey);
|
||||
_keepPasswordInOnResume = true;
|
||||
if (KeyProviderTypes.Contains(KeyProviders.Otp))
|
||||
{
|
||||
|
||||
if (_otpInfo == null)
|
||||
{
|
||||
//Entering OTPs not yet initialized:
|
||||
_pendingOtps.Add(otp);
|
||||
UpdateKeyProviderUiState();
|
||||
}
|
||||
else
|
||||
{
|
||||
//Entering OTPs is initialized. Write OTP into first empty field:
|
||||
bool foundEmptyField = false;
|
||||
foreach (int otpId in _otpTextViewIds)
|
||||
{
|
||||
EditText otpEdit = FindViewById<EditText>(otpId);
|
||||
if ((otpEdit.Visibility == ViewStates.Visible) && String.IsNullOrEmpty(otpEdit.Text))
|
||||
{
|
||||
otpEdit.Text = otp;
|
||||
foundEmptyField = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
//did we find a field?
|
||||
if (!foundEmptyField)
|
||||
{
|
||||
App.Kp2a.ShowMessage(this, GetString(Resource.String.otp_discarded_no_space), MessageSeverity.Error);
|
||||
}
|
||||
}
|
||||
|
||||
Spinner passwordModeSpinner = FindViewById<Spinner>(Resource.Id.password_mode_spinner);
|
||||
if (passwordModeSpinner.SelectedItemPosition != (int)KeyProviders.Otp)
|
||||
{
|
||||
passwordModeSpinner.SetSelection((int)KeyProviders.Otp);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//assume the key should be used as static password
|
||||
FindViewById<EditText>(Resource.Id.password_edit).Text += otp;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// if the activity is launched twice and the first initialization hasn't even finished, we cannot
|
||||
// reset the state and re-initialize the activity.
|
||||
// This can happen with autofill in some cases (#2869)
|
||||
if (_resumeCompleted)
|
||||
{
|
||||
|
||||
if (_otpInfo == null)
|
||||
{
|
||||
//Entering OTPs not yet initialized:
|
||||
_pendingOtps.Add(otp);
|
||||
UpdateKeyProviderUiState();
|
||||
}
|
||||
else
|
||||
{
|
||||
//Entering OTPs is initialized. Write OTP into first empty field:
|
||||
bool foundEmptyField = false;
|
||||
foreach (int otpId in _otpTextViewIds)
|
||||
{
|
||||
EditText otpEdit = FindViewById<EditText>(otpId);
|
||||
if ((otpEdit.Visibility == ViewStates.Visible) && String.IsNullOrEmpty(otpEdit.Text))
|
||||
{
|
||||
otpEdit.Text = otp;
|
||||
foundEmptyField = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
//did we find a field?
|
||||
if (!foundEmptyField)
|
||||
{
|
||||
Toast.MakeText(this, GetString(Resource.String.otp_discarded_no_space), ToastLength.Long).Show();
|
||||
}
|
||||
}
|
||||
|
||||
Spinner passwordModeSpinner = FindViewById<Spinner>(Resource.Id.password_mode_spinner);
|
||||
if (passwordModeSpinner.SelectedItemPosition != (int)KeyProviders.Otp)
|
||||
{
|
||||
passwordModeSpinner.SetSelection((int)KeyProviders.Otp);
|
||||
}
|
||||
ResetState();
|
||||
GetIocFromLaunchIntent(intent);
|
||||
InitializeAfterSetIoc();
|
||||
OnStart();
|
||||
}
|
||||
else
|
||||
{
|
||||
//assume the key should be used as static password
|
||||
FindViewById<EditText>(Resource.Id.password_edit).Text += otp;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
ResetState();
|
||||
GetIocFromLaunchIntent(intent);
|
||||
InitializeAfterSetIoc();
|
||||
OnStart();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1729,19 +1750,26 @@ namespace keepass2android
|
||||
UsedFingerprintUnlock = false;
|
||||
}
|
||||
|
||||
protected override void OnResume()
|
||||
protected override View? SnackbarAnchorView => FindViewById(Resource.Id.main_content);
|
||||
|
||||
protected override void OnResume()
|
||||
{
|
||||
base.OnResume();
|
||||
|
||||
_activityDesign.ReapplyTheme();
|
||||
|
||||
Kp2aLog.Log("starting: " + _starting + ", Finishing: " + IsFinishing + ", _performingLoad: " + _performingLoad);
|
||||
Kp2aLog.Log("starting: " + _starting + ", Finishing: " + IsFinishing + ", _performingLoad: " +
|
||||
_performingLoad);
|
||||
|
||||
CheckBox cbOfflineMode = (CheckBox)FindViewById(Resource.Id.work_offline);
|
||||
App.Kp2a.OfflineMode = cbOfflineMode.Checked = App.Kp2a.OfflineModePreference; //this won't overwrite new user settings because every change is directly saved in settings
|
||||
App.Kp2a.OfflineMode =
|
||||
cbOfflineMode.Checked =
|
||||
App.Kp2a
|
||||
.OfflineModePreference; //this won't overwrite new user settings because every change is directly saved in settings
|
||||
LinearLayout offlineModeContainer = FindViewById<LinearLayout>(Resource.Id.work_offline_container);
|
||||
var cachingFileStorage = App.Kp2a.GetFileStorage(_ioConnection) as CachingFileStorage;
|
||||
if ((cachingFileStorage != null) && cachingFileStorage.IsCached(_ioConnection))
|
||||
{
|
||||
{
|
||||
offlineModeContainer.Visibility = ViewStates.Visible;
|
||||
}
|
||||
else
|
||||
@@ -1749,18 +1777,18 @@ namespace keepass2android
|
||||
offlineModeContainer.Visibility = ViewStates.Gone;
|
||||
App.Kp2a.OfflineMode = false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
View killButton = FindViewById(Resource.Id.kill_app);
|
||||
if (PreferenceManager.GetDefaultSharedPreferences(this)
|
||||
.GetBoolean(GetString(Resource.String.show_kill_app_key), false))
|
||||
.GetBoolean(GetString(Resource.String.show_kill_app_key), false))
|
||||
{
|
||||
killButton.Click += (sender, args) =>
|
||||
{
|
||||
_killOnDestroy = true;
|
||||
SetResult(Result.Canceled);
|
||||
SetResult(Result.Canceled);
|
||||
Finish();
|
||||
|
||||
};
|
||||
@@ -1772,20 +1800,23 @@ namespace keepass2android
|
||||
killButton.Visibility = ViewStates.Gone;
|
||||
}
|
||||
|
||||
TryGetOtpFromClipboard();
|
||||
TryGetOtpFromClipboard();
|
||||
|
||||
if (!_keepPasswordInOnResume)
|
||||
{
|
||||
if (
|
||||
_lastOnPauseTime < DateTime.Now - TimeSpan.FromSeconds(5) //only clear when user left the app for more than 5 seconds (allows to use Yubiclip, also allows to switch shortly to another app)
|
||||
&&
|
||||
PreferenceManager.GetDefaultSharedPreferences(this)
|
||||
.GetBoolean(GetString(Resource.String.ClearPasswordOnLeave_key), true))
|
||||
{
|
||||
ClearEnteredPassword();
|
||||
}
|
||||
if (!_keepPasswordInOnResume)
|
||||
{
|
||||
if (
|
||||
_lastOnPauseTime <
|
||||
DateTime.Now -
|
||||
TimeSpan.FromSeconds(
|
||||
5) //only clear when user left the app for more than 5 seconds (allows to use Yubiclip, also allows to switch shortly to another app)
|
||||
&&
|
||||
PreferenceManager.GetDefaultSharedPreferences(this)
|
||||
.GetBoolean(GetString(Resource.String.ClearPasswordOnLeave_key), true))
|
||||
{
|
||||
ClearEnteredPassword();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -1797,71 +1828,74 @@ namespace keepass2android
|
||||
|
||||
if (KeyProviderTypes.Contains(KeyProviders.Challenge))
|
||||
{
|
||||
FindViewById(Resource.Id.otpInitView).Visibility = _challengeSecret == null ? ViewStates.Visible : ViewStates.Gone;
|
||||
FindViewById(Resource.Id.otpInitView).Visibility =
|
||||
_challengeSecret == null ? ViewStates.Visible : ViewStates.Gone;
|
||||
}
|
||||
|
||||
//use !IsFinishing to make sure we're not starting another activity when we're already finishing (e.g. due to TaskComplete in OnActivityResult)
|
||||
//use !performingLoad to make sure we're not already loading the database (after ActivityResult from File-Prepare-Activity; this would cause _loadDbFileTask to exist when we reload later!)
|
||||
if ( !IsFinishing && !_performingLoad)
|
||||
if (!IsFinishing && !_performingLoad)
|
||||
{
|
||||
|
||||
|
||||
// OnResume is run every time the activity comes to the foreground. This code should only run when the activity is started (OnStart), but must
|
||||
|
||||
|
||||
// OnResume is run every time the activity comes to the foreground. This code should only run when the activity is started (OnStart), but must
|
||||
// be run in OnResume rather than OnStart so that it always occurrs after OnActivityResult (when re-creating a killed activity, OnStart occurs before OnActivityResult)
|
||||
if (_starting)
|
||||
{
|
||||
if (_starting)
|
||||
{
|
||||
|
||||
_starting = false;
|
||||
_starting = false;
|
||||
|
||||
//database not yet loaded.
|
||||
//database not yet loaded.
|
||||
|
||||
//check if pre-loading is enabled but wasn't started yet:
|
||||
if (_loadDbFileTask == null &&
|
||||
_prefs.GetBoolean(GetString(Resource.String.PreloadDatabaseEnabled_key), true))
|
||||
{
|
||||
// Create task to kick off file loading while the user enters the password
|
||||
_loadDbFileTask = Task.Factory.StartNew(PreloadDbFile);
|
||||
_loadDbTaskOffline = App.Kp2a.OfflineMode;
|
||||
}
|
||||
}
|
||||
//check if pre-loading is enabled but wasn't started yet:
|
||||
if (_loadDbFileTask == null &&
|
||||
_prefs.GetBoolean(GetString(Resource.String.PreloadDatabaseEnabled_key), true))
|
||||
{
|
||||
// Create task to kick off file loading while the user enters the password
|
||||
_loadDbFileTask = Task.Factory.StartNew(PreloadDbFile);
|
||||
_loadDbTaskOffline = App.Kp2a.OfflineMode;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (compositeKeyForImmediateLoad != null)
|
||||
{
|
||||
//reload the database (without most other stuff performed in PerformLoadDatabase.
|
||||
// We're assuming that the db file (and if appropriate also the key file) are still available
|
||||
// and there's no need to re-init the file storage. if it is, loading will fail and the user has
|
||||
// to retry with typing the full password, but that's intended to avoid showing the password to a
|
||||
// a potentially unauthorized user (feature request https://keepass2android.codeplex.com/workitem/274)
|
||||
Handler handler = new Handler();
|
||||
OnFinish onFinish = new AfterLoad(handler, this, _ioConnection);
|
||||
_performingLoad = true;
|
||||
LoadDb task = new LoadDb(this, App.Kp2a, _ioConnection, _loadDbFileTask, compositeKeyForImmediateLoad, GetKeyProviderString(),
|
||||
onFinish, false, _makeCurrent);
|
||||
_loadDbFileTask = null; // prevent accidental re-use
|
||||
new ProgressTask(App.Kp2a, this, task).Run();
|
||||
compositeKeyForImmediateLoad = null; //don't reuse or keep in memory
|
||||
if (compositeKeyForImmediateLoad != null)
|
||||
{
|
||||
//reload the database (without most other stuff performed in PerformLoadDatabase.
|
||||
// We're assuming that the db file (and if appropriate also the key file) are still available
|
||||
// and there's no need to re-init the file storage. if it is, loading will fail and the user has
|
||||
// to retry with typing the full password, but that's intended to avoid showing the password to a
|
||||
// a potentially unauthorized user (feature request https://keepass2android.codeplex.com/workitem/274)
|
||||
Handler handler = new Handler();
|
||||
OnFinish onFinish = new AfterLoad(handler, this, _ioConnection);
|
||||
_performingLoad = true;
|
||||
LoadDb task = new LoadDb(this, App.Kp2a, _ioConnection, _loadDbFileTask, compositeKeyForImmediateLoad, GetKeyProviderString(),
|
||||
onFinish, false, _makeCurrent);
|
||||
_loadDbFileTask = null; // prevent accidental re-use
|
||||
new ProgressTask(App.Kp2a, this, task).Run();
|
||||
compositeKeyForImmediateLoad = null; //don't reuse or keep in memory
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
bool showKeyboard = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
bool showKeyboard = true;
|
||||
|
||||
|
||||
EditText pwd = (EditText) FindViewById(Resource.Id.password_edit);
|
||||
pwd.PostDelayed(() =>
|
||||
{
|
||||
InputMethodManager keyboard = (InputMethodManager) GetSystemService(InputMethodService);
|
||||
if (showKeyboard)
|
||||
{
|
||||
pwd.RequestFocus();
|
||||
keyboard.ShowSoftInput(pwd, 0);
|
||||
}
|
||||
else
|
||||
keyboard.HideSoftInputFromWindow(pwd.WindowToken, HideSoftInputFlags.ImplicitOnly);
|
||||
}, 50);
|
||||
}
|
||||
|
||||
EditText pwd = (EditText)FindViewById(Resource.Id.password_edit);
|
||||
pwd.PostDelayed(() =>
|
||||
{
|
||||
InputMethodManager keyboard = (InputMethodManager)GetSystemService(InputMethodService);
|
||||
if (showKeyboard)
|
||||
{
|
||||
pwd.RequestFocus();
|
||||
keyboard.ShowSoftInput(pwd, 0);
|
||||
}
|
||||
else
|
||||
keyboard.HideSoftInputFromWindow(pwd.WindowToken, HideSoftInputFlags.ImplicitOnly);
|
||||
}, 50);
|
||||
}
|
||||
|
||||
_resumeCompleted = true;
|
||||
}
|
||||
|
||||
private void TryGetOtpFromClipboard()
|
||||
@@ -1954,7 +1988,7 @@ namespace keepass2android
|
||||
|
||||
btn.Tag = error;
|
||||
|
||||
Toast.MakeText(this, Resource.String.fingerprint_reenable2, ToastLength.Long).Show();
|
||||
App.Kp2a.ShowMessage(this, Resource.String.fingerprint_reenable2, MessageSeverity.Error);
|
||||
|
||||
_biometricDec = null;
|
||||
return false;
|
||||
@@ -2024,7 +2058,7 @@ namespace keepass2android
|
||||
/*
|
||||
private void errorMessage(CharSequence text)
|
||||
{
|
||||
Toast.MakeText(this, text, ToastLength.Long).Show();
|
||||
App.Kp2a.ShowMessage(this, text, MessageSeverity.Error);
|
||||
}
|
||||
*/
|
||||
|
||||
@@ -2084,7 +2118,9 @@ namespace keepass2android
|
||||
_act.LoadingErrorCount++;
|
||||
}
|
||||
|
||||
if ((Exception != null) && (Exception.Message == KeePassLib.Resources.KLRes.FileCorrupted))
|
||||
|
||||
|
||||
if ((Exception != null) && (Exception.Message == KeePassLib.Resources.KLRes.FileCorrupted))
|
||||
{
|
||||
Message = _act.GetString(Resource.String.CorruptDatabaseHelp);
|
||||
}
|
||||
@@ -2150,7 +2186,8 @@ namespace keepass2android
|
||||
}
|
||||
else
|
||||
{
|
||||
DisplayMessage(_act);
|
||||
MessageSeverity severity = Success ? MessageSeverity.Info : MessageSeverity.Error;
|
||||
App.Kp2a.ShowMessage(_act, Message, severity);
|
||||
if (Success)
|
||||
{
|
||||
_act.LaunchNextActivity();
|
||||
@@ -2218,7 +2255,7 @@ namespace keepass2android
|
||||
{
|
||||
Kp2aLog.LogUnexpectedError(e);
|
||||
|
||||
ShowError( _act.GetString(Resource.String.ErrorUpdatingOtpAuxFile) + " " + e.Message);
|
||||
ShowError( _act.GetString(Resource.String.ErrorUpdatingOtpAuxFile) + " " + Util.GetErrorMessage(e));
|
||||
}
|
||||
|
||||
|
||||
@@ -2234,7 +2271,7 @@ namespace keepass2android
|
||||
|
||||
private void ShowError(string message)
|
||||
{
|
||||
App.Kp2a.ShowToast(message);
|
||||
App.Kp2a.ShowToast(message, MessageSeverity.Error);
|
||||
}
|
||||
}
|
||||
private class PasswordActivityBroadcastReceiver : BroadcastReceiver
|
||||
|
@@ -128,11 +128,11 @@ namespace keepass2android
|
||||
Kp2aLog.LogUnexpectedError(e);
|
||||
}
|
||||
if (String.IsNullOrEmpty(_requestedUrl))
|
||||
Toast.MakeText(this, GetString(Resource.String.query_credentials, new Java.Lang.Object[] {pluginDisplayName}), ToastLength.Long).Show();
|
||||
App.Kp2a.ShowMessage(this, GetString(Resource.String.query_credentials, new Java.Lang.Object[] {pluginDisplayName}), MessageSeverity.Info);
|
||||
else
|
||||
Toast.MakeText(this,
|
||||
App.Kp2a.ShowMessage(this,
|
||||
GetString(Resource.String.query_credentials_for_url,
|
||||
new Java.Lang.Object[] { pluginDisplayName, _requestedUrl }), ToastLength.Long).Show(); ;
|
||||
new Java.Lang.Object[] { pluginDisplayName, _requestedUrl }), MessageSeverity.Info); ;
|
||||
}
|
||||
|
||||
private void StartQuery()
|
||||
|
@@ -25,6 +25,7 @@ using Android.Widget;
|
||||
using Android.Content.PM;
|
||||
using KeePassLib.Keys;
|
||||
using Android.Preferences;
|
||||
using Android.Provider;
|
||||
using Android.Runtime;
|
||||
|
||||
using Android.Views.InputMethods;
|
||||
@@ -35,6 +36,7 @@ using KeePassLib;
|
||||
using KeePassLib.Serialization;
|
||||
using Toolbar = AndroidX.AppCompat.Widget.Toolbar;
|
||||
using AndroidX.Core.Content;
|
||||
using keepass2android.Utils;
|
||||
|
||||
namespace keepass2android
|
||||
{
|
||||
@@ -161,6 +163,29 @@ namespace keepass2android
|
||||
if (bundle != null)
|
||||
numFailedAttempts = bundle.GetInt(NumFailedAttemptsKey, 0);
|
||||
|
||||
FindViewById(Resource.Id.QuickUnlock_buttonEnableLock).Click += (object sender, EventArgs e) =>
|
||||
{
|
||||
Intent intent = new Intent(Settings.ActionSecuritySettings);
|
||||
StartActivity(intent);
|
||||
|
||||
};
|
||||
|
||||
FindViewById(Resource.Id.QuickUnlock_buttonCloseDb).Click += (object sender, EventArgs e) =>
|
||||
{
|
||||
App.Kp2a.Lock(false);
|
||||
};
|
||||
|
||||
if (App.Kp2a.ScreenLockWasEnabledWhenOpeningDatabase == false)
|
||||
{
|
||||
FindViewById(Resource.Id.QuickUnlockForm).Visibility = ViewStates.Gone;
|
||||
FindViewById(Resource.Id.QuickUnlockBlocked).Visibility = ViewStates.Visible;
|
||||
}
|
||||
else
|
||||
{
|
||||
FindViewById(Resource.Id.QuickUnlockForm).Visibility = ViewStates.Visible;
|
||||
FindViewById(Resource.Id.QuickUnlockBlocked).Visibility = ViewStates.Gone;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -203,7 +228,7 @@ namespace keepass2android
|
||||
btn.SetImageResource(Resource.Drawable.baseline_fingerprint_24);
|
||||
|
||||
}, 1300);
|
||||
Toast.MakeText(this, message, ToastLength.Long).Show();
|
||||
App.Kp2a.ShowMessage(this, message, MessageSeverity.Error);
|
||||
}
|
||||
|
||||
|
||||
@@ -325,7 +350,7 @@ namespace keepass2android
|
||||
{
|
||||
Kp2aLog.Log("QuickUnlock not successful!");
|
||||
App.Kp2a.Lock(false);
|
||||
Toast.MakeText(this, GetString(Resource.String.QuickUnlock_fail), ToastLength.Long).Show();
|
||||
App.Kp2a.ShowMessage(this, GetString(Resource.String.QuickUnlock_fail), MessageSeverity.Error);
|
||||
Finish();
|
||||
}
|
||||
|
||||
@@ -383,8 +408,9 @@ namespace keepass2android
|
||||
{
|
||||
base.OnResume();
|
||||
_design.ReapplyTheme();
|
||||
|
||||
CheckIfUnloaded();
|
||||
App.Kp2a.MessagePresenter = new ChainedSnackbarPresenter(FindViewById(Resource.Id.main_content));
|
||||
|
||||
CheckIfUnloaded();
|
||||
|
||||
InitFingerprintUnlock();
|
||||
|
||||
@@ -449,7 +475,8 @@ namespace keepass2android
|
||||
|
||||
protected override void OnPause()
|
||||
{
|
||||
if (_biometryIdentifier != null)
|
||||
App.Kp2a.MessagePresenter = new NonePresenter();
|
||||
if (_biometryIdentifier != null)
|
||||
{
|
||||
Kp2aLog.Log("FP: Stop listening");
|
||||
_biometryIdentifier.StopListening();
|
||||
|
@@ -78,20 +78,21 @@ android:paddingLeft="16dp"
|
||||
android:paddingRight="16dp"
|
||||
android:paddingTop="16dp">
|
||||
|
||||
|
||||
<TextView
|
||||
android:id="@+id/QuickUnlock_label"
|
||||
android:text="@string/QuickUnlock_label"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/filename_label"
|
||||
android:textSize="14sp"
|
||||
/>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="horizontal">
|
||||
android:orientation="horizontal"
|
||||
android:id="@+id/QuickUnlockForm">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/QuickUnlock_label"
|
||||
android:text="@string/QuickUnlock_label"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_below="@id/filename_label"
|
||||
android:textSize="14sp"
|
||||
/>
|
||||
|
||||
<EditText
|
||||
android:inputType="textPassword"
|
||||
@@ -121,6 +122,60 @@ android:paddingRight="16dp"
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical"
|
||||
android:background="@color/md_theme_secondaryContainer"
|
||||
android:id="@+id/QuickUnlockBlocked"
|
||||
android:padding="16dp"
|
||||
android:layout_gravity="center">
|
||||
|
||||
<TextView
|
||||
android:id="@+id/quick_unlock_blocked_title"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/password_based_quick_unlock_not_available"
|
||||
android:textSize="16sp"
|
||||
android:textStyle="bold"
|
||||
android:gravity="center"
|
||||
android:paddingBottom="8dp"/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/alert_message"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/password_based_quick_unlock_not_available_text"
|
||||
android:textSize="16sp"
|
||||
android:paddingBottom="8dp"/>
|
||||
<LinearLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:orientation="vertical">
|
||||
<Button
|
||||
android:id="@+id/QuickUnlock_buttonEnableLock"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:backgroundTint="@color/md_theme_secondary"
|
||||
android:textColor="@android:color/white"
|
||||
android:text="@string/enable_screen_lock"
|
||||
android:fontFamily="sans-serif-medium" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/QuickUnlock_buttonCloseDb"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:backgroundTint="@color/md_theme_secondary"
|
||||
android:textColor="@android:color/white"
|
||||
android:fontFamily="sans-serif-medium"
|
||||
android:text="@string/QuickUnlock_lockButton" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
<View
|
||||
android:id="@+id/spacing"
|
||||
|
@@ -1,5 +1,11 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/main_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fitsSystemWindows="true">
|
||||
|
||||
<ScrollView
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
android:id="@+id/entry_scroll"
|
||||
android:background="?android:attr/colorBackground"
|
||||
@@ -267,4 +273,5 @@
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</LinearLayout>
|
||||
</ScrollView>
|
||||
</ScrollView>
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
@@ -1,4 +1,9 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.coordinatorlayout.widget.CoordinatorLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:id="@+id/main_content"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
android:fitsSystemWindows="true">
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:orientation="vertical"
|
||||
@@ -14,6 +19,7 @@
|
||||
android:text="@string/switch_ime_text" />
|
||||
|
||||
<Button
|
||||
|
||||
android:id="@+id/btn_reopen"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
@@ -25,4 +31,51 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/cancel" />
|
||||
|
||||
<LinearLayout android:orientation="vertical"
|
||||
android:paddingTop="64dp"
|
||||
android:id="@+id/settings_notes_container"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content">
|
||||
<TextView
|
||||
android:paddingTop="12dp"
|
||||
android:id="@+id/note_kp2a_switch_rooted"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/autoswitch_enabled_but_not_setup"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:paddingTop="12dp"
|
||||
android:id="@+id/note_AutoFillTotp_prefs_ActivateKeyboard"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/switch_keyboard_for_totp_enabled"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:paddingTop="12dp"
|
||||
android:id="@+id/note_UseKp2aKeyboardInKp2a"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/switch_keyboard_inside_kp2a_enabled"
|
||||
/>
|
||||
|
||||
<TextView
|
||||
android:id="@+id/note_OpenKp2aKeyboardAutomatically"
|
||||
android:paddingTop="12dp"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/switch_keyboard_on_search_enabled"
|
||||
/>
|
||||
|
||||
<Button
|
||||
style="?attr/materialButtonOutlinedStyle"
|
||||
android:id="@+id/btn_open_settings"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="@string/IconVisibilityInfo_Android8_btnSettings" />
|
||||
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
</androidx.coordinatorlayout.widget.CoordinatorLayout>
|
@@ -546,6 +546,7 @@
|
||||
<string name="filestoragename_dropboxKP2A">Dropbox (KP2A složka)</string>
|
||||
<string name="filestoragehelp_dropboxKP2A">Pokud nechcete, aby měl KP2A plný přístup k vašemu Dropbox účtu, může vybrat tuto možnost. Bude vyžadován pouze přístup ke složce Apps/Keepass2Android. Toto je vhodné zejména při vytváření nové databáze. Pokud již máte databázi, zvolte na tuto možnost pro vytvoření složky, poté umístěte soubor (z PC) do této složky a zvolte tuto možnost znovu pro otevření souboru.</string>
|
||||
<string name="filestoragename_gdrive">Google Drive</string>
|
||||
<string name="filestoragehelp_gdrive">Upozornění: Společnost Google omezuje přístup k Disku Google z aplikací pro stále více uživatelů. Pokud vestavěná implementace Disku Google nefunguje, použijte místo toho systémový výběr souborů a vyberte Disk Google tam!</string>
|
||||
<string name="filestoragename_gdriveKP2A">Google Drive (KP2A soubory)</string>
|
||||
<string name="filestoragehelp_gdriveKP2A">Nechcete-li dát aplikaci KeePass2Android přístup k celému vašemu Google Drive, použijte tuto možnost. Upozorňujeme, že nejprve musíte vytvořit soubor s databází položek, existující soubory nejsou viditelné pro aplikaci. Toto můžete udělat z obrazovky Vytvořit databázi, nebo exportem právě otevřené databáze, volbou této možnosti</string>
|
||||
<string name="filestoragename_pcloud">PCloud (složka KP2A)</string>
|
||||
@@ -723,6 +724,7 @@
|
||||
<item>Aktualizováno na uživatelské rozhraní Material 3</item>
|
||||
<item>Vylepšení automatického vyplňování pro práci s aplikacemi Compose</item>
|
||||
<item>Oprava přiřazování názvů hostitelů v automatickém vyplňování a vyhledávání</item>
|
||||
<item>Oprava problému s generátorem hesel</item>
|
||||
</string-array>
|
||||
<string-array name="ChangeLog_1_12_net">
|
||||
<item>Aktualizováno OneDrive SDK na verzi 5.68</item>
|
||||
@@ -1165,5 +1167,10 @@ První veřejné vydání
|
||||
<string name="AutofillWarning_trustAsBrowser">Přijmout vždy v \"%1$s\"</string>
|
||||
<string name="kp2a_switch_on_sendgodone">Přepnout zpět po dokončení</string>
|
||||
<string name="kp2a_switch_on_sendgodone_summary">Přepnout zpět při stisknutí tlačítka odeslat/pokračovat/ukončit</string>
|
||||
<string name="qr_scanning_error_no_google_play_services">Skenování QR kódu vyžaduje služby Google Play. Nainstalujte nebo aktualizujte služby Google Play ve svém zařízení.</string>
|
||||
<string name="english_ime_settings">Nastavení klávesnice Keepass2Android</string>
|
||||
<string name="autoswitch_enabled_but_not_setup">Poznámka: Máte povoleno Aplikace - Nastavení - Přístup k heslu - Přepínání klávesnice - Automatické přepínání klávesnice, ale nezdá se, že je správně nakonfigurováno.</string>
|
||||
<string name="switch_keyboard_for_totp_enabled">Poznámka: Máte povoleno Aplikace - Přístup k heslu - Služba automatického vyplňování - Automatické vyplňování pro položky TOTP. To může způsobit, že se toto okno zobrazí, když otevřete položku s TOTP.</string>
|
||||
<string name="switch_keyboard_inside_kp2a_enabled">Poznámka: V aplikaci Keepass2Android jste povolili možnost Aplikace - Zabezpečení - Použít vestavěnou klávesnici. To může způsobit, že se toto okno zobrazí při otevření aplikace nebo úpravě položky.</string>
|
||||
<string name="switch_keyboard_on_search_enabled">Poznámka: Máte povoleno Aplikace - Zabezpečení - Přístup k heslu - Přepínání klávesnice - Přepínání klávesnice. To může způsobit, že se toto okno zobrazí při vyhledávání položky z prohlížeče.</string>
|
||||
</resources>
|
||||
|
@@ -164,7 +164,7 @@ Der Android Robot wird genutzt und wurde modifiziert basierend auf Arbeiten, die
|
||||
<string name="invalid_db_sig">Datenbank-Format wurde nicht erkannt.</string>
|
||||
<string name="keyfile_does_not_exist">Schlüssel-Datei existiert nicht.</string>
|
||||
<string name="no_keyfile_selected">Keine Schlüsseldatei ausgewählt.</string>
|
||||
<string name="keyfile_is_empty">Schlüssel-Datei ist leer.</string>
|
||||
<string name="keyfile_is_empty">Schlüsseldatei ist leer.</string>
|
||||
<string name="length">Länge</string>
|
||||
<string name="list_size_title">Größe der Gruppenliste</string>
|
||||
<string name="list_size_summary">Schriftgröße in der Gruppenliste</string>
|
||||
@@ -378,7 +378,7 @@ Der Android Robot wird genutzt und wurde modifiziert basierend auf Arbeiten, die
|
||||
<string name="ActivateSearchViewOnStart_summary">Aktiviert das Suchfeld in der Gruppenansicht nach dem Entsperren oder wenn ein Eintrag gesucht wird.</string>
|
||||
<string name="NoDonateOption_title">Spenden-Option ausblenden</string>
|
||||
<string name="NoDonateOption_summary">Diese Einstellung ist ein Dankeschön an alle, die gespendet haben. Sie steht erst nach einer gewissen Zeit der Benutzung von Keepass2Android zur Verfügung.</string>
|
||||
<string name="NoDonateOption_question">Ohne Spenden gäbe es diese App nicht und sie könnte nicht ständig verbessert werden! Wenn Sie noch nicht gespendet haben, sollten Sie dies jetzt in Betracht ziehen.</string>
|
||||
<string name="NoDonateOption_question">Ohne Spenden würde diese App nicht existieren und ständig verbessert werden! Wenn du noch nicht gespendet hast, erwäge bitte, dies jetzt zu tun</string>
|
||||
<string name="NoDonationReminder_title">Nie um eine Spende bitten</string>
|
||||
<string name="NoDonationReminder_summary">Ich werde keinen Cent spenden oder habe bereits gespendet. Bitte niemals um eine Spende, nicht einmal am Geburtstag des Autors.</string>
|
||||
<string name="UseOfflineCache_title">Datenbank-Caching</string>
|
||||
@@ -642,7 +642,7 @@ Der Android Robot wird genutzt und wurde modifiziert basierend auf Arbeiten, die
|
||||
<string name="FileReadOnlyTitle">Datenbank ist schreibgeschützt</string>
|
||||
<string name="FileReadOnlyMessagePre">Keepass2Android hat die aktuelle Datenbank im schreibgeschützten Modus geöffnet.</string>
|
||||
<string name="ReadOnlyReason_PreKitKat">Es scheint, dass die Datei von einer externen Anwendung aus geöffnet wurde. Über diesen Weg ist das Schreiben nicht möglich. Wenn Änderungen an der Datenbank vorgenommen werden sollen, bitte die Datenbank schließen und „Datenbank wechseln“ wählen. Danach die Datei über eine der verfügbaren Optionen öffnen, sofern möglich.</string>
|
||||
<string name="ReadOnlyReason_ReadOnlyFlag">Datei ist schreibgeschützt. Diese Attribut entfernen, wenn Änderungen an der Datenbank vorgenommen werden sollen.</string>
|
||||
<string name="ReadOnlyReason_ReadOnlyFlag">Datei ist schreibgeschützt. Dieses Attribut entfernen, wenn Änderungen an der Datenbank vorgenommen werden sollen.</string>
|
||||
<string name="ReadOnlyReason_ReadOnlyKitKat">Das Speichern ist aufgrund von Einschränkungen, die in Android KitKat eingeführt wurden, nicht möglich. Wenn Änderungen an der Datenbank vorgenommen werden sollen, bitte die Datenbank schließen und „Datenbank wechseln“ wählen. Danach die Datei über die systeminterne Dateiauswahl öffnen.</string>
|
||||
<string name="ReadOnlyReason_LocalBackup">Lokale Sicherungskopien können nicht bearbeitet werden. Du kannst über \"Datenbank-Einstellungen\" - \"Datenbank exportieren\" dieses Backup an einen anderen Ort exportieren und dann von dort öffnen. Dann kannst du auch wieder Änderungen vornehmen.</string>
|
||||
<string name="AddCustomIcon">Icon aus Datei hinzufügen...</string>
|
||||
@@ -716,6 +716,20 @@ Anbei einige Tipps, die bei der Diagnose des Problems helfen können:\n
|
||||
<string name="EntryChannel_desc">Benachrichtigung zum schnellen Zugriff auf den aktuell gewählten Eintrag.</string>
|
||||
<string name="CloseDbAfterFailedAttempts">Datenbank nach drei fehlgeschlagenen biometrischen Entsperrversuchen schließen.</string>
|
||||
<string name="WarnFingerprintInvalidated">Achtung! Die biometrische Authentifizierung kann von Android ungültig gemacht werden, z. B. nach dem Hinzufügen eines neuen Fingerabdrucks in den Geräteeinstellungen. Bitte sicherstellen, dass jederzeit klar ist, wie mit dem eigenen Hauptpasswort entsperrt werden kann!</string>
|
||||
<string-array name="ChangeLog_1_12">
|
||||
<item>Von Xamarin Android auf .NET 8 upgegradet</item>
|
||||
<item>Upgrade auf Target-SDK 34</item>
|
||||
<item>Auf MUI 3 upgegradet</item>
|
||||
<item>Verbessertes automatisches Ausfüllen damit Compose-Apps funktionieren</item>
|
||||
<item>Hostnamen-vergleiche im automatischen Ausfüllen und der Suche gefixt</item>
|
||||
<item>Probleme mit dem Passwort Generator behoben</item>
|
||||
</string-array>
|
||||
<string-array name="ChangeLog_1_12_net">
|
||||
<item>OneDrive SDK auf Version 5.68 aktualisiert</item>
|
||||
<item>Dropbox SDK auf Version 7.0.0 aktualisiert</item>
|
||||
<item>Gradle, NewtonsoftJson, FluentFTP, MegaApiClient und okhttp aktualisiert</item>
|
||||
<item>Bugfix in WebDav-Dateiauswahl</item>
|
||||
</string-array>
|
||||
<string-array name="ChangeLog_1_11">
|
||||
<item>Buttons für die Suche und eine TOTP-Übersicht hinzugefügt (falls TOTP-Einträge vorhanden sind)</item>
|
||||
<item>Darstellung von TOTP-Feldern verbessert: Timeout-Anzeige hinzugefügt und besser sichtbar gemacht.</item>
|
||||
@@ -1131,7 +1145,7 @@ Erstes öffentliches Release</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_head">Ist deine Datenbank gesichert?</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>
|
||||
<string name="backup_infotext_note">Um jetzt eine Sicherung zu erstellen, nach %1$s > %2$s > %3$s gehen.</string>
|
||||
<string name="emergency_infotext_head">Hast du für Notfälle vorgesorgt?</string>
|
||||
@@ -1146,5 +1160,7 @@ Erstes öffentliches Release</string>
|
||||
<string name="AutofillWarning_trustAsBrowser">Für „%1$s“ immer akzeptieren</string>
|
||||
<string name="kp2a_switch_on_sendgodone">Tastatur zurückwechseln wenn fertig</string>
|
||||
<string name="kp2a_switch_on_sendgodone_summary">Beim Drücken von Senden/Los/Fertig zurückschalten</string>
|
||||
<string name="qr_scanning_error_no_google_play_services">QR-Code-Scannen erfordert Google Play-Dienste. Bitte installiere oder aktualisiere Google Play-Dienste auf deinem Gerät.</string>
|
||||
<string name="english_ime_settings">Android-Tastatureinstellungen</string>
|
||||
<string name="autoswitch_enabled_but_not_setup">Notiz: Du hast Einstellungen - Anwendung - Passwortzugriff - Wechsel der Eingabemethode - Auto-Umschalten der Tastatur eingeschaltet, aber sieht aus als würde es nicht funktionieren</string>
|
||||
</resources>
|
||||
|
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<resources>
|
||||
<string name="about_feedback">Σχόλια</string>
|
||||
<string name="AboutText">Το KP2A είναι ένας διαχειριστής συνθηματικών, που παρέχει την δυνατότητα ανάγνωσης/εγγραφής σε βάσεις δεδομένων του KeePass 2.x στο Android.</string>
|
||||
<string name="AboutText">Το KP2A είναι ένας διαχειριστής συνθηματικών, που παρέχει δυνατότητα ανάγνωσης / εγγραφής σε βάσεις δεδομένων του KeePass 2.x στο Android.</string>
|
||||
<string name="CreditsText">Το περιβάλλον εργασίας χρήστη βασίζεται σε μια έκδοση του KeepassDroid που αναπτύχθηκε από τον Brian Pellin. Ο κώδικας για τις λειτουργίες της βάσης δεδομένων βασίζεται στο KeePass του Dominik Reichl. Το ρομπότ Android αναπαράγεται ή τροποποιείται από εργασία που δημιουργήθηκε και διαμοιράστηκε από την Google και χρησιμοποιείται σύμφωνα με τους όρους που περιγράφονται στο το Creative Commons 3.0 Attribution License.</string>
|
||||
<string name="CreditsTextSFTP">Το SFTP υποστηρίζεται με χρήση της βιβλιοθήκης JSch με άδεια BSD που δημιουργήθηκε από τη JCraft, Inc.</string>
|
||||
<string name="CreditsIcons">Το εικονίδιο Σφυρί δημιουργήθηκε από τον John Caserta, το εικονίδιο Πιγκουίνος δημιουργήθηκε από τον Adriano Emerick, το εικονίδιο Φτερό δημιουργήθηκε από τον Jon Testa και το εικονίδιο της Apple δημιουργήθηκε από την Ava Rowell. Όλα τα προηγούμενα εικονίδια είναι από το Noun Project. Το εικονίδιο της Εικόνας είναι από το https://icons8.com/icon/5570/Picture.</string>
|
||||
@@ -401,6 +401,14 @@
|
||||
<string name="ShowSeparateNotifications_summary">Εμφάνιση χωριστών ειδοποιήσεων για την αντιγραφή του ονόματος χρήστη και του συνθηματικού στο πρόχειρο και ενεργοποίηση του πληκτρολογίου.</string>
|
||||
<string name="AccServiceAutoFill_prefs">Αυτόματη συμπλήρωση υπηρεσίας προσβασιμότητας</string>
|
||||
<string name="AutoFill_prefs">Λειτουργία αυτόματης συμπλήρωσης</string>
|
||||
<string name="AutoFillTotp_prefs_ShowNotification_summary">Κατά την αυτόματη συμπλήρωση μιας καταχώρισης με TOTP, εμφανίστε την ειδοποίηση με ένα κουμπί Αντιγραφή TOTP</string>
|
||||
<string name="AutoFillTotp_prefs_ShowNotification_title">Εμφάνιση ειδοποίησης καταχώρισης</string>
|
||||
<string name="AutoFillTotp_prefs_title">Αυτόματη συμπλήρωση για καταχωρίσεις TOTP</string>
|
||||
<string name="AutoFillTotp_prefs_CopyTotpToClipboard_title">Αντιγραφή TOTP στο πρόχειρο</string>
|
||||
<string name="AutoFillTotp_prefs_CopyTotpToClipboard_summary">Κατά την αυτόματη συμπλήρωση μιας καταχώρισης με TOTP, αντιγράφει το TOTP στο πρόχειρο</string>
|
||||
<string name="AutoFillTotp_prefs_ActivateKeyboard_summary">Κατά την αυτόματη συμπλήρωση μιας καταχώρισης με TOTP, ενεργοποιήστε το ενσωματωμένο πληκτρολόγιο. Το πληκτρολόγιο έχει ένα κουμπί TOTP.</string>
|
||||
<string name="AutoFillTotp_prefs_ActivateKeyboard_title">Ενεργοποίηση ενσωματωμένου πληκτρολογίου</string>
|
||||
<string name="TotpCopiedToClipboard">Αντιγράφηκε το TOTP στο πρόχειρο</string>
|
||||
<string name="ShowKp2aKeyboardNotification_title">Ειδοποίηση πληκτρολογίου KP2A</string>
|
||||
<string name="ShowKp2aKeyboardNotification_summary">Κάντε προσβάσιμη την πλήρη καταχώριση μέσω του πληκτρολογίου KP2A (συνιστάται).</string>
|
||||
<string name="OpenKp2aKeyboardAutomatically_title">Εναλλαγή πληκτρολογίου</string>
|
||||
@@ -538,6 +546,7 @@
|
||||
<string name="filestoragename_dropboxKP2A">Dropbox (φάκελος KP2A)</string>
|
||||
<string name="filestoragehelp_dropboxKP2A">Αν δεν θέλεις να δώσεις στο Keepass2Android πλήρη πρόσβαση στο Dropbox, μπορείς να διαλέξεις αυτή την επιλογή. Θα ζητήσει πρόσβαση μόνο στο φάκελο Apps/Keepass2Android. Ταιριάζει ειδικά στη δημιουργία νέας βάσης δεδομένων. Αν ήδη έχεις μια βάση δεδομένων, διάλεξε αυτή την επιλογή για να δημιουργήσεις το φάκελο, μετά τοποθέτησε το αρχείο σου μέσα στο φάκελο (από το PC) και μετά διάλεξε αυτή την επιλογή πάλι για να ανοίξεις το αρχείο. </string>
|
||||
<string name="filestoragename_gdrive">Google Drive</string>
|
||||
<string name="filestoragehelp_gdrive">Παρακαλώ σημειώστε: Η Google περιορίζει την πρόσβαση στο Google Drive από εφαρμογές για όλο και περισσότερους χρήστες. Εάν η ενσωματωμένη υλοποίηση του Google Drive δεν λειτουργεί, χρησιμοποιήστε τον επιλογέα αρχείων συστήματος και επιλέξτε το Google Drive εκεί!</string>
|
||||
<string name="filestoragename_gdriveKP2A">Google Drive (αρχεία KP2A)</string>
|
||||
<string name="filestoragehelp_gdriveKP2A">Αν δεν θέλετε να δώσετε πρόσβαση KP2A πρόσβαση σε όλο το Google Drive σας, μπορείτε να επιλέξετε αυτή την επιλογή. Σημειώστε ότι πρέπει να δημιουργήσετε ένα αρχείο βάσης δεδομένων πρώτα - τα υπάρχοντα αρχεία δεν είναι ορατά στην εφαρμογή. Επιλέξτε αυτή την επιλογή από την οθόνη Δημιουργία βάσης δεδομένων ή, αν έχετε ήδη ανοίξει μια βάση δεδομένων, με την εξαγωγή της βάσης δεδομένων επιλέγοντας αυτή την επιλογή.</string>
|
||||
<string name="filestoragename_pcloud">PCloud (φάκελος KP2A)</string>
|
||||
@@ -588,6 +597,7 @@
|
||||
<string name="CouldntLoadChalAuxFile_Hint">Χρησιμοποιήστε το πρόσθετο KeeChallenge σε KeePass 2.x (PC) για να ρυθμίσετε τη βάση δεδομένων για χρήση με Πρόκληση-Απόκριση!</string>
|
||||
<string name="ErrorUpdatingChalAuxFile">Σφάλμα ενημέρωσης βοηθητικού αρχείου OTP!</string>
|
||||
<string name="TrayTotp_SeedField_title">Όνομα πεδίου για seed του TOTP</string>
|
||||
<string name="TOTP">TOTP</string>
|
||||
<string name="TrayTotp_SeedField_summary">Εάν χρησιμοποιείτε το πρόσθετο \"TrayTotp\" του Keepass 2 με μη προεπιλεγμένες ρυθμίσεις, πληκτρολογήστε το όνομα του πεδίου για το πεδίο seed σύμφωνα με τις ρυθμίσεις στον υπολογιστή.</string>
|
||||
<string name="TrayTotp_SettingsField_title">Όνομα πεδίου στις ρυθμίσεις TOTP</string>
|
||||
<string name="TrayTotp_SettingsField_summary">Εισάγετε όνομα πεδίου από ρυθμίσεις TrayTotp.</string>
|
||||
@@ -705,6 +715,33 @@
|
||||
<string name="EntryChannel_desc">Ειδοποίηση για απλοποιημένη πρόσβαση στην τρέχουσα καταχώριση.</string>
|
||||
<string name="CloseDbAfterFailedAttempts">Κλείσιμο της βάσης δεδομένων μετά από 3 ανεπιτυχείς προσπάθειες βιομετρικού ξεκλειδώματος.</string>
|
||||
<string name="WarnFingerprintInvalidated">Προσοχή! Ο βιομετρικός έλεγχος ταυτότητας μπορεί να ακυρωθεί από το Android, π.χ. μετά την προσθήκη ενός νέου δακτυλικού αποτυπώματος στις ρυθμίσεις της συσκευής σας. Βεβαιωθείτε ότι ξέρετε πάντα πώς να ξεκλειδώσετε με τον κύριο κωδικό πρόσβασης!</string>
|
||||
<string-array name="ChangeLog_1_12">
|
||||
<item>Αναβαθμίστηκε από Xamarin Android σε .ΝΕΤ 8</item>
|
||||
<item>Αναβαθμίστηκε στοχεύοντας το SDK 34</item>
|
||||
<item>Αναβαθμίστηκε σε διεπαφή χρήστη Material 3</item>
|
||||
<item>Βελτιώστε την αυτόματη συμπλήρωση για να εργαστείτε με Compose Apps</item>
|
||||
<item>Διόρθωση ονόματος host στην αυτόματη συμπλήρωση και αναζήτηση</item>
|
||||
<item>Διόρθωση προβλήματος με τη γεννήτρια κωδικού πρόσβασης</item>
|
||||
</string-array>
|
||||
<string-array name="ChangeLog_1_12_net">
|
||||
<item>Αναβαθμίστηκε το OneDrive SDK στην έκδοση 5.68</item>
|
||||
<item>Αναβαθμίστηκε το Dropbox SDK στην έκδοση 7.0.0</item>
|
||||
<item>Αναβαθμισμένο Gradle, NewtonsoftJson, FluentFTP, MegaApiClient και okhttp</item>
|
||||
<item>Επιδιόρθωση σφαλμάτων στην επιλογή αρχείου WebDav</item>
|
||||
</string-array>
|
||||
<string-array name="ChangeLog_1_11">
|
||||
<item>Προστέθηκαν τα αιωρούμενα κουμπιά ενεργειών για αναζήτηση και επισκόπηση TOTP (αν υπάρχουν καταχωρήσεις TOTP).</item>
|
||||
<item>Βελτιωμένη εμφάνιση των πεδίων TOTP με την προσθήκη ενός δείκτη χρονικού ορίου και πιο εμφανή εμφάνιση.</item>
|
||||
<item>Το TOTP εμφανίζεται από την προβολή ομάδας.</item>
|
||||
<item>Αντιγραφή τιμής κειμένου στο πρόχειρο με παρατεταμένο πάτημα στην προβολή καταχωρίσεων.</item>
|
||||
<item>Κάντε το TOTP πιο εύκολα προσβάσιμο στο ενσωματωμένο πληκτρολόγιο.</item>
|
||||
<item>Εμφάνιση ειδοποίησης καταχώρησης κατά την αυτόματη συμπλήρωση μιας καταχώρισης TOTP. Επιτρέπει την αντιγραφή του TOTP στο πρόχειρο. Δείτε τις προτιμήσεις για τη ρύθμιση της συμπεριφοράς.</item>
|
||||
<item>Ενημερώθηκε η υλοποίηση του TOTP για την επίλυση προβλημάτων συμβατότητας με το KeePass2 και το TrayTOTP</item>
|
||||
<item>Μικρές βελτιώσεις</item>
|
||||
</string-array>
|
||||
<string-array name="ChangeLog_1_11_net">
|
||||
<item>Ενημέρωση pCloud SDK για να παρέχει πρόσβαση σε κοινόχρηστους φακέλους</item>
|
||||
</string-array>
|
||||
<string-array name="ChangeLog_1_10">
|
||||
<item>Προσθήκη υποστήριξης για δικαιώματα ειδοποίησης στο Android 13+</item>
|
||||
<item>Βελτίωση της υλοποίησης FTP και SFTP</item>
|
||||
@@ -826,8 +863,8 @@
|
||||
</string-array>
|
||||
<string-array name="sftp_auth_modes">
|
||||
<item>Συνθηματικό</item>
|
||||
<item>KP2A Private/Public key</item>
|
||||
<item>Custom Private key</item>
|
||||
<item>Ιδιωτικό / Δημόσιο κλειδί KP2A</item>
|
||||
<item>Προσαρμοσμένο ιδιωτικό κλειδί</item>
|
||||
</string-array>
|
||||
<string-array name="AcceptAllServerCertificates_options">
|
||||
<item>Παράβλεψη αποτυχιών επικύρωσης πιστοποιητικού</item>
|
||||
@@ -845,6 +882,9 @@
|
||||
<string name="autofill_enable_for">Ενεργοποίηση AutoFill για %1$s</string>
|
||||
<string name="invalid_link_association">Δεν σχετίζεται το web domain %1$s με την εφαρμογή %2$s</string>
|
||||
<string name="enable_fingerprint_hint">Το Keepass2Android ανίχνευσε βιομετρικό εξοπλισμό. Θέλετε να ενεργοποιήσετε βιομετρικό ξεκλείδωμα για αυτή τη βάση δεδομένων;</string>
|
||||
<string name="post_notifications_dialog_title">Να επιτρέπονται οι ειδοποιήσεις</string>
|
||||
<string name="post_notifications_dialog_message">Το Keepass2Android μπορεί να εμφανίσει ειδοποιήσεις με κουμπιά για να αντιγράψετε τιμές, όπως κωδικούς πρόσβασης και TOTP στο πρόχειρο, ή για να εμφανιστεί το ενσωματωμένο πληκτρολόγιο. Αυτό είναι χρήσιμο για να μεταφέρετε τιμές σε άλλες εφαρμογές, χωρίς να μεταβείτε σε Keepass2Android επανειλημμένα. Θέλετε να ενεργοποιήσετε αυτές τις ειδοποιήσεις;</string>
|
||||
<string name="post_notifications_dialog_allow">Να επιτρέπονται οι ειδοποιήσεις</string>
|
||||
<string name="post_notifications_dialog_disable">Απενεργοποιήστε αυτό το χαρακτηριστικό</string>
|
||||
<string name="post_notifications_dialog_notnow">Όχι τώρα</string>
|
||||
<string name="understand">Καταλαβαίνω</string>
|
||||
@@ -865,5 +905,8 @@
|
||||
<string name="AutofillWarning_Intro">Πρόκειται να εισάγετε διαπιστευτήρια για τον τομέα \"%1$s\" στην εφαρμογή \"%2$s\".</string>
|
||||
<string name="AutofillWarning_FillDomainInUntrustedApp">Εάν εμπιστεύεστε ότι το \"%2$s\" ανήκει στο \"%1$s\" ή εμπιστεύεστε ότι η εφαρμογή \"%2$s\" δεν καταχράται τα διαπιστευτήρια (πχ. επειδή είναι μια αξιόπιστη εφαρμογή περιήγησης), είναι εντάξει να συνεχίσετε. Αν όχι, ακυρώστε.</string>
|
||||
<string name="AutofillWarning_trustAsBrowser">Αποδοχή πάντα στο \"%1$s\"</string>
|
||||
<string name="kp2a_switch_on_sendgodone">Εναλλαγή μετά την ολοκλήρωση</string>
|
||||
<string name="kp2a_switch_on_sendgodone_summary">Εναλλαγή πίσω όταν πατήσετε αποστολή / λήψη / ολοκλήρωση</string>
|
||||
<string name="qr_scanning_error_no_google_play_services">Η σάρωση QR κώδικα απαιτεί Google Play Services. Παρακαλώ εγκαταστήστε ή ενημερώστε τις Google Play Services στη συσκευή σας.</string>
|
||||
<string name="english_ime_settings">Ρυθμίσεις πληκτρολογίου Android</string>
|
||||
</resources>
|
||||
|
@@ -1178,4 +1178,5 @@
|
||||
<string name="kp2a_switch_on_sendgodone">Volver cuando termine</string>
|
||||
<string name="kp2a_switch_on_sendgodone_summary">Volver cuando se presione enviar/ir/finalizado</string>
|
||||
<string name="english_ime_settings">Ajustes del teclado de Keepass2Android</string>
|
||||
<string name="switch_keyboard_on_search_enabled">Nota: Ha habilitado la aplicación - Seguridad - Acceso a la contraseña - Interruptor de teclado - Cambiar teclado. Esto puede causar que esta ventana se muestre cuando busque una entrada desde el navegador.</string>
|
||||
</resources>
|
||||
|
@@ -546,6 +546,7 @@
|
||||
<string name="filestoragename_dropboxKP2A">Dropbox (dossier KP2A)</string>
|
||||
<string name="filestoragehelp_dropboxKP2A">Si vous ne voulez pas donner l\'accès KP2A à votre espace Dropbox complet, vous pouvez sélectionner cette option. Seul l\'accès au dossier Apps/Keepass2Android sera demandé. Ceci est particulièrement adapté lorsque vous créez une nouvelle base de données. Si vous avez déjà une base de données, cliquez sur cette option pour créer le dossier, puis placez votre fichier dans le dossier (à partir de votre PC) et puis sélectionnez à nouveau cette option pour ouvrir le fichier.</string>
|
||||
<string name="filestoragename_gdrive">Google Drive</string>
|
||||
<string name="filestoragehelp_gdrive">Attention : Google restreint l\'accès à Google Drive depuis les applications pour un nombre grandissant d\'utilisateurs. Si l\'intégration de Google Drive ne fonctionne pas, utilisez plutôt le sélecteur de fichiers système et sélectionnez Google Drive !</string>
|
||||
<string name="filestoragename_gdriveKP2A">Google Drive (fichiers KP2A)</string>
|
||||
<string name="filestoragehelp_gdriveKP2A">Si vous ne voulez pas donner à KP2A un accès complet à Google Drive, vous pouvez sélectionner cette option. Notez que vous devez d\'abord créer un fichier de base de données, les fichiers existants ne sont pas visibles pour l\'application. Choisissez cette option dans l\'écran Créer une base de données ou, si vous avez déjà ouvert une base de données, en exportant la base de données en choisissant cette option.</string>
|
||||
<string name="filestoragename_pcloud">PCloud (dossier KP2A)</string>
|
||||
@@ -723,8 +724,15 @@
|
||||
<item>Mise à niveau de Xamarin Android vers. net 8</item>
|
||||
<item>Mise à niveau vers Target SDK 34</item>
|
||||
<item>Mise à niveau vers l\'interface utilisateur Material 3</item>
|
||||
<item>Improve autofill to work with Compose apps</item>
|
||||
<item>Amélioration de la saisie automatique pour fonctionner avec les applications Compose</item>
|
||||
<item>Fix hostname matching in autofill and search</item>
|
||||
<item>Corriger le problème avec le générateur de mot de passe</item>
|
||||
</string-array>
|
||||
<string-array name="ChangeLog_1_12_net">
|
||||
<item>Mise à jour de OneDrive SDK vers la version 5.68</item>
|
||||
<item>Mise à jour du SDK Dropbox vers la version 7.0.0</item>
|
||||
<item>Mise à jour Gradle, NewtonsoftJson, FluentFTP, MegaApiClient et okhttp</item>
|
||||
<item>Correction de bugs dans la sélection de fichiers WebDav</item>
|
||||
</string-array>
|
||||
<string-array name="ChangeLog_1_11">
|
||||
<item>Ajout de boutons d\'action flottants pour la recherche et l\'aperçu TOTP (si des entrées TOTP sont présentes).</item>
|
||||
@@ -820,6 +828,89 @@
|
||||
* Nouvelle implémentation pour OneDrive : inclut la prise en charge de OneDrive Entreprise, des fichiers partagés, des périmètres d\'accès sélectionnables, des comptes multiples et des corrections de problèmes d\'accès en mode hors-ligne\n
|
||||
* Corrections d\'anomalies
|
||||
</string>
|
||||
<string name="ChangeLog_1_07"> Version 1.07\n
|
||||
* Corrige les crashs sur les Samsung avec Android 9\n
|
||||
* Permet d\'ouvrir plus d\'une base de données, compatible avec KeeAutoExec\n
|
||||
* SFTP : permet l\'authentification avec clé publique, vérifie si la clé de l\'hôte a changé\n
|
||||
* Introduction du support pCloud - merci à gilbsgilbs !\n
|
||||
* Mise en place explicite du support Nextcloud\n
|
||||
* Améliore l\'enregistrement et la mise à jour des pièces jointes des entrées\n
|
||||
* Plus d\'options pour adapter le comportement aux préférences personnelles\n
|
||||
* SSL : acceptation et confiance avec les certificats utilisateur\n
|
||||
* Améliore la saisie automatique (fonctionne maintenant avec Firefox, permet de réduire les popups)\n
|
||||
* Résolution de bugs\n
|
||||
</string>
|
||||
<string name="ChangeLog_1_06">Version 1.06\n
|
||||
* Changement vers ykDroid au lieu de YubiChallenge comme application pour le défi-réponse de Yubikey.\n
|
||||
* implémentation du support de défi-réponse compatible KeepassXC. Note : Le format de base de données doit être KDBX4 !\n
|
||||
* Blocage du chargement de fichiers supprimés depuis Google Drive\n
|
||||
* Changement d\'implémentation TLS pour FTPS, ajout d\'un contournement du bug JSch avec les serveurs compatibles avec gssapi-with-mic\n
|
||||
* Correction de bugs\n </string>
|
||||
<string name="ChangeLog_1_05"> Version 1.05\n * Utilisation des canaux de notification Android 8, ce qui permet la configuration via les paramètres système\n * Affichage de l’icône entrée dans la notification\n * Utilisation d\'icônes adaptatifs pour Android 8, utilisez l\'icône arrondi du lanceur pour Android 7\n * Permet d’activer la recherche au déverrouillage (voir réglages) \n * Modification de comment les fichiers sont écrits en utilisant le framework Storage Access, corrections de problèmes sur les mises à jour des fichiers ouvert sur Google Drive avec le sélecteur du système fichier\n * Ajout de textes d’informations afin d’éviter certaines incompréhensions commune \n * Création de sauvegardes locales pour les bases ouvertes avec succès pour réduire le risque de perte de donnée\n * Mise à jour de JSch pour supporté les derniers chiffrements SSH\n * Permettre la modification des paramètres de connexion, par exemple lorsque le mot de passe WebDav a changé\n * Ajout du support pour mot de passe statique Yubikey Neo\n * Permettre de désactiver les suggestions automatiques\n * Correction des fuites de données vers logcat\n * Corrections d\'anomalies\n
|
||||
</string>
|
||||
<string name="ChangeLog_1_04b"> Version 1.04b\n * Évite les plantages lorsque l’utilisateur essaie d’activer la fonctionnalité de remplissage automatique sur les appareils Huawei.\n
|
||||
</string>
|
||||
<string name="ChangeLog_1_04">Version 1.04
|
||||
* Ajout du service de saisie automatique pour Android 8.0 et plus.
|
||||
* Mise à niveau des librairies, des outils de build et de la version du sdk cible
|
||||
</string>
|
||||
<string name="ChangeLog_1_03">Version 1.03
|
||||
* Suppression du service d\'accessibilité pour le remplissage automatique tel que demandé par Google. Voir les paramètres d’accès mot de passe pour trouver un plugin reproduisant la fonctionnalité précédente.
|
||||
* Ajout d\'applications tierces comme option de stockage
|
||||
* Visionneuse intégrée pour le voir des images jointes sans les transférer sur d’autres applications
|
||||
* OkHttp mis à jour pour résoudre certains problèmes de connexion
|
||||
* Support des entrées de KeeTrayTOTP, supporte désormais les entrées Steam</string>
|
||||
<string name="ChangeLog_1_02"> Version 1.02\n
|
||||
* Quelques améliorations liées à la sécurité. Merci beaucoup pour le rapport jean-baptiste.cayrou@thalesgroup.com et vincent.fargues@thalesgroup.com et aussi pour votre collaboration !\n
|
||||
* Support de KeyboardSwapPlugin (voir les paramètres d\'accès aux mots de passe) : permet de changer de méthode de saisie automatiquement sur les appareils sans « root ». Merci à Mishaal Rahman d\'XDA-Developers de l\'avoir rendu possible.\n
|
||||
* Correction pour les services d’accessibilité avec les versions récentes de Chrome\n
|
||||
* Correction pour les nettoyages non nécessaires des données d\'empreintes digitales\n
|
||||
* Correction de plantages mineurs\n
|
||||
* Mise à jour du kit de développement Dropbox pour s\'assurer de la compatibilité future\n
|
||||
* Suppression des rapports d\'erreur en utilisant Xamarin Insights\n
|
||||
* Mise à jour des outils de compilation\n
|
||||
</string>
|
||||
<string name="ChangeLog_1_01g"> Version 1. 1-g\n
|
||||
* Correction pour un plantage lorsque vous essayez de travailler hors ligne\n
|
||||
* Correction pour un codage incorrect des identifiants FTP(S)\n
|
||||
* Correction pour les plantages lors de l\'utilisation de OneDrive et des anciennes versions d\'Android\n
|
||||
* Affiche les temps en temps local dans l\'écran d\'entrée\n
|
||||
</string>
|
||||
<string name="ChangeLog_1_01d">Version 1.01-d\n * Correction pour le listing des fichiers OneDrive\n * Possibilité d’ignorer les erreurs de certificat lorsque la vérification du nom de l’hôte échoue (non recommandé pour une utilisation en production) \n * Correction pour QuickUnlock qui parfois ne fonctionnait malgré la saisie correcte du code\n </string>
|
||||
<string name="ChangeLog_0_9_8c">Version 0.9.8c\n
|
||||
* Correctif pour la vulnérabilité SSL dans Microsoft Live SDK (utilisé lorsque vous accédez à des fichiers via OneDrive)\n
|
||||
* Bug fix : la version précédente contenait deux méthodes de saisie (l\'une des deux plante)\n </string>
|
||||
<string name="ChangeLog_1_01">Version 1.01\n * Ajout du support pour le nouveau format KDBX-4 (compatible avec Keepass 2.35) y compris la dérivation de clés Argon2 et ChaCha20 cryptage.\n * Nouvelle implémentation du stockage WebDav, il est maintenant possible de parcourir les fichiers et le stockage prend en charge un chiffrement moderne.\n * Nouvelle implémentation du stockage FTP qui permet maintenant de parcourir les fichiers et de prendre en charge le cryptage (FTPS).\n * Mise à jour du SDK OneDrive (le SDK Live précédemment utilisé n’est plus mis à jour).\n * Mise à jour du SDK Dropbox vers la version 2 (la version 1 n\'est plus supportée).\n * Ajout du support pour OwnCloud.\n *Demande d’autorisation de stockage avant d’ouvrir les fichiers locaux. </string>
|
||||
<string name="ChangeLog_1_0_0e">Version 1.0.0e\n
|
||||
* Règle un problème avec le scaneur d\'empreintes digitales sur les anciens appareils Samsung tournant avec Android 6.\n
|
||||
* Ajout d\'un support natif pour les processeurs x86.\n
|
||||
* Permet d\'afficher ou cacher les caractères dans les champs texte de saisie si le scanner d\'empreinte digital a été activé. \n
|
||||
* Construction de mise à jour système </string>
|
||||
<string name="ChangeLog_1_0_0">Version 1.0.0\n * Déverrouiller par empreinte digitale (nécessite Android 6.0+ ou un appareil Samsung)\n * Ajout du service de saisie automatique (nécessite Android 5.0+)\n * Ajout du support pour l\'entrée templates\n * Ajout d\'un mode \"hors connexion\"\n * Possibilité de copier les entrées\n * Mode semi-automatique pour les champs noms\n * Possibilité de supprimer des éléments de liste des fichiers récents\n * Demande des autorisations à l\'exécution pour Android 6.0\n * Corrections de bugs (dans le clavier intégré, lorsque vous sélectionnez les icônes)\n * Ajout d\'une option pour envoyer des rapports d\'erreur\n * Ajouts de plusieurs messages d\'aide\n </string>
|
||||
<string name="ChangeLog_0_9_9">Version 0.9.9\n
|
||||
* Refonte complète de l\'interface utilisateur. Merci beaucoup à Stefano Pignataro (http://www.spstudio.at) pour son aide!\n
|
||||
* Permet l\'ajout d\'icônes personnalisées\n
|
||||
* Support pour l\'affichage fractionné sur les appareils Samsung\n
|
||||
* Nombre de rotation par défaut pour le chiffrement de nouvelle base de données\n
|
||||
* Vérification des clés dupliquées des champs supplémentaires pour éviter la perte de données\n
|
||||
</string>
|
||||
<string name="ChangeLog_0_9_9c"> Version 0.9.9c
|
||||
* Retour du thème sombre
|
||||
* Vous pouvez installer d\'autres pack d\'icones (Icones Windows ancien sont disponibles sur le Play Store)
|
||||
* Ajout d\'une confirmation lors d\'une suppression d\'éléments sans passer par la corbeille
|
||||
* Correction de bugs (mauvais affichage de l\'encodage secret OTP, mauvaise icone de l\'application dans certains endroits)
|
||||
</string>
|
||||
<string name="ChangeLog_0_9_8b">Version 0.9.8b\n
|
||||
* corrections de bugs (Sauvegarde a échoué pour certaines bases, exporter vers le périphérique local ne fonctionne pas, sélectionner certaines options de préférence crash l\'app)\n</string>
|
||||
<string name="ChangeLog_0_9_8">Version 0.9.8\n
|
||||
* Support du Storage Access Framework (permet l\'écriture sur carte SD et Google Drive dans KP2A Offline)\n
|
||||
* Essai de détecter les erreurs de saisie dans les URL WebDAV (répertoire au lieu du fichier)\n
|
||||
* Police de mot de passe modifié\n
|
||||
* Autorise le changement de compte Dropbox\n
|
||||
* correction de bug: maintenant se souvient du mot de passe OTP\n</string>
|
||||
<string name="ChangeLog_0_9_7b">Version 0.9.7b\n
|
||||
* traductions actualisées\n
|
||||
* corrections de bugs : polices de mot de passe était manquant dans 0.9.7, trie par nom ne trie pas les groupes\n</string>
|
||||
<string name="ChangeLog_keptDonate">Possibilité élargie de faire un don d\'une bière ou autre chose</string>
|
||||
<string-array name="clipboard_timeout_options">
|
||||
<item>30 secondes</item>
|
||||
@@ -911,5 +1002,10 @@
|
||||
<string name="AutofillWarning_Intro">Vous êtes sur le point d\'insérer des identifiants pour le domaine \"%1$s\" dans l\'application \"%2$s\".</string>
|
||||
<string name="AutofillWarning_FillDomainInUntrustedApp">Si vous faites confiance à \"%2$s\" pour appartenir à \"%1$s\" ou que vous faites confiance à l\'application \"%2$s\" pour ne pas abuser des identifiants (ex. parce que c\'est une application de navigateur de confiance), il est possible de continuer. Si ce n\'est pas le cas, veuillez annuler.</string>
|
||||
<string name="AutofillWarning_trustAsBrowser">Accepter toujours dans \"%1$s\"</string>
|
||||
<string name="qr_scanning_error_no_google_play_services">Le scan de QR Code requiert les Services Google Play. Veuillez installer ou mettre à jour les Services Google Play sur votre périphérique.</string>
|
||||
<string name="english_ime_settings">Paramètres du clavier Keepass2Android</string>
|
||||
<string name="autoswitch_enabled_but_not_setup">Note : Vous avez activé le changement automatique de clavier, mais il ne semble pas être correctement configuré (Paramètres - Appli - Accès aux mots de passe - Changement de clavier).</string>
|
||||
<string name="switch_keyboard_for_totp_enabled">Note : Vous avez activé le remplissage automatique des entrées TOTP. Cela peut entrainer l\'apparition de cette fenêtre lorsque vous ouvrez une entrée avec un TOTP (Paramètres - Appli - Accès aux mots de passe - Service de saisie automatique).</string>
|
||||
<string name="switch_keyboard_inside_kp2a_enabled">Note : Vous avez activé le clavier intégré dans Keepass2Android. Cela peut faire apparaitre cette fenêtre quand vous ouvrez l\'application, ou que vous éditez une entrée (Paramètres - Appli - Sécurité).</string>
|
||||
<string name="switch_keyboard_on_search_enabled">Note : Vous avez activé le changement de clavier. Cela peut faire apparaitre cette fenêtre lorsque vous recherchez une entrée depuis le navigateur (Paramètres - Appli - Accès aux mots de passe - Changement de clavier).</string>
|
||||
</resources>
|
||||
|
@@ -151,6 +151,7 @@
|
||||
<string name="hint_keyfile">kulcsfájl</string>
|
||||
<string name="hint_length">hosszúság</string>
|
||||
<string name="hint_pass">jelszó</string>
|
||||
<string name="hint_keyfile_path">SSH privátkulcs elérési útvonala</string>
|
||||
<string name="hint_login_pass">Jelszó</string>
|
||||
<string name="hint_title">név</string>
|
||||
<string name="hint_url">URL</string>
|
||||
@@ -400,6 +401,14 @@
|
||||
<string name="ShowSeparateNotifications_summary">Külön értesítés jelenjen meg a felhasználónév és a jelszó vágólapra másolásáról és a billentyűzet aktiválásáról.</string>
|
||||
<string name="AccServiceAutoFill_prefs">Automatikus kitöltés akadálymentesítési szolgáltatás</string>
|
||||
<string name="AutoFill_prefs">Automatikus kitöltés szolgáltatás</string>
|
||||
<string name="AutoFillTotp_prefs_ShowNotification_summary">Egy bejegyzés TOTP-vel való kitöltésekor értesítés megjelenítése, TOTP másolása gombbal</string>
|
||||
<string name="AutoFillTotp_prefs_ShowNotification_title">Értesítés megjelenítése</string>
|
||||
<string name="AutoFillTotp_prefs_title">Automatikus kitöltés TOTP bejegyzésekhez</string>
|
||||
<string name="AutoFillTotp_prefs_CopyTotpToClipboard_title">TOTP másolása a vágólapra</string>
|
||||
<string name="AutoFillTotp_prefs_CopyTotpToClipboard_summary">Egy bejegyzés TOTP-vel való kitöltésekor a TOTP másolása a vágólapra</string>
|
||||
<string name="AutoFillTotp_prefs_ActivateKeyboard_summary">Egy bejegyzés TOTP-vel való kitöltésekor aktiválódjon a beépített billentyűzet</string>
|
||||
<string name="AutoFillTotp_prefs_ActivateKeyboard_title"> A beépített billentyűzet aktiválása</string>
|
||||
<string name="TotpCopiedToClipboard">TOTP a vágólapra másolva</string>
|
||||
<string name="ShowKp2aKeyboardNotification_title">KP2A billentyűzet</string>
|
||||
<string name="ShowKp2aKeyboardNotification_summary">A teljes bejegyzés elérhetővé tétele a KP2A billentyűzet segítségével (ajánlott).</string>
|
||||
<string name="OpenKp2aKeyboardAutomatically_title">Billentyűzetváltás</string>
|
||||
@@ -416,6 +425,7 @@
|
||||
<string name="ShowUnlockedNotification_summary">Egy értesítési ikon megjelenítése, amíg az adatbázis hozzáférhető.</string>
|
||||
<string name="IconVisibilityInfo_Android8_text">Az Android 8 bevezetett egy új működési módot az értesítésekhez. Ha el akarja rejteni a Keepass2Android értesítési ikonját, kérjük, ezt a rendszerbeállításokban tegye meg. Állítsa az értesítési kategória fontosságát minimumra.</string>
|
||||
<string name="IconVisibilityInfo_Android8_btnSettings">Beállítások megnyitása</string>
|
||||
<string name="PostNotificationsPermissionInfo_text">A Keepass2Android képes rendszerértesítést megjeleníteni, amíg az adatbázis nincs lezárva. Hogy ez működjön, kérjük, adja meg az engedélyt.</string>
|
||||
<string name="DontCare">Nem érdekel</string>
|
||||
<string name="DocumentAccessRevoked">A fájl már nem elérhető a Keepass2Android által. Vagy el lett távolítva, vagy a hozzáférési jogosultságok vissza lettek vonva. Kérjük használja a Fájl újra megnyitását, pl. az adatbázis-váltást használva.</string>
|
||||
<string name="PreloadDatabaseEnabled_title">Adatbázisok előrehozott betöltése</string>
|
||||
@@ -500,9 +510,27 @@
|
||||
<string name="hint_sftp_host">szerver (pl. 192.168.0.1)</string>
|
||||
<string name="hint_sftp_port">port</string>
|
||||
<string name="initial_directory">Kezdőkönyvtár (opcionális):</string>
|
||||
<string name="connect_timeout">Kapcsolódás időkorlátja, másodpercben (opcionális)</string>
|
||||
<string name="enter_sftp_login_title">SFTP tárhely adatai:</string>
|
||||
<string name="sftp_auth_mode">Hitelesítési mód</string>
|
||||
<string name="send_public_key">A nyilvános kulcs küldése...</string>
|
||||
<string name="select_private_keyfile">Privátkulcs kiválasztása</string>
|
||||
<string name="hint_sftp_key_name">Új kulcs neve</string>
|
||||
<string name="hint_sftp_key_content">Új kulcs tartalma</string>
|
||||
<string name="private_key_saved">Privátkulcs elmentve</string>
|
||||
<string name="private_key_save_failed">A privátkulcs mentése nem sikerült: %1$s</string>
|
||||
<string name="private_key_info">Adja meg az elmentendő kulcs nevét és tartalmát</string>
|
||||
<string name="private_key_delete">A privát kulcs törölve: %1$s</string>
|
||||
<string name="private_key_delete_failed">A privát kulcs törlése sikertelen: %1$s</string>
|
||||
<string name="save_key">Privát kulcs mentése</string>
|
||||
<string name="delete_key">Privát kulcs törlése</string>
|
||||
<string name="private_key_select">Privát kulcs kiválasztása</string>
|
||||
<string name="private_key_create_new">[Új hozzáadása...]</string>
|
||||
<string name="hint_sftp_key_passphrase">Kulcshoz tartozó jelmondata</string>
|
||||
<string name="sftp_kex_title">Kulcscsere (KEX) algoritmus (opcionális)</string>
|
||||
<string name="hint_sftp_kex">Nevek/specifikációk, vesszővel elválasztva</string>
|
||||
<string name="sftp_shk_title">Szerverazonosításhoz használt kulcs algoritmusa(i) (opcionális)</string>
|
||||
<string name="hint_sftp_shk">Nevek/specifikációk, vesszővel elválasztva</string>
|
||||
<string name="enter_ftp_login_title">Adja meg az FTP bejelentkezési adatait:</string>
|
||||
<string name="enter_mega_login_title">Adja meg a MEGA fiókjának belépési adatait:</string>
|
||||
<string name="select_storage_type">Tárolási típus kiválasztása:</string>
|
||||
@@ -518,9 +546,12 @@
|
||||
<string name="filestoragename_dropboxKP2A">Dropbox (KPA2 mappa)</string>
|
||||
<string name="filestoragehelp_dropboxKP2A">Válassza ezt az opciót, ha nem akarja, hogy a KP2A a teljes Dropbox tárhelyhez hozzáférjen. A KP2A csak az Apps/Keepass2Android könyvtárhoz fog hozzáférést igényelni. Ha már meglévő, de máshol tárolt adatbázist kíván ilyen módon elérni, akkor válassza ezt az opciót a könyvtár létrehozásához, majd helyezze át az adatbázisfájlt a létrehozott könyvtárba (például egy PC-ről), majd válassza még egyszer ezt az opciót a fájl megnyitásához.</string>
|
||||
<string name="filestoragename_gdrive">Google Drive</string>
|
||||
<string name="filestoragehelp_gdrive">Figyelem! A Google egyre több felhasználó számára korlátozza a Google Drive-hoz való hozzáférést az alkalmazásokból. Ha a beépített Google Drive implementáció nem működik, kérjük, használja helyette a Alapértelmezett fájlválasztót és válassza ott a Google Drive-ot!</string>
|
||||
<string name="filestoragename_gdriveKP2A">Google Drive (KP2A fájlok)</string>
|
||||
<string name="filestoragehelp_gdriveKP2A">Válassza ezt az opciót, ha nem akarja, hogy a KP2A a teljes Google Drive-hoz hozzáférjen. Fontos, hogy először egy új adatbázist kell létrehoznia, a korábban létrehozott fájlokat az alkalmazás nem fogja látni. Vagy válassza ezt az opciót az Új adatbázis létrehozása képernyőn, vagy, ha már létezik az opció, exportálja azt ennek ezzel az opcióval.</string>
|
||||
<string name="filestoragename_pcloud">PCloud (KP2A folder)</string>
|
||||
<string name="filestoragehelp_pcloud">Ez a tárhelytípus csak az \"Applications/Keepass2Android\" mappához igényel hozzáférést. Ahhoz, hogy a PCloud tárhelyed egy meglévő adatbázisát használd, azt ebben az mappában kell elhelyezned.</string>
|
||||
<string name="filestoragename_pcloudall">PCloud (teljes hozzáférés)</string>
|
||||
<string name="filestoragename_onedrive">OneDrive</string>
|
||||
<string name="filestoragename_onedrive2">OneDrive</string>
|
||||
<string name="filestoragename_onedrive2_full">Az összes fájl és a megosztott fájlok</string>
|
||||
@@ -567,12 +598,14 @@
|
||||
<string name="CouldntLoadChalAuxFile_Hint">Kérjük, konfigurálja az adatbázist hitelesítő kérdés-válasszal való használthoz a KeePass 2.x (PC-s verzió) KeeChallenge beépülő modulja segítségével.</string>
|
||||
<string name="ErrorUpdatingChalAuxFile">OTP kiegészítő fájl frissítése közben hiba történt!</string>
|
||||
<string name="TrayTotp_SeedField_title">TOTP mezőnév</string>
|
||||
<string name="TOTP">Idő alapú egyszer használatos jelszó (TOTP)</string>
|
||||
<string name="TrayTotp_SeedField_summary">Ha a \"TrayTotp\" beépülő-modult nem alapértelmezett beállításokkal használja, adja meg annak a mezőnek a nevét, amit a jelszógenerálásnál használni kell (megegyezően a PC-n használt beállítással).</string>
|
||||
<string name="TrayTotp_SettingsField_title">TOTP beállítások mező</string>
|
||||
<string name="TrayTotp_SettingsField_summary">Adja meg a TrayTotp beállítások mezőjének nevét.</string>
|
||||
<string name="TrayTotp_prefs">TrayTotp</string>
|
||||
<string name="DebugLog_prefs_prefs">Naplófájl a hibakereséshez</string>
|
||||
<string name="DebugLog_title">Naplófájl használata</string>
|
||||
<string name="FtpDebug_title">FTP/SFTP naplózása</string>
|
||||
<string name="DebugLog_summary">Az alkalmazás kimenetének egy helyi naplófájlba írása</string>
|
||||
<string name="DebugLog_send">Hibakeresési naplóbejegyzések küldése...</string>
|
||||
<string name="loading">Töltés...</string>
|
||||
@@ -641,6 +674,21 @@
|
||||
<string name="Continue">Folytatás</string>
|
||||
<string name="NoFilenameWarning">A megadott URI nem tűnik fájlnévnek. Biztos benne, hogy jó URI-t adott meg?</string>
|
||||
<string name="FirstInvalidCompositeKeyError">Az összetett kulcs érvénytelen! Próbálkozzon újra.</string>
|
||||
<string name="RepeatedInvalidCompositeKeyHelp">Az összetett kulcs érvénytelen! Kérjük, próbálja meg a következő lépésekkel feloldani az adatbázisát:\n
|
||||
|
||||
- Győződjön meg róla, hogy helyesen adta meg a jelszót. Használja a szem ikont a beírt jelszó felfedéséhez.\n
|
||||
- Győződjön meg róla, hogy a megfelelő jelszótípust választotta ki. Győződjön meg róla, hogy ez megegyezik az adatbázis létrehozásakor használt típussal.\n
|
||||
- Győződjön meg róla, hogy a megfelelő adatbázisfájlt választotta ki.</string>
|
||||
<string name="HintLocalBackupInvalidCompositeKey"> \n
|
||||
- Tipp: Ha úgy gondolja, hogy az adatbázis-fájlja sérült lehet, vagy nem emlékszik a főkulcsra (jelszó) a módosítás után, akkor a „%1$s” gombra koppintva és a helyi biztonsági mentést kiválasztva próbálkozhat a fájl utolsó sikeresen megnyitott verziójával.</string>
|
||||
<string name="HintLocalBackupOtherError"> \n
|
||||
- Tipp: A Keepass2Android az utolsó sikeresen megnyitott fájlverziót a belső tárhelyen tárolja. Megnyithatja azt a „%1$s” koppintással és a helyi biztonsági mentés kiválasztásával.</string>
|
||||
<string name="CorruptDatabaseHelp">A fájl sérült. \n
|
||||
Néhány tipp, amely segíthet a probléma diagnosztizálásában:\n
|
||||
|
||||
- Ha a fájlt USB-n keresztül másolta (MTP-mód), próbálja meg újra egy olyan eszközzel, mint a MyPhoneExplorer. Az MTP bizonyos esetekben csonkítja a fájlokat.\n
|
||||
- Ha nem tudja megnyitni a fájlt ugyanarról a helyről a számítógépéről sem, akkor nagyon valószínű, hogy a fájl valóban sérült. Kérjük, ekkor használja az adatbázis egy biztonsági mentését. Ha feltételezi, hogy a Keepass2Android okozta a sérülést, kérjük, lépjen kapcsolatba a támogatói csapatot.\n
|
||||
- Ha még meg tudja nyitni a fájlt a számítógépén, kérjük, lépjen kapcsolatba a támogatói csapattal. Megpróbálhatja más beállításokkal elmenteni a számítógépen (például tömörítetlenül), és azt megnyitni a Keepass2Androidban.</string>
|
||||
<string name="open_other_db">Egy másik adatbázis megnyitása…</string>
|
||||
<string name="select_database">Adatbázis kiválasztása</string>
|
||||
<string name="configure_child_dbs">Csatolt adatbázisok konfigurálása…</string>
|
||||
@@ -729,8 +777,8 @@
|
||||
</string-array>
|
||||
<string-array name="sftp_auth_modes">
|
||||
<item>Jelszó</item>
|
||||
<item>KP2A Private/Public key</item>
|
||||
<item>Custom Private key</item>
|
||||
<item>KP2A privát/publikus kulcs</item>
|
||||
<item>Egyedi privát kulcs</item>
|
||||
</string-array>
|
||||
<string-array name="AcceptAllServerCertificates_options">
|
||||
<item>Továbblépés, figyelmeztetés nélkül</item>
|
||||
@@ -748,6 +796,11 @@
|
||||
<string name="autofill_enable_for">Az automatikus kitöltés engedélyezése %1$s esetén</string>
|
||||
<string name="invalid_link_association">Nem sikerült összerendelni a %1$s internettartományt a %2$s alkalmazással</string>
|
||||
<string name="enable_fingerprint_hint">Biometrikus eszköz detektálva. Szeretné engedélyezni az adatbázis biometrikus feloldását?</string>
|
||||
<string name="post_notifications_dialog_title">Értesítések engedélyezése</string>
|
||||
<string name="post_notifications_dialog_message">A Keepass2Android képes értesítéseket megjeleníteni, ami lehetővé teszi, hogy többször vagy egyszer használatos jelszavakat másoljon a vágólapra, vagy aktiválja a beépített billentyűzetet. Ez hasznos többféle érték más alkalmazásokba történő átviteléhez, úgy, hogy ne kelljen többször is alkalmazást váltani. Szeretné engedélyezni az ilyen értesítéseket?</string>
|
||||
<string name="post_notifications_dialog_allow">Értesítések engedélyezése</string>
|
||||
<string name="post_notifications_dialog_disable">A lehetőség kikapcsolása</string>
|
||||
<string name="post_notifications_dialog_notnow">Ne most</string>
|
||||
<string name="understand">Értem</string>
|
||||
<string name="dont_show_again">Ne mutassa többet</string>
|
||||
<string name="masterkey_infotext_head">Emlékszik a főkulcsra (jelszó)?</string>
|
||||
@@ -766,5 +819,8 @@
|
||||
<string name="AutofillWarning_Intro">A(z) \"%1$s\" tartományhoz tartozó azonosítókat készül a(z) \"%2$s\" alkalmazás számára elérhetővé tenni.</string>
|
||||
<string name="AutofillWarning_FillDomainInUntrustedApp">Ha megbízik abban, hogy a(z) \"%1$s\" tartomány a(z) \"%2$s\" alkalmazáshoz tartozik, vagy megbízik abban, hogy az alkalmazás nem él vissza a titkos adatokkal (mert például egy megbízható böngészőprogram), folytassa. Ha nem, szakítsa meg a folyamatot.</string>
|
||||
<string name="AutofillWarning_trustAsBrowser">Mindig fogadja el itt: \"%1$s\"</string>
|
||||
<string name="kp2a_switch_on_sendgodone">Visszakapcsolás, ha végzett</string>
|
||||
<string name="kp2a_switch_on_sendgodone_summary">Visszaváltás a Küldés/Ugrás/Kész gombok megnyomásakor</string>
|
||||
<string name="qr_scanning_error_no_google_play_services">A QR-kód beolvasásához szükséges a Google Play Service. Kérjük, telepítse vagy frissítse a szolgáltatást a készülékén.</string>
|
||||
<string name="english_ime_settings">Keepass2Android billentyűzetbeállítások</string>
|
||||
</resources>
|
||||
|
@@ -546,6 +546,7 @@
|
||||
<string name="filestoragename_dropboxKP2A">Dropbox (cartella KP2A)</string>
|
||||
<string name="filestoragehelp_dropboxKP2A">Se non vuoi dare a KP2A accesso completo al tuo Dropbox, puoi selezionare questa opzione. Richiederà solo l\'accesso alla cartella Applicazioni/Keepass2Android. Ciò è particolarmente indicato quando si crea un nuovo database. Se hai già un database, fai click su questa opzione per creare la cartella, poi spostaci dentro il file (dal PC), quindi seleziona di nuovo questa opzione per aprire il file.</string>
|
||||
<string name="filestoragename_gdrive">Google Drive</string>
|
||||
<string name="filestoragehelp_gdrive">Nota: Google sta limitando l\'accesso a Google Drive dalle app per un numero sempre maggiore di utenti. Se la funzione integrata di Google Drive non funziona, si prega di utilizzare il selettore di file di sistema e selezionare Google Drive!</string>
|
||||
<string name="filestoragename_gdriveKP2A">Google Drive (file KP2A)</string>
|
||||
<string name="filestoragehelp_gdriveKP2A">Se non vuoi dare a KP2A accesso completo al tuo Google Drive completo, puoi selezionare questa opzione. Nota che è necessario prima creare un file di database, i file esistenti non sono visibili per l\'app. Scegli questa opzione dalla schermata Crea database o, se hai già aperto un database, esportando il database scegliendo questa opzione.</string>
|
||||
<string name="filestoragename_pcloud">PCloud (KP2A folder)</string>
|
||||
@@ -672,6 +673,22 @@
|
||||
<string name="Continue">Continua</string>
|
||||
<string name="NoFilenameWarning">L\'URI inserito non sembra il nome di un file. Sei sicuro che sia un file valido?</string>
|
||||
<string name="FirstInvalidCompositeKeyError">Chiave composita non valida! Riprova.</string>
|
||||
<string name="RepeatedInvalidCompositeKeyHelp">Chiave composta non valida! Per favore prova la seguente procedura per sbloccare il database: \n
|
||||
|
||||
• assicurati di aver inserito la password corretta. Usa l\'icona che rappresenta un occhio per vedere la password immessa.\n
|
||||
• assicurati di aver selezionato il tipo di password corretto. Assicurati che coincida con il tipo usato quando hai creato il database.\n
|
||||
• assicurati di aver selezionato il file del database corretto.</string>
|
||||
<string name="HintLocalBackupInvalidCompositeKey"> \n
|
||||
• Suggerimento: se pensi che il tuo file di database possa essere danneggiato oppure non ricordi la password principale dopo averla modificata, puoi provare con l\'ultima versione di file aperta correttamente facendo clic su \"%1$s\" e selezionando il backup locale.</string>
|
||||
<string name="HintLocalBackupOtherError"> \n
|
||||
• Suggerimento: Keepass2Android ha archiviato l\'ultima versione del file aperta correttamente nella memoria interna. È possibile aprirla facendo clic su \"%1$s\" e selezionando il backup locale.
|
||||
</string>
|
||||
<string name="CorruptDatabaseHelp">Il file è corrotto.\n
|
||||
Ecco alcuni suggerimenti che ti potrebbero aiutare a diagnosticare il problema:\n
|
||||
|
||||
• se hai copiato il file tramite USB (MTP-Mode), riprova usando uno strumento come MyPhoneExplorer. (MTP a volte tronca i file.)\n
|
||||
• se non puoi aprire il file dallo stesso percorso sul tuo PC, è molto probabile che il file sia effettivamente danneggiato. Per favore usa un backup del database. Se credi che Keepass2Android abbia corrotto il file, contatta il supporto.\n
|
||||
• se puoi ancora aprire il file sul tuo PC, contatta il supporto. Puoi provare a salvarlo con impostazioni differenti (es: non compresso) sul PC e, poi, riprovare ad aprirlo in Keepass2Android. </string>
|
||||
<string name="open_other_db">Apri un altro database…</string>
|
||||
<string name="select_database">Seleziona il database</string>
|
||||
<string name="configure_child_dbs">Configura i database figli…</string>
|
||||
@@ -699,6 +716,20 @@
|
||||
<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_12">
|
||||
<item>Aggiornato da Xamarin Android a .net 8</item>
|
||||
<item>Aggiornato a Target SDK 34</item>
|
||||
<item>Aggiornato all\'interfaccia utente Material 3</item>
|
||||
<item>Migliora l\'autofill per funzionare con le app Compose</item>
|
||||
<item>Corretta la corrispondenza con l\' hostname in riempimento automatico e ricerca</item>
|
||||
<item>Corretto problema con il generatore di password</item>
|
||||
</string-array>
|
||||
<string-array name="ChangeLog_1_12_net">
|
||||
<item>Aggiornato OneDrive SDK alla versione 5.68</item>
|
||||
<item>Aggiornato Dropbox SDK alla versione 7.0.0</item>
|
||||
<item>Aggiornati Gradle , NewtonsoftJson, FluentFTP, MegaApiClient e okhttp</item>
|
||||
<item>Bugfix nella selezione dei file WebDav</item>
|
||||
</string-array>
|
||||
<string-array name="ChangeLog_1_11">
|
||||
<item>Aggiunti pulsanti di azione fluttuanti per la ricerca e TOTP panoramica (se sono presenti voci TOTP).</item>
|
||||
<item>Vista migliorata dei campi TOTP aggiungendo un indicatore di tempo limite e mostrandolo in modo più evidente.</item>
|
||||
@@ -902,7 +933,153 @@
|
||||
* Puoi installare altri pacchetti di icone (le vecchie icone in stile Windows sono disponibili sul Play Store)\n
|
||||
* Aggiunta richiesta di conferma prima di eliminare voci senza passare dal cestino\n
|
||||
* Correzione errori (errata visualizzazione dell\'OTP-secret, icona dell\'app errata in certi posti)\n </string>
|
||||
<string name="ChangeLog_0_9_8b">Versione 0.9.8b\n
|
||||
* correzione di errori (il salvataggio di alcuni database fallisce, l\'esportazione su periferica locale non funziona, la selezione di alcune opzioni manda l\'app in crash)\n</string>
|
||||
<string name="ChangeLog_0_9_8">Versione 0.9.8\n
|
||||
* supporto per Storage Access Framework (permette a KP2A Offline di scrivere su scheda SD e Google Drive)\n
|
||||
* tenta di rilevare errori dell\'utente nell\'inserimento degli URL di WebDAV (cartella al posto di file)\n
|
||||
* cambiato il font della password\n
|
||||
* consente di modificare l\'account di Dropbox\n
|
||||
* bugfix: ora ricorda la password OTP</string>
|
||||
<string name="ChangeLog_0_9_7b">Versione 0.9.7b\n
|
||||
* aggiornate le traduzioni\n
|
||||
* bugfix: font Password mancante nella versione 0.9.7; ordina per nome non ordinava i gruppi\n</string>
|
||||
<string name="ChangeLog_0_9_7"> Versione 0.9.\n
|
||||
* scrivere il supporto per i database di Keepass 1 (kdb) (beta!\n
|
||||
* meglio tornare alla tastiera precedente (funziona anche su dispositivi non rootati)\n
|
||||
* supporto per KeeChallenge con sfide di lunghezza variabile\n
|
||||
* evitare di prendere screenshot dalle schermate di QuickUnlock e password\n
|
||||
* ordine inverso per Ordina per Modifica Data (ora discendente)\n
|
||||
* correzioni di bug: Note ora aggiornate correttamente dopo le modifiche, Viste password ora nascondere correttamente la password su (si spera) tutti i dispositivi, problema fisso che ha permesso di aggiungere una voce due volte, problema fisso con la visualizzazione di un avviso UUID duplicato anche dopo aver risolto il database\n
|
||||
</string>
|
||||
<string name="ChangeLog_0_9_6"> Versione 0.9.\n
|
||||
* consente di importare file chiave e/o file di database locale nella directory interna dell\'app (vedi impostazioni)\n
|
||||
* consente diverse opzioni di ordinamento\n
|
||||
* preferenze migliorate per il cambio automatico della tastiera\n
|
||||
* logo e design di notifica aggiornati, design di Stefano Pignataro (http://www. pstudio. t)\n
|
||||
* generatore di password ricorda le ultime impostazioni\n
|
||||
* imposta visibilità di notifica per Android 5 schermata di blocco\n
|
||||
* ora cancellare il campo password principale quando esce dall\'app senza toccare OK\n
|
||||
* problema fisso con i linguaggi di input mancanti nell\'impostazione della tastiera su alcuni dispositivi\n
|
||||
* problema fisso con l\'accensione automatica della tastiera su dispositivi radicati\n
|
||||
* aggiunto controllo per database corrotti (UUID duplicati)\n
|
||||
* ricaricare automaticamente il database quando è stato rilevato, risolve i timori di sicurezza per la rivelazione della master password\n
|
||||
* migliore lucido piccolo layout della tastiera, tema impostazioni tastiera fissa (grazie a Wiktor Ławski)\n
|
||||
</string>
|
||||
<string name="ChangeLog_0_9_5"><b>Versione 0.9.5</b>\n
|
||||
* corregge i problemi con la navigazione delle cartelle (in particolare su Android 4.4)\n
|
||||
* risolve il problema con il caricamento dei file .kdb (Keepass 1) su Nexus 5 con Android Lollipop\n
|
||||
* aggiunge un\'opzione per impedire la cattura delle schermate e nascondere KP2A dalla lista delle App Recenti\n
|
||||
* risolve il problema con l\'archiviazione su Google Drive (edizione normale)\n
|
||||
* permette i file chiave sui tipi di storage voluti (edizione normale)\n
|
||||
* aggiornato SDK di Dropbox per includere un aggiornamento di sicurezza (edizione normale)\n
|
||||
* aggiornati i tool di sviluppo --> aumentata dimensione apk :-(\n
|
||||
Avevo promesso alcune altre modifiche. Arriveranno con la prossima release - scusate. Ho voluto pubblicare queste correzioni il più presto possibile.</string>
|
||||
<string name="ChangeLog_0_9_4"><b>Versione 0.9.4</b>\n
|
||||
* aggiunto supporto ai plug-in: guarda nelle impostazioni per scoprire come ottenerli!\n
|
||||
* pubblicato QR plug-in (scansiona password, mostra password come QR-code, trasferisci voci ad altri dispositivi KP2A)\n
|
||||
* pubblicato InputStick plug-in (trasferisci credenziali al PC via bluetooth - richiede chiavetta InputStick USB)\n
|
||||
* le applicazioni di terze parti ora possono interrogare facilmente KP2A per ottenere le credenziali. Sei uno sviluppatore? Per favore aggiungi il supporto alle tue applicazioni se ti sembra conveniente!\n
|
||||
* aggiunto supporto a TOTP (compatibile con KeeOTP e TrayTotp)\n
|
||||
* l\'app non dovrebbe più essere chiusa da Android quando il database è aperto\n
|
||||
* il database non viene più chiuso quando si abbandona l\'app tramite il pulsante \"indietro\" (vedi impostazioni)\n
|
||||
* mostra i nomi dei gruppi nei risultati di ricerca (*)\n
|
||||
* aggiungo un menu contestuale nei risultati di ricerca con l\'opzione \"Passa al gruppo superiore\" (*)\n
|
||||
* aggiunta un\'opzione per mostrare, nella visualizzazione di una voce, il nome del gruppo a cui la voce appartiene (*)\n
|
||||
* (*) un grazie a Matthieu per aver implementato queste funzioni!\n
|
||||
* aggiunto supporto a KeeChallenge (con Yubikey NEO). Grazie a Ben Rush per l\'implementazione del connettore!\n
|
||||
* migliorata l\'interfaccia utente\n
|
||||
* corretto un bug nell\'interfaccia di Google Drive\n
|
||||
* aggiunta un\'opzione per disabilitare la funzione \"donazione\"\n
|
||||
* l\'icona QuickUnlock ora è nascosta di default su dispositivi Android 4.2+\n</string>
|
||||
<string name="ChangeLog_0_9_3_r5"><b>Versione 0.9.3 r5</b>\n
|
||||
* Incorporate correzioni da Xamarin: Keepass2Android è ora compatibile con ART su Android 4.4.2. Finalmente!\n
|
||||
* Correzioni di errori: errori in sincronizzazione (aggiornamento visualizzazione, corretto controllo per modifiche in http), errori su dispositivi Android 2.x, errori nelle implementazioni di archiviazione con Google Drive e OneDrive, pulizia degli appunti alla chiusura del database, errori in apertura allegati, problemi di visualizzazione della tastiera\n</string>
|
||||
<string name="ChangeLog_0_9_3"><b>Versione 0.9.3</b>\n
|
||||
* Nuova tastiera con molti miglioramenti. Vedi le Impostazioni.\n
|
||||
* Supporto in sola lettura per file kdb (Keepass 1). Sperimentale!\n
|
||||
* Aggiunto supporto SFTP\n
|
||||
* Aggiunto soluzione temporanea per il bug con ART (Android 4.4.2)\n
|
||||
* Bugfix\n</string>
|
||||
<string name="ChangeLog_0_9_2"><b>Versione 0.9.2</b>\n
|
||||
* Aggiunto supporto OTP (compatibile con il plugin OtpKeyProv)\n
|
||||
* Integrato supporto NFC per le OTP dal NEO YubiKey\n
|
||||
* Aggiornata l\'interfaccia utente\n
|
||||
* Integrata la libreria di Keepass 2.24\n
|
||||
* Aggiunta un\'opzione per terminare il processo dell\'app (vedi le Impostazioni)\n
|
||||
* Migliorata la validazione del certificato SSL\n
|
||||
* Corretti alcuni errori\n</string>
|
||||
<string name="ChangeLog_0_9_1"><b>Versione 0.9.1</b>\n
|
||||
* Aggiunto il supporto per SkyDrive (solo nell\'edizione normale di Keepass2Android)\n
|
||||
* Corretti i problemi di integrazione con Google Drive\n
|
||||
* Aggiunto supporto NTLM</string>
|
||||
<string name="ChangeLog_0_9"><b>Versione 0.9</b> \n
|
||||
* integrato supporto per Dropbox e Google Drive (database in lettura/scrittura; solo per Keepass2Android edizione regolare)\n
|
||||
* integrata la selezione dei file (basata su android-filechooser di HBA)\n
|
||||
* migliorata l\'interfaccia per la creazione di nuovi database\n
|
||||
* incluso il font DejaVu Sans Mono per la visualizzazione passwords\n
|
||||
* corretti alcuni errori</string>
|
||||
<string name="ChangeLog_0_8_6"><b>Versione 0.8.6</b>\n
|
||||
* Supporto per cifratura Twofish\n
|
||||
* Consentita la modifica dei gruppi\n
|
||||
* Consentito lo spostamento di voci e gruppi\n
|
||||
* L\'icona QuickUnlock può essere resa trasparente (vedi le impostazioni)\n
|
||||
* Correzioni di errori</string>
|
||||
<string name="ChangeLog_0_8_5"><b>Versione 0.8.5</b>\n
|
||||
* i file remoti vengono mantenuti nella cache locale dell\'applicazione per permetterne l\'uso offline (compresa la modifica e la successiva sincronizzazione). Vedi le impostazioni. \n
|
||||
* Icona di notifica per visualizzare lo stato del blocco del database (vedi Impostazioni)\n
|
||||
* Migliorato il rilevamento dello stato del blocco del database in alcune circostanze \n
|
||||
* I file dei database vengono caricati in memoria mentre stai digitando la password per aumentare la velocità di caricamento (vedi Impostazioni) \n
|
||||
* Le voci possono essere aggiunte al gruppo principale \n
|
||||
* Correzione di errori (risoluzione campi con riferimenti, problemi con la tastiera su dispositivi italiani e cinesi)</string>
|
||||
<string name="ChangeLog_0_8_4"><b>Versione 0.8.4</b>\n
|
||||
* Le modifiche al database esterno vengono rilevate ed unite durante il salvataggio\n
|
||||
* Migliorate le performance durante il caricamento\n
|
||||
* Migliorata la barra di ricerca con suggerimenti\n
|
||||
* Nuovo logo dell\'App!\n
|
||||
* Aggiunto supporto al formato .kdbp per apertura e salvataggio più veloci\n
|
||||
* Migliorata la modifica delle stringhe aggiuntive e la visualizzazione nascosta quando sono protette\n
|
||||
Grazie ad Alex Vallat per il suo contributo al codice!\n
|
||||
Grazie a Niki Hüttner (www.close-cut.de) per il logo!\n</string>
|
||||
<string name="ChangeLog_0_8_3"><b> Versione 0.8.3 </b>\n
|
||||
* Le voci nome utente e indice TAN vengono visualizzati nella lista delle voci di immissione (vedi le impostazioni)\n
|
||||
* Le voci possono essere create se la ricerca da browser non restituisce alcun risultato\n
|
||||
* La tastiera KP2A offre possibilità di ricercare le credenziali per l\'applicazione attuale\n
|
||||
* L\'applicazione si chiude automaticamente dopo aver selezionato una voce per l\'uso dalla tastiera\n
|
||||
* La finestra di selezione della tastiera si apre automaticamente dopo la ricerca di URL (vedi le impostazioni)\n
|
||||
* I segnaposto nei campi di immissione vengono sostituiti prima della copia (la maggior parte dei segnaposto sono supportati)\n
|
||||
* Correzioni di errori minori </string>
|
||||
<string name="ChangeLog_0_8_2"><b>Versione 0.8.2</b>\n
|
||||
* Supporto per la Digest Authentication in WebDAV\n
|
||||
* Correzione di errori (OI File manager, Open URL)</string>
|
||||
<string name="ChangeLog_0_8_1"><b>Versione 0.8.1</b>\n
|
||||
* KP2A Offline e \"Online\" possono di nuovo essere installati insieme\n
|
||||
* Aggiunte nuove traduzioni (grazie a tutti i collaboratori!)</string>
|
||||
<string name="ChangeLog_0_8"><b>Versione 0.8</b>\n
|
||||
* Migliorata l\'interfaccia utente in particolare per i dispositivi con Android 4.x\n
|
||||
* Consentito l\'utilizzo di gestori di file personali per selezionare file esistenti\n
|
||||
* Aggiunto un modo più sicuro per l\'apertura degli allegati (tramite cartella di cache)\n
|
||||
* sistemati alcuni errori nella finestra di modifica\n
|
||||
* probabilmente aggiunti nuovi errori :-)</string>
|
||||
<string name="ChangeLog_keptDonate">Estesa la possibilità di donare una birra o qualcos\'altro</string>
|
||||
<string name="ChangeLog_0_7"><b>Versione 0.7</b>\n
|
||||
* Aumentata la velocità di caricamento: l\'elaborazione delle chiavi ora è 10 volte più veloce!\n
|
||||
* Aggiunta la tastiera virtuale di Keepass2Android: usa questa tastiera quando inserisci le credenziali. Ti metterà al riparo dagli sniffer delle password basati sugli appunti (disabilita le vecchie notifiche degli appunti nelle impostazioni)\n
|
||||
* Aggiunta l\'opzione per donare una birra o qualcos\'altro (vedi menu)</string>
|
||||
<string name="ChangeLog"><b>Versione 0.6.2</b>\n
|
||||
* Integrazione con Google Drive/Dropbox/... : usa l\'app ufficiale di Google Drive o Dropbox App e apri un qualunque file \".kdbx\". In questo modo si aprirà KP2A.\n
|
||||
* Migliorato il dialogo di ricerca\n
|
||||
* Migliorati i risultati di ricerca per le URL condivise con sottodomini\n
|
||||
* Aggiunte al menu le opzioni per inviare feedback, valutazioni e per tradurre l\'app\n
|
||||
\n
|
||||
<b>Versione 0.6.1</b>\n
|
||||
* Aggiunto il rilevamento di modifiche in background (es.: dovute ad un\'app di sincronizzazione)\n
|
||||
* Migliorata la ricerca delle URL dal browser\n
|
||||
* Aggiunta una richiesta di conferma prima di annullare le modifiche\n
|
||||
\n
|
||||
<b>Versione 0.6</b>\n
|
||||
Prima release pubblica
|
||||
</string>
|
||||
<string-array name="clipboard_timeout_options">
|
||||
<item>30 secondi</item>
|
||||
<item>1 minuto</item>
|
||||
@@ -951,8 +1128,8 @@
|
||||
</string-array>
|
||||
<string-array name="sftp_auth_modes">
|
||||
<item>Password</item>
|
||||
<item>KP2A Private/Public key</item>
|
||||
<item>Custom Private key</item>
|
||||
<item>Chiave privata/pubblica di KP2A</item>
|
||||
<item>Chiave privata personalizzata</item>
|
||||
</string-array>
|
||||
<string-array name="AcceptAllServerCertificates_options">
|
||||
<item>Ignora gli errori di convalida del certificato</item>
|
||||
@@ -970,6 +1147,10 @@
|
||||
<string name="autofill_enable_for">Attiva Compilazione automatica per %1$s</string>
|
||||
<string name="invalid_link_association">Non è possibile associare il dominio web %1$s con l\'app %2$s</string>
|
||||
<string name="enable_fingerprint_hint">Keepass2Android ha rilevato il sensore biometrico. Desideri attivare lo sblocco biometrico per questo database?</string>
|
||||
<string name="post_notifications_dialog_title">Consenti le notifiche</string>
|
||||
<string name="post_notifications_dialog_message">Keepass2Android può mostrare le notifiche con i pulsanti per copiare valori come password e TOTP negli appunti, o per far apparire la tastiera integrata. Questo è utile per trasferire i valori in altre applicazioni senza passare a Keepass2Android ripetutamente. Vuoi abilitare tali notifiche?</string>
|
||||
<string name="post_notifications_dialog_allow">Consenti le notifiche</string>
|
||||
<string name="post_notifications_dialog_disable">Disabilita questa funzione</string>
|
||||
<string name="post_notifications_dialog_notnow">Non ora</string>
|
||||
<string name="understand">Ho capito</string>
|
||||
<string name="dont_show_again">Non mostrare più</string>
|
||||
@@ -989,5 +1170,11 @@
|
||||
<string name="AutofillWarning_Intro">Stai per inserire le credenziali per il dominio \"%1$s\" nell\'app \"%2$s\"</string>
|
||||
<string name="AutofillWarning_FillDomainInUntrustedApp">Se ti fidi di \"%2$s\" ad appartenere a \"%1$s\" o se ti fidi dell\'app \"%2$s\" a non abusare delle credenziali (es. perché si tratta di un\'applicazione sicura), è possibile continuare. Altrimenti si prega di annullare.</string>
|
||||
<string name="AutofillWarning_trustAsBrowser">Accetta sempre in \"%1$s\"</string>
|
||||
<string name="kp2a_switch_on_sendgodone">Cambia tastiera quando terminato</string>
|
||||
<string name="kp2a_switch_on_sendgodone_summary">Torna indietro quando premi invia/vai/fatto</string>
|
||||
<string name="qr_scanning_error_no_google_play_services">La scansione del codice QR richiede Google Play Services. Installa o aggiorna Google Play Services sul tuo dispositivo.</string>
|
||||
<string name="english_ime_settings">Impostazioni tastiera Keepass2Android</string>
|
||||
<string name="autoswitch_enabled_but_not_setup">Nota: Hai abilitato App - Impostazioni - Accesso password - Cambio di tastiera - Tastiera automatica, ma non sembra essere configurata correttamente.</string>
|
||||
<string name="switch_keyboard_for_totp_enabled">Nota: Hai abilitato App - Accesso password - Servizio di autocompilazione - Autocompilazione per le voci TOTP. Questo può causare la visualizzazione di questa finestra quando si apre una voce con un TOTP.</string>
|
||||
<string name="switch_keyboard_inside_kp2a_enabled">Nota: Hai abilitato App - Sicurezza - Usa la tastiera integrata all\'interno di Keepass2Android. Questo può causare la visualizzazione di questa finestra quando si apre l\'app o si modifica una voce.</string>
|
||||
</resources>
|
||||
|
@@ -724,6 +724,7 @@
|
||||
<item>ユーザーインターフェイスを Material 3 にアップグレード</item>
|
||||
<item>Compose アプリでの自動入力機能を改善</item>
|
||||
<item>自動入力と検索でホスト名の一致条件を修正</item>
|
||||
<item>Fix issue with password generator</item>
|
||||
</string-array>
|
||||
<string-array name="ChangeLog_1_12_net">
|
||||
<item>OneDrive SDK をバージョン 5.68 にアップグレード</item>
|
||||
|
@@ -548,6 +548,7 @@
|
||||
<string name="filestoragename_dropboxKP2A">Dropbox (pasta KP2A)</string>
|
||||
<string name="filestoragehelp_dropboxKP2A">Se você não quiser dar acesso KP2A para o seu Dropbox completo, você pode selecionar esta opção. Ele irá solicitar somente acesso para a pasta Apps/Keepass2Android. Isto é especialmente adequado ao criar um novo banco de dados. Se você já tiver um banco de dados, clique nesta opção para criar a pasta, em seguida, colocar o arquivo dentro da pasta (a partir de seu PC) e em seguida, selecione esta opção novamente para abrir o arquivo.</string>
|
||||
<string name="filestoragename_gdrive">Google Drive</string>
|
||||
<string name="filestoragehelp_gdrive">Observação: o Google está restringindo o acesso ao Google Drive a partir de aplicativos para cada vez mais usuários. Se a implementação integrada do Google Drive não funcionar, use o seletor de arquivos do sistema e selecione o Google Drive lá!</string>
|
||||
<string name="filestoragename_gdriveKP2A">Google Drive (Arquivos KP2A)</string>
|
||||
<string name="filestoragehelp_gdriveKP2A">Se você não quiser dar acesso KP2A ao seu Google Drive completo, você pode selecionar esta opção. Observe que você precisa criar um arquivo de banco de dados primeiro, os arquivos existentes não são visíveis para o aplicativo. Escolha esta opção na tela Criar banco de dados ou, se você já abriu um banco de dados, exportando o banco de dados escolhendo esta opção.</string>
|
||||
<string name="filestoragename_pcloud">PCloud (Pasta KP2A)</string>
|
||||
@@ -727,6 +728,7 @@
|
||||
<item>Atualizado para a interface de usuário Material 3</item>
|
||||
<item>Melhorado o preenchimento automático para trabalhar com aplicativos Compose</item>
|
||||
<item>Corrigido a correspondência do nome do host em preenchimento automático e pesquisa</item>
|
||||
<item>Corrigido um problema com gerador de senhas</item>
|
||||
</string-array>
|
||||
<string-array name="ChangeLog_1_12_net">
|
||||
<item>Atualizado o OneDrive SDK para a versão 5.68</item>
|
||||
@@ -1199,5 +1201,10 @@
|
||||
<string name="AutofillWarning_trustAsBrowser">Aceitar sempre em \"%1$s\"</string>
|
||||
<string name="kp2a_switch_on_sendgodone">Voltar quando terminar</string>
|
||||
<string name="kp2a_switch_on_sendgodone_summary">Voltar ao pressionar enviar/ir/concluído</string>
|
||||
<string name="qr_scanning_error_no_google_play_services">A leitura de código QR requer o Google Play Services. Instale ou atualize o Google Play Services no seu dispositivo.</string>
|
||||
<string name="english_ime_settings">Configurações do teclado Android</string>
|
||||
<string name="autoswitch_enabled_but_not_setup">Nota: Você ativou o Aplicativo - Configurações - Acesso por senha - Troca de teclado - Troca automática de teclado, mas não parece estar configurado corretamente.</string>
|
||||
<string name="switch_keyboard_for_totp_enabled">Nota: você ativou o Aplicativo - Acesso por senha - Serviço de preenchimento automático - Preenchimento automático para entradas TOTP. Isso pode fazer com que essa janela seja exibida quando você abre uma entrada com um TOTP.</string>
|
||||
<string name="switch_keyboard_inside_kp2a_enabled">Nota: Você ativou o Aplicativo - Segurança - Usar o teclado embutido dentro do Keepass2Android. Isso pode fazer com que essa janela seja exibida quando você abre o aplicativo ou edita uma entrada.</string>
|
||||
<string name="switch_keyboard_on_search_enabled">Nota: Você ativou o Aplicativo - Segurança - Acesso por senha - Troca de teclado - Alternar teclado. Isso pode fazer com que essa janela seja exibida quando você pesquisar uma entrada no navegador.</string>
|
||||
</resources>
|
||||
|
@@ -468,6 +468,8 @@
|
||||
<string name="NoOverwrite">Nu, suprascrie</string>
|
||||
<string name="UseOfflineMode">Funcționare doar cu cache intern</string>
|
||||
<string name="UseOnlineMode">Sincronizează copia cache cu sursa</string>
|
||||
<string name="UseOfflineMode_Info">Baza de date este încărcată din memoria cache internă. Modificările sunt stocate doar în cache-ul intern și vor fi sincronizate numai atunci când selectezi Sincronizare copie cache cu sursa.</string>
|
||||
<string name="InOfflineMode">Funcționare doar cu cache intern.</string>
|
||||
<string name="SynchronizingCachedDatabase">Sincronizează baza de date din cache…</string>
|
||||
<string name="DownloadingRemoteFile">Se încarcă fișierul sursă…</string>
|
||||
<string name="UploadingFile">Salvează fișierul…</string>
|
||||
@@ -475,13 +477,21 @@
|
||||
<string name="FilesInSync">Fişierele sunt sincronizate.</string>
|
||||
<string name="SynchronizedDatabaseSuccessfully">Baza de date s-a sincronizat cu succes!</string>
|
||||
<string name="CheckingDatabaseForChanges">Se verifică baza de date pentru modificări…</string>
|
||||
<string name="CouldNotSaveToRemote">Nu s-a putut salva în fișierul sursă: %1$s. Salvează din nou sau utilizează meniul Sincronizare atunci când fișierul este accesibil din nou.</string>
|
||||
<string name="CouldNotLoadFromRemote">Nu s-a putut accesa fișierul sursă: %1$s. Fișier încărcat din cache-ul intern. Poți face în continuare modificări în baza de date și să le sincronizezi mai târziu.</string>
|
||||
<string name="UpdatedRemoteFileOnLoad">Fișier sursă actualizat.</string>
|
||||
<string name="NotifyOpenFromLocalDueToConflict">S-a deschis fișierul cache intern din cauza conflictului cu modificările din fișierul sursă. Utilizează meniul Sincronizare pentru a fuziona.</string>
|
||||
<string name="LoadedFromRemoteInSync">Fișierul sursă și cache-ul sunt sincronizate.</string>
|
||||
<string name="UpdatedCachedFileOnLoad">S-a actualizat copia internă a cache-ului %1$s.</string>
|
||||
<string name="RemoteDatabaseUnchanged">Nu s-au detectat modificări.</string>
|
||||
<string name="ResolvedCacheConflictByUsingRemoteOtpAux">S-a actualizat fișierul auxiliar OTP din cache : Contorul sursă a fost mai mare.</string>
|
||||
<string name="ResolvedCacheConflictByUsingLocalOtpAux">S-a actualizat fișierul auxiliar OTP sursă: Contorul local a fost mai mare.</string>
|
||||
<string name="SynchronizingOtpAuxFile">Se sincronizează fișierul auxiliar OTP…</string>
|
||||
<string name="database_file">fișier bază de date</string>
|
||||
<string name="otp_aux_file">Fişier auxiliar OTP</string>
|
||||
<string name="ErrorOcurred">A apărut o eroare:</string>
|
||||
<string name="DuplicateUuidsError">Baza de date este coruptă: ID-uri duplicate au fost găsite. (Ai salvat cu Minikeepass?) Te rog să reimporți o bază de date nouă cu Keepass 2 pentru PC selectând \'Create new IDs\'.</string>
|
||||
<string name="DuplicateUuidsErrorAdditional">Poți dezactiva acest mesaj de eroare în Setări/Setările aplicației/Gestionare fișiere/Verificare duplicat UUID-uri. Reține că este posibil te confrunți cu un comportament neașteptat. Este recomandat să repari baza de date.</string>
|
||||
<string name="synchronize_database_menu">Sincronizează baza de date…</string>
|
||||
<string name="CannotMoveGroupHere">Nu se poate muta grupul în acest grup.</string>
|
||||
<string name="donate_question">Astăzi este Oktoberfest! Dacă vă place Keepass2Android: nu ar fi azi o zi potrivită să-mi cumpăraţi o bere?</string>
|
||||
@@ -498,11 +508,24 @@
|
||||
<string name="hint_sftp_host">host (ex: 192.168.0.1)</string>
|
||||
<string name="hint_sftp_port">port</string>
|
||||
<string name="initial_directory">Folder inițial (opțional):</string>
|
||||
<string name="connect_timeout">Secunde expirare conexiune (opțional)</string>
|
||||
<string name="enter_sftp_login_title">Introduceţi datele de conectare SFTP:</string>
|
||||
<string name="sftp_auth_mode">Mod autentificare</string>
|
||||
<string name="send_public_key">Trimite cheia publică...</string>
|
||||
<string name="select_private_keyfile">Selectează cheia privată...</string>
|
||||
<string name="hint_sftp_key_name">Nume cheie nouă</string>
|
||||
<string name="hint_sftp_key_content">Conținut cheie nouă</string>
|
||||
<string name="private_key_saved">Cheie privată salvată</string>
|
||||
<string name="private_key_save_failed">Salvarea cheii private a eșuat: %1$s</string>
|
||||
<string name="private_key_info">Introduc numele cheii și conținutul pentru a salva</string>
|
||||
<string name="private_key_delete">Cheie privată ștearsă: %1$s</string>
|
||||
<string name="private_key_delete_failed">Ștergerea cheii private a eșuat: %1$s</string>
|
||||
<string name="save_key">Salvează cheia privată</string>
|
||||
<string name="delete_key">Ștergere cheie privată</string>
|
||||
<string name="private_key_select">Selectează cheia privată</string>
|
||||
<string name="private_key_create_new">[Adaugă nou...]</string>
|
||||
<string name="hint_sftp_key_passphrase">Frază de acces pentru cheie (opțională)</string>
|
||||
<string name="sftp_kex_title">Algoritmi de schimb de chei (KEX) (opțional)</string>
|
||||
<string name="enter_ftp_login_title">Introdu datele de conectare FTP:</string>
|
||||
<string name="select_storage_type">Selectaţi tipul de stocare:</string>
|
||||
<string name="filestoragename_file">Fişier local</string>
|
||||
@@ -517,12 +540,15 @@
|
||||
<string name="filestoragename_dropboxKP2A">Dropbox (folder KP2A)</string>
|
||||
<string name="filestoragehelp_dropboxKP2A">Dacă nu doriți să dați KP2A acces la Dropbox-ul complet, puteți selecta această opțiune. Va solicita acces doar la directorul Apps/Keepass2Android. Acest lucru este potrivit în special atunci când se creează o bază de date nouă. Dacă aveţi deja o bază de date, selectaţi această opţiune pentru a crea directorul, apoi plasați fișierul în director (de la PC) și apoi selectați din nou această opțiune pentru deschiderea fișierului.</string>
|
||||
<string name="filestoragename_gdrive">Google Drive</string>
|
||||
<string name="filestoragename_gdriveKP2A">Google Drive (fișiere KP2A)</string>
|
||||
<string name="filestoragename_pcloudall">PCloud (Acces complet)</string>
|
||||
<string name="filestoragename_onedrive">OneDrive</string>
|
||||
<string name="filestoragename_onedrive2">OneDrive</string>
|
||||
<string name="filestoragename_onedrive2_full">Toate fișierele și fișierele partajate</string>
|
||||
<string name="filestoragename_onedrive2_myfiles">Fișierele mele</string>
|
||||
<string name="filestoragename_onedrive2_appfolder">Directorul Keepass2Android App</string>
|
||||
<string name="filestoragename_sftp">SFTP (SSH File Transfer)</string>
|
||||
<string name="filestoragename_mega">MEGA</string>
|
||||
<string name="filestoragename_content">Selector de fisiere sistem</string>
|
||||
<string name="filestorage_setup_title">Iniţializare acces fişier</string>
|
||||
<string name="database_location">Locaţie bază de date</string>
|
||||
@@ -549,6 +575,8 @@
|
||||
<string name="OtpKeyError">Imposibil de creat cheia OTP! Asigură-te că ai introdus OTP-urile corecte.</string>
|
||||
<string name="ErrorUpdatingOtpAuxFile">Eroare în actualizare fișier auxiliar OTP!</string>
|
||||
<string name="SavingOtpAuxFile">Se salvează fișierul auxiliar OTP…</string>
|
||||
<string name="PleaseInstallApp">Instalează %1$s de pe Google Play.</string>
|
||||
<string name="AppOutdated">%1$s nu mai este suportat.</string>
|
||||
<string name="bad_resp">Răspunsul la provocare este incorect.</string>
|
||||
<string name="CouldntLoadChalAuxFile">Nu se poate încărca fișierul auxiliar de provocare!</string>
|
||||
<string name="CouldntLoadChalAuxFile_Hint">Vă rugăm să folosiți plugin-ul KeeChallenge în KeePass 2,x (PC) pentru a configura data de baze cu răspunsuri-provocare!</string>
|
||||
@@ -588,7 +616,9 @@
|
||||
<string name="CopyFileRequired">Pentru a-l folosi, trebuie copiat într-o altă locație.</string>
|
||||
<string name="CopyFileRequiredForEditing">Pentru a-l edita, trebuie copiat fișierul într-o altă locație.</string>
|
||||
<string name="FileReadOnlyTitle">Baza de date permite doar citirea</string>
|
||||
<string name="FileReadOnlyMessagePre">Keepass2Android a deschis baza de date curentă în modul doar pentru citire.</string>
|
||||
<string name="ReadOnlyReason_PreKitKat">Se pare ca ai deschis fişierul dintr-o aplicaţie externă. În acest fel nu se acceptă modificări. Dacă doriţi să faceţi modificări în baza de date, închideţi baza de date şi selectaţi Schimbare bază de date. Apoi deschide fisierul folosind una dintre opţiunile disponibile.</string>
|
||||
<string name="ReadOnlyReason_ReadOnlyFlag">Steagul doar-în-citire este setat. Elimină-l dacă dorești să faci modificări în baza de date.</string>
|
||||
<string name="ReadOnlyReason_ReadOnlyKitKat">Modificarea nu este posibilă din cauza restricţiilor introduse în Android KitKat. Dacă doriţi să faceţi modificări în baza de date, închideți baza de date şi selectaţi Schimbare bază de date. Apoi deschide fisierul folosind selectorul de fisiere al sistemului.</string>
|
||||
<string name="AddCustomIcon">Adaugă pictogramă din file...</string>
|
||||
<string name="CopyingFile">Se copiază fișierul...</string>
|
||||
@@ -612,6 +642,7 @@
|
||||
<string name="TemplateTitle_Membership">Apartenenta</string>
|
||||
<string name="ChangeLog_title">Jurnal modificări</string>
|
||||
<string name="AskAddTemplatesTitle">Adauga template-uri?</string>
|
||||
<string name="AskAddTemplatesMessage">Keepass2Android conține șabloane de intrare pentru conturi de e-mail, parole wireless-LAN, note sigure și multe altele. Dorești să le adaugi în baza de date? Dacă alegi Nu, le poți adăuga mai târziu în setările bazei de date.</string>
|
||||
<string name="AddTemplates_pref">Adauga template-uri in baza de date</string>
|
||||
<string name="Continue">Continuare</string>
|
||||
<string name="NoFilenameWarning">URI introdus nu arata ca un nume de file. Sunteţi sigur că acesta este un file valid?</string>
|
||||
@@ -628,8 +659,24 @@
|
||||
<string name="child_db_Enabled_title">Deschide automat</string>
|
||||
<string name="database_file_heading">Fișier bază de date</string>
|
||||
<string name="if_device_text">Activează pentru %1$s</string>
|
||||
<string name="restore_history">Restaurează această versiune</string>
|
||||
<string name="remove_history">Elimină această versiune</string>
|
||||
<string name="DbUnlockedChannel_name">Bază de date deblocată</string>
|
||||
<string name="DbUnlockedChannel_desc">Notificare despre deblocarea bazei de date</string>
|
||||
<string name="DbQuicklockedChannel_name">QuickUnlock</string>
|
||||
<string name="DbQuicklockedChannel_desc">Notificare despre blocarea bazei de date cu QuickUnlock</string>
|
||||
<string name="EntryChannel_name">Notificări intrare</string>
|
||||
<string name="EntryChannel_desc">Notificare pentru simplificarea accesului la intrarea selectată în prezent.</string>
|
||||
<string name="CloseDbAfterFailedAttempts">Închide baza de date după trei încercări de deblocare biometrică eșuate.</string>
|
||||
<string name="WarnFingerprintInvalidated">Avertizare! Autentificarea biometrică poate fi invalidată de Android, de ex. după adăugarea unei amprente noi în setările dispozitivului. Asigură-te că știi întotdeauna cum să deblochezi cu parola principală!</string>
|
||||
<string-array name="ChangeLog_1_12">
|
||||
<item>Upgraded from Xamarin Android to .net 8</item>
|
||||
<item>Upgraded to Target SDK 34</item>
|
||||
<item>Upgraded to Material 3 user interface</item>
|
||||
<item>Improve autofill to work with Compose apps</item>
|
||||
<item>Fix hostname matching in autofill and search</item>
|
||||
<item>S-a reparat problema cu generatorul de parole</item>
|
||||
</string-array>
|
||||
<string-array name="ChangeLog_1_11">
|
||||
<item>Added floating action buttons for search and TOTP overview (if TOTP entries are present).</item>
|
||||
<item>Improved display of TOTP fields by adding a timeout indicator and showing it more prominently.</item>
|
||||
@@ -669,8 +716,8 @@
|
||||
<string name="design_title">Design</string>
|
||||
<string-array name="ftp_encryption_modes">
|
||||
<item>Fără criptare (FTP)</item>
|
||||
<item>Implicit encryption (FTP over TLS, FTPS)</item>
|
||||
<item>Explicit encryption (FTP over TLS, FTPS)</item>
|
||||
<item>Criptare implicită (FTP peste TLS, FTPS)</item>
|
||||
<item>Criptare explicită (FTP prin TLS, FTPS)</item>
|
||||
</string-array>
|
||||
<string-array name="cred_remember_modes">
|
||||
<item>Nu reține numele utilizator și parola</item>
|
||||
@@ -684,30 +731,46 @@
|
||||
<item>Parolă + OTP secret (modul de recuperare)</item>
|
||||
<item>Parolă + Challenge-Response</item>
|
||||
<item>Parolă + Challenge-Response secret (modul de recuperare)</item>
|
||||
<item>Password + Challenge-Response for Keepass XC</item>
|
||||
<item>Password + Key file + Challenge-Response for Keepass XC</item>
|
||||
<item>Parolă + provocare-răspuns pentru Keepass XC</item>
|
||||
<item>Parolă + fișier cheie + provocare-răspuns pentru Keepass XC</item>
|
||||
</string-array>
|
||||
<string-array name="sftp_auth_modes">
|
||||
<item>Parolă</item>
|
||||
<item>KP2A Private/Public key</item>
|
||||
<item>Custom Private key</item>
|
||||
<item>Cheie Privată/Publică KP2A</item>
|
||||
<item>Cheie privată personalizată</item>
|
||||
</string-array>
|
||||
<string-array name="AcceptAllServerCertificates_options">
|
||||
<item>Ignoră eșecuri de validare a certificatului</item>
|
||||
<item>Avertizează când validarea eșuează</item>
|
||||
<item>Nu accepta certificate invalide</item>
|
||||
</string-array>
|
||||
<string name="ClearClipboardWarning">Asigură-te că aceasta funcționează pe sistemul tău, dacă nu, ia în considerare folosirea tastaturii încorporate.</string>
|
||||
<string name="PluginDescription">Descrierea furnizată de plugin:</string>
|
||||
<string name="autofill_hint">Keepass2Android suportă caracteristica de completare automată a Android, dar se pare că nu ai activat-o încă.</string>
|
||||
<string name="autofill_enable">Activare autocompletare</string>
|
||||
<string name="autofill_enable_failed">Ne pare rău, se pare că dispozitivul nu acceptă deschiderea setărilor din interiorul aplicației. Accesează manual setările de sistem pentru completare automată pentru a activa serviciul.</string>
|
||||
<string name="show_autofill_help">Afișează ajutorul pentru completarea automată</string>
|
||||
<string name="autofill_sign_in_prompt">Completează cu Keepass2Android</string>
|
||||
<string name="autofill_disable">Dezactivează completarea automată pentru %1$s</string>
|
||||
<string name="autofill_enable_for">Activează completare automată pentru %1$s</string>
|
||||
<string name="invalid_link_association">Domeniul web %1$s nu a putut fi asociat cu aplicația %2$s</string>
|
||||
<string name="enable_fingerprint_hint">Keepass2Android a detectat dispozitive biometrice. Doriţi să activaţi deblocarea biometrică pentru această bază de date?</string>
|
||||
<string name="post_notifications_dialog_title">Permite notificări</string>
|
||||
<string name="post_notifications_dialog_message">Keepass2Android poate afișa notificări cu butoane pentru a copia valori cum ar fi parole și coduri TOTP în clipboard, sau pentru a aduce tastatura integrată. Acest lucru este util pentru a transfera valori în alte aplicații fără a trece la Keepass2Android în mod repetat. Doriești să activezi astfel de notificări?</string>
|
||||
<string name="post_notifications_dialog_allow">Permite notificări</string>
|
||||
<string name="post_notifications_dialog_disable">Dezactivează această caracteristică</string>
|
||||
<string name="post_notifications_dialog_notnow">Nu acum</string>
|
||||
<string name="understand">Am înțeles</string>
|
||||
<string name="dont_show_again">Nu mai afișa</string>
|
||||
<string name="masterkey_infotext_head">Îți amintești parola principală?</string>
|
||||
<string name="masterkey_infotext_main">Reține că nu vei putea deschide baza de date fără cheia principală. Nu există nici o modalitate de a \"reseta\" parola principală.</string>
|
||||
<string name="masterkey_infotext_fingerprint_note">De asemenea, rețineți că Deblocarea biometrică funcționează prin stocarea cheii principale în spațiul de stocare securizat Android. Această stocare poate fi ștearsă de Android în orice moment, de ex. dacă adăugați o nouă amprentă în setările sistemului. Așa că nu vă bazați pe deblocarea biometrică ci retineți parola principală, vă rog!</string>
|
||||
<string name="backup_infotext_head">S-a creat o copie de rezervă pentru baza de date?</string>
|
||||
<string name="backup_infotext_main">Keepass2Android stochează parolele într-un fișier într-o locație la alegerea ta. Ești sigur că încă poți accesa acest fișier atunci când telefonul este pierdut sau furat sau când fișierul este distrus sau șters? Asigură-te că ai întotdeauna o copie de rezervă actualizată într-un loc sigur!</string>
|
||||
<string name="backup_infotext_note">Pentru a crea o copie de rezervă acum, accesează %1$s > %2$s > %3$s.</string>
|
||||
<string name="emergency_infotext_head">Ești pregătit pentru cazuri de urgență?</string>
|
||||
<string name="emergency_infotext_main">Te-ai gândit vreodată ce se întâmplă dacă nu mai poți accesa baza de date a parolelor? Ce se întâmplă dacă ai un accident? Este o bună practică să transmiți cheia principală unei persoane de încredere pentru cazuri de urgență. În caz contrar, nimeni nu va avea acces la parole.</string>
|
||||
<string name="no_secure_display">Afișajul valabil în prezent nu este marcat ca fiind sigur. Aceasta înseamnă că capturile de ecran ar putea fi luate de alte aplicații. Keepass2Android este configurat pentru a afișa informații sensibile doar pe afișaje securizate. Schimbă la un afișaj securizat (de exemplu, detașând un monitor HDMI) sau modifică setările aplicației.</string>
|
||||
<string name="disable_secure_screen_check">Dezactivează acest mesaj</string>
|
||||
<string name="switch_ime_text">Activează tastatura Keepass2Android.</string>
|
||||
<string name="switch_ime_reopen">Reîncercați</string>
|
||||
@@ -717,5 +780,6 @@
|
||||
<string name="AutofillWarning_trustAsBrowser">Acceptați întotdeauna în \"%1$s\"</string>
|
||||
<string name="kp2a_switch_on_sendgodone">Comută înapoi când ai terminat</string>
|
||||
<string name="kp2a_switch_on_sendgodone_summary">Comută înapoi după apăsarea trimitere/înainte/terminat</string>
|
||||
<string name="qr_scanning_error_no_google_play_services">Scanarea codului QR necesită servicii Google Play. Instalează sau actualizează serviciile Google Play de pe dispozitiv.</string>
|
||||
<string name="english_ime_settings">Setările tastaturii Keepass2Android</string>
|
||||
</resources>
|
||||
|
@@ -546,6 +546,7 @@
|
||||
<string name="filestoragename_dropboxKP2A">Dropbox (priečinok KP2A)</string>
|
||||
<string name="filestoragehelp_dropboxKP2A">Túto voľbu môžete aktivovať ak udelíte KP2A prístup do celého Dropboxu. Vyžaduje sa prístup iba do priečinka Apps/Keepass2Android. Je to osobitne vhodné pri vytváraní novej databázy. Ak už máte databázu, tak aktivovaním tejto voľby vytvoríte priečinok, potom premiestnite súbor do priečinka (zo svojho PC) a potom znovu aktivujte voľbu, pre otvorenie súboru.</string>
|
||||
<string name="filestoragename_gdrive">Google Drive</string>
|
||||
<string name="filestoragehelp_gdrive">Pamätajte na to, že: Google čoraz viac obmedzuje prístup ku Google Drive z aplikácií. Ak vám nefunguje zabudovaná integrácia s Google Drive, použite výber súboru priamo v systéme a vyberte Google Drive tam!</string>
|
||||
<string name="filestoragename_gdriveKP2A">Google Drive (súbory KP2A)</string>
|
||||
<string name="filestoragehelp_gdriveKP2A">Ak nechcete poskytnúť KP2A prístup k celému úložisku Google Drive, môžete vybrať túto možnosť. Pamätajte na to, že najskôr musíte vytvoriť súbor s databázou, existujúce súbory aplikácia neuvidí. Buď vyberte takúto možnosť z obrazovky pre vytvorenie databázy, alebo už otvorenú databázu exportujte vybratím tejto možnosti.</string>
|
||||
<string name="filestoragename_pcloud">PCloud (priečinok KP2A)</string>
|
||||
@@ -725,6 +726,7 @@
|
||||
<item>Aktualizované na používateľské rozhranie Material 3</item>
|
||||
<item>Vylepšené automatické dopĺňanie kvôli fungovaniu s aplikáciami Compose</item>
|
||||
<item>Oprava zhody mena hostiteľa v automatickom dopĺňaní a vyhľadávaní</item>
|
||||
<item>Oprava problému s generátorom hesiel</item>
|
||||
</string-array>
|
||||
<string-array name="ChangeLog_1_12_net">
|
||||
<item>Aktualizované na OneDrive SDK, verziu 5.68</item>
|
||||
@@ -1199,5 +1201,10 @@
|
||||
<string name="AutofillWarning_trustAsBrowser">Vždy súhlasiť v \"%1$s\"</string>
|
||||
<string name="kp2a_switch_on_sendgodone">Po dokončení prepnúť späť</string>
|
||||
<string name="kp2a_switch_on_sendgodone_summary">Po stlačení Odoslať/Prejsť/Hotovo prejsť späť</string>
|
||||
<string name="qr_scanning_error_no_google_play_services">Na skenovanie QR kódov sú potrebné služby Google Play. Nainštalujte alebo aktualizujte si ich vo vašom zariadení.</string>
|
||||
<string name="english_ime_settings">Nastavenia klávesnice Keepass2Android</string>
|
||||
<string name="autoswitch_enabled_but_not_setup">Poznámka: aktivovali ste automatické prepínanie klávesnice v sekcii Nastavenia aplikácie - Prístup k záznamu s heslom - Prepínanie klávesnice, ale zdá sa, že táto funkcia nie je správne nakonfigurovaná.</string>
|
||||
<string name="switch_keyboard_for_totp_enabled">Poznámka: aktivovali ste automatické dopĺňanie pre záznamy TOTP, v sekcii Apl. - Prístup k záznamu s heslom - Služba automatického dopĺňania. Môže to spôsobiť zobrazenie tohto okna pri otvorení záznamu s TOTP.</string>
|
||||
<string name="switch_keyboard_inside_kp2a_enabled">Poznámka: aktivovali ste použitie klávesnice integrovanej v Keepass2Android, v sekcii Apl. - Zabezpečenie. Môže to spôsobiť zobrazenie tohto okna pri otvorení aplikácie alebo pri úprave záznamu.</string>
|
||||
<string name="switch_keyboard_on_search_enabled">Poznámka: aktivovali ste prepínanie klávesnice v sekcii Apl. - Zabezpečenie - Prístup k záznamu s heslom - Prepínanie klávesnice. Môže to spôsobovať zobrazenie tohto okna pri vyhľadávaní nejakého záznamu z prehliadača.</string>
|
||||
</resources>
|
||||
|
@@ -546,6 +546,7 @@
|
||||
<string name="filestoragename_dropboxKP2A">Dropbox (mapa KP2A)</string>
|
||||
<string name="filestoragehelp_dropboxKP2A">Če dostopa KP2A ne želite dati celemu Dropboxu, lahko izberete to možnost. Zahtevala bo samo dostop do mape Apps/Keepass2Android. To je posebej primerno ob ustvarjanju nove podatkovne zbirke. Če jo že imate, tapnite na to možnost, da ustvarite mapo, v njo vstavite svojo datoteko (iz računalnika) in ponovno izberete to možnost, da datoteko odprete.</string>
|
||||
<string name="filestoragename_gdrive">Google Drive</string>
|
||||
<string name="filestoragehelp_gdrive">Opomba: Google omejuje dostop do storitve Google Drive iz aplikacij za vse več uporabnikov. Če vgrajena implementacija Googlovega pogona ne deluje, uporabite sistemski izbirnik datotek in tam izberite Googlov pogon!</string>
|
||||
<string name="filestoragename_gdriveKP2A">Google Drive (KP2A datoteke)</string>
|
||||
<string name="filestoragehelp_gdriveKP2A">Če KP2A ne želite omogočiti dostopa do celotnega Google Drive, lahko izberete to možnost. Upoštevajte, da morate najprej ustvariti novo datoteko baze podatkov, obstoječe datoteke niso vidne aplikaciji. To možnost izberite na zaslonu Ustvari bazo podatkov ali, če ste že odprli bazo podatkov, izvozite bazo podatkov in izberete to možnost.</string>
|
||||
<string name="filestoragename_pcloud">PCloud (KP2A mapa)</string>
|
||||
@@ -725,6 +726,7 @@
|
||||
<item>Nadgrajen na uporabniški vmesnik Material 3</item>
|
||||
<item>Izboljšanje samodejnega izpolnjevanja za delovanje z aplikacijami Compose</item>
|
||||
<item>Popravek ujemanja gostiteljskega imena v samodejnem izpolnjevanju in iskanju</item>
|
||||
<item>Odpravljena težava z generatorjem gesel</item>
|
||||
</string-array>
|
||||
<string-array name="ChangeLog_1_12_net">
|
||||
<item>Nadgradnja OneDrive SDK na različico 5.68</item>
|
||||
@@ -1197,5 +1199,10 @@
|
||||
<string name="AutofillWarning_trustAsBrowser">Sprejmi vedno v \"%1$s\"</string>
|
||||
<string name="kp2a_switch_on_sendgodone">Preklopi nazaj, ko je končano</string>
|
||||
<string name="kp2a_switch_on_sendgodone_summary">Preklopi nazaj, ko pritisnete gumb za pošiljanje/prehajanje/končano</string>
|
||||
<string name="qr_scanning_error_no_google_play_services">Za optično branje kode QR so potrebne storitve Google Play. V svojo napravo namestite ali posodobite storitve Google Play.</string>
|
||||
<string name="english_ime_settings">Nastavitve tipkovnice Keepass2Android</string>
|
||||
<string name="autoswitch_enabled_but_not_setup">Opomba: Omogočili ste Aplikacije - Nastavitve - Dostop z geslom - Preklop tipkovnice - Samodejni preklop tipkovnice, vendar se zdi, da ta ni pravilno konfigurirana.</string>
|
||||
<string name="switch_keyboard_for_totp_enabled">Opomba: Omogočili ste Aplikacije - Dostop do gesla - Storitev samodejnega izpolnjevanja - Samodejno izpolnjevanje za vnose TOTP. To lahko povzroči, da se to okno prikaže, ko odprete vnos s TOTP.</string>
|
||||
<string name="switch_keyboard_inside_kp2a_enabled">Opomba: Omogočili ste Aplikacije - Varnost - Uporabi vgrajeno tipkovnico znotraj Keepass2Android. To lahko povzroči, da se to okno prikaže, ko odprete aplikacijo ali urejate vnos.</string>
|
||||
<string name="switch_keyboard_on_search_enabled">Opomba: Omogočili ste možnost Aplikacija - Varnost - Dostop z geslom - Preklop tipkovnice - Preklop tipkovnice. To lahko povzroči, da se to okno prikaže, ko iščete vnos v brskalniku.</string>
|
||||
</resources>
|
||||
|
@@ -151,6 +151,7 @@
|
||||
<string name="hint_keyfile">Anahtar dosyası</string>
|
||||
<string name="hint_length">Uzunluk</string>
|
||||
<string name="hint_pass">parola</string>
|
||||
<string name="hint_keyfile_path">SSH özel anahtar yolu</string>
|
||||
<string name="hint_login_pass">Parola</string>
|
||||
<string name="hint_title">Başlık</string>
|
||||
<string name="hint_url">URL</string>
|
||||
@@ -300,6 +301,8 @@
|
||||
<string name="NoDalVerification_summary">Etki alanı ve uygulama paketinin eşleşip eşleşmediğini kontrol etmeyi devre dışı bırakır</string>
|
||||
<string name="InlineSuggestions_title">Klavye ile entegre et</string>
|
||||
<string name="InlineSuggestions_summary">Otomatik doldurma önerilerini klavyede satır içi seçenekler olarak gösterir (giriş yöntemi tarafından destekleniyorsa)</string>
|
||||
<string name="LogAutofillView_title">Günlük otomatik doldurma görünümü</string>
|
||||
<string name="LogAutofillView_summary">Otomatik doldurma görünümü hakkında ayrıntıları hata ayıklama günlüğüne yaz (eğer hata ayıklama günlüğü etkinse). Eğer otomatik doldurma beklendiği gibi çalışmıyorsa bu ayrıntılar geliştiriciye gönderilebilir.</string>
|
||||
<string name="requires_android11">Android 11 veya sonraki bir sürümünü gerektirir</string>
|
||||
<string name="kp2a_findUrl">Parola bul</string>
|
||||
<string name="excludeExpiredEntries">Hızlı aramalara süresi dolmuş kayıtlar katılmasın</string>
|
||||
@@ -398,6 +401,11 @@
|
||||
<string name="ShowSeparateNotifications_summary">Kullanıcı adıyla parolayı panoya kopyalamak ve klavyeyi etkinleştirmek için bildirimleri göster.</string>
|
||||
<string name="AccServiceAutoFill_prefs">Otomatik Doldurma Erişilebilirlik Hizmeti</string>
|
||||
<string name="AutoFill_prefs">Otomatik Doldurma Hizmeti</string>
|
||||
<string name="AutoFillTotp_prefs_ShowNotification_summary">Bir girişi TOTP ile otomatik doldururken, giriş bildirimini TOTP Kopyala düğmesiyle göster</string>
|
||||
<string name="AutoFillTotp_prefs_ShowNotification_title">Giriş bildirimlerini göster</string>
|
||||
<string name="AutoFillTotp_prefs_CopyTotpToClipboard_title">TOTP \'yi panoya kopyala</string>
|
||||
<string name="AutoFillTotp_prefs_ActivateKeyboard_title">Yerleşik klavyeyi etkinleştir</string>
|
||||
<string name="TotpCopiedToClipboard">TOTP panoya kopyalandı</string>
|
||||
<string name="ShowKp2aKeyboardNotification_title">KP2A klavye bildirimi</string>
|
||||
<string name="ShowKp2aKeyboardNotification_summary">Tam girişi KP2A klavyesinden erişilebilir yapın (önerilir).</string>
|
||||
<string name="OpenKp2aKeyboardAutomatically_title">Klavyeyi değiştir</string>
|
||||
@@ -414,6 +422,7 @@
|
||||
<string name="ShowUnlockedNotification_summary">Veritabanı kilitli değilken devam eden bir bildirim gösterir.</string>
|
||||
<string name="IconVisibilityInfo_Android8_text">Android 8, bildirimler için yeni davranışlar getirdi. Keepass2Android\'in bildirimleri için simgeyi gizlemek istiyorsanız, lütfen bunu sistem ayarlarından yapılandırın. Bildirim kategorisinin önemini Minimum olarak ayarlayın.</string>
|
||||
<string name="IconVisibilityInfo_Android8_btnSettings">Ayarları aç</string>
|
||||
<string name="PostNotificationsPermissionInfo_text">Keepass2Android bilgi bankanız kilitli değilken size bir sistem uyarısı görüntüler. Bunun çalışması için lütfen izin verin.</string>
|
||||
<string name="DontCare">Umrumda değil</string>
|
||||
<string name="DocumentAccessRevoked">Keepass2Android artık dosyaya erişemiyor. Dosya ya silindi yada erişim izinleri iptal edildi. Lütfen Veritabanını değiştir seçeneğiyle dosyayı yeniden açın.</string>
|
||||
<string name="PreloadDatabaseEnabled_title">Veritabanı dosyasını önceden yükleme</string>
|
||||
@@ -498,9 +507,15 @@
|
||||
<string name="hint_sftp_host">sunucu (ör: 192.168.0.1)</string>
|
||||
<string name="hint_sftp_port">bağlantı noktası</string>
|
||||
<string name="initial_directory">Başlangıç dizini (isteğe bağlı):</string>
|
||||
<string name="connect_timeout">Bağlantı zaman aşımı saniyesi (isteğe bağlı)</string>
|
||||
<string name="enter_sftp_login_title">SFTP oturum açma verilerini girin:</string>
|
||||
<string name="sftp_auth_mode">Kimlik doğrulama modu</string>
|
||||
<string name="send_public_key">Ortak anahtar gönder...</string>
|
||||
<string name="select_private_keyfile">Özel anahtarı seç...</string>
|
||||
<string name="hint_sftp_key_name">Yeni anahtar adı</string>
|
||||
<string name="hint_sftp_key_content">Yeni anahtar içeriği</string>
|
||||
<string name="private_key_saved">Özel anahtar kaydedildi</string>
|
||||
<string name="private_key_save_failed">Özel anahtar kayıt edilemedi: %1$s</string>
|
||||
<string name="enter_ftp_login_title">FTP oturum açma verilerini girin:</string>
|
||||
<string name="enter_mega_login_title">MEGA hesap bilgilerinizi girin:</string>
|
||||
<string name="select_storage_type">Depolama türünü seçin:</string>
|
||||
|
@@ -546,6 +546,7 @@
|
||||
<string name="filestoragename_dropboxKP2A">Dropbox (thư mục KP2A)</string>
|
||||
<string name="filestoragehelp_dropboxKP2A">Nếu bạn không muốn cấp cho KP2A quyền truy cập vào Dropbox đầy đủ của mình, bạn có thể chọn tùy chọn này. Nó sẽ chỉ yêu cầu quyền truy cập vào thư mục Apps/Keepass2Android. Điều này đặc biệt phù hợp khi tạo cơ sở dữ liệu mới. Nếu bạn đã có cơ sở dữ liệu, hãy chọn tùy chọn này để tạo thư mục, sau đó đặt tệp của bạn bên trong thư mục (từ PC của bạn) và sau đó chọn lại tùy chọn này để mở tệp.</string>
|
||||
<string name="filestoragename_gdrive">Google Drive</string>
|
||||
<string name="filestoragehelp_gdrive">Xin lưu ý: Google ngày càng giới hạn quyền truy cập Google Drive của các ứng dụng đối với nhiều người dùng hơn. Nếu mục Google Drive không dùng được, hãy chọn Trình chọn tập tin của hệ thống sau đó chọn mục Google Drive!</string>
|
||||
<string name="filestoragename_gdriveKP2A">Google Drive (tệp KP2A)</string>
|
||||
<string name="filestoragehelp_gdriveKP2A">Nếu bạn không muốn cấp cho KP2A quyền truy cập vào Google Drive đầy đủ của mình, bạn có thể chọn tùy chọn này. Lưu ý rằng trước tiên bạn cần tạo tệp cơ sở dữ liệu, các tệp hiện có sẽ không hiển thị với ứng dụng. Chọn tùy chọn này từ màn hình Tạo cơ sở dữ liệu hoặc, nếu bạn đã mở cơ sở dữ liệu, bằng cách xuất cơ sở dữ liệu chọn tùy chọn này.</string>
|
||||
<string name="filestoragename_pcloud">PCloud (thư mục KP2A)</string>
|
||||
@@ -672,6 +673,26 @@
|
||||
<string name="Continue">Tiếp tục</string>
|
||||
<string name="NoFilenameWarning">URI bạn đã nhập không có dạng tên tập tin. Bạn có chắc chắn đây là tập tin hợp lệ không?</string>
|
||||
<string name="FirstInvalidCompositeKeyError">Khoá hỗn hợp không hợp lệ. Xin thử lại.</string>
|
||||
<string name="RepeatedInvalidCompositeKeyHelp"> Khoá tổng hợp không hợp lệ! Hãy thử các bước sau để mở khoá cơ sở dữ liệu của bạn:\n
|
||||
|
||||
• Nhập đúng mật khẩu. Ấn vào biểu tượng con mắt để hiện mật khẩu đã nhập.\n
|
||||
• Chọn đúng loại mật khẩu. Loại mật khẩu phải giống với loại mật khẩu đã chọn khi tạo cơ sở dữ liệu.\n
|
||||
• Chọn đúng tập tin cơ sở dữ liệu.
|
||||
</string>
|
||||
<string name="HintLocalBackupInvalidCompositeKey"> \n
|
||||
• Gợi ý: Nếu bạn nghĩ rằng tập tin cơ sở dữ liệu bị hỏng hoặc bạn đã quên khoá chính sau khi thay đổi nó, bạn có thể nhấn \"%1$s\" và chọn bản sao lưu cục bộ để mở phiên bản tập tin được mở thành công gần đây nhất.
|
||||
</string>
|
||||
<string name="HintLocalBackupOtherError"> \n
|
||||
• Gợi ý: Keepass2Android đã lưu trữ phiên bản tập tin được mở thành công gần đây nhất trên bộ nhớ trong. Bạn có thể mở nó bằng cách nhấn vào \"%1$s\" và chọn bản sao lưu cục bộ.
|
||||
</string>
|
||||
<string name="CorruptDatabaseHelp"> Tập tin bị hỏng. \n
|
||||
Có một số mẹo giúp chẩn đoán vấn đề như sau:\n
|
||||
|
||||
• Nếu bạn sao chép tập tin qua USB (sử dụng chế độ MTP), hãy thử sao chép lại bằng một phần mềm như MyPhoneExplorer. Trong một số trường hợp, MTP có thể cắt bớt nội dung tập tin.\n
|
||||
• Nếu không mở được tập tin ở cùng một vị trí trên máy tính, rất có thể tập tin đó thực sự bị hỏng. Trong trường hợp này, hãy sử dụng một bản sao lưu cơ sở dữ liệu. Nếu bạn nghi ngờ rằng Keepass2Android làm hỏng tập tin, hãy liên hệ với bộ phận hỗ trợ.\n
|
||||
• Nếu tập tin vẫn mở được bằng máy tính, hãy liên hệ với bộ phận hỗ trợ. Bạn có thể thử lưu lại tập tin trên máy tính với cài đặt khác (ví dụ như không nén) sau đó thử mở lại bằng Keepass2Android.
|
||||
|
||||
</string>
|
||||
<string name="open_other_db">Mở cơ sở dữ liệu khác…</string>
|
||||
<string name="select_database">Chọn cơ sở dữ liệu</string>
|
||||
<string name="configure_child_dbs">Định cấu hình cơ sở dữ liệu con…</string>
|
||||
|
@@ -546,6 +546,7 @@
|
||||
<string name="filestoragename_dropboxKP2A">Dropbox(KP2A 文件夹)</string>
|
||||
<string name="filestoragehelp_dropboxKP2A">如果您不想让 KP2A 访问整个 Dropbox,您可以选中此选项。它将只有访问 Apps/Keepass2Android 文件夹的权限。特别适合创建一个新的数据库。如果您已经有一个数据库,触击此选项将创建该新文件夹,然后将您在电脑上的数据库文件放在此文件夹内,然后再选该选项,以打开该文件。</string>
|
||||
<string name="filestoragename_gdrive">Google Drive</string>
|
||||
<string name="filestoragehelp_gdrive">请注意:谷歌正在限制越来越多的用户从应用程序访问Google Drive。 如果内置的 Google Drive 实现无法正常工作,请使用系统文件选择器并在那里选择 Google Drive !</string>
|
||||
<string name="filestoragename_gdriveKP2A">Google Drive (KP2A文件)</string>
|
||||
<string name="filestoragehelp_gdriveKP2A">如果您不想给予KP2A对您Google Drive的完整访问权,您可以选择此选项。 请注意,您需要先创建一个数据库文件,现有文件对本应用不可见。 您可以从“创建数据库”屏幕中选择此选项,或者选择此选项导出数据库,前提是您已经打开了一个数据库。</string>
|
||||
<string name="filestoragename_pcloud">PCloud (KP2A 文件夹)</string>
|
||||
@@ -719,6 +720,14 @@
|
||||
<string name="EntryChannel_desc">选定条目快速进入通知</string>
|
||||
<string name="CloseDbAfterFailedAttempts">三次失败的生物识别解锁后关闭数据库。</string>
|
||||
<string name="WarnFingerprintInvalidated">警告!生物识别认证可能会被Android系统作废,例如在你的设备设置中添加一个新的指纹后。确保你总是知道如何用你的主密码解锁!</string>
|
||||
<string-array name="ChangeLog_1_12">
|
||||
<item>Upgraded from Xamarin Android to .net 8</item>
|
||||
<item></item>
|
||||
<item>Upgraded to Material 3 user interface</item>
|
||||
<item>Improve autofill to work with Compose apps</item>
|
||||
<item>Fix hostname matching in autofill and search</item>
|
||||
<item>Fix issue with password generator</item>
|
||||
</string-array>
|
||||
<string-array name="ChangeLog_1_11">
|
||||
<item>添加了用于搜索和概览 TOTP 的浮动按钮(如果存在TOTP条目)</item>
|
||||
<item>通过添加超时指示器并突出显示,改进 TOTP 字段的显示效果</item>
|
||||
@@ -1158,5 +1167,10 @@ Initial public release
|
||||
<string name="AutofillWarning_trustAsBrowser">总是在 \"%1$s 中接受</string>
|
||||
<string name="kp2a_switch_on_sendgodone">完成后切换回来</string>
|
||||
<string name="kp2a_switch_on_sendgodone_summary">按下发送/转到/完成时切换回来</string>
|
||||
<string name="qr_scanning_error_no_google_play_services">二维码扫描需要 Google Play 服务。请在您的设备上安装或更新 Google Play 服务。</string>
|
||||
<string name="english_ime_settings">键盘设置</string>
|
||||
<string name="autoswitch_enabled_but_not_setup">注意:您已启用应用-设置-密码访问-键盘切换-自动切换键盘,但它似乎配置不正确。</string>
|
||||
<string name="switch_keyboard_for_totp_enabled">注意:您已启用应用 - 密码访问-自动填充服务 - TOTP 条目自动填充。 当您打开一条有TOTP的条目时,这会导致此窗口显示。</string>
|
||||
<string name="switch_keyboard_inside_kp2a_enabled">注意:您已经启用了应用 - 安全性 - 使用 Keepass2Android 中的内置键盘。 当您打开应用或编辑条目时,这会导致此窗口显示。</string>
|
||||
<string name="switch_keyboard_on_search_enabled">注意: 您已经启用了应用-安全性-密码访问-键盘切换-切换键盘。当您从浏览器搜索条目时,这会导致此窗口显示。</string>
|
||||
</resources>
|
||||
|
@@ -200,7 +200,7 @@
|
||||
<item>System</item>
|
||||
</string-array>
|
||||
|
||||
<string name="AcceptAllServerCertificates_default">WARN</string>
|
||||
<string name="AcceptAllServerCertificates_default">ERROR</string>
|
||||
<string-array name="AcceptAllServerCertificates_values">
|
||||
<item>IGNORE</item>
|
||||
<item>WARN</item>
|
||||
|
@@ -93,6 +93,8 @@
|
||||
<string name="disable_fingerprint_unlock">Disable Biometric Unlock</string>
|
||||
<string name="enable_fingerprint_unlock">Enable full Biometric Unlock</string>
|
||||
<string name="enable_fingerprint_quickunlock">Enable Biometric Unlock for QuickUnlock</string>
|
||||
<string name="password_based_quick_unlock_not_available">Password-based QuickUnlock not available</string>
|
||||
<string name="password_based_quick_unlock_not_available_text">QuickUnlock using a part of your password is blocked because screen lock is not activated on your device. This behavior is to protect you in case somebody watched you entering your QuickUnlock key.</string>
|
||||
<string name="fingerprint_unlock_failed">Biometric Unlock failed. Decryption key was invalidated by Android OS. This usually happens if a biometric authentication or security settings were changed. </string>
|
||||
<string name="fingerprint_disabled_wrong_masterkey">Unlocking the database failed: Invalid composite key. Biometric Unlock was disabled because apparently the stored master password is no longer valid. </string>
|
||||
<string name="fingerprint_reenable">Please re-enable Biometric Unlock for the new master password.</string>
|
||||
@@ -319,6 +321,7 @@
|
||||
<string name="QuickUnlock_label_secure">Enter QuickUnlock code:</string>
|
||||
<string name="QuickUnlock_button">QuickUnlock!</string>
|
||||
<string name="QuickUnlock_lockButton">Close database</string>
|
||||
<string name="enable_screen_lock">Enable screen lock</string>
|
||||
<string name="QuickUnlockDefaultEnabled_title">Enable QuickUnlock by default</string>
|
||||
<string name="QuickUnlockDefaultEnabled_summary">Defines whether QuickUnlock is enabled by default or not.</string>
|
||||
<string name="ViewDatabaseSecure_title">Protect database display</string>
|
||||
@@ -1249,5 +1252,9 @@
|
||||
<string name="kp2a_switch_on_sendgodone_summary">Switch back when pressing send/go/done</string>
|
||||
<string name="qr_scanning_error_no_google_play_services">QR code scanning requires Google Play Services. Please install or update Google Play Services on your device.</string>
|
||||
<string name="english_ime_settings">Android keyboard settings</string>
|
||||
|
||||
</resources>
|
||||
<string name="autoswitch_enabled_but_not_setup">Note: You have enabled App - Settings - Password access - Keyboard switching - Auto-switch keyboard, but it doesn\'t seem to be configured correctly.</string>
|
||||
<string name="switch_keyboard_for_totp_enabled">Note: You have enabled App - Password access - Autofill-Service - Autofill for TOTP entries. This can cause this window to show when you open an entry with a TOTP.</string>
|
||||
<string name="switch_keyboard_inside_kp2a_enabled">Note: You have enabled App - Security - Use built-in keyboard inside Keepass2Android. This can cause this window to show when you open the app or edit an entry.</string>
|
||||
<string name="switch_keyboard_on_search_enabled">Note: You have enabled App - Security - Password access - Keyboard switching - Switch keyboard. This can cause this window to show when you search for an entry from the browser.</string>
|
||||
|
||||
</resources>
|
@@ -1,6 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<network-security-config>
|
||||
<base-config cleartextTrafficPermitted="true">
|
||||
<base-config>
|
||||
<trust-anchors>
|
||||
<certificates src="system" />
|
||||
<certificates src="user" />
|
||||
|
@@ -392,7 +392,7 @@ namespace keepass2android
|
||||
if (ioc.Path.Length == 0)
|
||||
{
|
||||
// No file name
|
||||
Toast.MakeText(this, Resource.String.FileNotFound, ToastLength.Long).Show();
|
||||
App.Kp2a.ShowMessage(this, Resource.String.FileNotFound, MessageSeverity.Error);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -400,7 +400,7 @@ namespace keepass2android
|
||||
if (!dbFile.Exists())
|
||||
{
|
||||
// File does not exist
|
||||
Toast.MakeText(this, Resource.String.FileNotFound, ToastLength.Long).Show();
|
||||
App.Kp2a.ShowMessage(this, Resource.String.FileNotFound, MessageSeverity.Error);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -408,7 +408,7 @@ namespace keepass2android
|
||||
{
|
||||
if (!ioc.Path.StartsWith("content://"))
|
||||
{
|
||||
Toast.MakeText(this, Resource.String.error_can_not_handle_uri, ToastLength.Long).Show();
|
||||
App.Kp2a.ShowMessage(this, Resource.String.error_can_not_handle_uri, MessageSeverity.Error);
|
||||
return false;
|
||||
}
|
||||
IoUtil.TryTakePersistablePermissions(this.ContentResolver, intent.Data);
|
||||
@@ -468,7 +468,7 @@ namespace keepass2android
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Toast.MakeText(this, "Failed to open child databases",ToastLength.Long).Show();
|
||||
App.Kp2a.ShowMessage(this, "Failed to open child databases", MessageSeverity.Error);
|
||||
Kp2aLog.LogUnexpectedError(e);
|
||||
}
|
||||
|
||||
|
@@ -70,15 +70,15 @@ namespace keepass2android
|
||||
|
||||
protected Bundle State { get; set; }
|
||||
|
||||
protected override void ShowToast(string text)
|
||||
protected override void ShowErrorToast(string text)
|
||||
{
|
||||
Toast.MakeText(this, text, ToastLength.Long).Show();
|
||||
App.Kp2a.ShowMessage(this, text, MessageSeverity.Error);
|
||||
}
|
||||
|
||||
protected override void ShowInvalidSchemeMessage(string dataString)
|
||||
{
|
||||
Toast.MakeText(this, Resources.GetString(Resource.String.unknown_uri_scheme, new Java.Lang.Object[] { dataString }),
|
||||
ToastLength.Long).Show();
|
||||
App.Kp2a.ShowMessage(this, Resources.GetString(Resource.String.unknown_uri_scheme, new Java.Lang.Object[] { dataString }),
|
||||
MessageSeverity.Error);
|
||||
}
|
||||
|
||||
protected override string IntentToFilename(Intent data)
|
||||
@@ -194,7 +194,7 @@ namespace keepass2android
|
||||
|
||||
StartActivityForResult(intent, requestCode);
|
||||
#else
|
||||
Toast.MakeText(this, "File chooser is excluded!", ToastLength.Long).Show();
|
||||
App.Kp2a.ShowMessage(this, "File chooser is excluded!", MessageSeverity.Error);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
@@ -57,7 +57,7 @@ namespace keepass2android
|
||||
// Verify that passwords match
|
||||
if ( ! pass.Equals(confpass) ) {
|
||||
// Passwords do not match
|
||||
Toast.MakeText(Context, Resource.String.error_pass_match, ToastLength.Long).Show();
|
||||
App.Kp2a.ShowMessage(Context, Resource.String.error_pass_match, MessageSeverity.Error);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ namespace keepass2android
|
||||
|
||||
// Verify that a password or keyfile is set
|
||||
if ( pass.Length == 0 && keyfile.Length == 0 ) {
|
||||
Toast.MakeText(Context, Resource.String.error_nopass, ToastLength.Long).Show();
|
||||
App.Kp2a.ShowMessage(Context, Resource.String.error_nopass, MessageSeverity.Error);
|
||||
return;
|
||||
|
||||
}
|
||||
@@ -114,7 +114,7 @@ namespace keepass2android
|
||||
edit.PutString(App.Kp2a.CurrentDb.CurrentFingerprintModePrefKey, FingerprintUnlockMode.Disabled.ToString());
|
||||
edit.Commit();
|
||||
|
||||
Toast.MakeText(_dlg.Context, Resource.String.fingerprint_reenable, ToastLength.Long).Show();
|
||||
App.Kp2a.ShowMessage(_dlg.Context, Resource.String.fingerprint_reenable, MessageSeverity.Warning);
|
||||
_dlg.Context.StartActivity(typeof(BiometricSetupActivity));
|
||||
}
|
||||
|
||||
|
@@ -121,7 +121,7 @@ namespace keepass2android
|
||||
|
||||
} catch (Exception e)
|
||||
{
|
||||
Toast.MakeText(this, e.Message, ToastLength.Long).Show();
|
||||
App.Kp2a.ShowMessage(this, Util.GetErrorMessage(e), MessageSeverity.Error);
|
||||
SetResult(Result.Canceled);
|
||||
Finish();
|
||||
return;
|
||||
@@ -184,7 +184,7 @@ namespace keepass2android
|
||||
createUrlEntry.Click += (sender, e) =>
|
||||
{
|
||||
GroupActivity.Launch(this, new CreateEntryThenCloseTask { Url = searchUrl, ShowUserNotifications = (AppTask as SelectEntryTask)?.ShowUserNotifications ?? ActivationCondition.Always }, new ActivityLaunchModeRequestCode(0));
|
||||
Toast.MakeText(this, GetString(Resource.String.select_group_then_add, new Java.Lang.Object[] { GetString(Resource.String.add_entry) }), ToastLength.Long).Show();
|
||||
App.Kp2a.ShowMessage(this, GetString(Resource.String.select_group_then_add, new Java.Lang.Object[] { GetString(Resource.String.add_entry) }), MessageSeverity.Info);
|
||||
};
|
||||
}
|
||||
else
|
||||
|
@@ -6,6 +6,7 @@ using System.Threading;
|
||||
using Android.App;
|
||||
using Android.Content;
|
||||
using Android.OS;
|
||||
using Android.Preferences;
|
||||
using Android.Runtime;
|
||||
using Android.Util;
|
||||
using Android.Views;
|
||||
@@ -15,8 +16,8 @@ using keepass2android;
|
||||
|
||||
namespace keepass2android
|
||||
{
|
||||
[Activity(Label = AppNames.AppName, TaskAffinity = "", NoHistory = true)]
|
||||
public class SwitchImeActivity : Activity
|
||||
[Activity(Label = AppNames.AppName, Theme = "@style/Kp2aTheme_BlueActionBar")]
|
||||
public class SwitchImeActivity : AndroidX.AppCompat.App.AppCompatActivity
|
||||
{
|
||||
protected override void OnCreate(Bundle savedInstanceState)
|
||||
{
|
||||
@@ -24,7 +25,26 @@ namespace keepass2android
|
||||
SetContentView(Resource.Layout.switch_ime_activity_layout);
|
||||
FindViewById<Button>(Resource.Id.btn_reopen).Click += (sender, args) => TrySwitchKeyboard();
|
||||
FindViewById<Button>(Resource.Id.btn_cancel).Click += (sender, args) => Finish();
|
||||
FindViewById<Button>(Resource.Id.btn_open_settings).Click += (sender, args) => AppSettingsActivity.Launch(this);
|
||||
|
||||
var prefs = PreferenceManager.GetDefaultSharedPreferences(LocaleManager.LocalizedAppContext);
|
||||
|
||||
bool useKp2aKeyboardInKp2a = prefs.GetBoolean(GetString(Resource.String.UseKp2aKeyboardInKp2a_key), false);
|
||||
bool kp2a_switch_rooted = prefs.GetBoolean("kp2a_switch_rooted", false);
|
||||
bool AutoFillTotp_prefs_ActivateKeyboard = prefs.GetBoolean("AutoFillTotp_prefs_ActivateKeyboard_key", false);
|
||||
bool OpenKp2aKeyboardAutomatically = prefs.GetBoolean(GetString(Resource.String.OpenKp2aKeyboardAutomatically_key), Resources.GetBoolean(Resource.Boolean.OpenKp2aKeyboardAutomatically_default));
|
||||
|
||||
FindViewById(Resource.Id.note_UseKp2aKeyboardInKp2a).Visibility = useKp2aKeyboardInKp2a ? ViewStates.Visible : ViewStates.Gone;
|
||||
FindViewById(Resource.Id.note_kp2a_switch_rooted).Visibility = kp2a_switch_rooted ? ViewStates.Visible : ViewStates.Gone;
|
||||
FindViewById(Resource.Id.note_AutoFillTotp_prefs_ActivateKeyboard).Visibility = AutoFillTotp_prefs_ActivateKeyboard ? ViewStates.Visible : ViewStates.Gone;
|
||||
FindViewById(Resource.Id.note_OpenKp2aKeyboardAutomatically).Visibility = OpenKp2aKeyboardAutomatically ? ViewStates.Visible : ViewStates.Gone;
|
||||
|
||||
bool hasNote = useKp2aKeyboardInKp2a || kp2a_switch_rooted || AutoFillTotp_prefs_ActivateKeyboard || OpenKp2aKeyboardAutomatically;
|
||||
((LinearLayout)FindViewById(Resource.Id.settings_notes_container)).Visibility = hasNote ? ViewStates.Visible : ViewStates.Gone;
|
||||
|
||||
}
|
||||
|
||||
|
||||
private string Kp2aInputMethodName
|
||||
{
|
||||
get { return PackageName + "/keepass2android.softkeyboard.KP2AKeyboard"; }
|
||||
|
@@ -40,7 +40,7 @@ namespace keepass2android
|
||||
catch (Exception e)
|
||||
{
|
||||
|
||||
Finish(false, e.Message);
|
||||
Finish(false, Util.GetErrorMessage(e));
|
||||
}
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ namespace keepass2android
|
||||
OnFinish onFinish = new ActionOnFinish(_activity, (success, message, activity) =>
|
||||
{
|
||||
if (!String.IsNullOrEmpty(message))
|
||||
Toast.MakeText(activity, message, ToastLength.Long).Show();
|
||||
App.Kp2a.ShowMessage(activity, message, success ? MessageSeverity.Info : MessageSeverity.Error);
|
||||
|
||||
// Tell the adapter to refresh it's list
|
||||
BaseAdapter adapter = (activity as GroupBaseActivity)?.ListAdapter;
|
||||
|
@@ -161,7 +161,7 @@ namespace PluginTOTP
|
||||
return;
|
||||
try
|
||||
{
|
||||
_uiThreadHandler.Post(() => Toast.MakeText(_ctx, warning, ToastLength.Short).Show());
|
||||
_uiThreadHandler.Post(() => App.Kp2a.ShowMessage(_ctx, warning, MessageSeverity.Warning));
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
|
162
src/keepass2android-app/Utils/MessagePresenter.cs
Normal file
162
src/keepass2android-app/Utils/MessagePresenter.cs
Normal file
@@ -0,0 +1,162 @@
|
||||
using Android.OS;
|
||||
using Android.Views;
|
||||
using Google.Android.Material.Snackbar;
|
||||
|
||||
namespace keepass2android.Utils
|
||||
{
|
||||
public struct Message
|
||||
{
|
||||
public Message()
|
||||
{
|
||||
Text = null;
|
||||
Severity = MessageSeverity.Info;
|
||||
}
|
||||
|
||||
public string Text { get; set; }
|
||||
public MessageSeverity Severity { get; set; }
|
||||
public bool ShowOnSubsequentScreens { get; set; } = true;
|
||||
}
|
||||
public interface IMessagePresenter
|
||||
{
|
||||
void ShowMessage(Message message);
|
||||
|
||||
List<Message> PendingMessages
|
||||
{
|
||||
get;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
internal class NonePresenter : IMessagePresenter
|
||||
{
|
||||
public void ShowMessage(Message message)
|
||||
{
|
||||
PendingMessages.Add(message);
|
||||
}
|
||||
|
||||
public List<Message> PendingMessages
|
||||
{
|
||||
get;
|
||||
set;
|
||||
} = new List<Message>();
|
||||
}
|
||||
|
||||
|
||||
internal class ToastPresenter : IMessagePresenter
|
||||
{
|
||||
public void ShowMessage(Message message)
|
||||
{
|
||||
Toast.MakeText(App.Context, message.Text, ToastLength.Long).Show();
|
||||
}
|
||||
|
||||
public List<Message> PendingMessages => new();
|
||||
}
|
||||
|
||||
internal class ChainedSnackbarPresenter: IMessagePresenter
|
||||
{
|
||||
internal ChainedSnackbarPresenter(View anchorView)
|
||||
{
|
||||
this.AnchorView = anchorView;
|
||||
|
||||
}
|
||||
|
||||
private DateTime nextSnackbarShowTime = DateTime.Now;
|
||||
private List<Message> queuedMessages = new List<Message>();
|
||||
|
||||
public View AnchorView { get; set; }
|
||||
|
||||
private TimeSpan chainingTime = TimeSpan.FromSeconds(1.5);
|
||||
private Snackbar snackbar;
|
||||
private Message lastMessage;
|
||||
|
||||
public void ShowMessage(Message message)
|
||||
{
|
||||
if (DateTime.Now <= nextSnackbarShowTime)
|
||||
{
|
||||
var waitDuration = nextSnackbarShowTime - DateTime.Now;
|
||||
nextSnackbarShowTime = nextSnackbarShowTime.Add(chainingTime);
|
||||
|
||||
if (!queuedMessages.Any())
|
||||
{
|
||||
if (Looper.MainLooper != null)
|
||||
{
|
||||
new Handler(Looper.MainLooper).PostDelayed(ShowNextSnackbar,
|
||||
(long)waitDuration.TotalMilliseconds);
|
||||
}
|
||||
else
|
||||
{
|
||||
Kp2aLog.Log("Currently cannot show message");
|
||||
}
|
||||
}
|
||||
|
||||
queuedMessages.Add(message);
|
||||
|
||||
return;
|
||||
}
|
||||
ShowSnackbarNow(message);
|
||||
nextSnackbarShowTime = DateTime.Now.Add(chainingTime);
|
||||
|
||||
}
|
||||
|
||||
public List<Message> PendingMessages
|
||||
{
|
||||
get
|
||||
{
|
||||
List<Message> pendingMessages = new List<Message>();
|
||||
if (snackbar?.IsShown == true)
|
||||
{
|
||||
pendingMessages.Add(lastMessage);
|
||||
}
|
||||
|
||||
pendingMessages.AddRange(queuedMessages);
|
||||
return pendingMessages;
|
||||
}
|
||||
}
|
||||
|
||||
private void ShowNextSnackbar()
|
||||
{
|
||||
if (!queuedMessages.Any())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
ShowSnackbarNow(queuedMessages.First());
|
||||
queuedMessages.RemoveAt(0);
|
||||
|
||||
if (!queuedMessages.Any())
|
||||
{
|
||||
new Handler().PostDelayed(() => { ShowNextSnackbar(); }, (long)chainingTime.TotalMilliseconds);
|
||||
}
|
||||
}
|
||||
|
||||
private void ShowSnackbarNow(Message message)
|
||||
{
|
||||
snackbar = Snackbar
|
||||
.Make(AnchorView, message.Text,
|
||||
Snackbar.LengthLong);
|
||||
snackbar.SetTextMaxLines(10);
|
||||
if ((int)Build.VERSION.SdkInt >= 23)
|
||||
{
|
||||
if (message.Severity == MessageSeverity.Error)
|
||||
{
|
||||
snackbar.SetBackgroundTint(App.Context.GetColor(Resource.Color.md_theme_errorContainer));
|
||||
snackbar.SetTextColor(App.Context.GetColor(Resource.Color.md_theme_onErrorContainer));
|
||||
}
|
||||
else if (message.Severity == MessageSeverity.Warning)
|
||||
{
|
||||
snackbar.SetBackgroundTint(App.Context.GetColor(Resource.Color.md_theme_inverseSurface));
|
||||
snackbar.SetTextColor(App.Context.GetColor(Resource.Color.md_theme_inverseOnSurface));
|
||||
}
|
||||
else
|
||||
{
|
||||
snackbar.SetBackgroundTint(App.Context.GetColor(Resource.Color.md_theme_secondaryContainer));
|
||||
snackbar.SetTextColor(App.Context.GetColor(Resource.Color.md_theme_onSecondaryContainer));
|
||||
}
|
||||
}
|
||||
|
||||
snackbar.Show();
|
||||
lastMessage = message;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
@@ -43,8 +43,10 @@ using keepass2android.Io;
|
||||
using keepass2android.addons.OtpKeyProv;
|
||||
using keepass2android.database.edit;
|
||||
using keepass2android;
|
||||
using keepass2android.Utils;
|
||||
using KeePassLib.Interfaces;
|
||||
using KeePassLib.Utility;
|
||||
using Message = keepass2android.Utils.Message;
|
||||
#if !NoNet
|
||||
#if !EXCLUDE_JAVAFILESTORAGE
|
||||
using Android.Gms.Common;
|
||||
@@ -52,6 +54,8 @@ using Keepass2android.Javafilestorage;
|
||||
using GoogleDriveFileStorage = keepass2android.Io.GoogleDriveFileStorage;
|
||||
using GoogleDriveAppDataFileStorage = keepass2android.Io.GoogleDriveAppDataFileStorage;
|
||||
using PCloudFileStorage = keepass2android.Io.PCloudFileStorage;
|
||||
using static keepass2android.Util;
|
||||
using static Android.Provider.Telephony.MmsSms;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -187,8 +191,8 @@ namespace keepass2android
|
||||
var prefs = PreferenceManager.GetDefaultSharedPreferences(LocaleManager.LocalizedAppContext);
|
||||
var createBackup = prefs.GetBoolean(LocaleManager.LocalizedAppContext.GetString(Resource.String.CreateBackups_key), true)
|
||||
&& !(new LocalFileStorage(this).IsLocalBackup(ioConnectionInfo));
|
||||
|
||||
MemoryStream backupCopy = new MemoryStream();
|
||||
Kp2aLog.Log("LoadDb: Copying database for backup");
|
||||
MemoryStream backupCopy = new MemoryStream();
|
||||
if (createBackup)
|
||||
{
|
||||
|
||||
@@ -197,6 +201,7 @@ namespace keepass2android
|
||||
//reset stream if we need to reuse it later:
|
||||
memoryStream.Seek(0, SeekOrigin.Begin);
|
||||
}
|
||||
Kp2aLog.Log("LoadDb: Checking open databases");
|
||||
|
||||
foreach (Database openDb in _openDatabases)
|
||||
{
|
||||
@@ -346,7 +351,10 @@ namespace keepass2android
|
||||
QuickUnlockEnabled = enabled;
|
||||
}
|
||||
|
||||
public bool QuickUnlockEnabled { get; private set; }
|
||||
public bool ScreenLockWasEnabledWhenOpeningDatabase { get; set; }
|
||||
|
||||
|
||||
public bool QuickUnlockEnabled { get; private set; }
|
||||
|
||||
public int QuickUnlockKeyLength { get; private set; }
|
||||
|
||||
@@ -472,6 +480,7 @@ namespace keepass2android
|
||||
private readonly HashSet<RealProgressDialog> _activeProgressDialogs = new HashSet<RealProgressDialog>();
|
||||
// Whether the app is currently showing a dialog that requires user input, like a yesNoCancel dialog
|
||||
private bool _isShowingUserInputDialog = false;
|
||||
private IMessagePresenter? _messagePresenter;
|
||||
|
||||
private void AskForReload(Activity activity, Action<bool> actionOnResult)
|
||||
{
|
||||
@@ -831,7 +840,7 @@ namespace keepass2android
|
||||
new DropboxAppFolderFileStorage(LocaleManager.LocalizedAppContext, this),
|
||||
GoogleApiAvailability.Instance.IsGooglePlayServicesAvailable(LocaleManager.LocalizedAppContext)==ConnectionResult.Success ? new GoogleDriveFileStorage(LocaleManager.LocalizedAppContext, this) : null,
|
||||
GoogleApiAvailability.Instance.IsGooglePlayServicesAvailable(LocaleManager.LocalizedAppContext)==ConnectionResult.Success ? new GoogleDriveAppDataFileStorage(LocaleManager.LocalizedAppContext, this) : null,
|
||||
new OneDriveFileStorage(),
|
||||
new OneDriveFileStorage(this),
|
||||
new OneDrive2FullFileStorage(),
|
||||
new OneDrive2MyFilesFileStorage(),
|
||||
new OneDrive2AppFolderFileStorage(),
|
||||
@@ -913,14 +922,16 @@ namespace keepass2android
|
||||
{
|
||||
var prefs = PreferenceManager.GetDefaultSharedPreferences(LocaleManager.LocalizedAppContext);
|
||||
|
||||
ValidationMode validationMode = ValidationMode.Warn;
|
||||
ValidationMode validationMode = ValidationMode.Error;
|
||||
|
||||
string strValMode = prefs.GetString(LocaleManager.LocalizedAppContext.Resources.GetString(Resource.String.AcceptAllServerCertificates_key),
|
||||
LocaleManager.LocalizedAppContext.Resources.GetString(Resource.String.AcceptAllServerCertificates_default));
|
||||
|
||||
if (strValMode == "IGNORE")
|
||||
validationMode = ValidationMode.Ignore;
|
||||
else if (strValMode == "ERROR")
|
||||
else if (strValMode == "WARN")
|
||||
validationMode = ValidationMode.Warn;
|
||||
else if (strValMode == "ERROR")
|
||||
validationMode = ValidationMode.Error;
|
||||
return validationMode;
|
||||
}
|
||||
@@ -977,7 +988,7 @@ namespace keepass2android
|
||||
#endif
|
||||
private void ShowValidationWarning(string error)
|
||||
{
|
||||
ShowToast(LocaleManager.LocalizedAppContext.GetString(Resource.String.CertificateWarning, error));
|
||||
App.Kp2a.ShowMessage(LocaleManager.LocalizedAppContext, LocaleManager.LocalizedAppContext.GetString(Resource.String.CertificateWarning, error), MessageSeverity.Warning);
|
||||
}
|
||||
|
||||
|
||||
@@ -1026,25 +1037,21 @@ namespace keepass2android
|
||||
return newDatabase;
|
||||
}
|
||||
|
||||
internal void ShowToast(string message)
|
||||
internal void ShowToast(string message, MessageSeverity severity)
|
||||
{
|
||||
var handler = new Handler(Looper.MainLooper);
|
||||
handler.Post(() => { var toast = Toast.MakeText(LocaleManager.LocalizedAppContext, message, ToastLength.Long);
|
||||
toast.SetGravity(GravityFlags.Center, 0, 0);
|
||||
toast.Show();
|
||||
});
|
||||
App.Kp2a.ShowMessage(LocaleManager.LocalizedAppContext, message, severity);
|
||||
}
|
||||
|
||||
public void CouldntSaveToRemote(IOConnectionInfo ioc, Exception e)
|
||||
{
|
||||
var errorMessage = GetErrorMessageForFileStorageException(e);
|
||||
ShowToast(LocaleManager.LocalizedAppContext.GetString(Resource.String.CouldNotSaveToRemote, errorMessage));
|
||||
ShowToast(LocaleManager.LocalizedAppContext.GetString(Resource.String.CouldNotSaveToRemote, errorMessage), MessageSeverity.Error);
|
||||
}
|
||||
|
||||
private string GetErrorMessageForFileStorageException(Exception e)
|
||||
{
|
||||
string errorMessage = e.Message;
|
||||
if (e is OfflineModeException)
|
||||
{
|
||||
var errorMessage = Util.GetErrorMessage(e);
|
||||
if (e is OfflineModeException)
|
||||
errorMessage = GetResourceString(UiStringKey.InOfflineMode);
|
||||
if (e is DocumentAccessRevokedException)
|
||||
errorMessage = GetResourceString(UiStringKey.DocumentAccessRevoked);
|
||||
@@ -1053,31 +1060,31 @@ namespace keepass2android
|
||||
}
|
||||
|
||||
|
||||
public void CouldntOpenFromRemote(IOConnectionInfo ioc, Exception ex)
|
||||
public void CouldntOpenFromRemote(IOConnectionInfo ioc, Exception ex)
|
||||
{
|
||||
var errorMessage = GetErrorMessageForFileStorageException(ex);
|
||||
ShowToast(LocaleManager.LocalizedAppContext.GetString(Resource.String.CouldNotLoadFromRemote, errorMessage));
|
||||
ShowToast(LocaleManager.LocalizedAppContext.GetString(Resource.String.CouldNotLoadFromRemote, errorMessage), MessageSeverity.Error);
|
||||
}
|
||||
|
||||
public void UpdatedCachedFileOnLoad(IOConnectionInfo ioc)
|
||||
{
|
||||
ShowToast(LocaleManager.LocalizedAppContext.GetString(Resource.String.UpdatedCachedFileOnLoad,
|
||||
new Java.Lang.Object[] { LocaleManager.LocalizedAppContext.GetString(Resource.String.database_file) }));
|
||||
new Java.Lang.Object[] { LocaleManager.LocalizedAppContext.GetString(Resource.String.database_file) }), MessageSeverity.Info);
|
||||
}
|
||||
|
||||
public void UpdatedRemoteFileOnLoad(IOConnectionInfo ioc)
|
||||
{
|
||||
ShowToast(LocaleManager.LocalizedAppContext.GetString(Resource.String.UpdatedRemoteFileOnLoad));
|
||||
ShowToast(LocaleManager.LocalizedAppContext.GetString(Resource.String.UpdatedRemoteFileOnLoad), MessageSeverity.Warning);
|
||||
}
|
||||
|
||||
public void NotifyOpenFromLocalDueToConflict(IOConnectionInfo ioc)
|
||||
{
|
||||
ShowToast(LocaleManager.LocalizedAppContext.GetString(Resource.String.NotifyOpenFromLocalDueToConflict));
|
||||
ShowToast(LocaleManager.LocalizedAppContext.GetString(Resource.String.NotifyOpenFromLocalDueToConflict), MessageSeverity.Info);
|
||||
}
|
||||
|
||||
public void LoadedFromRemoteInSync(IOConnectionInfo ioc)
|
||||
{
|
||||
ShowToast(LocaleManager.LocalizedAppContext.GetString(Resource.String.LoadedFromRemoteInSync));
|
||||
ShowToast(LocaleManager.LocalizedAppContext.GetString(Resource.String.LoadedFromRemoteInSync), MessageSeverity.Info);
|
||||
}
|
||||
|
||||
public void ClearOfflineCache()
|
||||
@@ -1241,7 +1248,7 @@ namespace keepass2android
|
||||
{
|
||||
var db = TryFindDatabaseForElement(element);
|
||||
if (db == null)
|
||||
throw new Exception("Database element not found!");
|
||||
throw new Exception($"Database element {element.Uuid} not found in any of {OpenDatabases.Count()} databases!");
|
||||
return db;
|
||||
}
|
||||
|
||||
@@ -1286,7 +1293,47 @@ namespace keepass2android
|
||||
return GetResourceString("filestoragename_" + protocolId);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void ShowMessage(Context ctx, int resourceId, MessageSeverity severity)
|
||||
{
|
||||
ShowMessage(ctx, ctx.Resources.GetString(resourceId), severity);
|
||||
|
||||
}
|
||||
public void ShowMessage(Context ctx, string text, MessageSeverity severity)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(text))
|
||||
{
|
||||
return;
|
||||
}
|
||||
MessagePresenter.ShowMessage(new Message{Text=text, Severity = severity});
|
||||
}
|
||||
|
||||
public IMessagePresenter MessagePresenter
|
||||
{
|
||||
get => _messagePresenter ?? new ToastPresenter();
|
||||
set
|
||||
{
|
||||
if (value == null)
|
||||
{
|
||||
// Presenter is being reset. Use a NonePresenter to remember pending messages
|
||||
value = new NonePresenter();
|
||||
}
|
||||
// transfer pending messages to new presenter
|
||||
if (_messagePresenter != null)
|
||||
{
|
||||
foreach (var message in _messagePresenter.PendingMessages)
|
||||
{
|
||||
if (message.ShowOnSubsequentScreens)
|
||||
{
|
||||
value.ShowMessage(message);
|
||||
}
|
||||
}
|
||||
}
|
||||
_messagePresenter = value;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
///Application class for Keepass2Android: Contains static Database variable to be used by all components.
|
||||
|
@@ -15,6 +15,7 @@ using Android.Content.Res;
|
||||
using Android.Preferences;
|
||||
using Google.Android.Material.Dialog;
|
||||
using keepass2android;
|
||||
using PluginTOTP;
|
||||
|
||||
namespace keepass2android
|
||||
{
|
||||
@@ -638,19 +639,7 @@ namespace keepass2android
|
||||
|
||||
if (CopyTotpToClipboard && isTotpEntry)
|
||||
{
|
||||
Dictionary<string, string> entryFields = pwEntryOutput.OutputStrings.ToDictionary(pair => StrUtil.SafeXmlString(pair.Key), pair => pair.Value.ReadString());
|
||||
var totpData= totpPluginAdapter.GetTotpData(entryFields, activity, true);
|
||||
if (totpData.IsTotpEntry)
|
||||
{
|
||||
TOTPProvider prov = new TOTPProvider(totpData);
|
||||
string totp = prov.GenerateByByte(totpData.TotpSecret);
|
||||
CopyToClipboardService.CopyValueToClipboardWithTimeout(activity, totp, true);
|
||||
|
||||
Toast.MakeText(activity, activity.GetString(Resource.String.TotpCopiedToClipboard),
|
||||
ToastLength.Long).Show();
|
||||
}
|
||||
|
||||
|
||||
DoCopyTotpToClipboard(activity, pwEntryOutput, totpPluginAdapter);
|
||||
}
|
||||
|
||||
if (CloseAfterCreate)
|
||||
@@ -661,7 +650,23 @@ namespace keepass2android
|
||||
activity.CloseAfterTaskComplete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static void DoCopyTotpToClipboard(EntryActivity activity, PwEntryOutput pwEntryOutput,
|
||||
ITotpPluginAdapter? totpPluginAdapter)
|
||||
{
|
||||
Dictionary<string, string> entryFields = pwEntryOutput.OutputStrings.ToDictionary(pair => StrUtil.SafeXmlString(pair.Key), pair => pair.Value.ReadString());
|
||||
var totpData = totpPluginAdapter.GetTotpData(entryFields, activity, true);
|
||||
if (totpData.IsTotpEntry)
|
||||
{
|
||||
TOTPProvider prov = new TOTPProvider(totpData);
|
||||
string totp = prov.GenerateByByte(totpData.TotpSecret);
|
||||
CopyToClipboardService.CopyValueToClipboardWithTimeout(activity, totp, true);
|
||||
|
||||
App.Kp2a.ShowMessage(activity, activity.GetString(Resource.String.TotpCopiedToClipboard),
|
||||
MessageSeverity.Info);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
@@ -990,9 +995,9 @@ namespace keepass2android
|
||||
|
||||
if (ToastEnable) {
|
||||
String toastMessage = groupBaseActivity.GetString (Resource.String.NavigationToGroupCompleted_message, new Java.Lang.Object[] { FullGroupName});
|
||||
|
||||
Toast.MakeText (groupBaseActivity, toastMessage, ToastLength.Long).Show ();
|
||||
}
|
||||
|
||||
App.Kp2a.ShowMessage(groupBaseActivity, toastMessage, MessageSeverity.Info);
|
||||
}
|
||||
|
||||
groupBaseActivity.StartTask (TaskToBeLaunchedAfterNavigation);
|
||||
return;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user