aboutsummaryrefslogtreecommitdiff
path: root/app/src/main/java/org/pacien/tincapp/activities/LaunchActivity.kt
blob: 74a059ba55dee04dc2bba01ffe61ba7b0e8318ef (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))
        }

    }

}