mirror of
https://github.com/android-password-store/Android-Password-Store.git
synced 2025-09-07 16:09:38 +02:00
Add support for "work/example.org.gpg" folder layout
This commit is contained in:
parent
5a3220527f
commit
441b4d3b68
|
@ -97,7 +97,7 @@ private fun PasswordItem.Companion.makeComparator(
|
||||||
.then(compareBy(nullsLast(CaseInsensitiveComparator)) {
|
.then(compareBy(nullsLast(CaseInsensitiveComparator)) {
|
||||||
directoryStructure.getIdentifierFor(it.file)
|
directoryStructure.getIdentifierFor(it.file)
|
||||||
})
|
})
|
||||||
.then(compareBy(CaseInsensitiveComparator) {
|
.then(compareBy(nullsLast(CaseInsensitiveComparator)) {
|
||||||
directoryStructure.getUsernameFor(it.file)
|
directoryStructure.getUsernameFor(it.file)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,6 +19,7 @@ import com.github.ajalt.timberkt.Timber.tag
|
||||||
import com.github.ajalt.timberkt.e
|
import com.github.ajalt.timberkt.e
|
||||||
import com.zeapo.pwdstore.PasswordEntry
|
import com.zeapo.pwdstore.PasswordEntry
|
||||||
import com.zeapo.pwdstore.R
|
import com.zeapo.pwdstore.R
|
||||||
|
import com.zeapo.pwdstore.utils.PasswordRepository
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.security.MessageDigest
|
import java.security.MessageDigest
|
||||||
|
|
||||||
|
@ -100,7 +101,10 @@ private fun makeRemoteView(
|
||||||
|
|
||||||
fun makeFillMatchRemoteView(context: Context, file: File, formOrigin: FormOrigin): RemoteViews {
|
fun makeFillMatchRemoteView(context: Context, file: File, formOrigin: FormOrigin): RemoteViews {
|
||||||
val title = formOrigin.getPrettyIdentifier(context, untrusted = false)
|
val title = formOrigin.getPrettyIdentifier(context, untrusted = false)
|
||||||
val summary = AutofillPreferences.directoryStructure(context).getUsernameFor(file)
|
val directoryStructure = AutofillPreferences.directoryStructure(context)
|
||||||
|
val relativeFile = file.relativeTo(PasswordRepository.getRepositoryDirectory(context))
|
||||||
|
val summary = directoryStructure.getUsernameFor(relativeFile)
|
||||||
|
?: directoryStructure.getPathToIdentifierFor(relativeFile) ?: ""
|
||||||
val iconRes = R.drawable.ic_person_black_24dp
|
val iconRes = R.drawable.ic_person_black_24dp
|
||||||
return makeRemoteView(context, title, summary, iconRes)
|
return makeRemoteView(context, title, summary, iconRes)
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@ private val Context.defaultSharedPreferences: SharedPreferences
|
||||||
get() = PreferenceManager.getDefaultSharedPreferences(this)
|
get() = PreferenceManager.getDefaultSharedPreferences(this)
|
||||||
|
|
||||||
enum class DirectoryStructure(val value: String) {
|
enum class DirectoryStructure(val value: String) {
|
||||||
|
EncryptedUsername("encrypted_username"),
|
||||||
FileBased("file"),
|
FileBased("file"),
|
||||||
DirectoryBased("directory");
|
DirectoryBased("directory");
|
||||||
|
|
||||||
|
@ -24,11 +25,13 @@ enum class DirectoryStructure(val value: String) {
|
||||||
* [DirectoryStructure].
|
* [DirectoryStructure].
|
||||||
*
|
*
|
||||||
* Examples:
|
* Examples:
|
||||||
|
* - * --> null (EncryptedUsername)
|
||||||
* - work/example.org/john@doe.org.gpg --> john@doe.org (FileBased)
|
* - work/example.org/john@doe.org.gpg --> john@doe.org (FileBased)
|
||||||
* - work/example.org/john@doe.org/password.gpg --> john@doe.org (DirectoryBased)
|
* - work/example.org/john@doe.org/password.gpg --> john@doe.org (DirectoryBased)
|
||||||
* - Temporary PIN.gpg --> Temporary PIN (DirectoryBased, fallback)
|
* - Temporary PIN.gpg --> Temporary PIN (DirectoryBased, fallback)
|
||||||
*/
|
*/
|
||||||
fun getUsernameFor(file: File): String = when (this) {
|
fun getUsernameFor(file: File): String? = when (this) {
|
||||||
|
EncryptedUsername -> null
|
||||||
FileBased -> file.nameWithoutExtension
|
FileBased -> file.nameWithoutExtension
|
||||||
DirectoryBased -> file.parentFile?.name ?: file.nameWithoutExtension
|
DirectoryBased -> file.parentFile?.name ?: file.nameWithoutExtension
|
||||||
}
|
}
|
||||||
|
@ -41,12 +44,14 @@ enum class DirectoryStructure(val value: String) {
|
||||||
* [DirectoryStructure.getAccountPartFor] will always return a non-null result.
|
* [DirectoryStructure.getAccountPartFor] will always return a non-null result.
|
||||||
*
|
*
|
||||||
* Examples:
|
* Examples:
|
||||||
|
* - work/example.org.gpg --> example.org (EncryptedUsername)
|
||||||
* - work/example.org/john@doe.org.gpg --> example.org (FileBased)
|
* - work/example.org/john@doe.org.gpg --> example.org (FileBased)
|
||||||
* - example.org.gpg --> example.org (FileBased, fallback)
|
* - example.org.gpg --> example.org (FileBased, fallback)
|
||||||
* - work/example.org/john@doe.org/password.gpg --> example.org (DirectoryBased)
|
* - work/example.org/john@doe.org/password.gpg --> example.org (DirectoryBased)
|
||||||
* - Temporary PIN.gpg --> null (DirectoryBased)
|
* - Temporary PIN.gpg --> null (DirectoryBased)
|
||||||
*/
|
*/
|
||||||
fun getIdentifierFor(file: File): String? = when (this) {
|
fun getIdentifierFor(file: File): String? = when (this) {
|
||||||
|
EncryptedUsername -> file.nameWithoutExtension
|
||||||
FileBased -> file.parentFile?.name ?: file.nameWithoutExtension
|
FileBased -> file.parentFile?.name ?: file.nameWithoutExtension
|
||||||
DirectoryBased -> file.parentFile?.parent
|
DirectoryBased -> file.parentFile?.parent
|
||||||
}
|
}
|
||||||
|
@ -55,10 +60,8 @@ enum class DirectoryStructure(val value: String) {
|
||||||
* Returns the path components of [file] until right before the component that contains the
|
* Returns the path components of [file] until right before the component that contains the
|
||||||
* origin identifier according to the current [DirectoryStructure].
|
* origin identifier according to the current [DirectoryStructure].
|
||||||
*
|
*
|
||||||
* At least one of [DirectoryStructure.getIdentifierFor] and
|
|
||||||
* [DirectoryStructure.getAccountPartFor] will always return a non-null result.
|
|
||||||
*
|
|
||||||
* Examples:
|
* Examples:
|
||||||
|
* - work/example.org.gpg --> work (EncryptedUsername)
|
||||||
* - work/example.org/john@doe.org.gpg --> work (FileBased)
|
* - work/example.org/john@doe.org.gpg --> work (FileBased)
|
||||||
* - example.org/john@doe.org.gpg --> null (FileBased)
|
* - example.org/john@doe.org.gpg --> null (FileBased)
|
||||||
* - john@doe.org.gpg --> null (FileBased)
|
* - john@doe.org.gpg --> null (FileBased)
|
||||||
|
@ -66,6 +69,7 @@ enum class DirectoryStructure(val value: String) {
|
||||||
* - example.org/john@doe.org/password.gpg --> null (DirectoryBased)
|
* - example.org/john@doe.org/password.gpg --> null (DirectoryBased)
|
||||||
*/
|
*/
|
||||||
fun getPathToIdentifierFor(file: File): String? = when (this) {
|
fun getPathToIdentifierFor(file: File): String? = when (this) {
|
||||||
|
EncryptedUsername -> file.parent
|
||||||
FileBased -> file.parentFile?.parent
|
FileBased -> file.parentFile?.parent
|
||||||
DirectoryBased -> file.parentFile?.parentFile?.parent
|
DirectoryBased -> file.parentFile?.parentFile?.parent
|
||||||
}
|
}
|
||||||
|
@ -74,13 +78,18 @@ enum class DirectoryStructure(val value: String) {
|
||||||
* Returns the path component of [file] following the origin identifier according to the current
|
* Returns the path component of [file] following the origin identifier according to the current
|
||||||
* [DirectoryStructure] (without file extension).
|
* [DirectoryStructure] (without file extension).
|
||||||
*
|
*
|
||||||
|
* At least one of [DirectoryStructure.getIdentifierFor] and
|
||||||
|
* [DirectoryStructure.getAccountPartFor] will always return a non-null result.
|
||||||
|
*
|
||||||
* Examples:
|
* Examples:
|
||||||
|
* - * --> null (EncryptedUsername)
|
||||||
* - work/example.org/john@doe.org.gpg --> john@doe.org (FileBased)
|
* - work/example.org/john@doe.org.gpg --> john@doe.org (FileBased)
|
||||||
* - example.org.gpg --> null (FileBased, fallback)
|
* - example.org.gpg --> null (FileBased, fallback)
|
||||||
* - work/example.org/john@doe.org/password.gpg --> john@doe.org/password (DirectoryBased)
|
* - work/example.org/john@doe.org/password.gpg --> john@doe.org/password (DirectoryBased)
|
||||||
* - Temporary PIN.gpg --> Temporary PIN (DirectoryBased, fallback)
|
* - Temporary PIN.gpg --> Temporary PIN (DirectoryBased, fallback)
|
||||||
*/
|
*/
|
||||||
fun getAccountPartFor(file: File): String? = when (this) {
|
fun getAccountPartFor(file: File): String? = when (this) {
|
||||||
|
EncryptedUsername -> null
|
||||||
FileBased -> file.nameWithoutExtension.takeIf { file.parentFile != null }
|
FileBased -> file.nameWithoutExtension.takeIf { file.parentFile != null }
|
||||||
DirectoryBased -> file.parentFile?.let { parentFile ->
|
DirectoryBased -> file.parentFile?.let { parentFile ->
|
||||||
"${parentFile.name}/${file.nameWithoutExtension}"
|
"${parentFile.name}/${file.nameWithoutExtension}"
|
||||||
|
@ -89,11 +98,13 @@ enum class DirectoryStructure(val value: String) {
|
||||||
|
|
||||||
@RequiresApi(Build.VERSION_CODES.O)
|
@RequiresApi(Build.VERSION_CODES.O)
|
||||||
fun getSaveFolderName(sanitizedIdentifier: String, username: String?) = when (this) {
|
fun getSaveFolderName(sanitizedIdentifier: String, username: String?) = when (this) {
|
||||||
|
EncryptedUsername -> "/"
|
||||||
FileBased -> sanitizedIdentifier
|
FileBased -> sanitizedIdentifier
|
||||||
DirectoryBased -> Paths.get(sanitizedIdentifier, username ?: "username").toString()
|
DirectoryBased -> Paths.get(sanitizedIdentifier, username ?: "username").toString()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getSaveFileName(username: String?) = when (this) {
|
fun getSaveFileName(username: String?, identifier: String) = when (this) {
|
||||||
|
EncryptedUsername -> identifier
|
||||||
FileBased -> username
|
FileBased -> username
|
||||||
DirectoryBased -> "password"
|
DirectoryBased -> "password"
|
||||||
}
|
}
|
||||||
|
|
|
@ -60,7 +60,7 @@ class AutofillSaveActivity : Activity() {
|
||||||
sanitizedIdentifier = sanitizedIdentifier,
|
sanitizedIdentifier = sanitizedIdentifier,
|
||||||
username = credentials?.username
|
username = credentials?.username
|
||||||
)
|
)
|
||||||
val fileName = directoryStructure.getSaveFileName(username = credentials?.username)
|
val fileName = directoryStructure.getSaveFileName(username = credentials?.username, identifier = identifier)
|
||||||
val intent = Intent(context, AutofillSaveActivity::class.java).apply {
|
val intent = Intent(context, AutofillSaveActivity::class.java).apply {
|
||||||
putExtras(
|
putExtras(
|
||||||
bundleOf(
|
bundleOf(
|
||||||
|
|
|
@ -52,10 +52,12 @@
|
||||||
<item>xkpasswd</item>
|
<item>xkpasswd</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
<string-array name="oreo_autofill_directory_structure_entries">
|
<string-array name="oreo_autofill_directory_structure_entries">
|
||||||
<item>/example.org/john@doe.org(.gpg)</item>
|
<item>work/example.org(.gpg)</item>
|
||||||
<item>/example.org/john@doe.org/password(.gpg)</item>
|
<item>work/example.org/john@doe.org(.gpg)</item>
|
||||||
|
<item>work/example.org/john@doe.org/password(.gpg)</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
<string-array name="oreo_autofill_directory_structure_values">
|
<string-array name="oreo_autofill_directory_structure_values">
|
||||||
|
<item>encrypted_username</item>
|
||||||
<item>file</item>
|
<item>file</item>
|
||||||
<item>directory</item>
|
<item>directory</item>
|
||||||
</string-array>
|
</string-array>
|
||||||
|
|
Loading…
Reference in a new issue