diff options
Diffstat (limited to 'app/src/main')
20 files changed, 93 insertions, 4 deletions
diff --git a/app/src/main/java/app/passwordstore/data/repo/PasswordRepository.kt b/app/src/main/java/app/passwordstore/data/repo/PasswordRepository.kt index a4b3f316..1ddf1c61 100644 --- a/app/src/main/java/app/passwordstore/data/repo/PasswordRepository.kt +++ b/app/src/main/java/app/passwordstore/data/repo/PasswordRepository.kt @@ -29,6 +29,7 @@ object PasswordRepository { private val settings by unsafeLazy { Application.instance.sharedPrefs } private val filesDir get() = Application.instance.filesDir + val isInitialized: Boolean get() = repository != null diff --git a/app/src/main/java/app/passwordstore/ui/adapters/PasswordItemRecyclerAdapter.kt b/app/src/main/java/app/passwordstore/ui/adapters/PasswordItemRecyclerAdapter.kt index 9457cc0d..35c34690 100644 --- a/app/src/main/java/app/passwordstore/ui/adapters/PasswordItemRecyclerAdapter.kt +++ b/app/src/main/java/app/passwordstore/ui/adapters/PasswordItemRecyclerAdapter.kt @@ -78,6 +78,7 @@ open class PasswordItemRecyclerAdapter(coroutineScope: CoroutineScope) : itemDetails = object : ItemDetailsLookup.ItemDetails<String>() { override fun getPosition() = absoluteAdapterPosition + override fun getSelectionKey() = item.stableId } } diff --git a/app/src/main/java/app/passwordstore/ui/crypto/BasePgpActivity.kt b/app/src/main/java/app/passwordstore/ui/crypto/BasePgpActivity.kt index 14f6c843..ede3839a 100644 --- a/app/src/main/java/app/passwordstore/ui/crypto/BasePgpActivity.kt +++ b/app/src/main/java/app/passwordstore/ui/crypto/BasePgpActivity.kt @@ -163,10 +163,8 @@ open class BasePgpActivity : AppCompatActivity() { fun getParentPath(fullPath: String, repositoryPath: String): String { val relativePath = getRelativePath(fullPath, repositoryPath) val index = relativePath.lastIndexOf("/") - return "/${relativePath.substring(startIndex = 0, endIndex = index + 1)}/".replace( - "/+".toRegex(), - "/" - ) + return "/${relativePath.substring(startIndex = 0, endIndex = index + 1)}/" + .replace("/+".toRegex(), "/") } /** /path/to/store/social/facebook.gpg -> social/facebook */ diff --git a/app/src/main/java/app/passwordstore/ui/dialogs/FolderCreationDialogFragment.kt b/app/src/main/java/app/passwordstore/ui/dialogs/FolderCreationDialogFragment.kt index cac3bcd7..3923a997 100644 --- a/app/src/main/java/app/passwordstore/ui/dialogs/FolderCreationDialogFragment.kt +++ b/app/src/main/java/app/passwordstore/ui/dialogs/FolderCreationDialogFragment.kt @@ -20,6 +20,7 @@ import java.io.File class FolderCreationDialogFragment : DialogFragment() { private lateinit var newFolder: File + override fun onCreateDialog(savedInstanceState: Bundle?): Dialog { val alertDialogBuilder = MaterialAlertDialogBuilder(requireContext()) alertDialogBuilder.setTitle(R.string.title_create_folder) @@ -65,6 +66,7 @@ class FolderCreationDialogFragment : DialogFragment() { companion object { private const val CURRENT_DIR_EXTRA = "CURRENT_DIRECTORY" + fun newInstance(startingDirectory: String): FolderCreationDialogFragment { val extras = bundleOf(CURRENT_DIR_EXTRA to startingDirectory) val fragment = FolderCreationDialogFragment() diff --git a/app/src/main/java/app/passwordstore/ui/dialogs/TextInputDialog.kt b/app/src/main/java/app/passwordstore/ui/dialogs/TextInputDialog.kt index 1830c299..08f52227 100644 --- a/app/src/main/java/app/passwordstore/ui/dialogs/TextInputDialog.kt +++ b/app/src/main/java/app/passwordstore/ui/dialogs/TextInputDialog.kt @@ -49,6 +49,7 @@ class TextInputDialog : DialogFragment() { super.onCancel(dialog) finish() } + companion object { const val REQUEST_KEY = "text_input_dialog" const val BUNDLE_KEY_TEXT = "text" diff --git a/app/src/main/java/app/passwordstore/ui/passwords/PasswordStore.kt b/app/src/main/java/app/passwordstore/ui/passwords/PasswordStore.kt index fce45b5a..4c35d6d0 100644 --- a/app/src/main/java/app/passwordstore/ui/passwords/PasswordStore.kt +++ b/app/src/main/java/app/passwordstore/ui/passwords/PasswordStore.kt @@ -600,6 +600,7 @@ class PasswordStore : BaseGitActivity() { companion object { const val REQUEST_ARG_PATH = "PATH" + private fun isPrintable(c: Char): Boolean { val block = UnicodeBlock.of(c) return (!Character.isISOControl(c) && block != null && block !== UnicodeBlock.SPECIALS) diff --git a/app/src/main/java/app/passwordstore/ui/settings/RepositorySettings.kt b/app/src/main/java/app/passwordstore/ui/settings/RepositorySettings.kt index 8c20becc..d0c08439 100644 --- a/app/src/main/java/app/passwordstore/ui/settings/RepositorySettings.kt +++ b/app/src/main/java/app/passwordstore/ui/settings/RepositorySettings.kt @@ -195,6 +195,7 @@ class RepositorySettings( @InstallIn(SingletonComponent::class) interface RepositorySettingsEntryPoint { fun gitSettings(): GitSettings + @GitPreferences fun encryptedPreferences(): SharedPreferences } } diff --git a/app/src/main/java/app/passwordstore/util/autofill/AutofillMatcher.kt b/app/src/main/java/app/passwordstore/util/autofill/AutofillMatcher.kt index 4fbccd87..52c3d778 100644 --- a/app/src/main/java/app/passwordstore/util/autofill/AutofillMatcher.kt +++ b/app/src/main/java/app/passwordstore/util/autofill/AutofillMatcher.kt @@ -52,10 +52,12 @@ class AutofillMatcher { private const val MAX_NUM_MATCHES = 10 private const val PREFERENCE_PREFIX_TOKEN = "token;" + private fun tokenKey(formOrigin: FormOrigin.App) = "$PREFERENCE_PREFIX_TOKEN${formOrigin.identifier}" private const val PREFERENCE_PREFIX_MATCHES = "matches;" + private fun matchesKey(formOrigin: FormOrigin) = "$PREFERENCE_PREFIX_MATCHES${formOrigin.identifier}" 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 dc587cda..f9b07fa1 100644 --- a/app/src/main/java/app/passwordstore/util/autofill/AutofillPreferences.kt +++ b/app/src/main/java/app/passwordstore/util/autofill/AutofillPreferences.kt @@ -121,6 +121,7 @@ enum class DirectoryStructure(val value: String) { val DEFAULT = FileBased private val reverseMap = values().associateBy { it.value } + fun fromValue(value: String?) = if (value != null) reverseMap[value] ?: DEFAULT else DEFAULT } } diff --git a/app/src/main/java/app/passwordstore/util/git/ErrorMessages.kt b/app/src/main/java/app/passwordstore/util/git/ErrorMessages.kt index 3ff932d0..41ed8e9a 100644 --- a/app/src/main/java/app/passwordstore/util/git/ErrorMessages.kt +++ b/app/src/main/java/app/passwordstore/util/git/ErrorMessages.kt @@ -29,6 +29,7 @@ sealed class GitException(@StringRes res: Int, vararg fmt: String) : sealed class PullException(@StringRes res: Int, vararg fmt: String) : GitException(res, *fmt) { object PullRebaseFailed : PullException(R.string.git_pull_rebase_fail_error) + object PullMergeFailed : PullException(R.string.git_pull_merge_fail_error) } @@ -36,7 +37,9 @@ sealed class GitException(@StringRes res: Int, vararg fmt: String) : sealed class PushException(@StringRes res: Int, vararg fmt: String) : GitException(res, *fmt) { object NonFastForward : PushException(R.string.git_push_nff_error) + object RemoteRejected : PushException(R.string.git_push_other_error) + class Generic(message: String) : PushException(R.string.git_push_generic_error, message) } } diff --git a/app/src/main/java/app/passwordstore/util/git/GitCommandExecutor.kt b/app/src/main/java/app/passwordstore/util/git/GitCommandExecutor.kt index f2e647c2..1fdcf24e 100644 --- a/app/src/main/java/app/passwordstore/util/git/GitCommandExecutor.kt +++ b/app/src/main/java/app/passwordstore/util/git/GitCommandExecutor.kt @@ -41,6 +41,7 @@ class GitCommandExecutor( GitCommandExecutorEntryPoint::class.java ) } + suspend fun execute(): Result<Unit, Throwable> { val gitSettings = hiltEntryPoint.gitSettings() val snackbar = diff --git a/app/src/main/java/app/passwordstore/util/git/sshj/SshKey.kt b/app/src/main/java/app/passwordstore/util/git/sshj/SshKey.kt index e7f5dd96..2251f72b 100644 --- a/app/src/main/java/app/passwordstore/util/git/sshj/SshKey.kt +++ b/app/src/main/java/app/passwordstore/util/git/sshj/SshKey.kt @@ -77,10 +77,13 @@ object SshKey { val sshPublicKey get() = if (publicKeyFile.exists()) publicKeyFile.readText() else null + val canShowSshPublicKey get() = type in listOf(Type.LegacyGenerated, Type.KeystoreNative, Type.KeystoreWrappedEd25519) + val exists get() = type != null + val mustAuthenticate: Boolean get() { return runCatching { @@ -111,6 +114,7 @@ object SshKey { private val privateKeyFile get() = File(context.filesDir, ".ssh_key") + private val publicKeyFile get() = File(context.filesDir, ".ssh_key.pub") diff --git a/app/src/main/java/app/passwordstore/util/git/sshj/SshjSessionFactory.kt b/app/src/main/java/app/passwordstore/util/git/sshj/SshjSessionFactory.kt index 0875913f..787b3e2d 100644 --- a/app/src/main/java/app/passwordstore/util/git/sshj/SshjSessionFactory.kt +++ b/app/src/main/java/app/passwordstore/util/git/sshj/SshjSessionFactory.kt @@ -45,6 +45,7 @@ import org.eclipse.jgit.util.FS sealed class SshAuthMethod(val activity: AppCompatActivity) { class Password(activity: AppCompatActivity) : SshAuthMethod(activity) + class SshKey(activity: AppCompatActivity) : SshAuthMethod(activity) } diff --git a/app/src/main/java/app/passwordstore/util/log/AbstractLogger.kt b/app/src/main/java/app/passwordstore/util/log/AbstractLogger.kt index d0b82c5e..3b4e45fc 100644 --- a/app/src/main/java/app/passwordstore/util/log/AbstractLogger.kt +++ b/app/src/main/java/app/passwordstore/util/log/AbstractLogger.kt @@ -10,26 +10,41 @@ import org.slf4j.Marker abstract class AbstractLogger(private val name: String) : Logger { abstract fun t(message: String, t: Throwable? = null, vararg args: Any?) + abstract fun d(message: String, t: Throwable? = null, vararg args: Any?) + abstract fun i(message: String, t: Throwable? = null, vararg args: Any?) + abstract fun w(message: String, t: Throwable? = null, vararg args: Any?) + abstract fun e(message: String, t: Throwable? = null, vararg args: Any?) override fun getName() = name override fun isTraceEnabled(marker: Marker?): Boolean = isTraceEnabled + override fun isDebugEnabled(marker: Marker?): Boolean = isDebugEnabled + override fun isInfoEnabled(marker: Marker?): Boolean = isInfoEnabled + override fun isWarnEnabled(marker: Marker?): Boolean = isWarnEnabled + override fun isErrorEnabled(marker: Marker?): Boolean = isErrorEnabled override fun trace(msg: String) = t(msg) + override fun trace(format: String, arg: Any?) = t(format, null, arg) + override fun trace(format: String, arg1: Any?, arg2: Any?) = t(format, null, arg1, arg2) + override fun trace(format: String, vararg arguments: Any?) = t(format, null, *arguments) + override fun trace(msg: String, t: Throwable?) = t(msg, t) + override fun trace(marker: Marker, msg: String) = trace(msg) + override fun trace(marker: Marker?, format: String, arg: Any?) = trace(format, arg) + override fun trace(marker: Marker?, format: String, arg1: Any?, arg2: Any?) = trace(format, arg1, arg2) @@ -39,12 +54,19 @@ abstract class AbstractLogger(private val name: String) : Logger { override fun trace(marker: Marker?, msg: String, t: Throwable?) = trace(msg, t) override fun debug(msg: String) = d(msg) + override fun debug(format: String, arg: Any?) = d(format, null, arg) + override fun debug(format: String, arg1: Any?, arg2: Any?) = d(format, null, arg1, arg2) + override fun debug(format: String, vararg arguments: Any?) = d(format, null, *arguments) + override fun debug(msg: String, t: Throwable?) = d(msg, t) + override fun debug(marker: Marker, msg: String) = debug(msg) + override fun debug(marker: Marker?, format: String, arg: Any?) = debug(format, arg) + override fun debug(marker: Marker?, format: String, arg1: Any?, arg2: Any?) = debug(format, arg1, arg2) @@ -54,12 +76,19 @@ abstract class AbstractLogger(private val name: String) : Logger { override fun debug(marker: Marker?, msg: String, t: Throwable?) = debug(msg, t) override fun info(msg: String) = i(msg) + override fun info(format: String, arg: Any?) = i(format, null, arg) + override fun info(format: String, arg1: Any?, arg2: Any?) = i(format, null, arg1, arg2) + override fun info(format: String, vararg arguments: Any?) = i(format, null, *arguments) + override fun info(msg: String, t: Throwable?) = i(msg, t) + override fun info(marker: Marker, msg: String) = info(msg) + override fun info(marker: Marker?, format: String, arg: Any?) = info(format, arg) + override fun info(marker: Marker?, format: String, arg1: Any?, arg2: Any?) = info(format, arg1, arg2) @@ -69,12 +98,19 @@ abstract class AbstractLogger(private val name: String) : Logger { override fun info(marker: Marker?, msg: String, t: Throwable?) = info(msg, t) override fun warn(msg: String) = w(msg) + override fun warn(format: String, arg: Any?) = w(format, null, arg) + override fun warn(format: String, arg1: Any?, arg2: Any?) = w(format, null, arg1, arg2) + override fun warn(format: String, vararg arguments: Any?) = w(format, null, *arguments) + override fun warn(msg: String, t: Throwable?) = w(msg, t) + override fun warn(marker: Marker, msg: String) = warn(msg) + override fun warn(marker: Marker?, format: String, arg: Any?) = warn(format, arg) + override fun warn(marker: Marker?, format: String, arg1: Any?, arg2: Any?) = warn(format, arg1, arg2) @@ -84,12 +120,19 @@ abstract class AbstractLogger(private val name: String) : Logger { override fun warn(marker: Marker?, msg: String, t: Throwable?) = warn(msg, t) override fun error(msg: String) = e(msg) + override fun error(format: String, arg: Any?) = e(format, null, arg) + override fun error(format: String, arg1: Any?, arg2: Any?) = e(format, null, arg1, arg2) + override fun error(format: String, vararg arguments: Any?) = e(format, null, *arguments) + override fun error(msg: String, t: Throwable?) = e(msg, t) + override fun error(marker: Marker, msg: String) = error(msg) + override fun error(marker: Marker?, format: String, arg: Any?) = error(format, arg) + override fun error(marker: Marker?, format: String, arg1: Any?, arg2: Any?) = error(format, arg1, arg2) diff --git a/app/src/main/java/app/passwordstore/util/log/LogcatLogger.kt b/app/src/main/java/app/passwordstore/util/log/LogcatLogger.kt index 5e4490ce..81e9c688 100644 --- a/app/src/main/java/app/passwordstore/util/log/LogcatLogger.kt +++ b/app/src/main/java/app/passwordstore/util/log/LogcatLogger.kt @@ -8,9 +8,13 @@ import logcat.logcat class LogcatLogger(name: String) : AbstractLogger(name) { override fun isTraceEnabled() = true + override fun isDebugEnabled() = true + override fun isInfoEnabled() = true + override fun isWarnEnabled() = true + override fun isErrorEnabled() = true // Replace slf4j's "{}" format string style with standard Java's "%s". diff --git a/app/src/main/java/app/passwordstore/util/log/LogcatLoggerFactory.kt b/app/src/main/java/app/passwordstore/util/log/LogcatLoggerFactory.kt index 92464446..6961bdf3 100644 --- a/app/src/main/java/app/passwordstore/util/log/LogcatLoggerFactory.kt +++ b/app/src/main/java/app/passwordstore/util/log/LogcatLoggerFactory.kt @@ -11,6 +11,7 @@ import org.slf4j.Logger class LogcatLoggerFactory : ILoggerFactory { private val loggers = ConcurrentHashMap<String, Logger>() + override fun getLogger(name: String): Logger { return loggers.getOrPut(name) { LogcatLogger(name) } } diff --git a/app/src/main/java/app/passwordstore/util/settings/GitSettings.kt b/app/src/main/java/app/passwordstore/util/settings/GitSettings.kt index 048f021d..00ace530 100644 --- a/app/src/main/java/app/passwordstore/util/settings/GitSettings.kt +++ b/app/src/main/java/app/passwordstore/util/settings/GitSettings.kt @@ -27,6 +27,7 @@ enum class Protocol(val pref: String) { companion object { private val map = values().associateBy(Protocol::pref) + fun fromString(type: String?): Protocol { return map[type ?: return Ssh] ?: throw IllegalArgumentException("$type is not a valid Protocol") @@ -43,6 +44,7 @@ enum class AuthMode(val pref: String) { companion object { private val map = values().associateBy(AuthMode::pref) + fun fromString(type: String?): AuthMode { return map[type ?: return SshKey] ?: throw IllegalArgumentException("$type is not a valid AuthMode") @@ -66,6 +68,7 @@ constructor( private set(value) { settings.edit { putString(PreferenceKeys.GIT_REMOTE_AUTH, value.pref) } } + var url get() = settings.getString(PreferenceKeys.GIT_REMOTE_URL) private set(value) { @@ -79,41 +82,49 @@ constructor( encryptedSettings.edit { remove(PreferenceKeys.HTTPS_PASSWORD) } clearSavedHostKey() } + var authorName get() = settings.getString(PreferenceKeys.GIT_CONFIG_AUTHOR_NAME) ?: "" set(value) { settings.edit { putString(PreferenceKeys.GIT_CONFIG_AUTHOR_NAME, value) } } + var authorEmail get() = settings.getString(PreferenceKeys.GIT_CONFIG_AUTHOR_EMAIL) ?: "" set(value) { settings.edit { putString(PreferenceKeys.GIT_CONFIG_AUTHOR_EMAIL, value) } } + var useMultiplexing get() = settings.getBoolean(PreferenceKeys.GIT_REMOTE_USE_MULTIPLEXING, true) set(value) { settings.edit { putBoolean(PreferenceKeys.GIT_REMOTE_USE_MULTIPLEXING, value) } } + var proxyHost get() = proxySettings.getString(PreferenceKeys.PROXY_HOST) set(value) { proxySettings.edit { putString(PreferenceKeys.PROXY_HOST, value) } } + var proxyPort get() = proxySettings.getInt(PreferenceKeys.PROXY_PORT, -1) set(value) { proxySettings.edit { putInt(PreferenceKeys.PROXY_PORT, value) } } + var proxyUsername get() = settings.getString(PreferenceKeys.PROXY_USERNAME) set(value) { proxySettings.edit { putString(PreferenceKeys.PROXY_USERNAME, value) } } + var proxyPassword get() = proxySettings.getString(PreferenceKeys.PROXY_PASSWORD) set(value) { proxySettings.edit { putString(PreferenceKeys.PROXY_PASSWORD, value) } } + var rebaseOnPull get() = settings.getBoolean(PreferenceKeys.REBASE_ON_PULL, true) set(value) { @@ -122,9 +133,12 @@ constructor( sealed class UpdateConnectionSettingsResult { class MissingUsername(val newProtocol: Protocol) : UpdateConnectionSettingsResult() + class AuthModeMismatch(val newProtocol: Protocol, val validModes: List<AuthMode>) : UpdateConnectionSettingsResult() + object Valid : UpdateConnectionSettingsResult() + object FailedToParseUrl : UpdateConnectionSettingsResult() } diff --git a/app/src/main/java/app/passwordstore/util/ssh/SSHFacade.kt b/app/src/main/java/app/passwordstore/util/ssh/SSHFacade.kt index 956e2a71..8d8c8aa6 100644 --- a/app/src/main/java/app/passwordstore/util/ssh/SSHFacade.kt +++ b/app/src/main/java/app/passwordstore/util/ssh/SSHFacade.kt @@ -75,6 +75,7 @@ constructor( SshKey.mustAuthenticate } } + fun keyProvider(client: SSHClient, credentialFinder: CredentialFinder): KeyProvider? { return if (useNewSSH) { sshKeyManager.keyProvider(client, credentialFinder) diff --git a/app/src/main/java/app/passwordstore/util/viewmodel/SearchableRepositoryViewModel.kt b/app/src/main/java/app/passwordstore/util/viewmodel/SearchableRepositoryViewModel.kt index ba42bb34..fcc62ab7 100644 --- a/app/src/main/java/app/passwordstore/util/viewmodel/SearchableRepositoryViewModel.kt +++ b/app/src/main/java/app/passwordstore/util/viewmodel/SearchableRepositoryViewModel.kt @@ -130,8 +130,10 @@ constructor( private val root get() = PasswordRepository.getRepositoryDirectory() + private val showHiddenContents get() = settings.getBoolean(PreferenceKeys.SHOW_HIDDEN_CONTENTS, false) + private val defaultSearchMode get() = if (settings.getBoolean(PreferenceKeys.FILTER_RECURSIVELY, true)) { @@ -142,8 +144,10 @@ constructor( private val typeSortOrder get() = PasswordSortOrder.getSortOrder(settings) + private val directoryStructure get() = AutofillPreferences.directoryStructure(getApplication()) + private val itemComparator get() = PasswordItem.makeComparator(typeSortOrder, directoryStructure) @@ -428,6 +432,7 @@ open class SearchableRepositoryAdapter<T : RecyclerView.ViewHolder>( } private var onItemClickedListener: ((holder: T, item: PasswordItem) -> Unit)? = null + open fun onItemClicked( listener: (holder: T, item: PasswordItem) -> Unit ): SearchableRepositoryAdapter<T> { @@ -439,6 +444,7 @@ open class SearchableRepositoryAdapter<T : RecyclerView.ViewHolder>( } private var onSelectionChangedListener: ((selection: Selection<String>) -> Unit)? = null + open fun onSelectionChanged( listener: (selection: Selection<String>) -> Unit ): SearchableRepositoryAdapter<T> { @@ -458,6 +464,7 @@ open class SearchableRepositoryAdapter<T : RecyclerView.ViewHolder>( } private var selectionTracker: SelectionTracker<String>? = null + fun requireSelectionTracker() = selectionTracker!! private val selectedFiles @@ -483,6 +490,7 @@ open class SearchableRepositoryAdapter<T : RecyclerView.ViewHolder>( } } } + final override fun getPopupText(position: Int): String { return getItem(position).name[0].toString().uppercase(Locale.getDefault()) } diff --git a/app/src/main/java/org/slf4j/impl/StaticLoggerBinder.kt b/app/src/main/java/org/slf4j/impl/StaticLoggerBinder.kt index 85ab4d42..7a078602 100644 --- a/app/src/main/java/org/slf4j/impl/StaticLoggerBinder.kt +++ b/app/src/main/java/org/slf4j/impl/StaticLoggerBinder.kt @@ -13,6 +13,7 @@ class StaticLoggerBinder : LoggerFactoryBinder { override fun getLoggerFactory(): ILoggerFactory { return loggerFactory } + override fun getLoggerFactoryClassStr(): String { return loggerFactoryClassStr } |