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() { 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 { 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() + 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) : 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( } private var onItemClickedListener: ((holder: T, item: PasswordItem) -> Unit)? = null + open fun onItemClicked( listener: (holder: T, item: PasswordItem) -> Unit ): SearchableRepositoryAdapter { @@ -439,6 +444,7 @@ open class SearchableRepositoryAdapter( } private var onSelectionChangedListener: ((selection: Selection) -> Unit)? = null + open fun onSelectionChanged( listener: (selection: Selection) -> Unit ): SearchableRepositoryAdapter { @@ -458,6 +464,7 @@ open class SearchableRepositoryAdapter( } private var selectionTracker: SelectionTracker? = null + fun requireSelectionTracker() = selectionTracker!! private val selectedFiles @@ -483,6 +490,7 @@ open class SearchableRepositoryAdapter( } } } + 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 } diff --git a/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/AutofillFormParser.kt b/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/AutofillFormParser.kt index fc1fcca3..49c3b4c9 100644 --- a/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/AutofillFormParser.kt +++ b/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/AutofillFormParser.kt @@ -21,6 +21,7 @@ import logcat.logcat public sealed class FormOrigin(public open val identifier: String) { public data class Web(override val identifier: String) : FormOrigin(identifier) + public data class App(override val identifier: String) : FormOrigin(identifier) public companion object { diff --git a/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/AutofillScenario.kt b/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/AutofillScenario.kt index 9d620fe6..2670a77d 100644 --- a/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/AutofillScenario.kt +++ b/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/AutofillScenario.kt @@ -199,12 +199,16 @@ internal data class ClassifiedAutofillScenario( override val allPasswordFields get() = currentPassword + newPassword + override val passwordFieldsToFillOnMatch get() = currentPassword + override val passwordFieldsToFillOnSearch get() = currentPassword + override val passwordFieldsToFillOnGenerate get() = newPassword + override val passwordFieldsToSave get() = newPassword.ifEmpty { currentPassword } } @@ -219,12 +223,16 @@ internal data class GenericAutofillScenario( override val allPasswordFields get() = genericPassword + override val passwordFieldsToFillOnMatch get() = if (genericPassword.size == 1) genericPassword else emptyList() + override val passwordFieldsToFillOnSearch get() = if (genericPassword.size == 1) genericPassword else emptyList() + override val passwordFieldsToFillOnGenerate get() = genericPassword + override val passwordFieldsToSave get() = genericPassword } diff --git a/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/FormField.kt b/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/FormField.kt index dc03e82b..4d4dd218 100644 --- a/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/FormField.kt +++ b/autofill-parser/src/main/java/com/github/androidpasswordstore/autofillparser/FormField.kt @@ -76,6 +76,7 @@ internal class FormField( "com.google.android.material.textfield.TextInputEditText", ) private const val ANDROID_WEB_VIEW_CLASS_NAME = "android.webkit.WebView" + private fun isPasswordInputType(inputType: Int): Boolean { val typeClass = inputType and InputType.TYPE_MASK_CLASS val typeVariation = inputType and InputType.TYPE_MASK_VARIATION @@ -116,6 +117,7 @@ internal class FormField( @RequiresApi(Build.VERSION_CODES.O) private fun isSupportedHint(hint: String?) = hint in HINTS_FILLABLE + private val EXCLUDED_TERMS = listOf( "url_bar", // Chrome/Edge/Firefox address bar @@ -157,6 +159,7 @@ internal class FormField( private val List.anyMatchesFieldInfo get() = any { fieldId.contains(it) || hint.contains(it) || htmlName.contains(it) } + val autofillId: AutofillId = node.autofillId!! // Information for heuristics and exclusion rules based only on the current field diff --git a/autofill-parser/src/main/java/mozilla/components/lib/publicsuffixlist/PublicSuffixListData.kt b/autofill-parser/src/main/java/mozilla/components/lib/publicsuffixlist/PublicSuffixListData.kt index b64b1b2f..97a2fbae 100644 --- a/autofill-parser/src/main/java/mozilla/components/lib/publicsuffixlist/PublicSuffixListData.kt +++ b/autofill-parser/src/main/java/mozilla/components/lib/publicsuffixlist/PublicSuffixListData.kt @@ -156,6 +156,8 @@ internal class PublicSuffixListData( internal sealed class PublicSuffixOffset { data class Offset(val value: Int) : PublicSuffixOffset() + object PublicSuffix : PublicSuffixOffset() + object PrevailingRule : PublicSuffixOffset() } diff --git a/build-logic/build.gradle.kts b/build-logic/build.gradle.kts index 5d7ab383..14130749 100644 --- a/build-logic/build.gradle.kts +++ b/build-logic/build.gradle.kts @@ -17,9 +17,11 @@ tasks.withType().configureEach { tasks.withType().configureEach { kotlinOptions { jvmTarget = JavaVersion.VERSION_11.toString() - freeCompilerArgs = freeCompilerArgs + listOf( - "-opt-in=kotlin.RequiresOptIn", - ) + freeCompilerArgs = + freeCompilerArgs + + listOf( + "-opt-in=kotlin.RequiresOptIn", + ) } } diff --git a/coroutine-utils-testing/build.gradle.kts b/coroutine-utils-testing/build.gradle.kts index 49683422..6b1c3d81 100644 --- a/coroutine-utils-testing/build.gradle.kts +++ b/coroutine-utils-testing/build.gradle.kts @@ -2,9 +2,7 @@ * Copyright © 2014-2021 The Android Password Store Authors. All Rights Reserved. * SPDX-License-Identifier: GPL-3.0-only */ -plugins { - id("com.github.android-password-store.kotlin-jvm-library") -} +plugins { id("com.github.android-password-store.kotlin-jvm-library") } dependencies { implementation(projects.coroutineUtils) diff --git a/coroutine-utils-testing/src/main/kotlin/app/passwordstore/test/CoroutineTestRule.kt b/coroutine-utils-testing/src/main/kotlin/app/passwordstore/test/CoroutineTestRule.kt index 785d438f..e5e01ba9 100644 --- a/coroutine-utils-testing/src/main/kotlin/app/passwordstore/test/CoroutineTestRule.kt +++ b/coroutine-utils-testing/src/main/kotlin/app/passwordstore/test/CoroutineTestRule.kt @@ -28,8 +28,11 @@ public class CoroutineTestRule( public val testDispatcherProvider: DispatcherProvider = object : DispatcherProvider { override fun default(): CoroutineDispatcher = testDispatcher + override fun io(): CoroutineDispatcher = testDispatcher + override fun main(): CoroutineDispatcher = testDispatcher + override fun unconfined(): CoroutineDispatcher = testDispatcher } diff --git a/coroutine-utils/build.gradle.kts b/coroutine-utils/build.gradle.kts index a7074506..65ed2d9d 100644 --- a/coroutine-utils/build.gradle.kts +++ b/coroutine-utils/build.gradle.kts @@ -2,9 +2,7 @@ * Copyright © 2014-2021 The Android Password Store Authors. All Rights Reserved. * SPDX-License-Identifier: GPL-3.0-only */ -plugins { - id("com.github.android-password-store.kotlin-jvm-library") -} +plugins { id("com.github.android-password-store.kotlin-jvm-library") } dependencies { implementation(libs.kotlin.coroutines.core) diff --git a/coroutine-utils/src/main/kotlin/app/passwordstore/util/coroutines/DispatcherProvider.kt b/coroutine-utils/src/main/kotlin/app/passwordstore/util/coroutines/DispatcherProvider.kt index c8edd654..61ef0b47 100644 --- a/coroutine-utils/src/main/kotlin/app/passwordstore/util/coroutines/DispatcherProvider.kt +++ b/coroutine-utils/src/main/kotlin/app/passwordstore/util/coroutines/DispatcherProvider.kt @@ -13,8 +13,11 @@ import kotlinx.coroutines.Dispatchers public interface DispatcherProvider { public fun main(): CoroutineDispatcher = Dispatchers.Main + public fun default(): CoroutineDispatcher = Dispatchers.Default + public fun io(): CoroutineDispatcher = Dispatchers.IO + public fun unconfined(): CoroutineDispatcher = Dispatchers.Unconfined } diff --git a/crypto-common/build.gradle.kts b/crypto-common/build.gradle.kts index c7651695..110664bd 100644 --- a/crypto-common/build.gradle.kts +++ b/crypto-common/build.gradle.kts @@ -2,8 +2,6 @@ * Copyright © 2014-2021 The Android Password Store Authors. All Rights Reserved. * SPDX-License-Identifier: GPL-3.0-only */ -plugins { - id("com.github.android-password-store.kotlin-jvm-library") -} +plugins { id("com.github.android-password-store.kotlin-jvm-library") } dependencies { implementation(libs.thirdparty.kotlinResult) } diff --git a/crypto-pgpainless/build.gradle.kts b/crypto-pgpainless/build.gradle.kts index 7933bf2e..6c424e08 100644 --- a/crypto-pgpainless/build.gradle.kts +++ b/crypto-pgpainless/build.gradle.kts @@ -2,9 +2,7 @@ * Copyright © 2014-2021 The Android Password Store Authors. All Rights Reserved. * SPDX-License-Identifier: GPL-3.0-only */ -plugins { - id("com.github.android-password-store.kotlin-jvm-library") -} +plugins { id("com.github.android-password-store.kotlin-jvm-library") } dependencies { api(projects.cryptoCommon) diff --git a/crypto-pgpainless/src/main/kotlin/app/passwordstore/crypto/GpgIdentifier.kt b/crypto-pgpainless/src/main/kotlin/app/passwordstore/crypto/GpgIdentifier.kt index 29d1fa42..d99213d5 100644 --- a/crypto-pgpainless/src/main/kotlin/app/passwordstore/crypto/GpgIdentifier.kt +++ b/crypto-pgpainless/src/main/kotlin/app/passwordstore/crypto/GpgIdentifier.kt @@ -31,6 +31,7 @@ public sealed class GpgIdentifier { return hexString } } + public data class UserId(val email: String) : GpgIdentifier() { override fun toString(): String { return email diff --git a/crypto-pgpainless/src/test/kotlin/app/passwordstore/crypto/TestUtils.kt b/crypto-pgpainless/src/test/kotlin/app/passwordstore/crypto/TestUtils.kt index 2c1b8851..96614ee9 100644 --- a/crypto-pgpainless/src/test/kotlin/app/passwordstore/crypto/TestUtils.kt +++ b/crypto-pgpainless/src/test/kotlin/app/passwordstore/crypto/TestUtils.kt @@ -8,9 +8,12 @@ package app.passwordstore.crypto object TestUtils { fun getArmoredSecretKey() = this::class.java.classLoader.getResource("secret_key").readBytes() + fun getArmoredPublicKey() = this::class.java.classLoader.getResource("public_key").readBytes() + fun getArmoredSecretKeyWithMultipleIdentities() = this::class.java.classLoader.getResource("secret_key_multiple_identities").readBytes() + fun getArmoredPublicKeyWithMultipleIdentities() = this::class.java.classLoader.getResource("public_key_multiple_identities").readBytes() } diff --git a/format-common/build.gradle.kts b/format-common/build.gradle.kts index 2571a5ac..3377eb86 100644 --- a/format-common/build.gradle.kts +++ b/format-common/build.gradle.kts @@ -2,9 +2,7 @@ * Copyright © 2014-2021 The Android Password Store Authors. All Rights Reserved. * SPDX-License-Identifier: GPL-3.0-only */ -plugins { - id("com.github.android-password-store.kotlin-jvm-library") -} +plugins { id("com.github.android-password-store.kotlin-jvm-library") } dependencies { api(libs.kotlin.coroutines.core) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index bdafe10a..c467f757 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -39,7 +39,7 @@ build-agp = { module = "com.android.tools.build:gradle", version.ref = "agp" } build-diffutils = "io.github.java-diff-utils:java-diff-utils:4.12" build-download = "de.undercouch:gradle-download-task:5.4.0" build-kotlin = { module = "org.jetbrains.kotlin:kotlin-gradle-plugin", version.ref = "kotlin" } -build-ktfmt = "com.facebook:ktfmt:0.43" +build-ktfmt = "com.facebook:ktfmt:0.44" build-mavenpublish = "com.vanniktech:gradle-maven-publish-plugin:0.25.2" build-metalava = "me.tylerbwong.gradle.metalava:plugin:0.3.3" build-moshi = "com.squareup.moshi:moshi:1.14.0" diff --git a/openpgp-ktx/src/main/java/me/msfjarvis/openpgpktx/util/OpenPgpServiceConnection.kt b/openpgp-ktx/src/main/java/me/msfjarvis/openpgpktx/util/OpenPgpServiceConnection.kt index 5a2682ed..52610ea8 100644 --- a/openpgp-ktx/src/main/java/me/msfjarvis/openpgpktx/util/OpenPgpServiceConnection.kt +++ b/openpgp-ktx/src/main/java/me/msfjarvis/openpgpktx/util/OpenPgpServiceConnection.kt @@ -17,12 +17,14 @@ public class OpenPgpServiceConnection(context: Context, providerPackageName: Str public interface OnBound { public fun onBound(service: IOpenPgpService2) + public fun onError(e: Exception) } private val mApplicationContext: Context = context.applicationContext public var service: IOpenPgpService2? = null private set + private val mProviderPackageName: String? = providerPackageName private var mOnBoundListener: OnBound? = null diff --git a/passgen/diceware/src/test/kotlin/app/passwordstore/passgen/diceware/DicewarePassphraseGeneratorTest.kt b/passgen/diceware/src/test/kotlin/app/passwordstore/passgen/diceware/DicewarePassphraseGeneratorTest.kt index 69febaf1..c12161c2 100644 --- a/passgen/diceware/src/test/kotlin/app/passwordstore/passgen/diceware/DicewarePassphraseGeneratorTest.kt +++ b/passgen/diceware/src/test/kotlin/app/passwordstore/passgen/diceware/DicewarePassphraseGeneratorTest.kt @@ -14,6 +14,7 @@ class DicewarePassphraseGeneratorTest { private val random = Random(1_00_000) private val intGenerator = RandomIntGenerator { it.random(random) } + @Test fun generatePassphrase() { val die = Die(6, intGenerator) diff --git a/passgen/random/build.gradle.kts b/passgen/random/build.gradle.kts index 9e5770e6..698a36b5 100644 --- a/passgen/random/build.gradle.kts +++ b/passgen/random/build.gradle.kts @@ -2,6 +2,4 @@ * Copyright © 2014-2021 The Android Password Store Authors. All Rights Reserved. * SPDX-License-Identifier: GPL-3.0-only */ -plugins { - id("com.github.android-password-store.kotlin-jvm-library") -} +plugins { id("com.github.android-password-store.kotlin-jvm-library") } diff --git a/sentry-stub/build.gradle.kts b/sentry-stub/build.gradle.kts index 9e5770e6..698a36b5 100644 --- a/sentry-stub/build.gradle.kts +++ b/sentry-stub/build.gradle.kts @@ -2,6 +2,4 @@ * Copyright © 2014-2021 The Android Password Store Authors. All Rights Reserved. * SPDX-License-Identifier: GPL-3.0-only */ -plugins { - id("com.github.android-password-store.kotlin-jvm-library") -} +plugins { id("com.github.android-password-store.kotlin-jvm-library") } diff --git a/sentry-stub/src/main/kotlin/io/sentry/Scope.kt b/sentry-stub/src/main/kotlin/io/sentry/Scope.kt index 34557a84..46726d8f 100644 --- a/sentry-stub/src/main/kotlin/io/sentry/Scope.kt +++ b/sentry-stub/src/main/kotlin/io/sentry/Scope.kt @@ -6,5 +6,6 @@ import io.sentry.protocol.User public class Scope { public var user: User? = null + public fun setTag(tag: String, value: String) {} }