diff --git a/app/src/main/java/app/passwordstore/ui/autofill/AutofillSaveActivity.kt b/app/src/main/java/app/passwordstore/ui/autofill/AutofillSaveActivity.kt index 138c4a737c..176f148e0c 100644 --- a/app/src/main/java/app/passwordstore/ui/autofill/AutofillSaveActivity.kt +++ b/app/src/main/java/app/passwordstore/ui/autofill/AutofillSaveActivity.kt @@ -128,6 +128,7 @@ class AutofillSaveActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) val repo = PasswordRepository.getRepositoryDirectory() + val saveRoot = AutofillPreferences.saveDirectory(this) val saveIntent = Intent(this, PasswordCreationActivity::class.java).apply { putExtras( @@ -136,7 +137,7 @@ class AutofillSaveActivity : AppCompatActivity() { putString(BasePGPActivity.EXTRA_REPO_PATH, repo.absolutePath) putString( BasePGPActivity.EXTRA_FILE_PATH, - repo + saveRoot .resolve(intent.getStringExtra(EXTRA_FOLDER_NAME) ?: throw NullPointerException()) .absolutePath, ) diff --git a/app/src/main/java/app/passwordstore/ui/settings/AutofillSettings.kt b/app/src/main/java/app/passwordstore/ui/settings/AutofillSettings.kt index ce009a1071..684a09cc11 100644 --- a/app/src/main/java/app/passwordstore/ui/settings/AutofillSettings.kt +++ b/app/src/main/java/app/passwordstore/ui/settings/AutofillSettings.kt @@ -109,6 +109,18 @@ class AutofillSettings(private val activity: FragmentActivity) : SettingsProvide summaryProvider = { activity.getString(R.string.preference_custom_public_suffixes_summary) } textInputHintRes = R.string.preference_custom_public_suffixes_hint } + editText(PreferenceKeys.AUTOFILL_SAVE_DIRECTORY) { + dependency = PreferenceKeys.AUTOFILL_ENABLE + titleRes = R.string.preference_autofill_save_directory_title + summaryProvider = { value -> + activity.getString( + R.string.preference_autofill_save_directory_summary, + value?.takeUnless { it.isBlank() } + ?: activity.getString(R.string.preference_autofill_save_directory_root_placeholder), + ) + } + textInputHintRes = R.string.preference_autofill_save_directory_hint + } } } } diff --git a/app/src/main/java/app/passwordstore/util/autofill/AutofillPreferences.kt b/app/src/main/java/app/passwordstore/util/autofill/AutofillPreferences.kt index f9298b2c11..2b7d03708b 100644 --- a/app/src/main/java/app/passwordstore/util/autofill/AutofillPreferences.kt +++ b/app/src/main/java/app/passwordstore/util/autofill/AutofillPreferences.kt @@ -7,6 +7,7 @@ package app.passwordstore.util.autofill import android.content.Context import androidx.core.content.edit import app.passwordstore.data.passfile.PasswordEntry +import app.passwordstore.data.repo.PasswordRepository import app.passwordstore.util.extensions.getString import app.passwordstore.util.extensions.sharedPrefs import app.passwordstore.util.services.getDefaultUsername @@ -22,6 +23,25 @@ object AutofillPreferences { return DirectoryStructure.fromValue(value) } + /** + * The directory Autofill-saved credentials should be placed under, relative to the repository + * root. Backed by [PreferenceKeys.AUTOFILL_SAVE_DIRECTORY]; falls back to the repository root + * itself when unset. This only affects saves made through the Autofill framework (the system + * "Save to Password Store?" prompt) — it has no effect on entries created from within the app. + */ + fun saveDirectory(context: Context): File { + val root = PasswordRepository.getRepositoryDirectory() + // Drop empty and ".." segments to prevent escaping the repository root. + val configured = + context.sharedPrefs + .getString(PreferenceKeys.AUTOFILL_SAVE_DIRECTORY) + ?.split('/') + ?.filter { it.isNotBlank() && it != ".." } + ?.joinToString("/") + ?.takeUnless { it.isBlank() } + return if (configured == null) root else root.resolve(configured) + } + fun strictDomainSearch(context: Context): Boolean { return context.sharedPrefs.getBoolean(PreferenceKeys.STRICT_DOMAIN_SEARCH, true) } diff --git a/app/src/main/java/app/passwordstore/util/settings/PreferenceKeys.kt b/app/src/main/java/app/passwordstore/util/settings/PreferenceKeys.kt index c090b7cc0f..5261d0c57f 100644 --- a/app/src/main/java/app/passwordstore/util/settings/PreferenceKeys.kt +++ b/app/src/main/java/app/passwordstore/util/settings/PreferenceKeys.kt @@ -58,6 +58,7 @@ object PreferenceKeys { const val OREO_AUTOFILL_CUSTOM_PUBLIC_SUFFIXES = "oreo_autofill_custom_public_suffixes" const val OREO_AUTOFILL_DEFAULT_USERNAME = "oreo_autofill_default_username" const val DIRECTORY_STRUCTURE = "oreo_autofill_directory_structure" + const val AUTOFILL_SAVE_DIRECTORY = "oreo_autofill_save_directory" const val STRICT_DOMAIN_SEARCH = "oreo_autofill_strict_domain_search" const val PREF_KEY_PWGEN_TYPE = "pref_key_pwgen_type" const val REPOSITORY_INITIALIZED = "repository_initialized" diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index cb18607fe7..88d50e883b 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -330,6 +330,10 @@ Custom domains Autofill will distinguish subdomains of these domains. company.com\npersonal.com + Save directory + Credentials saved via Autofill are placed under this folder instead of the store root. Currently: %1$s + e.g. www + store root Password item edited