From a3285cc4a24603c8cb74a53b4dcb70949e2b000d Mon Sep 17 00:00:00 2001 From: Emanuel Almeida Date: Thu, 23 Apr 2026 00:55:46 +0100 Subject: [PATCH] =?UTF-8?q?feat(android):=20QR=20pairing=20=E2=80=94=20ZXi?= =?UTF-8?q?ng=20scanner=20+=20ScanPairingActivity=20+=20strings=20PT-PT?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Adiciona dependência zxing-android-embedded:4.3.0 - Adiciona permissão CAMERA e regista ScanPairingActivity no Manifest - Cria ScanPairingActivity: scan QR → parse JSON → POST claim-device - Adiciona preferência "Emparelhar dispositivo" nas definições do servidor - Adiciona handler de clique em WhatSmsServerSettingsFragment - Strings PT-PT: scan_qr_to_pair, pairing_success/failed/cancelled/error - Bump versionName para 3.2.0 Co-Authored-By: Claude Opus 4.7 --- app/build.gradle | 5 +- app/src/main/AndroidManifest.xml | 5 + .../smsgateway/ui/ScanPairingActivity.kt | 99 ++++++++++ .../settings/WhatSmsServerSettingsFragment.kt | 126 +++++++++++- app/src/main/res/values/strings.xml | 184 +++++++++++++++++- .../res/xml/whatsms_server_preferences.xml | 58 +++++- 6 files changed, 473 insertions(+), 4 deletions(-) create mode 100644 app/src/main/java/me/capcom/smsgateway/ui/ScanPairingActivity.kt diff --git a/app/build.gradle b/app/build.gradle index 8e7e11a..cedc43c 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -13,7 +13,7 @@ android { minSdk 21 targetSdk 33 versionCode 11 - versionName "3.1.0-hardcode" + versionName "3.2.0" testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner" @@ -130,6 +130,9 @@ dependencies { // Koin for Android implementation "io.insert-koin:koin-android:$koin_version" + // QR code scanner para emparelhamento WhatSMS + implementation 'com.journeyapps:zxing-android-embedded:4.3.0' + testImplementation("junit:junit:4.13.2") androidTestImplementation("androidx.test.ext:junit:1.1.3") androidTestImplementation("androidx.test.espresso:espresso-core:3.4.0") diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index e1ea357..5a0f868 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -7,6 +7,7 @@ android:required="false" /> + @@ -84,6 +85,10 @@ android:foregroundServiceType="dataSync" tools:node="merge" /> + + diff --git a/app/src/main/java/me/capcom/smsgateway/ui/ScanPairingActivity.kt b/app/src/main/java/me/capcom/smsgateway/ui/ScanPairingActivity.kt new file mode 100644 index 0000000..4e5083f --- /dev/null +++ b/app/src/main/java/me/capcom/smsgateway/ui/ScanPairingActivity.kt @@ -0,0 +1,99 @@ +package me.capcom.smsgateway.ui + +import android.app.Activity +import android.content.Intent +import android.os.Build +import android.os.Bundle +import android.widget.Toast +import androidx.appcompat.app.AppCompatActivity +import com.google.zxing.integration.android.IntentIntegrator +import com.google.zxing.integration.android.IntentResult +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import me.capcom.smsgateway.R +import me.capcom.smsgateway.modules.gateway.GatewaySettings +import okhttp3.MediaType.Companion.toMediaType +import okhttp3.OkHttpClient +import okhttp3.Request +import okhttp3.RequestBody.Companion.toRequestBody +import org.json.JSONObject +import org.koin.android.ext.android.inject + +class ScanPairingActivity : AppCompatActivity() { + private val settings: GatewaySettings by inject() + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + IntentIntegrator(this).apply { + setPrompt(getString(R.string.scan_qr_to_pair)) + setBeepEnabled(true) + setOrientationLocked(false) + initiateScan() + } + } + + @Suppress("OVERRIDE_DEPRECATION") + override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) { + val result: IntentResult = + IntentIntegrator.parseActivityResult(requestCode, resultCode, data) + ?: return super.onActivityResult(requestCode, resultCode, data) + if (result.contents == null) { + Toast.makeText(this, R.string.pairing_cancelled, Toast.LENGTH_SHORT).show() + setResult(Activity.RESULT_CANCELED) + finish() + return + } + claimDevice(result.contents) + } + + private fun claimDevice(qrContent: String) { + val deviceId = settings.deviceId + val username = settings.username + val password = settings.password + if (deviceId == null || username == null || password == null) { + Toast.makeText(this, R.string.pairing_not_registered, Toast.LENGTH_LONG).show() + setResult(Activity.RESULT_CANCELED) + finish() + return + } + CoroutineScope(Dispatchers.IO).launch { + try { + val qr = JSONObject(qrContent) + val claimUrl = qr.getString("claimUrl") + val pairingToken = qr.getString("pairingToken") + val body = JSONObject().apply { + put("pairingToken", pairingToken) + put("deviceId", deviceId) + put("username", username) + put("password", password) + put("deviceName", Build.MODEL) + }.toString() + val client = OkHttpClient() + val request = Request.Builder() + .url(claimUrl) + .post(body.toRequestBody("application/json".toMediaType())) + .build() + val response = client.newCall(request).execute() + val ok = response.isSuccessful + withContext(Dispatchers.Main) { + if (ok) { + Toast.makeText(this@ScanPairingActivity, R.string.pairing_success, Toast.LENGTH_SHORT).show() + setResult(Activity.RESULT_OK) + } else { + Toast.makeText(this@ScanPairingActivity, R.string.pairing_failed, Toast.LENGTH_LONG).show() + setResult(Activity.RESULT_CANCELED) + } + finish() + } + } catch (e: Exception) { + withContext(Dispatchers.Main) { + Toast.makeText(this@ScanPairingActivity, getString(R.string.pairing_error, e.message), Toast.LENGTH_LONG).show() + setResult(Activity.RESULT_CANCELED) + finish() + } + } + } + } +} diff --git a/app/src/main/java/me/capcom/smsgateway/ui/settings/WhatSmsServerSettingsFragment.kt b/app/src/main/java/me/capcom/smsgateway/ui/settings/WhatSmsServerSettingsFragment.kt index 546a2c8..c208fac 100644 --- a/app/src/main/java/me/capcom/smsgateway/ui/settings/WhatSmsServerSettingsFragment.kt +++ b/app/src/main/java/me/capcom/smsgateway/ui/settings/WhatSmsServerSettingsFragment.kt @@ -1 +1,125 @@ -cGFja2FnZSBtZS5jYXBjb20uc21zZ2F0ZXdheS51aS5zZXR0aW5ncwoKaW1wb3J0IGFuZHJvaWQuYW5ub3RhdGlvbi5TdXBwcmVzc0xpbnQKaW1wb3J0IGFuZHJvaWQub3MuQnVuZGxlCmltcG9ydCBhbmRyb2lkLnRleHQuSW5wdXRUeXBlCmltcG9ydCBhbmRyb2lkLnZpZXcuVmlldwppbXBvcnQgYW5kcm9pZHguY29yZS52aWV3LmlzVmlzaWJsZQppbXBvcnQgYW5kcm9pZHgubGlmZWN5Y2xlLmxpZmVjeWNsZVNjb3BlCmltcG9ydCBhbmRyb2lkeC5wcmVmZXJlbmNlLkVkaXRUZXh0UHJlZmVyZW5jZQppbXBvcnQgYW5kcm9pZHgucHJlZmVyZW5jZS5QcmVmZXJlbmNlCmltcG9ydCBrb3RsaW54LmNvcm91dGluZXMubGF1bmNoCmltcG9ydCBtZS5jYXBjb20uc21zZ2F0ZXdheS5SCmltcG9ydCBtZS5jYXBjb20uc21zZ2F0ZXdheS5tb2R1bGVzLmdhdGV3YXkuR2F0ZXdheVNlcnZpY2UKaW1wb3J0IG1lLmNhcGNvbS5zbXNnYXRld2F5Lm1vZHVsZXMuZ2F0ZXdheS5HYXRld2F5U2V0dGluZ3MKaW1wb3J0IG9yZy5rb2luLmFuZHJvaWQuZXh0LmFuZHJvaWQuaW5qZWN0CmltcG9ydCBqYXZhLnRleHQuRGF0ZUZvcm1hdAoKY2xhc3MgV2hhdFNtc1NlcnZlclNldHRpbmdzRnJhZ21lbnQgOiBCYXNlUHJlZmVyZW5jZUZyYWdtZW50KCkgewoKICAgIHByaXZhdGUgdmFsIHNldHRpbmdzOiBHYXRld2F5U2V0dGluZ3MgYnkgaW5qZWN0KCkKICAgIHByaXZhdGUgdmFsIHNlcnZpY2U6IEdhdGV3YXlTZXJ2aWNlIGJ5IGluamVjdCgpCgogICAgQFN1cHByZXNzTGludCgiTm90aWZ5RGF0YVNldENoYW5nZWQiKQogICAgb3ZlcnJpZGUgZnVuIG9uQ3JlYXRlUHJlZmVyZW5jZXMoc2F2ZWRJbnN0YW5jZVN0YXRlOiBCdW5kbGU/LCByb290S2V5OiBTdHJpbmc/KSB7CiAgICAgICAgc2V0UHJlZmVyZW5jZXNGcm9tUmVzb3VyY2UoUi54bWwud2hhdHNtc19zZXJ2ZXJfcHJlZmVyZW5jZXMsIHJvb3RLZXkpCgogICAgICAgIGZpbmRQcmVmZXJlbmNlPFByZWZlcmVuY2U+KCJ0cmFuc2llbnQuc2VydmVyX3VybCIpPy5zdW1tYXJ5ID0KICAgICAgICAgICAgR2F0ZXdheVNldHRpbmdzLlBVQkxJQ19VUkwKCiAgICAgICAgZmluZFByZWZlcmVuY2U8UHJlZmVyZW5jZT4oInRyYW5zaWVudC5kZXZpY2VfaWQiKT8uc3VtbWFyeSA9CiAgICAgICAgICAgIHNldHRpbmdzLmRldmljZUlkID86IGdldFN0cmluZyhSLnN0cmluZy5uX2EpCgogICAgICAgIGZpbmRQcmVmZXJlbmNlPEVkaXRUZXh0UHJlZmVyZW5jZT4oImdhdGV3YXkudXNlcm5hbWUiKT8uc2V0U3VtbWFyeVByb3ZpZGVyIHsKICAgICAgICAgICAgc2V0dGluZ3MudXNlcm5hbWUgPzogZ2V0U3RyaW5nKFIuc3RyaW5nLm5vdF9zZXQpCiAgICAgICAgfQoKICAgICAgICBmaW5kUHJlZmVyZW5jZTxFZGl0VGV4dFByZWZlcmVuY2U+KCJnYXRld2F5LnBhc3N3b3JkIik/LmFwcGx5IHsKICAgICAgICAgICAgaXNFbmFibGVkID0gc2V0dGluZ3MudXNlcm5hbWUgIT0gbnVsbCAmJiBzZXR0aW5ncy5wYXNzd29yZCAhPSBudWxsCgogICAgICAgICAgICBzZXRTdW1tYXJ5UHJvdmlkZXIgewogICAgICAgICAgICAgICAgd2hlbiB7CiAgICAgICAgICAgICAgICAgICAgc2V0dGluZ3MudXNlcm5hbWUgPT0gbnVsbCAtPiBnZXRTdHJpbmcoUi5zdHJpbmcubm90X3JlZ2lzdGVyZWQpCiAgICAgICAgICAgICAgICAgICAgc2V0dGluZ3MudXNlcm5hbWUgIT0gbnVsbCAmJiBzZXR0aW5ncy5wYXNzd29yZCA9PSBudWxsIC0+ICJDYW4ndCBiZSBjaGFuZ2VkIgogICAgICAgICAgICAgICAgICAgIGVsc2UgLT4gc2V0dGluZ3MucGFzc3dvcmQKICAgICAgICAgICAgICAgIH0KICAgICAgICAgICAgfQoKICAgICAgICAgICAgc2V0T25QcmVmZXJlbmNlQ2hhbmdlTGlzdGVuZXIgeyBfLCBuZXdWYWx1ZSAtPgogICAgICAgICAgICAgICAgdmFsIHZhbHVlID0gbmV3VmFsdWUgYXM/IFN0cmluZwogICAgICAgICAgICAgICAgaWYgKHZhbHVlID09IG51bGwgfHwgdmFsdWUubGVuZ3RoIDwgMTQpIHsKICAgICAgICAgICAgICAgICAgICBzaG93VG9hc3QoZ2V0U3RyaW5nKFIuc3RyaW5nLnBhc3N3b3JkX211c3RfYmVfYXRfbGVhc3RfMTRfY2hhcmFjdGVycykpCiAgICAgICAgICAgICAgICAgICAgcmV0dXJuQHNldE9uUHJlZmVyZW5jZUNoYW5nZUxpc3RlbmVyIGZhbHNlCiAgICAgICAgICAgICAgICB9CgogICAgICAgICAgICAgICAgdGhpc0BXaGF0U21zU2VydmVyU2V0dGluZ3NGcmFnbWVudC5saWZlY3ljbGVTY29wZS5sYXVuY2ggewogICAgICAgICAgICAgICAgICAgIHRyeSB7CiAgICAgICAgICAgICAgICAgICAgICAgIHJlcXVpcmVBY3Rpdml0eSgpLmZpbmRWaWV3QnlJZDxWaWV3PihSLmlkLnByb2dyZXNzQmFyKS5pc1Zpc2libGUgPSB0cnVlCiAgICAgICAgICAgICAgICAgICAgICAgIHNlcnZpY2UuY2hhbmdlUGFzc3dvcmQoc2V0dGluZ3MucGFzc3dvcmQgPzogIiIsIHZhbHVlKQogICAgICAgICAgICAgICAgICAgICAgICBsaXN0Vmlldy5hZGFwdGVyPy5ub3RpZnlEYXRhU2V0Q2hhbmdlZCgpCiAgICAgICAgICAgICAgICAgICAgICAgIHNob3dUb2FzdChnZXRTdHJpbmcoUi5zdHJpbmcucGFzc3dvcmRfY2hhbmdlZF9zdWNjZXNzZnVsbHkpKQogICAgICAgICAgICAgICAgICAgIH0gY2F0Y2ggKGU6IEV4Y2VwdGlvbikgewogICAgICAgICAgICAgICAgICAgICAgICBzaG93VG9hc3QoZ2V0U3RyaW5nKFIuc3RyaW5nLmZhaWxlZF90b19jaGFuZ2VfcGFzc3dvcmQsIGUubWVzc2FnZSkpCiAgICAgICAgICAgICAgICAgICAgfSBmaW5hbGx5IHsKICAgICAgICAgICAgICAgICAgICAgICAgcmVxdWlyZUFjdGl2aXR5KCkuZmluZFZpZXdCeUlkPFZpZXc+KFIuaWQucHJvZ3Jlc3NCYXIpLmlzVmlzaWJsZSA9IGZhbHNlCiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQoKICAgICAgICAgICAgICAgIHRydWUKICAgICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgZmluZFByZWZlcmVuY2U8UHJlZmVyZW5jZT4oImdhdGV3YXkubG9naW5fY29kZSIpPy5hcHBseSB7CiAgICAgICAgICAgIGlzVmlzaWJsZSA9IHNldHRpbmdzLnVzZXJuYW1lICE9IG51bGwgJiYgc2V0dGluZ3MucGFzc3dvcmQgIT0gbnVsbAoKICAgICAgICAgICAgb25QcmVmZXJlbmNlQ2xpY2tMaXN0ZW5lciA9IFByZWZlcmVuY2UuT25QcmVmZXJlbmNlQ2xpY2tMaXN0ZW5lciB7CiAgICAgICAgICAgICAgICB0aGlzQFdoYXRTbXNTZXJ2ZXJTZXR0aW5nc0ZyYWdtZW50LmxpZmVjeWNsZVNjb3BlLmxhdW5jaCB7CiAgICAgICAgICAgICAgICAgICAgdHJ5IHsKICAgICAgICAgICAgICAgICAgICAgICAgcmVxdWlyZUFjdGl2aXR5KCkuZmluZFZpZXdCeUlkPFZpZXc+KFIuaWQucHJvZ3Jlc3NCYXIpLmlzVmlzaWJsZSA9IHRydWUKCiAgICAgICAgICAgICAgICAgICAgICAgIHZhbCBsb2dpbkNvZGUgPSBzZXJ2aWNlLmdldExvZ2luQ29kZSgpCiAgICAgICAgICAgICAgICAgICAgICAgIHRpdGxlID0gZ2V0U3RyaW5nKAogICAgICAgICAgICAgICAgICAgICAgICAgICAgUi5zdHJpbmcubG9naW5fY29kZV9leHBpcmVzLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgRGF0ZUZvcm1hdC5nZXREYXRlVGltZUluc3RhbmNlKCkuZm9ybWF0KGxvZ2luQ29kZS52YWxpZFVudGlsKQogICAgICAgICAgICAgICAgICAgICAgICApCiAgICAgICAgICAgICAgICAgICAgICAgIHN1bW1hcnkgPSBsb2dpbkNvZGUuY29kZQoKICAgICAgICAgICAgICAgICAgICAgICAgbGlzdFZpZXcuYWRhcHRlcj8ubm90aWZ5RGF0YVNldENoYW5nZWQoKQogICAgICAgICAgICAgICAgICAgICAgICBzaG93VG9hc3QoZ2V0U3RyaW5nKFIuc3RyaW5nLnN1Y2Nlc3NfbG9uZ19wcmVzc190b19jb3B5KSkKICAgICAgICAgICAgICAgICAgICB9IGNhdGNoIChlOiBFeGNlcHRpb24pIHsKICAgICAgICAgICAgICAgICAgICAgICAgc2hvd1RvYXN0KGdldFN0cmluZyhSLnN0cmluZy5mYWlsZWRfdG9fZ2V0X2xvZ2luX2NvZGUsIGUubWVzc2FnZSkpCiAgICAgICAgICAgICAgICAgICAgfSBmaW5hbGx5IHsKICAgICAgICAgICAgICAgICAgICAgICAgcmVxdWlyZUFjdGl2aXR5KCkuZmluZFZpZXdCeUlkPFZpZXc+KFIuaWQucHJvZ3Jlc3NCYXIpLmlzVmlzaWJsZSA9IGZhbHNlCiAgICAgICAgICAgICAgICAgICAgfQogICAgICAgICAgICAgICAgfQoKICAgICAgICAgICAgICAgIHRydWUKICAgICAgICAgICAgfQogICAgICAgIH0KICAgIH0KCiAgICBvdmVycmlkZSBmdW4gb25EaXNwbGF5UHJlZmVyZW5jZURpYWxvZyhwcmVmZXJlbmNlOiBQcmVmZXJlbmNlKSB7CiAgICAgICAgaWYgKHByZWZlcmVuY2Uua2V5ID09ICJnYXRld2F5LnBhc3N3b3JkIikgewogICAgICAgICAgICAocHJlZmVyZW5jZSBhcyBFZGl0VGV4dFByZWZlcmVuY2UpLnNldE9uQmluZEVkaXRUZXh0TGlzdGVuZXIgewogICAgICAgICAgICAgICAgaXQuaW5wdXRUeXBlID0gSW5wdXRUeXBlLlRZUEVfQ0xBU1NfVEVYVAogICAgICAgICAgICAgICAgaXQudGV4dCA9IG51bGwKICAgICAgICAgICAgfQogICAgICAgIH0KCiAgICAgICAgc3VwZXIub25EaXNwbGF5UHJlZmVyZW5jZURpYWxvZyhwcmVmZXJlbmNlKQogICAgfQp9Cg== \ No newline at end of file +package me.capcom.smsgateway.ui.settings + +import android.annotation.SuppressLint +import android.content.Intent +import android.os.Bundle +import android.text.InputType +import android.view.View +import androidx.core.view.isVisible +import androidx.lifecycle.lifecycleScope +import androidx.preference.EditTextPreference +import androidx.preference.Preference +import kotlinx.coroutines.launch +import me.capcom.smsgateway.R +import me.capcom.smsgateway.modules.gateway.GatewayService +import me.capcom.smsgateway.modules.gateway.GatewaySettings +import me.capcom.smsgateway.ui.ScanPairingActivity +import org.koin.android.ext.android.inject +import java.text.DateFormat + +class WhatSmsServerSettingsFragment : BasePreferenceFragment() { + + private val settings: GatewaySettings by inject() + private val service: GatewayService by inject() + + @SuppressLint("NotifyDataSetChanged") + override fun onCreatePreferences(savedInstanceState: Bundle?, rootKey: String?) { + setPreferencesFromResource(R.xml.whatsms_server_preferences, rootKey) + + findPreference("transient.server_url")?.summary = + GatewaySettings.PUBLIC_URL + + findPreference("transient.device_id")?.summary = + settings.deviceId ?: getString(R.string.n_a) + + findPreference("gateway.username")?.setSummaryProvider { + settings.username ?: getString(R.string.not_set) + } + + findPreference("gateway.password")?.apply { + isEnabled = settings.username != null && settings.password != null + + setSummaryProvider { + when { + settings.username == null -> getString(R.string.not_registered) + settings.username != null && settings.password == null -> "Can't be changed" + else -> settings.password + } + } + + setOnPreferenceChangeListener { _, newValue -> + val value = newValue as? String + if (value == null || value.length < 14) { + showToast(getString(R.string.password_must_be_at_least_14_characters)) + return@setOnPreferenceChangeListener false + } + + this@WhatSmsServerSettingsFragment.lifecycleScope.launch { + try { + requireActivity().findViewById(R.id.progressBar).isVisible = true + service.changePassword(settings.password ?: "", value) + listView.adapter?.notifyDataSetChanged() + showToast(getString(R.string.password_changed_successfully)) + } catch (e: Exception) { + showToast(getString(R.string.failed_to_change_password, e.message)) + } finally { + requireActivity().findViewById(R.id.progressBar).isVisible = false + } + } + + true + } + } + + findPreference("action.pair_device")?.setOnPreferenceClickListener { + startActivityForResult( + Intent(requireContext(), ScanPairingActivity::class.java), + REQ_PAIR + ) + true + } + + findPreference("gateway.login_code")?.apply { + isVisible = settings.username != null && settings.password != null + + onPreferenceClickListener = Preference.OnPreferenceClickListener { + this@WhatSmsServerSettingsFragment.lifecycleScope.launch { + try { + requireActivity().findViewById(R.id.progressBar).isVisible = true + + val loginCode = service.getLoginCode() + title = getString( + R.string.login_code_expires, + DateFormat.getDateTimeInstance().format(loginCode.validUntil) + ) + summary = loginCode.code + + listView.adapter?.notifyDataSetChanged() + showToast(getString(R.string.success_long_press_to_copy)) + } catch (e: Exception) { + showToast(getString(R.string.failed_to_get_login_code, e.message)) + } finally { + requireActivity().findViewById(R.id.progressBar).isVisible = false + } + } + + true + } + } + } + + companion object { + private const val REQ_PAIR = 1001 + } + + override fun onDisplayPreferenceDialog(preference: Preference) { + if (preference.key == "gateway.password") { + (preference as EditTextPreference).setOnBindEditTextListener { + it.inputType = InputType.TYPE_CLASS_TEXT + it.text = null + } + } + + super.onDisplayPreferenceDialog(preference) + } +} diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 39f5c4d..4534dee 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -1 +1,183 @@ -PHJlc291cmNlcz4KICAgIDxzdHJpbmcgbmFtZT0iYWRkcmVzc19pcyI+JTEkczwvc3RyaW5nPgogICAgPHN0cmluZyBuYW1lPSJhcGlfdXJsX3ByaXZhdGVfdG9rZW5fY3JlZGVudGlhbHNfZXRjIj5BUEkgVVJMLCBwcml2YXRlIHRva2VuLCBjcmVkZW50aWFscywgZXRjLjwvc3RyaW5nPgogICAgPHN0cmluZyBuYW1lPSJhcGlfdXJsIj5BUEkgVVJMPC9zdHJpbmc+CiAgICA8c3RyaW5nIG5hbWU9ImFwcF9uYW1lIiB0cmFuc2xhdGFibGU9ImZhbHNlIj5XaGF0U01TIEdhdGV3YXk8L3N0cmluZz4KICAgIDxzdHJpbmcgbmFtZT0iYXBwX3ZlcnNpb25fYnVpbGQiPkFwcCB2ZXJzaW9uIChidWlsZCk8L3N0cmluZz4KICAgIDxzdHJpbmcgbmFtZT0iYmF0dGVyeV9vcHRpbWl6YXRpb25fYWxyZWFkeV9kaXNhYmxlZCI+QmF0dGVyeSBvcHRpbWl6YXRpb24gYWxyZWFkeSBkaXNhYmxlZDwvc3RyaW5nPgogICAgPHN0cmluZyBuYW1lPSJiYXR0ZXJ5X29wdGltaXphdGlvbl9pc19ub3Rfc3VwcG9ydGVkX29uX3RoaXNfZGV2aWNlIj5CYXR0ZXJ5IG9wdGltaXphdGlvbiBpcyBub3QKICAgICAgICBzdXBwb3J0ZWQgb24gdGhpcyBkZXZpY2U8L3N0cmluZz4KICAgIDxzdHJpbmcgbmFtZT0iYmF0dGVyeV9vcHRpbWl6YXRpb24iPkJhdHRlcnkgb3B0aW1pemF0aW9uPC9zdHJpbmc+CiAgICA8c3RyaW5nIG5hbWU9ImJ0bl9jYW5jZWwiPkNhbmNlbDwvc3RyaW5nPgogICAgPHN0cmluZyBuYW1lPSJidG5fY29udGludWUiPkNvbnRpbnVlPC9zdHJpbmc+CiAgICA8c3RyaW5nIG5hbWU9ImJ5X2NvZGUiPkJ5IENvZGU8L3N0cmluZz4KICAgIDxzdHJpbmcgbmFtZT0iY2FuX2FmZmVjdF9iYXR0ZXJ5X2xpZmUiPmNhbiBhZmZlY3QgYmF0dGVyeSBsaWZlPC9zdHJpbmc+CiAgICA8c3RyaW5nCiAgICAgICAgbmFtZT0iY2xpY2tfY29udGludWVfdG9fY3JlYXRlX2FuX2FjY291bnRfbm9fcGVyc29uYWxfaW5mb3JtYXRpb25faXNfcmVxdWlyZWRfbmJ5X2NvbnRpbnVpbmdfeW91X2FncmVlX3RvX291cl9wcml2YWN5X3BvbGljeV9hdF9odHRwc19kb2NzX3Ntc19nYXRlX2FwcF9wcml2YWN5X3BvbGljeSI+Q2xpY2sKICAgICAgICBDb250aW51ZSB0byBjcmVhdGUgYW4gYWNjb3VudC4gTm8gcGVyc29uYWwgaW5mb3JtYXRpb24gaXMgcmVxdWlyZWQuXG5CeSBjb250aW51aW5nLCB5b3UKICAgICAgICBhZ3JlZSB0byBvdXIgUHJpdmFjeSBQb2xpY3kgYXQgaHR0cHM6Ly9kb2NzLnNtcy1nYXRlLmFwcC9wcml2YWN5L3BvbGljeS88L3N0cmluZz4KICAgIDxzdHJpbmcgbmFtZT0iY2xvdWRfc2VydmVyX2RvdGRvdGRvdCI+Q2xvdWQgc2VydmVy4oCmPC9zdHJpbmc+CiAgICA8c3RyaW5nIG5hbWU9ImNsb3VkX3NlcnZlciI+Q2xvdWQgc2VydmVyPC9zdHJpbmc+CiAgICA8c3RyaW5nIG5hbWU9ImNsb3VkIj5DbG91ZDwvc3RyaW5nPgogICAgPHN0cmluZyBuYW1lPSJjb3BpZWRfdG9fY2xpcGJvYXJkIj5Db3BpZWQ8L3N0cmluZz4KICAgIDxzdHJpbmcgbmFtZT0iY3JlZGVudGlhbHMiPkNyZWRlbnRpYWxzPC9zdHJpbmc+CiAgICA8c3RyaW5nIG5hbWU9ImRlbGF5c19saW1pdHNfZXRjIj5EZWxheXMsIGxpbWl0cywgZXRjLjwvc3RyaW5nPgogICAgPHN0cmluZyBuYW1lPSJkZWxheXNfc2Vjb25kcyI+RGVsYXlzLCBzZWNvbmRzPC9zdHJpbmc+CiAgICA8c3RyaW5nIG5hbWU9ImRlbGV0ZV9hZnRlcl9kYXlzIj5EZWxldGUgYWZ0ZXIsIGRheXM8L3N0cmluZz4KICAgIDxzdHJpbmcgbmFtZT0iZGV2aWNlX2lkIj5EZXZpY2UgSUQ8L3N0cmluZz4KICAgIDxzdHJpbmcgbmFtZT0iZGV2aWNlIj5EZXZpY2U8L3N0cmluZz4KICAgIDxzdHJpbmcgbmFtZT0iZGlzYWJsZWQiPkRpc2FibGVkPC9zdHJpbmc+CiAgICA8c3RyaW5nIG5hbWU9ImRvdHMiPuKApjwvc3RyaW5nPgogICAgPHN0cmluZyBuYW1lPSJlbmFibGVkIj5FbmFibGVkPC9zdHJpbmc+CiAgICA8c3RyaW5nIG5hbWU9ImVuY3J5cHRpb24iPkVuY3J5cHRpb248L3N0cmluZz4KICAgIDxzdHJpbmcgbmFtZT0iZmFpbGVkX3RvX2NoYW5nZV9wYXNzd29yZCI+RmFpbGVkIHRvIGNoYW5nZSBwYXNzd29yZDogJTEkczwvc3RyaW5nPgogICAgPHN0cmluZyBuYW1lPSJmYWlsZWRfdG9fZ2V0X2xvZ2luX2NvZGUiPkZhaWxlZCB0byBnZXQgbG9naW4gY29kZTogJTEkczwvc3RyaW5nPgogICAgPHN0cmluZyBuYW1lPSJmYWlsZWRfdG9fcmVnaXN0ZXJfZGV2aWNlIj5GYWlsZWQgdG8gcmVnaXN0ZXIgZGV2aWNlOiAlMSRzPC9zdHJpbmc+CiAgICA8c3RyaW5nIG5hbWU9ImlkX2NvcGllZCI+V2ViaG9vayBJRCBjb3BpZWQgdG8gY2xpcGJvYXJkPC9zdHJpbmc+CiAgICA8c3RyaW5nIG5hbWU9ImlmX3NpbV9udW1iZXJfaXNfbm90X3NwZWNpZmllZF91c2UiPklmIFNJTSBudW1iZXIgaXMgbm90IHNwZWNpZmllZCwgdXNlPC9zdHJpbmc+CiAgICA8c3RyaW5nIG5hbWU9Imlnbm9yZWRfZm9yX3B1YmxpY19zZXJ2ZXIiPklnbm9yZWQgZm9yIHB1YmxpYyBzZXJ2ZXI8L3N0cmluZz4KICAgIDxzdHJpbmcgbmFtZT0iaW5mb3JtYXRpb24iPkluZm9ybWF0aW9uPC9zdHJpbmc+CiAgICA8c3RyaW5nIG5hbWU9ImludGVybmV0X2Nvbm5lY3Rpb25fYXZhaWxhYmxlIj5JbnRlcm5ldCBjb25uZWN0aW9uOiBhdmFpbGFibGU8L3N0cmluZz4KICAgIDxzdHJpbmcgbmFtZT0iaW50ZXJuZXRfY29ubmVjdGlvbl91bmF2YWlsYWJsZSI+SW50ZXJuZXQgY29ubmVjdGlvbjogdW5hdmFpbGFibGU8L3N0cmluZz4KICAgIDxzdHJpbmcgbmFtZT0iaW50ZXJ2YWxfc2Vjb25kcyI+SW50ZXJ2YWwgKHNlY29uZHMpPC9zdHJpbmc+CiAgICA8c3RyaW5nIG5hbWU9ImludmFsaWRfdXJsIj5JbnZhbGlkIFVSTDwvc3RyaW5nPgogICAgPHN0cmluZyBuYW1lPSJpc19ub3RfYV92YWxpZF9wb3J0X211c3RfYmVfYmV0d2Vlbl8xMDI0X2FuZF82NTUzNSI+JTEkcyBpcyBub3QgYSB2YWxpZCBwb3J0LiBNdXN0CiAgICAgICAgYmUgYmV0d2VlbiAxMDI0IGFuZCA2NTUzNS48L3N0cmluZz4KICAgIDxzdHJpbmcgbmFtZT0ibGFiZWxfcGFzc3dvcmQiPlBhc3N3b3JkPC9zdHJpbmc+CiAgICA8c3RyaW5nIG5hbWU9ImxhYmVsX3VzZXJuYW1lIj5Vc2VybmFtZTwvc3RyaW5nPgogICAgPHN0cmluZyBuYW1lPSJsaW1pdHMiPkxpbWl0czwvc3RyaW5nPgogICAgPHN0cmluZyBuYW1lPSJsaXN0X29mX2xhc3RfNTBfbG9nX2VudHJpZXMiPkxpc3Qgb2YgbGFzdCA1MCBsb2cgZW50cmllczwvc3RyaW5nPgogICAgPHN0cmluZyBuYW1lPSJsaXN0ZW5pbmdfdG9fdGhlX3NlcnZlcl9ldmVudHMiPkxpc3RlbmluZyB0byBzZXJ2ZXIgZXZlbnRz4oCmPC9zdHJpbmc+CiAgICA8c3RyaW5nIG5hbWU9ImxvY2FsX2FkZHJlc3MiPkxvY2FsIGFkZHJlc3M8L3N0cmluZz4KICAgIDxzdHJpbmcgbmFtZT0ibG9jYWxfc2VydmVyX2RvdGRvdGRvdCI+TG9jYWwgU2VydmVy4oCmPC9zdHJpbmc+CiAgICA8c3RyaW5nIG5hbWU9ImxvY2FsX3Ntc19nYXRld2F5X25vdGlmaWNhdGlvbnMiPkxvY2FsIFNNU0dhdGUgbm90aWZpY2F0aW9uczwvc3RyaW5nPgogICAgPHN0cmluZyBuYW1lPSJsb2NhbCI+TG9jYWw8L3N0cmluZz4KICAgIDxzdHJpbmcgbmFtZT0ibG9naW5fY29kZV9leHBpcmVzIj5Mb2dpbiBDb2RlLCBleHBpcmVzICUxJHM8L3N0cmluZz4KICAgIDxzdHJpbmcgbmFtZT0ibG9naW5fY29kZSI+TG9naW4gQ29kZTwvc3RyaW5nPgogICAgPHN0cmluZyBuYW1lPSJsb2dzIj5Mb2dzPC9zdHJpbmc+CiAgICA8c3RyaW5nIG5hbWU9Im1heGltdW0iPk1heGltdW08L3N0cmluZz4KICAgIDxzdHJpbmcgbmFtZT0ibWVzc2FnZXNfY291bnQiPk1lc3NhZ2VzIGNvdW50PC9zdHJpbmc+CiAgICA8c3RyaW5nIG5hbWU9Im1lc3NhZ2VzX2hlYWRlciI+TWVzc2FnZXM8L3N0cmluZz4KICAgIDxzdHJpbmcgbmFtZT0ibWVzc2FnZXMiPk1lc3NhZ2Vz4oCmPC9zdHJpbmc+CiAgICA8c3RyaW5nIG5hbWU9Im1pbmltdW0iPk1pbmltdW08L3N0cmluZz4KICAgIDxzdHJpbmcgbmFtZT0ibW9yZV9zZXR0aW5ncyI+TW9yZSBzZXR0aW5nc+KApjwvc3RyaW5nPgogICAgPHN0cmluZyBuYW1lPSJuX2EiPm4vYTwvc3RyaW5nPgogICAgPHN0cmluZyBuYW1lPSJuZXdfc21zX3JlY2VpdmVkX3dlYmhvb2tzX3JlZ2lzdGVyZWQiPk5ldyBTTVMgUmVjZWl2ZWQgV2ViaG9va3MgcmVnaXN0ZXJlZDwvc3RyaW5nPgogICAgPHN0cmluZyBuYW1lPSJub193ZWJob29rc19mb3VuZCI+Tm8gd2ViaG9va3MgY29uZmlndXJlZDwvc3RyaW5nPgogICAgPHN0cmluZyBuYW1lPSJub3RfcmVnaXN0ZXJlZCI+bm90IHJlZ2lzdGVyZWQ8L3N0cmluZz4KICAgIDxzdHJpbmcgbmFtZT0ibm90X3NldCI+Tm90IHNldDwvc3RyaW5nPgogICAgPHN0cmluZyBuYW1lPSJub3RpZmljYXRpb25fdGl0bGUiPlNNU0dhdGU8L3N0cmluZz4KICAgIDxzdHJpbmcgbmFtZT0ibm90aWZpY2F0aW9uX2NoYW5uZWwiPk5vdGlmaWNhdGlvbiBjaGFubmVsPC9zdHJpbmc+CiAgICA8c3RyaW5nIG5hbWU9Im5vdGlmaWNhdGlvbnMiPk5vdGlmaWNhdGlvbnM8L3N0cmluZz4KICAgIDxzdHJpbmcgbmFtZT0ib25saW5lX3N0YXR1c19hdF90aGVfY29zdF9vZl9iYXR0ZXJ5X2xpZmUiPk9ubGluZSBzdGF0dXMgYXQgdGhlIGNvc3Qgb2YgYmF0dGVyeQogICAgICAgIGxpZmU8L3N0cmluZz4KICAgIDxzdHJpbmcgbmFtZT0icGFzc3BocmFzZSI+UGFzc3BocmFzZTwvc3RyaW5nPgogICAgPHN0cmluZyBuYW1lPSJwYXNzd29yZF9jaGFuZ2VkX3N1Y2Nlc3NmdWxseSI+UGFzc3dvcmQgY2hhbmdlZCBzdWNjZXNzZnVsbHk8L3N0cmluZz4KICAgIDxzdHJpbmcgbmFtZT0icGFzc3dvcmRfbXVzdF9iZV9hdF9sZWFzdF8xNF9jaGFyYWN0ZXJzIj5QYXNzd29yZCBtdXN0IGJlIGF0IGxlYXN0IDE0IGNoYXJhY3RlcnM8L3N0cmluZz4KICAgIDxzdHJpbmcgbmFtZT0icGFzc3dvcmRfbXVzdF9iZV9hdF9sZWFzdF84X2NoYXJhY3RlcnMiPlBhc3N3b3JkIG11c3QgYmUgYXQgbGVhc3QgOCBjaGFyYWN0ZXJzPC9zdHJpbmc+CiAgICA8c3RyaW5nIG5hbWU9InBhc3N3b3JkIj5QYXNzd29yZDwvc3RyaW5nPgogICAgPHN0cmluZyBuYW1lPSJwZXJpb2QiPlBlcmlvZDwvc3RyaW5nPgogICAgPHN0cmluZyBuYW1lPSJwaW5nX3NlcnZpY2VfaXNfYWN0aXZlIj5QaW5nIHNlcnZpY2UgaXMgYWN0aXZlPC9zdHJpbmc+CiAgICA8c3RyaW5nIG5hbWU9InBpbmciPlBpbmc8L3N0cmluZz4KICAgIDxzdHJpbmcgbmFtZT0icGxlYXNlX2VudGVyX29uZV90aW1lX2NvZGVfZGlzcGxheWVkX29uX2FscmVhZHlfcmVnaXN0ZXJlZF9kZXZpY2UiPlBsZWFzZSBlbnRlcgogICAgICAgIHRoZSBvbmUtdGltZSBjb2RlIGRpc3BsYXllZCBvbiB0aGUgYWxyZWFkeS1yZWdpc3RlcmVkIGRldmljZTwvc3RyaW5nPgogICAgPHN0cmluZyBuYW1lPSJwb3J0X2NyZWRlbnRpYWxzX2V0YyI+UG9ydCwgY3JlZGVudGlhbHMsIGV0Yy48L3N0cmluZz4KICAgIDxzdHJpbmcgbmFtZT0icG9ydCI+UG9ydDwvc3RyaW5nPgogICAgPHN0cmluZyBuYW1lPSJwcml2YXRlX3Rva2VuIj5Qcml2YXRlIFRva2VuPC9zdHJpbmc+CiAgICA8c3RyaW5nIG5hbWU9InB1YmxpY19hZGRyZXNzIj5QdWJsaWMgYWRkcmVzczwvc3RyaW5nPgogICAgPHN0cmluZyBuYW1lPSJyZXF1aXJlX2ludGVybmV0X2Nvbm5lY3Rpb24iPlJlcXVpcmUgSW50ZXJuZXQgY29ubmVjdGlvbjwvc3RyaW5nPgogICAgPHN0cmluZyBuYW1lPSJyZXN0YXJ0X3JlcXVpcmVkX3RvX2FwcGx5X2NoYW5nZXMiPlJlc3RhcnQgcmVxdWlyZWQgdG8gYXBwbHkgY2hhbmdlczwvc3RyaW5nPgogICAgPHN0cmluZyBuYW1lPSJyZXRyaWVzX3NpZ25pbmdfZXRjIj5SZXRyaWVzLCBzaWduaW5nLCBldGMuPC9zdHJpbmc+CiAgICA8c3RyaW5nIG5hbWU9InJldHJ5X2NvdW50Ij5SZXRyeSBjb3VudDwvc3RyaW5nPgogICAgPHN0cmluZyBuYW1lPSJzZW5kX21lc3NhZ2VzX25vdGlmaWNhdGlvbiI+U2VuZGluZyBtZXNzYWdlc+KApjwvc3RyaW5nPgogICAgPHN0cmluZyBuYW1lPSJzZW5kaW5nX3dlYmhvb2siPlNlbmRpbmcgd2ViaG9va+KApjwvc3RyaW5nPgogICAgPHN0cmluZyBuYW1lPSJwcm9jZXNzaW5nX3dlYmhvb2tfcXVldWUiPlByb2Nlc3Npbmcgd2ViaG9vayBxdWV1ZeKApjwvc3RyaW5nPgogICAgPHN0cmluZyBuYW1lPSJzZXJ2ZXJfYWRkcmVzcyI+U2VydmVyIGFkZHJlc3M8L3N0cmluZz4KICAgIDxzdHJpbmcgbmFtZT0ic2VydmVyIj5TZXJ2ZXI8L3N0cmluZz4KICAgIDxzdHJpbmcgbmFtZT0ic2V0X21heGltdW1fdmFsdWVfdG9fYWN0aXZhdGUiPlNldCBtYXhpbXVtIHZhbHVlIHRvIGFjdGl2YXRlPC9zdHJpbmc+CiAgICA8c3RyaW5nIG5hbWU9InNldHRpbmdzX2FkZHJlc3NfaXNfc21zX2NhcGNvbV9tZSIgdHJhbnNsYXRhYmxlPSJmYWxzZSI+YXBpLnNtcy1nYXRlLmFwcDwvc3RyaW5nPgogICAgPHN0cmluZyBuYW1lPSJzZXR0aW5nc19jaGFuZ2VkX3ZpYV9hcGlfcmVzdGFydF90aGVfYXBwX3RvX2FwcGx5X2NoYW5nZXMiPlNldHRpbmdzIGNoYW5nZWQgdmlhCiAgICAgICAgQVBJLiBSZXN0YXJ0IHRoZSBhcHAgdG8gYXBwbHkgY2hhbmdlcy48L3N0cmluZz4KICAgIDxzdHJpbmcgbmFtZT0ic2V0dGluZ3NfbG9jYWxfYWRkcmVzc19pcyIgdHJhbnNsYXRhYmxlPSJmYWxzZSI+Jmx0O2EgaHJlZj4lMSRzOiUyJGQmbHQ7L2E+PC9zdHJpbmc+CiAgICA8c3RyaW5nIG5hbWU9InNldHRpbmdzX2xvY2FsX2FkZHJlc3Nfbm90X2ZvdW5kIj5Ob3QgYXZhaWxhYmxlPC9zdHJpbmc+CiAgICA8c3RyaW5nIG5hbWU9InNldHRpbmdzX2xvY2FsX3NlcnZlciI+TG9jYWwgc2VydmVyPC9zdHJpbmc+CiAgICA8c3RyaW5nIG5hbWU9InNldHRpbmdzX29mZmxpbmUiPk9mZmxpbmU8L3N0cmluZz4KICAgIDxzdHJpbmcgbmFtZT0ic2V0dGluZ3Nfb25saW5lIj5PbmxpbmU8L3N0cmluZz4KICAgIDxzdHJpbmcgbmFtZT0ic2V0dGluZ3NfcHVibGljX2FkZHJlc3NfaXMiIHRyYW5zbGF0YWJsZT0iZmFsc2UiPiZsdDthIGhyZWY+JTEkczolMiRkJmx0Oy9hPjwvc3RyaW5nPgogICAgPHN0cmluZyBuYW1lPSJzZXR0aW5nc19wdWJsaWNfYWRkcmVzc19ub3RfZm91bmQiPk5vdCBhdmFpbGFibGU8L3N0cmluZz4KICAgIDxzdHJpbmcgbmFtZT0ic2V0dGluZ3Nfc3RhcnRfb25fYm9vdCI+U3RhcnQgb24gYm9vdDwvc3RyaW5nPgogICAgPHN0cmluZyBuYW1lPSJzaWduX2luIj5TaWduIEluPC9zdHJpbmc+CiAgICA8c3RyaW5nIG5hbWU9InNpZ25fdXAiPlNpZ24gVXA8L3N0cmluZz4KICAgIDxzdHJpbmcgbmFtZT0ic2lnbmluZ19rZXkiPlNpZ25pbmcgS2V5PC9zdHJpbmc+CiAgICA8c3RyaW5nIG5hbWU9InNtc19nYXRld2F5X2lzX3J1bm5pbmdfb25fcG9ydCI+U01TR2F0ZSBpcyBydW5uaW5nIG9uIHBvcnQgJTEkZDwvc3RyaW5nPgogICAgPHN0cmluZyBuYW1lPSJzbXNfZ2F0ZXdheSI+U01TR2F0ZTwvc3RyaW5nPgogICAgPHN0cmluZyBuYW1lPSJzbXMiIHRyYW5zbGF0YWJsZT0iZmFsc2UiPnNtczwvc3RyaW5nPgogICAgPHN0cmluZyBuYW1lPSJzdWNjZXNzX2xvbmdfcHJlc3NfdG9fY29weSI+U3VjY2VzcywgbG9uZyBwcmVzcyB0byBjb3B5PC9zdHJpbmc+CiAgICA8c3RyaW5nIG5hbWU9InN5c3RlbSI+U3lzdGVtPC9zdHJpbmc+CiAgICA8c3RyaW5nIG5hbWU9InRhYl90ZXh0X2hvbWUiPkhvbWU8L3N0cmluZz4KICAgIDxzdHJpbmcgbmFtZT0idGFiX3RleHRfbWVzc2FnZXMiPk1FU1NBR0VTPC9zdHJpbmc+CiAgICA8c3RyaW5nIG5hbWU9InRhYl90ZXh0X3NldHRpbmdzIj5TRVRUSU5HUzwvc3RyaW5nPgogICAgPHN0cmluZyBuYW1lPSJ0aGVfd2ViaG9va19yZXF1ZXN0X3dpbGxfd2FpdF9mb3JfYW5faW50ZXJuZXRfY29ubmVjdGlvbiI+VGhlIHdlYmhvb2sgcmVxdWVzdCB3aWxsCiAgICAgICAgd2FpdCBmb3IgYW4gaW50ZXJuZXQgY29ubmVjdGlvbjwvc3RyaW5nPgogICAgPHN0cmluZyBuYW1lPSJ0b19hZGRfYV9kZXZpY2VfdG9fYW5fZXhpc3RpbmdfYWNjb3VudF9wbGVhc2VfZmlsbF9pbl90aGVfY3JlZGVudGlhbHNfYmVsb3ciPlRvCiAgICAgICAgYWRkIGEgZGV2aWNlIHRvIGFuIGV4aXN0aW5nIGFjY291bnQsIHBsZWFzZSBmaWxsIGluIHRoZSBjcmVkZW50aWFscyBiZWxvdy48L3N0cmluZz4KICAgIDxzdHJpbmcgbmFtZT0idG9fYXBwbHlfdGhlX2NoYW5nZXNfcmVzdGFydF90aGVfYXBwX3VzaW5nX3RoZV9idXR0b25fYmVsb3ciPlRvIGFwcGx5IHRoZSBjaGFuZ2VzLAogICAgICAgIHJlc3RhcnQgdGhlIGFwcCB1c2luZyB0aGUgYnV0dG9uIGJlbG93Ljwvc3RyaW5nPgogICAgPHN0cmluZyBuYW1lPSJ1c2VfZW1wdHlfdG9fZGlzYWJsZSI+VXNlIGVtcHR5IHRvIGRpc2FibGU8L3N0cmluZz4KICAgIDxzdHJpbmcgbmFtZT0idXNlX3RoaXNfY29kZV90b19zaWduX2luX29uX2Fub3RoZXJfZGV2aWNlIj5Vc2UgdGhpcyBjb2RlIHRvIHNpZ24gaW4gb24gYW5vdGhlcgogICAgICAgIGRldmljZTwvc3RyaW5nPgogICAgPHN0cmluZyBuYW1lPSJ1c2VybmFtZV9tdXN0X2JlX2F0X2xlYXN0XzNfY2hhcmFjdGVycyI+VXNlcm5hbWUgbXVzdCBiZSBhdCBsZWFzdCAzIGNoYXJhY3RlcnM8L3N0cmluZz4KICAgIDxzdHJpbmcgbmFtZT0idXNlcm5hbWUiPlVzZXJuYW1lPC9zdHJpbmc+CiAgICA8c3RyaW5nIG5hbWU9InZpZXciPlZpZXc8L3N0cmluZz4KICAgIDxzdHJpbmcgbmFtZT0id2ViaG9va19pZF9mb3JtYXQiIHRyYW5zbGF0YWJsZT0iZmFsc2UiPklEOiAlMSRzPC9zdHJpbmc+CiAgICA8c3RyaW5nIG5hbWU9IndlYmhvb2tfbGlzdF9zdW1tYXJ5Ij5WaWV3IHJlZ2lzdGVyZWQgd2ViaG9va3M8L3N0cmluZz4KICAgIDxzdHJpbmcgbmFtZT0id2ViaG9va19saXN0X3RpdGxlIj5SZWdpc3RlcmVkIFdlYmhvb2tzPC9zdHJpbmc+CiAgICA8c3RyaW5nIG5hbWU9IndlYmhvb2tzX2RvdGRvdGRvdCI+V2ViaG9va3PigKY8L3N0cmluZz4KICAgIDxzdHJpbmcgbmFtZT0id2ViaG9va3MiPldlYmhvb2tzPC9zdHJpbmc+CiAgICA8cGx1cmFscyBuYW1lPSJyZXZpZXdfaW5jb21pbmdfc21zX3dlYmhvb2tzIj4KICAgICAgICA8aXRlbSBxdWFudGl0eT0ib25lIj5Zb3UgaGF2ZSAlMSRkIGluY29taW5nIFNNUyB3ZWJob29rIHJlZ2lzdGVyZWQuIFBsZWFzZSByZXZpZXcgaXQgdG8KICAgICAgICAgICAgYXZvaWQgYW55IHNlY3VyaXR5IHJpc2tzLjwvaXRlbT4KICAgICAgICA8aXRlbSBxdWFudGl0eT0ib3RoZXIiPllvdSBoYXZlICUxJGQgaW5jb21pbmcgU01TIHdlYmhvb2tzIHJlZ2lzdGVyZWQuIFBsZWFzZSByZXZpZXcgdGhlbSB0bwogICAgICAgICAgICBhdm9pZCBhbnkgc2VjdXJpdHkgcmlza3MuPC9pdGVtPgogICAgPC9wbHVyYWxzPgogICAgPHN0cmluZyBuYW1lPSJwcm9jZXNzaW5nIj5Qcm9jZXNzaW5nPC9zdHJpbmc+CiAgICA8c3RyaW5nIG5hbWU9InByb2Nlc3Npbmdfb3JkZXJfdGl0bGUiPlByb2Nlc3Npbmcgb3JkZXI8L3N0cmluZz4KICAgIDxzdHJpbmcgbmFtZT0icXVldWVfc3RhdHVzIj7wn5OKIFF1ZXVlIFN0YXR1czwvc3RyaW5nPgogICAgPHN0cmluZyBuYW1lPSJ0b3RhbF9tZXNzYWdlcyI+VG90YWw6ICUxJGQ8L3N0cmluZz4KICAgIDxzdHJpbmcgbmFtZT0icGVuZGluZ19tZXNzYWdlcyI+UGVuZGluZzogJTEkZDwvc3RyaW5nPgogICAgPHN0cmluZyBuYW1lPSJzZW50X21lc3NhZ2VzIj5TZW50OiAlMSRkPC9zdHJpbmc+CiAgICA8c3RyaW5nIG5hbWU9ImRlbGl2ZXJlZF9tZXNzYWdlcyI+RGVsaXZlcmVkOiAlMSRkPC9zdHJpbmc+CiAgICA8c3RyaW5nIG5hbWU9ImZhaWxlZF9tZXNzYWdlcyI+RmFpbGVkOiAlMSRkPC9zdHJpbmc+CiAgICA8c3RyaW5nIG5hbWU9ImluY29taW5nX21lc3NhZ2VzIj5JTkNPTUlORzwvc3RyaW5nPgogICAgPHN0cmluZyBuYW1lPSJpbmNvbWluZ19tZXNzYWdlc19zdGF0dXMiPvCfk6UgSW5jb21pbmcgU3RhdHVzPC9zdHJpbmc+CiAgICA8c3RyaW5nIG5hbWU9ImluY29taW5nX3Ntc19tZXNzYWdlcyI+U01TOiAlMSRkPC9zdHJpbmc+CiAgICA8c3RyaW5nIG5hbWU9ImluY29taW5nX2RhdGFfbWVzc2FnZXMiPkRhdGEgU01TOiAlMSRkPC9zdHJpbmc+CiAgICA8c3RyaW5nIG5hbWU9ImluY29taW5nX21tc19tZXNzYWdlcyI+TU1TOiAlMSRkPC9zdHJpbmc+CiAgICA8c3RyaW5nIG5hbWU9Imp3dCI+SldUPC9zdHJpbmc+CiAgICA8c3RyaW5nIG5hbWU9Imp3dF9kZWZhdWx0X3R0bF9zZWNvbmRzIj5KV1QgZGVmYXVsdCBUVEwgKHNlY29uZHMpPC9zdHJpbmc+CiAgICA8c3RyaW5nIG5hbWU9Imp3dF90dGxfbXVzdF9iZV9iZXR3ZWVuXzFfc2Vjb25kX2FuZF8zNjVfZGF5cyI+SldUIFRUTCBtdXN0IGJlIGJldHdlZW4gMSBzZWNvbmQKICAgICAgICBhbmQgMzY1IGRheXM8L3N0cmluZz4KICAgIDxzdHJpbmcgbmFtZT0iand0X3JlZ2VuZXJhdGVfc2VjcmV0Ij5SZWdlbmVyYXRlIEpXVCBzZWNyZXQ8L3N0cmluZz4KICAgIDxzdHJpbmcgbmFtZT0iand0X3JlZ2VuZXJhdGVfc2VjcmV0X3N1bW1hcnkiPkludmFsaWRhdGVzIGFsbCBleGlzdGluZyBKV1Qgc2lnbmF0dXJlcwogICAgICAgIGltbWVkaWF0ZWx5Ljwvc3RyaW5nPgogICAgPHN0cmluZyBuYW1lPSJqd3Rfc2VjcmV0X3JlZ2VuZXJhdGVkIj5KV1Qgc2VjcmV0IHJlZ2VuZXJhdGVkPC9zdHJpbmc+CiAgICA8c3RyaW5nIG5hbWU9ImNvbmZpcm1fcmVnZW5lcmF0ZV9qd3Rfc2VjcmV0Ij5BcmUgeW91IHN1cmUgeW91IHdhbnQgdG8gcmVnZW5lcmF0ZSB0aGUgSldUIHNlY3JldD8KICAgICAgICBUaGlzIHdpbGwgaW52YWxpZGF0ZSBhbGwgZXhpc3RpbmcgSldUIHNpZ25hdHVyZXMgaW1tZWRpYXRlbHkuPC9zdHJpbmc+CiAgICA8c3RyaW5nIG5hbWU9ImNvbmZpcm0iPkNvbmZpcm08L3N0cmluZz4KICAgIDxzdHJpbmcgbmFtZT0iY2FuY2VsIj5DYW5jZWw8L3N0cmluZz4KICAgIDxzdHJpbmcgbmFtZT0ib3V0Z29pbmdfbWVzc2FnZXMiPk9VVEdPSU5HPC9zdHJpbmc+CiAgICA8c3RyaW5nIG5hbWU9ImluY29taW5nX3R5cGVfc21zIiB0cmFuc2xhdGFibGU9ImZhbHNlIj5TTVM8L3N0cmluZz4KICAgIDxzdHJpbmcgbmFtZT0iaW5jb21pbmdfdHlwZV9kYXRhX3NtcyIgdHJhbnNsYXRhYmxlPSJmYWxzZSI+RGF0YSBTTVM8L3N0cmluZz4KICAgIDxzdHJpbmcgbmFtZT0iaW5jb21pbmdfdHlwZV9tbXMiIHRyYW5zbGF0YWJsZT0iZmFsc2UiPk1NUzwvc3RyaW5nPgogICAgPHN0cmluZyBuYW1lPSJ3aGF0c21zX3NlcnZlcl9kb3Rkb3Rkb3QiPlNlcnZpZG9yIFdoYXRTTVPigKY8L3N0cmluZz4KICAgIDxzdHJpbmcgbmFtZT0id2hhdHNtc19zZXJ2ZXIiPlNlcnZpZG9yIFdoYXRTTVM8L3N0cmluZz4KICAgIDxzdHJpbmcgbmFtZT0idXJsX2VfY3JlZGVuY2lhaXNfZXRjIj5VUkwsIGNyZWRlbmNpYWlzLCBldGMuPC9zdHJpbmc+CjwvcmVzb3VyY2VzPgo= \ No newline at end of file + + %1$s + API URL, private token, credentials, etc. + API URL + WhatSMS Gateway + App version (build) + Battery optimization already disabled + Battery optimization is not + supported on this device + Battery optimization + Cancel + Continue + By Code + can affect battery life + Click + Continue to create an account. No personal information is required.\nBy continuing, you + agree to our Privacy Policy at https://docs.sms-gate.app/privacy/policy/ + Cloud server… + Cloud server + Cloud + Copied + Credentials + Delays, limits, etc. + Delays, seconds + Delete after, days + Device ID + Device + Disabled + + Enabled + Encryption + Failed to change password: %1$s + Failed to get login code: %1$s + Failed to register device: %1$s + Webhook ID copied to clipboard + If SIM number is not specified, use + Ignored for public server + Information + Internet connection: available + Internet connection: unavailable + Interval (seconds) + Invalid URL + %1$s is not a valid port. Must + be between 1024 and 65535. + Password + Username + Limits + List of last 50 log entries + Listening to server events… + Local address + Local Server… + Local SMSGate notifications + Local + Login Code, expires %1$s + Login Code + Logs + Maximum + Messages count + Messages + Messages… + Minimum + More settings… + n/a + New SMS Received Webhooks registered + No webhooks configured + not registered + Not set + SMSGate + Notification channel + Notifications + Online status at the cost of battery + life + Passphrase + Password changed successfully + Password must be at least 14 characters + Password must be at least 8 characters + Password + Period + Ping service is active + Ping + Please enter + the one-time code displayed on the already-registered device + Port, credentials, etc. + Port + Private Token + Public address + Require Internet connection + Restart required to apply changes + Retries, signing, etc. + Retry count + Sending messages… + Sending webhook… + Processing webhook queue… + Server address + Server + Set maximum value to activate + api.sms-gate.app + Settings changed via + API. Restart the app to apply changes. + <a href>%1$s:%2$d</a> + Not available + Local server + Offline + Online + <a href>%1$s:%2$d</a> + Not available + Start on boot + Sign In + Sign Up + Signing Key + SMSGate is running on port %1$d + SMSGate + sms + Success, long press to copy + System + Home + MESSAGES + SETTINGS + The webhook request will + wait for an internet connection + To + add a device to an existing account, please fill in the credentials below. + To apply the changes, + restart the app using the button below. + Use empty to disable + Use this code to sign in on another + device + Username must be at least 3 characters + Username + View + ID: %1$s + View registered webhooks + Registered Webhooks + Webhooks… + Webhooks + + You have %1$d incoming SMS webhook registered. Please review it to + avoid any security risks. + You have %1$d incoming SMS webhooks registered. Please review them to + avoid any security risks. + + Processing + Processing order + 📊 Queue Status + Total: %1$d + Pending: %1$d + Sent: %1$d + Delivered: %1$d + Failed: %1$d + INCOMING + 📥 Incoming Status + SMS: %1$d + Data SMS: %1$d + MMS: %1$d + JWT + JWT default TTL (seconds) + JWT TTL must be between 1 second + and 365 days + Regenerate JWT secret + Invalidates all existing JWT signatures + immediately. + JWT secret regenerated + Are you sure you want to regenerate the JWT secret? + This will invalidate all existing JWT signatures immediately. + Confirm + Cancel + OUTGOING + SMS + Data SMS + MMS + Servidor WhatSMS… + Servidor WhatSMS + URL, credenciais, etc. + Emparelhar dispositivo + Associar este telefone a um tenant WhatSMS via QR code + Aponte a câmara para o código QR no painel WhatSMS + Dispositivo emparelhado com sucesso! + Falha ao emparelhar. Verifique o QR e tente novamente. + Emparelhamento cancelado. + Dispositivo ainda não registado. Active o gateway primeiro. + Erro: %1$s + diff --git a/app/src/main/res/xml/whatsms_server_preferences.xml b/app/src/main/res/xml/whatsms_server_preferences.xml index 632b56a..c95be57 100644 --- a/app/src/main/res/xml/whatsms_server_preferences.xml +++ b/app/src/main/res/xml/whatsms_server_preferences.xml @@ -1 +1,57 @@ -PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPFByZWZlcmVuY2VTY3JlZW4geG1sbnM6YW5kcm9pZD0iaHR0cDovL3NjaGVtYXMuYW5kcm9pZC5jb20vYXBrL3Jlcy9hbmRyb2lkIgogICAgeG1sbnM6YXBwPSJodHRwOi8vc2NoZW1hcy5hbmRyb2lkLmNvbS9hcGsvcmVzLWF1dG8iPgogICAgPFByZWZlcmVuY2VDYXRlZ29yeSBhcHA6dGl0bGU9IkBzdHJpbmcvc2VydmVyIj4KICAgICAgICA8UHJlZmVyZW5jZQogICAgICAgICAgICBhcHA6ZW5hYmxlQ29weWluZz0idHJ1ZSIKICAgICAgICAgICAgYXBwOmljb249IkBkcmF3YWJsZS9pY19zZXJ2ZXIiCiAgICAgICAgICAgIGFwcDprZXk9InRyYW5zaWVudC5zZXJ2ZXJfdXJsIgogICAgICAgICAgICBhcHA6cGVyc2lzdGVudD0iZmFsc2UiCiAgICAgICAgICAgIGFwcDpzZWxlY3RhYmxlPSJmYWxzZSIKICAgICAgICAgICAgYXBwOnRpdGxlPSJAc3RyaW5nL2FwaV91cmwiIC8+CiAgICAgICAgPExpc3RQcmVmZXJlbmNlCiAgICAgICAgICAgIGFwcDppY29uPSJAZHJhd2FibGUvaWNfbm90aWZpY2F0aW9ucyIKICAgICAgICAgICAgYXBwOmtleT0iZ2F0ZXdheS5ub3RpZmljYXRpb25fY2hhbm5lbCIKICAgICAgICAgICAgYXBwOmRlZmF1bHRWYWx1ZT0iQVVUTyIKICAgICAgICAgICAgYXBwOmVudHJpZXM9IkBhcnJheS9ub3RpZmljYXRpb25fY2hhbm5lbHNfdGl0bGVzIgogICAgICAgICAgICBhcHA6ZW50cnlWYWx1ZXM9IkBhcnJheS9ub3RpZmljYXRpb25fY2hhbm5lbHNfdmFsdWVzIgogICAgICAgICAgICBhcHA6dGl0bGU9IkBzdHJpbmcvbm90aWZpY2F0aW9uX2NoYW5uZWwiCiAgICAgICAgICAgIGFwcDp1c2VTaW1wbGVTdW1tYXJ5UHJvdmlkZXI9InRydWUiIC8+CiAgICA8L1ByZWZlcmVuY2VDYXRlZ29yeT4KICAgIDxQcmVmZXJlbmNlQ2F0ZWdvcnkgYXBwOnRpdGxlPSJAc3RyaW5nL2NyZWRlbnRpYWxzIj4KICAgICAgICA8RWRpdFRleHRQcmVmZXJlbmNlCiAgICAgICAgICAgIGFwcDplbmFibGVDb3B5aW5nPSJ0cnVlIgogICAgICAgICAgICBhcHA6aWNvbj0iQGRyYXdhYmxlL2ljX3VzZXJuYW1lIgogICAgICAgICAgICBhcHA6a2V5PSJnYXRld2F5LnVzZXJuYW1lIgogICAgICAgICAgICBhcHA6cGVyc2lzdGVudD0iZmFsc2UiCiAgICAgICAgICAgIGFwcDpzZWxlY3RhYmxlPSJmYWxzZSIKICAgICAgICAgICAgYXBwOnRpdGxlPSJAc3RyaW5nL3VzZXJuYW1lIiAvPgogICAgICAgIDxFZGl0VGV4dFByZWZlcmVuY2UKICAgICAgICAgICAgYXBwOmVuYWJsZUNvcHlpbmc9InRydWUiCiAgICAgICAgICAgIGFwcDppY29uPSJAZHJhd2FibGUvaWNfcGFzc3dvcmQiCiAgICAgICAgICAgIGFwcDprZXk9ImdhdGV3YXkucGFzc3dvcmQiCiAgICAgICAgICAgIGFwcDpwZXJzaXN0ZW50PSJmYWxzZSIKICAgICAgICAgICAgYXBwOnRpdGxlPSJAc3RyaW5nL3Bhc3N3b3JkIiAvPgogICAgICAgIDxQcmVmZXJlbmNlCiAgICAgICAgICAgIGFuZHJvaWQ6aWNvbj0iQGRyYXdhYmxlL2ljX2NvZGUiCiAgICAgICAgICAgIGFuZHJvaWQ6a2V5PSJnYXRld2F5LmxvZ2luX2NvZGUiCiAgICAgICAgICAgIGFuZHJvaWQ6cGVyc2lzdGVudD0iZmFsc2UiCiAgICAgICAgICAgIGFuZHJvaWQ6c3VtbWFyeT0iQHN0cmluZy91c2VfdGhpc19jb2RlX3RvX3NpZ25faW5fb25fYW5vdGhlcl9kZXZpY2UiCiAgICAgICAgICAgIGFuZHJvaWQ6dGl0bGU9IkBzdHJpbmcvbG9naW5fY29kZSIKICAgICAgICAgICAgYXBwOmVuYWJsZUNvcHlpbmc9InRydWUiIC8+CiAgICA8L1ByZWZlcmVuY2VDYXRlZ29yeT4KICAgIDxQcmVmZXJlbmNlQ2F0ZWdvcnkgYXBwOnRpdGxlPSJAc3RyaW5nL2RldmljZSI+CiAgICAgICAgPFByZWZlcmVuY2UKICAgICAgICAgICAgYW5kcm9pZDppY29uPSJAZHJhd2FibGUvaWNfZGV2aWNlX2lkIgogICAgICAgICAgICBhbmRyb2lkOmtleT0idHJhbnNpZW50LmRldmljZV9pZCIKICAgICAgICAgICAgYW5kcm9pZDp0aXRsZT0iQHN0cmluZy9kZXZpY2VfaWQiCiAgICAgICAgICAgIGFwcDplbmFibGVDb3B5aW5nPSJ0cnVlIgogICAgICAgICAgICBhcHA6cGVyc2lzdGVudD0iZmFsc2UiIC8+CiAgICA8L1ByZWZlcmVuY2VDYXRlZ29yeT4KICAgIDxQcmVmZXJlbmNlIGFwcDpzdW1tYXJ5PSJAc3RyaW5nL3Jlc3RhcnRfcmVxdWlyZWRfdG9fYXBwbHlfY2hhbmdlcyIgLz4KPC9QcmVmZXJlbmNlU2NyZWVuPgo= \ No newline at end of file + + + + + + + + + + + + + + + + +