aboutsummaryrefslogtreecommitdiff
path: root/app/src/main/java/org/pacien/tincapp/activities/LaunchActivity.kt
blob: 0179040c938625beac9ccd4cc10fbf8e2bac9614 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
package org.pacien.tincapp.activities

import android.annotation.SuppressLint
import android.app.Activity
import android.content.Intent
import android.net.Uri
import android.net.VpnService
import android.os.Bundle
import android.support.v7.app.AlertDialog
import android.support.v7.app.AppCompatActivity
import kotlinx.android.synthetic.main.dialog_decrypt_keys.view.*
import org.pacien.tincapp.R
import org.pacien.tincapp.commands.TincApp
import org.pacien.tincapp.context.App
import org.pacien.tincapp.intent.action.ACTION_CONNECT
import org.pacien.tincapp.intent.action.ACTION_DISCONNECT
import org.pacien.tincapp.intent.action.TINC_SCHEME
import org.pacien.tincapp.service.TincVpnService
import org.pacien.tincapp.utils.PemUtils
import java.io.FileNotFoundException

/**
 * @author pacien
 */
class LaunchActivity : AppCompatActivity() {

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)

    when (intent.action) {
      ACTION_CONNECT -> requestPerm()
      ACTION_DISCONNECT -> disconnect()
    }
  }

  override fun onActivityResult(request: Int, result: Int, data: Intent?) {
    if (request == PERMISSION_REQUEST_CODE && result == Activity.RESULT_OK) askPassphrase()
  }

  private fun requestPerm() = VpnService.prepare(this).let {
    if (it != null)
      startActivityForResult(it, PERMISSION_REQUEST_CODE)
    else
      onActivityResult(PERMISSION_REQUEST_CODE, Activity.RESULT_OK, null)
  }

  @SuppressLint("InflateParams")
  private fun askPassphrase() {
    val netName = intent.data.schemeSpecificPart

    if (needPassphrase(netName) && intent.data.fragment == null) {
      val dialog = layoutInflater.inflate(R.layout.dialog_decrypt_keys, null, false)
      AlertDialog.Builder(this)
        .setTitle(R.string.title_unlock_private_keys).setView(dialog)
        .setPositiveButton(R.string.action_unlock) { _, _ -> connect(netName, dialog.passphrase.text.toString()) }
        .setNegativeButton(R.string.action_cancel, { _, _ -> finish() })
        .show()
    } else {
      connect(netName, intent.data.fragment)
    }
  }

  private fun needPassphrase(netName: String) = try {
    TincApp.listPrivateKeys(netName).filter { it.exists() }.any { PemUtils.isEncrypted(PemUtils.read(it)) }
  } catch (e: FileNotFoundException) {
    false
  }

  private fun connect(netName: String, passphrase: String? = null) {
    TincVpnService.startVpn(netName, passphrase)
    finish()
  }

  private fun disconnect() {
    TincVpnService.stopVpn()
    finish()
  }

  companion object {

    private val PERMISSION_REQUEST_CODE = 0

    fun connect(netName: String, passphrase: String? = null) {
      App.getContext().startActivity(Intent(App.getContext(), LaunchActivity::class.java)
        .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
        .setAction(ACTION_CONNECT)
        .setData(Uri.Builder().scheme(TINC_SCHEME).opaquePart(netName).fragment(passphrase).build()))
    }

    fun disconnect() {
      App.getContext().startActivity(Intent(App.getContext(), LaunchActivity::class.java)
        .addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
        .setAction(ACTION_DISCONNECT))
    }

  }

}