diff options
| author | Fabian Henneke <FabianHenneke@users.noreply.github.com> | 2020-05-28 06:27:30 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2020-05-28 09:57:30 +0530 |
| commit | 97911c587754a7c11e594004b77c4ac53af8a468 (patch) | |
| tree | 680453c63fc3873139a3937268f73ec6985cf03a /app/src/main/java/com/zeapo/pwdstore/git/GitAsyncTask.kt | |
| parent | fea82fed47d87138a9a24eb0358fc9a917474dc7 (diff) | |
| download | HardenedPass-97911c587754a7c11e594004b77c4ac53af8a468.tar.gz HardenedPass-97911c587754a7c11e594004b77c4ac53af8a468.zip | |
Use SSHJ for SSH public key authentication (#801)
Diffstat (limited to 'app/src/main/java/com/zeapo/pwdstore/git/GitAsyncTask.kt')
| -rw-r--r-- | app/src/main/java/com/zeapo/pwdstore/git/GitAsyncTask.kt | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/app/src/main/java/com/zeapo/pwdstore/git/GitAsyncTask.kt b/app/src/main/java/com/zeapo/pwdstore/git/GitAsyncTask.kt new file mode 100644 index 00000000..631bbf88 --- /dev/null +++ b/app/src/main/java/com/zeapo/pwdstore/git/GitAsyncTask.kt @@ -0,0 +1,148 @@ +/* + * Copyright © 2014-2020 The Android Password Store Authors. All Rights Reserved. + * SPDX-License-Identifier: GPL-3.0-only + */ +package com.zeapo.pwdstore.git + +import android.app.Activity +import android.app.ProgressDialog +import android.content.Context +import android.content.Intent +import android.os.AsyncTask +import com.github.ajalt.timberkt.e +import com.zeapo.pwdstore.PasswordStore +import com.zeapo.pwdstore.R +import net.schmizz.sshj.userauth.UserAuthException +import org.eclipse.jgit.api.CommitCommand +import org.eclipse.jgit.api.GitCommand +import org.eclipse.jgit.api.PullCommand +import org.eclipse.jgit.api.PushCommand +import org.eclipse.jgit.api.RebaseResult +import org.eclipse.jgit.api.StatusCommand +import org.eclipse.jgit.transport.RemoteRefUpdate +import java.io.IOException +import java.lang.ref.WeakReference + + +class GitAsyncTask( + activity: Activity, + private val refreshListOnEnd: Boolean, + private val operation: GitOperation, + private val finishWithResultOnEnd: Intent?) : AsyncTask<GitCommand<*>, Int, GitAsyncTask.Result>() { + + private val activityWeakReference: WeakReference<Activity> = WeakReference(activity) + private val activity: Activity? + get() = activityWeakReference.get() + private val context: Context = activity.applicationContext + private val dialog = ProgressDialog(activity) + + sealed class Result { + object Ok : Result() + data class Err(val err: Exception) : Result() + } + + override fun onPreExecute() { + dialog.run { + setMessage(activity!!.resources.getString(R.string.running_dialog_text)) + setCancelable(false) + show() + } + } + + override fun doInBackground(vararg commands: GitCommand<*>): Result? { + var nbChanges: Int? = null + for (command in commands) { + try { + when (command) { + is StatusCommand -> { + // in case we have changes, we want to keep track of it + val status = command.call() + nbChanges = status.changed.size + status.missing.size + } + is CommitCommand -> { + // the previous status will eventually be used to avoid a commit + if (nbChanges == null || nbChanges > 0) command.call() + } + is PullCommand -> { + val result = command.call() + val rr = result.rebaseResult + if (rr.status === RebaseResult.Status.STOPPED) { + return Result.Err(IOException(context.getString(R.string + .git_pull_fail_error))) + } + } + is PushCommand -> { + for (result in command.call()) { + // Code imported (modified) from Gerrit PushOp, license Apache v2 + for (rru in result.remoteUpdates) { + val error = when (rru.status) { + RemoteRefUpdate.Status.REJECTED_NONFASTFORWARD -> + context.getString(R.string.git_push_nff_error) + RemoteRefUpdate.Status.REJECTED_NODELETE, + RemoteRefUpdate.Status.REJECTED_REMOTE_CHANGED, + RemoteRefUpdate.Status.NON_EXISTING, + RemoteRefUpdate.Status.NOT_ATTEMPTED -> + (activity!!.getString(R.string.git_push_generic_error) + rru.status.name) + RemoteRefUpdate.Status.REJECTED_OTHER_REASON -> { + if + ("non-fast-forward" == rru.message) { + context.getString(R.string.git_push_other_error) + } else { + (context.getString(R.string.git_push_generic_error) + + rru.message) + } + } + else -> null + + } + if (error != null) + Result.Err(IOException(error)) + } + } + } + else -> { + command.call() + } + } + } catch (e: Exception) { + return Result.Err(e) + } + } + return Result.Ok + } + + private fun rootCauseException(e: Exception): Exception { + var rootCause = e + // JGit's TransportException hides the more helpful SSHJ exceptions. + // Also, SSHJ's UserAuthException about exhausting available authentication methods hides + // more useful exceptions. + while ((rootCause is org.eclipse.jgit.errors.TransportException || + rootCause is org.eclipse.jgit.api.errors.TransportException || + (rootCause is UserAuthException && + rootCause.message == "Exhausted available authentication methods"))) { + rootCause = rootCause.cause as? Exception ?: break + } + return rootCause + } + + override fun onPostExecute(maybeResult: Result?) { + dialog.dismiss() + when (val result = maybeResult ?: Result.Err(IOException("Unexpected error"))) { + is Result.Err -> { + e(result.err) + operation.onError(rootCauseException(result.err)) + } + is Result.Ok -> { + operation.onSuccess() + if (finishWithResultOnEnd != null) { + activity?.setResult(Activity.RESULT_OK, finishWithResultOnEnd) + activity?.finish() + } + if (refreshListOnEnd) { + (activity as? PasswordStore)?.resetPasswordList() + } + } + } + } + +} |
