diff --git a/app/src/main/kotlin/com/tutpro/baresip/Account.kt b/app/src/main/kotlin/com/tutpro/baresip/Account.kt index e7b92ec2..54ecd33e 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/Account.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/Account.kt @@ -214,6 +214,29 @@ class Account(val accp: String) { return false } + fun checkDisplayName(dn: String): Boolean { + if (dn == "") return true + val dnRegex = Regex("^([* .!%_`'~]|[+]|[-a-zA-Z0-9]){1,63}\$") + return dnRegex.matches(dn) + } + + fun checkAuthUser(au: String): Boolean { + if (au == "") return true + val ud = au.split("@") + val userIDRegex = Regex("^([* .!%_`'~]|[+]|[-a-zA-Z0-9]){1,63}\$") + val telnoRegex = Regex("^[+]?[0-9]{1,16}\$") + if (ud.size == 1) { + return userIDRegex.matches(ud[0]) || telnoRegex.matches(ud[0]) + } else { + return (userIDRegex.matches(ud[0]) || telnoRegex.matches(ud[0])) && + Utils.checkDomain(ud[1]) + } + } + + fun checkAuthPass(ap: String): Boolean { + return (ap.length > 0) && (ap.length <= 64) && + Regex("^[ -~]*\$").matches(ap) && !ap.contains('"') + } } } diff --git a/app/src/main/kotlin/com/tutpro/baresip/AccountActivity.kt b/app/src/main/kotlin/com/tutpro/baresip/AccountActivity.kt index 1d96098e..e188730b 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/AccountActivity.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/AccountActivity.kt @@ -9,6 +9,10 @@ import android.view.MenuItem import android.view.View import android.widget.LinearLayout.LayoutParams import android.widget.* +import com.tutpro.baresip.Account.Companion.checkAuthPass +import com.tutpro.baresip.Account.Companion.checkAuthUser +import com.tutpro.baresip.Account.Companion.checkDisplayName +import com.tutpro.baresip.MainActivity.Companion.aorPasswords import kotlinx.android.synthetic.main.activity_account.* @@ -62,7 +66,7 @@ class AccountActivity : AppCompatActivity() { authUser.setText(acc.authUser) authPass = findViewById(R.id.AuthPass) as EditText - if (MainActivity.aorPasswords.containsKey(aor)) + if (aorPasswords.containsKey(aor)) authPass.setText("") else authPass.setText(acc.authPass) @@ -246,32 +250,33 @@ class AccountActivity : AppCompatActivity() { } } - if (ap != acc.authPass) { - if (ap != "") { - if (Utils.checkPrintAscii(ap) && (ap.length <= 64)) { - if (account_set_auth_pass(acc.accp, ap) == 0) { - acc.authPass = account_auth_pass(acc.accp) - MainActivity.aorPasswords.remove(aor) - // Log.d("Baresip", "New auth password is ${acc.authPass}") - save = true - } else { - Log.e("Baresip", "Setting of auth pass failed") - } + if (ap != "") { + if (ap != acc.authPass) { + if (checkAuthPass(ap)) { + setAuthPass(acc, ap) + aorPasswords.remove(aor) } else { Utils.alertView(this, getString(R.string.notice), String.format(getString(R.string.invalid_authentication_password), ap)) return false } } else { - if ((au != "") && !MainActivity.aorPasswords.containsKey(aor)) { - MainActivity.aorPasswords.put(aor, acc.authPass) + if (aorPasswords.containsKey(aor)) { + aorPasswords.remove(aor) save = true } } - } else { - if (MainActivity.aorPasswords.containsKey(aor)) { - MainActivity.aorPasswords.remove(aor) - save = true + } else { // ap == "" + if (acc.authUser != "") { + if (!aorPasswords.containsKey(aor)) { + setAuthPass(acc, "") + aorPasswords.put(aor, "") + } + } else { + if (acc.authPass != "") { + setAuthPass(acc, "") + aorPasswords.remove(aor) + } } } @@ -457,10 +462,12 @@ class AccountActivity : AppCompatActivity() { //Api.ua_debug(ua.uap) } - if (regCheck.isChecked) Api.ua_register(ua.uap) + if (regCheck.isChecked && !((acc.authUser != "") && (acc.authPass == ""))) + Api.ua_register(ua.uap) BaresipService.activities.remove("account,$accp") val i = Intent() + i.putExtra("accp", accp) setResult(Activity.RESULT_OK, i) finish() @@ -470,7 +477,7 @@ class AccountActivity : AppCompatActivity() { BaresipService.activities.remove("account,$accp") val i = Intent() - setResult(Activity.RESULT_OK, i) + setResult(Activity.RESULT_CANCELED, i) finish() } @@ -485,7 +492,7 @@ class AccountActivity : AppCompatActivity() { BaresipService.activities.remove("account,$accp") val i = Intent() - setResult(Activity.RESULT_OK, i) + setResult(Activity.RESULT_CANCELED, i) finish() super.onBackPressed() @@ -548,29 +555,20 @@ class AccountActivity : AppCompatActivity() { } } + private fun setAuthPass(acc: Account, ap: String) { + if (account_set_auth_pass(acc.accp, ap) == 0) { + acc.authPass = account_auth_pass(acc.accp) + aorPasswords.remove(acc.aor) + save = true + } else { + Log.e("Baresip", "Setting of auth pass failed") + } + } + private fun checkOutboundUri(uri: String): Boolean { if (!uri.startsWith("sip:")) return false return Utils.checkHostPortParams(uri.substring(4)) } - private fun checkDisplayName(dn: String): Boolean { - if (dn == "") return true - val dnRegex = Regex("^([* .!%_`'~]|[+]|[-a-zA-Z0-9]){1,63}\$") - return dnRegex.matches(dn) - } - - private fun checkAuthUser(au: String): Boolean { - if (au == "") return true - val ud = au.split("@") - val userIDRegex = Regex("^([* .!%_`'~]|[+]|[-a-zA-Z0-9]){1,63}\$") - val telnoRegex = Regex("^[+]?[0-9]{1,16}\$") - if (ud.size == 1) { - return userIDRegex.matches(ud[0]) || telnoRegex.matches(ud[0]) - } else { - return (userIDRegex.matches(ud[0]) || telnoRegex.matches(ud[0])) && - Utils.checkDomain(ud[1]) - } - } - } diff --git a/app/src/main/kotlin/com/tutpro/baresip/AccountsActivity.kt b/app/src/main/kotlin/com/tutpro/baresip/AccountsActivity.kt index 39032c2d..c5c5a9cd 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/AccountsActivity.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/AccountsActivity.kt @@ -3,10 +3,18 @@ package com.tutpro.baresip import android.app.Activity import android.content.Intent import android.os.Bundle +import android.support.v7.app.AlertDialog import android.support.v7.app.AppCompatActivity +import android.text.method.HideReturnsTransformationMethod +import android.text.method.PasswordTransformationMethod +import android.view.LayoutInflater import android.view.Menu import android.view.MenuItem +import android.view.ViewGroup import android.widget.* +import com.tutpro.baresip.Account.Companion.checkAuthPass +import com.tutpro.baresip.MainActivity.Companion.ACCOUNT_CODE +import com.tutpro.baresip.MainActivity.Companion.aorPasswords import java.util.ArrayList @@ -59,13 +67,60 @@ class AccountsActivity : AppCompatActivity() { val b = Bundle() b.putString("accp", ua.account.accp) i.putExtras(b) - startActivity(i) + startActivityForResult(i, ACCOUNT_CODE) } } } } + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { + when (requestCode) { + ACCOUNT_CODE -> { + if (resultCode == Activity.RESULT_OK) { + val aor = Account.find(data!!.getStringExtra("accp"))!!.aor + val ua = UserAgent.uas()[UserAgent.findAorIndex(aor)!!] + if (aorPasswords.containsKey(aor) && aorPasswords[aor] == "") + askPassword(String.format(getString(R.string.account_password), aor), ua) + } + } + } + } + + private fun askPassword(title: String, ua: UserAgent) { + val builder = AlertDialog.Builder(this) + builder.setTitle(title) + val viewInflated = LayoutInflater.from(this) + .inflate(R.layout.password_dialog, findViewById(android.R.id.content) as ViewGroup, + false) + val input = viewInflated.findViewById(R.id.password) as EditText + val checkBox = viewInflated.findViewById(R.id.checkbox) as CheckBox + checkBox.setOnCheckedChangeListener { buttonView, isChecked -> + if (isChecked) + input.transformationMethod = HideReturnsTransformationMethod() + else + input.transformationMethod = PasswordTransformationMethod() + } + builder.setView(viewInflated) + builder.setPositiveButton(android.R.string.ok) { dialog, _ -> + dialog.dismiss() + var password = input.text.toString().trim() + if (!checkAuthPass(password)) { + Utils.alertView(this, getString(R.string.notice), + String.format(getString(R.string.invalid_authentication_password), password)) + password = "" + } + aorPasswords[ua.account.aor] = password + account_set_auth_pass(ua.account.accp, password) + if (password != "") + if (ua.account.regint > 0) Api.ua_register(ua.uap) + } + builder.setNegativeButton(android.R.string.cancel) { dialog, _ -> + dialog.cancel() + } + builder.show() + } + override fun onOptionsItemSelected(item: MenuItem): Boolean { if (BaresipService.activities.indexOf("accounts") == -1) return true diff --git a/app/src/main/kotlin/com/tutpro/baresip/MainActivity.kt b/app/src/main/kotlin/com/tutpro/baresip/MainActivity.kt index 2c1976f5..2d9aa72d 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/MainActivity.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/MainActivity.kt @@ -19,6 +19,7 @@ import android.text.method.HideReturnsTransformationMethod import android.text.method.PasswordTransformationMethod import android.widget.* import android.view.* +import com.tutpro.baresip.Account.Companion.checkAuthPass import java.io.File import kotlin.collections.ArrayList @@ -951,7 +952,7 @@ class MainActivity : AppCompatActivity() { } } - private fun askPassword(title: String) { + private fun askPassword(title: String, ua: UserAgent? = null) { val builder = AlertDialog.Builder(this) builder.setTitle(title) val viewInflated = LayoutInflater.from(this) @@ -968,12 +969,23 @@ class MainActivity : AppCompatActivity() { builder.setView(viewInflated) builder.setPositiveButton(android.R.string.ok) { dialog, _ -> dialog.dismiss() - val password = input.text.toString() - if (password != "") { - if (title == getString(R.string.encrypt_password)) - backup(password) - else - restore(password) + var password = input.text.toString().trim() + if (!checkAuthPass(password)) { + Utils.alertView(this, getString(R.string.notice), + String.format(getString(R.string.invalid_authentication_password), password)) + password = "" + } + when (title) { + getString(R.string.encrypt_password) -> + if (password != "") backup(password) + getString(R.string.decrypt_password) -> + if (password != "") restore(password) + else -> { + aorPasswords[ua!!.account.aor] = password + account_set_auth_pass(ua.account.accp, password) + if (password != "") + if (ua.account.regint > 0) Api.ua_register(ua.uap) + } } } builder.setNegativeButton(android.R.string.cancel) { dialog, _ -> @@ -1005,11 +1017,10 @@ class MainActivity : AppCompatActivity() { builder.setView(viewInflated) builder.setPositiveButton(android.R.string.ok) { dialog, _ -> dialog.dismiss() - val password = input.text.toString() - if ((password.length < 1) || (password.length > 64) || !Utils.checkPrintAscii(password)) { + val password = input.text.toString().trim() + if (!checkAuthPass(password)) { Utils.alertView(this, getString(R.string.notice), String.format(getString(R.string.invalid_authentication_password), password)) - accounts.add(0, account) } else { aorPasswords.put(aor, password) } @@ -1111,10 +1122,16 @@ class MainActivity : AppCompatActivity() { } baresipService.setAction("UpdateNotification") startService(baresipService) + for (ua in UserAgent.uas()) updateIcons(ua.account) } ACCOUNT_CODE -> { - updateIcons(UserAgent.uas()[aorSpinner.selectedItemPosition].account) + val ua = UserAgent.uas()[aorSpinner.selectedItemPosition] + val account = ua.account + updateIcons(account) + if (aorPasswords.containsKey(account.aor) && aorPasswords[account.aor] == "") + askPassword(String.format(getString(R.string.account_password), + Utils.plainAor(account.aor)), ua) } CONTACTS_CODE -> { @@ -1435,6 +1452,8 @@ class MainActivity : AppCompatActivity() { var resumeUap = "" var resumeCall: Call? = null var resumeUri = "" + + // of those accounts that have auth username without auth password val aorPasswords = mutableMapOf() const val ACCOUNTS_CODE = 1 diff --git a/app/src/main/kotlin/com/tutpro/baresip/Utils.kt b/app/src/main/kotlin/com/tutpro/baresip/Utils.kt index 07dc4c3f..4c27fcd4 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/Utils.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/Utils.kt @@ -224,11 +224,6 @@ object Utils { return false } - fun checkPrintAscii(s: String): Boolean { - if (s == "") return true - return Regex("^[ -~]*\$").matches(s) - } - fun checkName(name: String): Boolean { return name.isNotEmpty() && name == String(name.toByteArray(), Charsets.UTF_8) && name.lines().size == 1 && !name.contains('"') @@ -566,4 +561,5 @@ object Utils { if ((BaresipService.activities.size == 0) || (BaresipService.activities[0] != activity)) BaresipService.activities.add(0, activity) } + }