From 74fa0c97e6b49c396cdd8ebc8072a06ccbdb5e8d Mon Sep 17 00:00:00 2001 From: Juha Heinanen Date: Sun, 29 Sep 2024 12:13:59 +0300 Subject: [PATCH] Added User Agent setting that can be used to set custom SIP request/response User-Agent header value --- .../com/tutpro/baresip/BaresipService.kt | 6 +- .../main/kotlin/com/tutpro/baresip/Config.kt | 12 ++-- .../com/tutpro/baresip/ConfigActivity.kt | 25 ++++++++ .../main/kotlin/com/tutpro/baresip/Utils.kt | 21 ++++++ app/src/main/res/layout/activity_config.xml | 64 ++++++++++++------- app/src/main/res/values-fi/strings.xml | 3 + app/src/main/res/values/strings.xml | 3 + 7 files changed, 107 insertions(+), 27 deletions(-) diff --git a/app/src/main/kotlin/com/tutpro/baresip/BaresipService.kt b/app/src/main/kotlin/com/tutpro/baresip/BaresipService.kt index 754395cd..cb21b782 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/BaresipService.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/BaresipService.kt @@ -441,12 +441,16 @@ class BaresipService: Service() { activeNetwork = cm.activeNetwork Log.i(TAG, "Active network: $activeNetwork") + val userAgent = Config.variable("user_agent") Thread { baresipStart( filesPath, addresses.removePrefix(";"), logLevel, - "baresip v${BuildConfig.VERSION_NAME} " + + if (userAgent != "") + userAgent + else + "baresip v${BuildConfig.VERSION_NAME} " + "(Android ${VERSION.RELEASE}/${System.getProperty("os.arch") ?: "?"})" ) }.start() diff --git a/app/src/main/kotlin/com/tutpro/baresip/Config.kt b/app/src/main/kotlin/com/tutpro/baresip/Config.kt index e7a69980..78766c9e 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/Config.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/Config.kt @@ -107,6 +107,10 @@ object Config { BaresipService.dynDns = true } + val userAgent = previousVariable("user_agent") + if (userAgent != "") + config = "${config}user_agent $userAgent\n" + val darkTheme = previousVariable("dark_theme") Preferences(ctx).displayTheme = if (darkTheme == "yes") { config = "${config}dark_theme yes\n" @@ -185,7 +189,7 @@ object Config { private fun previousVariable(name: String): String { for (line in previousLines) { - val nameValue = line.split(" ") + val nameValue = line.split(" ", limit = 2) if (nameValue.size == 2 && nameValue[0] == name) return nameValue[1].trim() } @@ -195,7 +199,7 @@ object Config { private fun previousVariables(name: String): ArrayList { val result = ArrayList() for (line in previousLines) { - val nameValue = line.split(" ") + val nameValue = line.split(" ", limit = 2) if (nameValue.size == 2 && nameValue[0] == name) result.add(nameValue[1].trim()) } @@ -204,7 +208,7 @@ object Config { fun variable(name: String): String { for (line in config.split("\n")) { - val nameValue = line.split(" ") + val nameValue = line.split(" ", limit = 2) if (nameValue.size == 2 && nameValue[0] == name) return nameValue[1].trim() } @@ -214,7 +218,7 @@ object Config { fun variables(name: String): ArrayList { val result = ArrayList() for (line in config.split("\n")) { - val nameValue = line.split(" ") + val nameValue = line.split(" ", limit = 2) if (nameValue.size == 2 && nameValue[0] == name) result.add(nameValue[1].trim()) } diff --git a/app/src/main/kotlin/com/tutpro/baresip/ConfigActivity.kt b/app/src/main/kotlin/com/tutpro/baresip/ConfigActivity.kt index cd08c759..a6c80b7d 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/ConfigActivity.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/ConfigActivity.kt @@ -52,6 +52,7 @@ class ConfigActivity : AppCompatActivity() { private lateinit var certificateFile: CheckBox private lateinit var verifyServer: CheckBox private lateinit var caFile: CheckBox + private lateinit var userAgent: EditText private lateinit var darkTheme: CheckBox private lateinit var contactsSpinner: Spinner private lateinit var contactsMode: String @@ -70,6 +71,7 @@ class ConfigActivity : AppCompatActivity() { private var oldDnsServers = "" private var oldCertificateFile = false private var oldVerifyServer = false + private var oldUserAgent = "" private var oldLogLevel = "" private var oldDisplayTheme = -1 private var oldContactsMode = "" @@ -390,6 +392,10 @@ class ConfigActivity : AppCompatActivity() { } } + userAgent = binding.UserAgent + oldUserAgent = Config.variable("user_agent") + userAgent.setText(oldUserAgent) + darkTheme = binding.DarkTheme oldDisplayTheme = Preferences(applicationContext).displayTheme darkTheme.isChecked = oldDisplayTheme == AppCompatDelegate.MODE_NIGHT_YES @@ -615,6 +621,21 @@ class ConfigActivity : AppCompatActivity() { save = true } + val userAgent = userAgent.text.toString().trim() + if (userAgent != oldUserAgent) { + if ((userAgent != "") && !Utils.checkServerVal(userAgent)) { + Utils.alertView(this, getString(R.string.notice), + "${getString(R.string.invalid_user_agent)}: $userAgent") + return false + } + if (userAgent != "") + Config.replaceVariable("user_agent", userAgent) + else + Config.removeVariable("user_agent") + save = true + restart = true + } + val newDisplayTheme = if (darkTheme.isChecked) AppCompatDelegate.MODE_NIGHT_YES else @@ -738,6 +759,10 @@ class ConfigActivity : AppCompatActivity() { Utils.alertView(this, getString(R.string.tls_ca_file), getString(R.string.tls_ca_file_help)) } + binding.UserAgentTitle.setOnClickListener { + Utils.alertView(this, getString(R.string.user_agent), + getString(R.string.user_agent_help)) + } binding.AudioSettingsTitle.setOnClickListener { audioRequest.launch(Intent(this, AudioActivity::class.java)) } diff --git a/app/src/main/kotlin/com/tutpro/baresip/Utils.kt b/app/src/main/kotlin/com/tutpro/baresip/Utils.kt index c37404d7..46eaf466 100644 --- a/app/src/main/kotlin/com/tutpro/baresip/Utils.kt +++ b/app/src/main/kotlin/com/tutpro/baresip/Utils.kt @@ -363,6 +363,27 @@ object Utils { cc.substring(1).isDigitsOnly() && cc[1] != '0' } + fun checkServerVal(server: String): Boolean { + val parts = server.replace(Regex("[(][^()\\\\]+[)]"), "") + .trim().split("\\s+".toRegex()) + for (part in parts) + if (!checkProduct(part)) + return false + return true + } + + private fun checkProduct(product: String): Boolean { + val parts = product.split("/", limit = 2) + return if (parts.count() == 2) + checkToken(parts[0]) && checkToken(parts[1]) + else + checkToken(parts[0]) + } + + private fun checkToken(token: String): Boolean { + return Regex("^[-a-zA-Z0-9.!%*_+`'~]+\$").matches(token) + } + fun setAvatar(ctx: Context, imageView: ImageView, textView: TextView, uri: String) { when (val contact = Contact.findContact(uri)) { diff --git a/app/src/main/res/layout/activity_config.xml b/app/src/main/res/layout/activity_config.xml index 85c2ffd1..9445fbbe 100644 --- a/app/src/main/res/layout/activity_config.xml +++ b/app/src/main/res/layout/activity_config.xml @@ -175,31 +175,25 @@ - + + + - - - - - + android:textSize="18sp" + android:inputType="text" + android:importantForAutofill="no" > + + + + + + + + + Videokehysten lähetystaajuus per sekuntti, jota tarjotaan SDP-neuvottelun aikana. Arvon on oltava välillä 10-30. Virheellinen videokehysten lähetystaajuus \'%1$d\' + User Agent + Räätälöity SIP sanoman User-Agent otsikkokentän arvo + Virheellinen User-Agent otsikkokentän arvo Valitsee käytetäänkö baresip-sovelluksen yhteystietoja, Androidin yhteystietoja vai molempia. Jos molempia ja sama yhteystieto on molemmissa, käytetään baresip-sovelluksen yhteystietoa. diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 1bf18905..5eb46d60 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -371,6 +371,9 @@ Video frame rate that will be offered during the SDP handshake. Valid values are from 10 to 30. Invalid Frames Per Second \'%1$d\' + User Agent + Custom SIP request/response User-Agent header field value + Invalid User-Agent header field value Chooses if baresip contacts, Android contacts, or both are used. If both are used and a contact with the same name exists in both contacts, the baresip contact will be chosen.