got the logic down - need to check if it works

Signed-off-by: rapterjet2004 <juliuslinus1@gmail.com>
This commit is contained in:
rapterjet2004 2025-07-10 11:24:13 -05:00
parent 04ad846a18
commit e643039488
No known key found for this signature in database
GPG Key ID: 3AA5FDFED7944099
9 changed files with 347 additions and 137 deletions

View File

@ -210,6 +210,7 @@ dependencies {
exclude group: 'org.ogce', module: 'xpp3' // Android comes with its own XmlPullParser exclude group: 'org.ogce', module: 'xpp3' // Android comes with its own XmlPullParser
}) })
implementation 'org.conscrypt:conscrypt-android:2.5.3' implementation 'org.conscrypt:conscrypt-android:2.5.3'
implementation 'com.github.blikoon:QRCodeScanner:0.1.2'
implementation "androidx.camera:camera-core:${androidxCameraVersion}" implementation "androidx.camera:camera-core:${androidxCameraVersion}"
implementation "androidx.camera:camera-camera2:${androidxCameraVersion}" implementation "androidx.camera:camera-camera2:${androidxCameraVersion}"

View File

@ -16,6 +16,7 @@ import android.os.Bundle
import android.text.TextUtils import android.text.TextUtils
import android.util.Log import android.util.Log
import androidx.activity.OnBackPressedCallback import androidx.activity.OnBackPressedCallback
import androidx.activity.result.contract.ActivityResultContracts
import androidx.core.net.toUri import androidx.core.net.toUri
import androidx.lifecycle.Lifecycle import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleEventObserver import androidx.lifecycle.LifecycleEventObserver
@ -23,6 +24,7 @@ import androidx.work.OneTimeWorkRequest
import androidx.work.WorkInfo import androidx.work.WorkInfo
import androidx.work.WorkManager import androidx.work.WorkManager
import autodagger.AutoInjector import autodagger.AutoInjector
import com.blikoon.qrcodescanner.QrCodeActivity
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
import com.google.gson.JsonParser import com.google.gson.JsonParser
import com.nextcloud.talk.R import com.nextcloud.talk.R
@ -55,6 +57,7 @@ import okhttp3.RequestBody
import org.json.JSONException import org.json.JSONException
import org.json.JSONObject import org.json.JSONObject
import java.io.IOException import java.io.IOException
import java.net.URLDecoder
import java.util.concurrent.Executors import java.util.concurrent.Executors
import java.util.concurrent.ScheduledExecutorService import java.util.concurrent.ScheduledExecutorService
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
@ -113,7 +116,6 @@ class BrowserLoginActivity : BaseActivity() {
initViews() initViews()
onBackPressedDispatcher.addCallback(this, onBackPressedCallback) onBackPressedDispatcher.addCallback(this, onBackPressedCallback)
handleIntent() handleIntent()
anonymouslyPostLoginRequest()
lifecycle.addObserver(lifecycleEventObserver) lifecycle.addObserver(lifecycleEventObserver)
} }
@ -129,6 +131,13 @@ class BrowserLoginActivity : BaseActivity() {
if (extras.containsKey(BundleKeys.KEY_PASSWORD)) { if (extras.containsKey(BundleKeys.KEY_PASSWORD)) {
password = extras.getString(BundleKeys.KEY_PASSWORD) password = extras.getString(BundleKeys.KEY_PASSWORD)
} }
if (extras.containsKey(BundleKeys.KEY_FROM_QR)) {
val intent = Intent(this, QrCodeActivity::class.java)
qrScanResultLauncher.launch(intent)
} else {
anonymouslyPostLoginRequest()
}
} }
private fun initViews() { private fun initViews() {
@ -141,6 +150,29 @@ class BrowserLoginActivity : BaseActivity() {
} }
} }
private val qrScanResultLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
if (result.resultCode == RESULT_OK) {
val data = result.data
if (data == null) {
return@registerForActivityResult
}
val resultData = data.getStringExtra("com.blikoon.qrcodescanner.got_qr_scan_relult")
if (resultData == null || !resultData.startsWith("nc")) {
Snackbar.make(binding.root, getString(R.string.qr_code_error), Snackbar.LENGTH_SHORT).show()
return@registerForActivityResult
}
try {
parseLoginDataUrl(resultData)
} catch (e: IllegalArgumentException) {
Log.e(TAG, "Error in scanning QR Code: $e")
}
}
}
private fun anonymouslyPostLoginRequest() { private fun anonymouslyPostLoginRequest() {
CoroutineScope(Dispatchers.IO).launch { CoroutineScope(Dispatchers.IO).launch {
val url = "$baseUrl/index.php/login/v2" val url = "$baseUrl/index.php/login/v2"
@ -236,6 +268,44 @@ class BrowserLoginActivity : BaseActivity() {
} }
} }
/**
* QR returns a URI of format `nc://login/server:xxx&user:xxx&password:xxx`
* with the variables not always been in the provided order
*
* @throws IllegalArgumentException
*/
fun parseLoginDataUrl(dataString: String) {
if (!dataString.startsWith(PREFIX)) {
throw IllegalArgumentException("Invalid login URL detected" )
}
val data = dataString.removePrefix(PREFIX)
val values = data.split('&')
if(values.size !in 1..3) {
throw IllegalArgumentException("Illegal number of login URL elements detected: ${values.size}")
}
val loginData = LoginData()
values.forEach { value ->
when {
value.startsWith(USER_KEY) -> {
loginData.username = URLDecoder.decode(value.removePrefix(USER_KEY), "UTF-8")
}
value.startsWith(PASS_KEY) -> {
loginData.token = URLDecoder.decode(value.removePrefix(PASS_KEY), "UTF-8")
}
value.startsWith(SERVER_KEY) -> {
loginData.serverUrl = URLDecoder.decode(value.removePrefix(SERVER_KEY), "UTF-8")
baseUrl = loginData.serverUrl
}
}
}
parseAndLogin(loginData)
}
private fun completeLoginFlow(response: String, status: Int) { private fun completeLoginFlow(response: String, status: Int) {
try { try {
val jsonObject = JSONObject(response) val jsonObject = JSONObject(response)
@ -357,5 +427,9 @@ class BrowserLoginActivity : BaseActivity() {
private val TAG = BrowserLoginActivity::class.java.simpleName private val TAG = BrowserLoginActivity::class.java.simpleName
private const val INTERVAL = 30L private const val INTERVAL = 30L
private const val HTTP_OK = 200 private const val HTTP_OK = 200
private const val USER_KEY = "user:"
private const val SERVER_KEY = "server:"
private const val PASS_KEY = "password:"
private const val PREFIX = "nc://login/"
} }
} }

View File

@ -8,6 +8,7 @@
*/ */
package com.nextcloud.talk.account package com.nextcloud.talk.account
import android.Manifest
import android.accounts.Account import android.accounts.Account
import android.annotation.SuppressLint import android.annotation.SuppressLint
import android.content.Intent import android.content.Intent
@ -21,8 +22,11 @@ import android.view.View
import android.view.inputmethod.EditorInfo import android.view.inputmethod.EditorInfo
import android.widget.TextView import android.widget.TextView
import androidx.activity.OnBackPressedCallback import androidx.activity.OnBackPressedCallback
import androidx.activity.result.contract.ActivityResultContracts
import androidx.core.net.toUri import androidx.core.net.toUri
import androidx.core.os.bundleOf
import autodagger.AutoInjector import autodagger.AutoInjector
import com.github.dhaval2404.imagepicker.util.PermissionUtil
import com.nextcloud.talk.R import com.nextcloud.talk.R
import com.nextcloud.talk.activities.BaseActivity import com.nextcloud.talk.activities.BaseActivity
import com.nextcloud.talk.api.NcApi import com.nextcloud.talk.api.NcApi
@ -120,6 +124,8 @@ class ServerSelectionActivity : BaseActivity() {
} }
binding.certTextView.setOnClickListener { onCertClick() } binding.certTextView.setOnClickListener { onCertClick() }
binding.scanQr.setOnClickListener { onScan() }
if (ApplicationWideMessageHolder.getInstance().messageType != null) { if (ApplicationWideMessageHolder.getInstance().messageType != null) {
if (ApplicationWideMessageHolder.getInstance().messageType if (ApplicationWideMessageHolder.getInstance().messageType
== ApplicationWideMessageHolder.MessageType.SERVER_WITHOUT_TALK == ApplicationWideMessageHolder.MessageType.SERVER_WITHOUT_TALK
@ -390,6 +396,30 @@ class ServerSelectionActivity : BaseActivity() {
} }
} }
private val requestCameraPermissionLauncher = registerForActivityResult(ActivityResultContracts.RequestPermission()) { isGranted: Boolean ->
if (isGranted) {
// Permission was granted
startQRScanner()
}
}
fun onScan() {
if (PermissionUtil.isPermissionGranted(this, Manifest.permission.CAMERA)) {
startQRScanner()
} else {
requestCameraPermissionLauncher.launch(Manifest.permission.CAMERA)
}
}
private fun startQRScanner() {
val intent = Intent(this, BrowserLoginActivity::class.java)
val bundle = bundleOf().apply {
putBoolean(BundleKeys.KEY_FROM_QR, true)
}
intent.putExtras(bundle)
startActivity(intent)
}
public override fun onDestroy() { public override fun onDestroy() {
super.onDestroy() super.onDestroy()
dispose() dispose()

View File

@ -82,4 +82,5 @@ object BundleKeys {
const val KEY_CHAT_URL: String = "KEY_CHAT_URL" const val KEY_CHAT_URL: String = "KEY_CHAT_URL"
const val KEY_SCROLL_TO_NOTIFICATION_CATEGORY: String = "KEY_SCROLL_TO_NOTIFICATION_CATEGORY" const val KEY_SCROLL_TO_NOTIFICATION_CATEGORY: String = "KEY_SCROLL_TO_NOTIFICATION_CATEGORY"
const val KEY_FOCUS_INPUT: String = "KEY_FOCUS_INPUT" const val KEY_FOCUS_INPUT: String = "KEY_FOCUS_INPUT"
const val KEY_FROM_QR: String = "KEY_FROM_QR"
} }

View File

@ -0,0 +1,12 @@
<!--
~ Nextcloud Talk - Android Client
~
~ SPDX-FileCopyrightText: 2025 Google LLC
~ SPDX-License-Identifier: Apache-2.0
-->
<vector xmlns:android="http://schemas.android.com/apk/res/android" android:height="24dp" android:tint="#000000" android:viewportHeight="960" android:viewportWidth="960" android:width="24dp">
<path android:fillColor="@android:color/white" android:pathData="M120,440L120,120L440,120L440,440L120,440ZM200,360L360,360L360,200L200,200L200,360ZM120,840L120,520L440,520L440,840L120,840ZM200,760L360,760L360,600L200,600L200,760ZM520,440L520,120L840,120L840,440L520,440ZM600,360L760,360L760,200L600,200L600,360ZM760,840L760,760L840,760L840,840L760,840ZM520,600L520,520L600,520L600,600L520,600ZM600,680L600,600L680,600L680,680L600,680ZM520,760L520,680L600,680L600,760L520,760ZM600,840L600,760L680,760L680,840L600,840ZM680,760L680,680L760,680L760,760L680,760ZM680,600L680,520L760,520L760,600L680,600ZM760,680L760,600L840,600L840,680L760,680Z"/>
</vector>

View File

@ -152,6 +152,16 @@
tools:text="@string/nc_server_unsupported" /> tools:text="@string/nc_server_unsupported" />
</LinearLayout> </LinearLayout>
<com.google.android.material.button.MaterialButton
android:id="@+id/scan_Qr"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
app:iconTint="@color/white"
android:textColor="@color/white"
android:theme="@style/Widget.Material3.Button.TextButton.Icon"
app:icon="@drawable/outline_qr_code_24"
android:text="@string/scan_qr_code"/>
<TextView <TextView
android:id="@+id/import_or_choose_provider_text" android:id="@+id/import_or_choose_provider_text"
android:layout_width="wrap_content" android:layout_width="wrap_content"

View File

@ -871,4 +871,6 @@ How to translate with transifex:
<string name="open_notes">Open Notes</string> <string name="open_notes">Open Notes</string>
<string name="cancel_login">Cancel Login</string> <string name="cancel_login">Cancel Login</string>
<string name="please_continue_the_login_process_in_the_browser">Please continue the login process in the browser</string> <string name="please_continue_the_login_process_in_the_browser">Please continue the login process in the browser</string>
<string name="scan_qr_code">Scan QR Code</string>
<string name="qr_code_error">QR code could not be read</string>
</resources> </resources>

View File

@ -307,6 +307,50 @@ CqZ5vSc=
=B+Kr =B+Kr
-----END PGP PUBLIC KEY BLOCK----- -----END PGP PUBLIC KEY BLOCK-----
pub 893A028475557671
uid Gradle Inc. <info@gradle.com>
sub 5E9AEEBA28836032
-----BEGIN PGP PUBLIC KEY BLOCK-----
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
WzZKkqBVoahM3qqyoKOy7mfpt1hB4gEq
=E5AV
-----END PGP PUBLIC KEY BLOCK-----
pub 8CD7D660AE857DAD pub 8CD7D660AE857DAD
uid Emarc Magtanong <emarc@getkeepsafe.com> uid Emarc Magtanong <emarc@getkeepsafe.com>
@ -377,8 +421,6 @@ HdZk2xusuOEx27cIovRPHwvLcgY+4u3j
-----END PGP PUBLIC KEY BLOCK----- -----END PGP PUBLIC KEY BLOCK-----
pub 928B20E9AD5298CC pub 928B20E9AD5298CC
uid Jakarta Contexts and Dependency Injection <cdi-dev@eclipse.org>
sub 0AA3E5C3D232E79B sub 0AA3E5C3D232E79B
-----BEGIN PGP PUBLIC KEY BLOCK----- -----BEGIN PGP PUBLIC KEY BLOCK-----
@ -393,44 +435,42 @@ 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 =Y1uz
s5E5s0wc
=+V3C
-----END PGP PUBLIC KEY BLOCK----- -----END PGP PUBLIC KEY BLOCK-----
pub 928FBF39003C0425 pub 928FBF39003C0425
@ -1357,8 +1397,6 @@ IprKXtD8103BdNqrPJev2azwqWwxFpN83tEPbK4SwWPgk1nSELXZZ5ClcDgqatg+
-----END PGP PUBLIC KEY BLOCK----- -----END PGP PUBLIC KEY BLOCK-----
pub B943F5CB616566CD pub B943F5CB616566CD
uid Marcel Schnelle <marcelschnelle@aol.com>
sub D73B23600E60600B sub D73B23600E60600B
-----BEGIN PGP PUBLIC KEY BLOCK----- -----BEGIN PGP PUBLIC KEY BLOCK-----
@ -1373,34 +1411,35 @@ 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 =bif8
=mH9D
-----END PGP PUBLIC KEY BLOCK----- -----END PGP PUBLIC KEY BLOCK-----
pub BAC30622339994C4 pub BAC30622339994C4
uid Chris Povirk <cpovirk@google.com>
sub FC9BDC25FB378008 sub FC9BDC25FB378008
-----BEGIN PGP PUBLIC KEY BLOCK----- -----BEGIN PGP PUBLIC KEY BLOCK-----
@ -1409,20 +1448,21 @@ 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
i8/b+PwSW+nW3EpQZdLqZtOU QzLSAVn44AHSomlgzecMR6RZk/fwbzSSiOc3rW1mNFOG70iLz9v4/BJb6dbcSlBl
=2H2i 0upm05Q=
=Gf3Y
-----END PGP PUBLIC KEY BLOCK----- -----END PGP PUBLIC KEY BLOCK-----
pub BCF4173966770193 pub BCF4173966770193
@ -1451,15 +1491,18 @@ IaddzrPZPmaZ8CtzzyB7+JdSNItBB2Sp
-----END PGP PUBLIC KEY BLOCK----- -----END PGP PUBLIC KEY BLOCK-----
pub BDD2A76422470515 pub BDD2A76422470515
uid Dave Brosius <dbrosius@mebigfatguy.com>
sub 0C77E993AC36C97C sub 0C77E993AC36C97C
-----BEGIN PGP PUBLIC KEY BLOCK----- -----BEGIN PGP PUBLIC KEY BLOCK-----
mDMEaDypvxYJKwYBBAHaRw8BAQdAv3OEFRIQWBhSii0M3S9P3eGlZLalGY9smzBQ mDMEaDypvxYJKwYBBAHaRw8BAQdAv3OEFRIQWBhSii0M3S9P3eGlZLalGY9smzBQ
C0aiVXW4OARoPKm/EgorBgEEAZdVAQUBAQdA2THBTS3MqZPdTuKmc7QkAvlvwmJa C0aiVXW0J0RhdmUgQnJvc2l1cyA8ZGJyb3NpdXNAbWViaWdmYXRndXkuY29tPrg4
WEQsXXqkjQdEwD4DAQgHiH4EGBYKACYWIQSu/rh4kM398rwIxKq90qdkIkcFFQUC BGg8qb8SCisGAQQBl1UBBQEBB0DZMcFNLcypk91O4qZztCQC+W/CYlpYRCxdeqSN
aDypvwIbDAUJBaOagAAKCRC90qdkIkcFFfyUAPsGJcpKQP2/sQe+XN69rVZMFXhk B0TAPgMBCAeIfgQYFgoAJhYhBK7+uHiQzf3yvAjEqr3Sp2QiRwUVBQJoPKm/AhsM
dYg0U9EhpY/7GHDpHQD+J5Uy2s3USLxeyIylXUFWtxqOocB+vZhvH3Yhmjhwmgw= BQkFo5qAAAoJEL3Sp2QiRwUV/JQA+wYlykpA/b+xB75c3r2tVkwVeGR1iDRT0SGl
=zAHg j/sYcOkdAP4nlTLazdRIvF7IjKVdQVa3Go6hwH69mG8fdiGaOHCaDA==
=wcNA
-----END PGP PUBLIC KEY BLOCK----- -----END PGP PUBLIC KEY BLOCK-----
pub BEDE11EAF1164480 pub BEDE11EAF1164480
@ -5049,34 +5092,6 @@ vzqZL9WH1qfOB26bczhzqYBdpE3HRRqvOaFo2o7Rm9biGIJ/QqTk9C0xcI1/5BNv
=tT4f =tT4f
-----END PGP PUBLIC KEY BLOCK----- -----END PGP PUBLIC KEY BLOCK-----
pub 479D601F3A7B5C1A
uid AJ Alt <ajalt@users.noreply.github.com>
sub 868FF6CCEF26A83C
-----BEGIN PGP PUBLIC KEY BLOCK-----
mQENBF5CDMYBCADC1/aWU6ZbGZEphRbmjUPNfqh3N5goSnDCou97mmQ9Uq8iBuKS
UXJnGSOHudXK56f+Drx5lGZdLAzveZdqaqb1o3yLFO3PJxwj3Ulhab3O3uTG2eR0
2Xo7GKjRW13kEfphJrfVIaQq/TiyIG8IQ1dbm9Vuzc5NLDIeC4jxYD2S3hUqCLGQ
BiZAEH9un2cPax+hiT+9MGzdfQwdVrSQ9aEA9mtMhEGsk80XtxXJnd+hw2va6l5s
lSErmH5nMtyKh/n9uo/ap1CfPl98n5VUI8dDtUfWVrqRrkyHgdX+MII0t0nABV5X
rJLneg4dVy5Yw/+FVbLWB1Ta21reyytcIYQXABEBAAG0J0FKIEFsdCA8YWphbHRA
dXNlcnMubm9yZXBseS5naXRodWIuY29tPrkBDQReQgzGAQgA1oQHEM6wP40xPfpa
YBBRAWVoEj/CbAV6BooApSqQkV0cocM9wK905az2FmlKn4WTZyNwiA2eHjHlevsI
jKuHJWhSDVhulcKDi0cD6wTcjctcDWm7M3tvaICbieZQXPH7lju5Ct80kBo5ojdJ
oXGD72kVhSuiF8vOrAOiLOXP8+bpCpY4+LZ4qt3XjSnrkZq+h/vcy9crwuzuFlSL
wMRltOvfirrK/CSQZZtqG2PbT30CWFQ61DLo4DkXeNG1fKpnOaDAMaCedt+pNCAQ
1Vdzy1vT9b85LtOH/CmhumjM3S6x/VWwWZVBXi2xVLFCkm3LlWioSvVs6Na0Vvaq
0WDsbwARAQABiQE2BBgBCAAgFiEEA8EjA4wgqunihshXR51gHzp7XBoFAl5CDMYC
GwwACgkQR51gHzp7XBpoYQgAjnYuxyXaFSbCc2EFWDrBA8+OnlbSgJ3etaIOoLQH
+Czv6+wLYc9snZDBm+IvbzEi3tXfi1TKcRI5ii9wDkti0KcVFrR2tpuXDLWYIF92
cSC7VyBiyT/aZpm0zX8qP8tjRZvy7mewbnoit1R6ea5UifSLvO0bHqNoswfgv90s
rnuUYMY8tv1sSo4j0f0zre/k4QT8sCTeMDsLsviMIvy1Wls1IPRo1SW1euGGGvCo
bxgke8Dw5QgumudwPqehOZVOkIbuddgcur55ZFFeitMOqdRoXkrGod9v6hYY1Jz8
W/Y2tzZmWsedFIc4ahuAeZG6cH6Ac8prHrQEz6lSbZ0flg==
=td3S
-----END PGP PUBLIC KEY BLOCK-----
pub 4B1E11D5A4B91E89 pub 4B1E11D5A4B91E89
uid Adam Cozzette <acozzette@google.com> uid Adam Cozzette <acozzette@google.com>
@ -6270,8 +6285,6 @@ c8LNGrDaCFdXnOdlNV/zT9VvBk/RkV+Tl/Lk4g==
-----END PGP PUBLIC KEY BLOCK----- -----END PGP PUBLIC KEY BLOCK-----
pub 7905DE25C78AD456 pub 7905DE25C78AD456
uid Protobuf Release <protobuf@googlegroups.com>
sub DBC5123E2E98FEFE sub DBC5123E2E98FEFE
-----BEGIN PGP PUBLIC KEY BLOCK----- -----BEGIN PGP PUBLIC KEY BLOCK-----
@ -6283,26 +6296,25 @@ Uul7vR3iNRXtbnS31qIgCYWAoX6w0xHf6KUeIPWV21ZIUu5cg6kQr/sPt/OQuGS2
nKk+InYtopDi6d7AUh8WI2TP7qAMIoRkhAeDEQ99DiopwFNPA/7M4g99AQfFSmp3 nKk+InYtopDi6d7AUh8WI2TP7qAMIoRkhAeDEQ99DiopwFNPA/7M4g99AQfFSmp3
acPCdeXXAZeDAqoFGFKTlqzg3FLWpGkubI/iXyHkpQfOXv4MtYuPGVNheBXGcWbf acPCdeXXAZeDAqoFGFKTlqzg3FLWpGkubI/iXyHkpQfOXv4MtYuPGVNheBXGcWbf
XPjbkFYjkGIN2Wx4i7yf43hMCk6ArhswfgCcgoORI+DCVdm7ORID1PjIU2Z71EA2 XPjbkFYjkGIN2Wx4i7yf43hMCk6ArhswfgCcgoORI+DCVdm7ORID1PjIU2Z71EA2
qDdFwdoOdEV42YUAEQEAAbQsUHJvdG9idWYgUmVsZWFzZSA8cHJvdG9idWZAZ29v qDdFwdoOdEV42YUAEQEAAbkBjQRkrGQrAQwArgt5OPV2vwX0T3xSnrLgAodjRlt5
Z2xlZ3JvdXBzLmNvbT65AY0EZKxkKwEMAK4LeTj1dr8F9E98Up6y4AKHY0Zbeb5v vm9z9POwlfpQK53PKBhNtCcRys8hwnlMlXmV6eICXGepTP+onGakG0YI0frdz36I
c/TzsJX6UCudzygYTbQnEcrPIcJ5TJV5leniAlxnqUz/qJxmpBtGCNH63c9+iJNh k2FWokRmH11u6mpCf6aq0G+w8AFsdT4LjpMt5uY4rhH33OC3FWVJhpsm5u4bYyqe
VqJEZh9dbupqQn+mqtBvsPABbHU+C46TLebmOK4R99zgtxVlSYabJubuG2Mqnq96 r3qa60FRYojeJjmPQkAwtjUMl6wAbABY/yC9RkeF3gsk3eKKQ1JNbJQTQefCbZUo
mutBUWKI3iY5j0JAMLY1DJesAGwAWP8gvUZHhd4LJN3iikNSTWyUE0Hnwm2VKFq4 WrhzEj/qpoKnO1+5IPXLQmmVJ+YpF355wtKqEO+UxmTCKBSmMK8XuJJo++nFZ2QV
cxI/6qaCpztfuSD1y0JplSfmKRd+ecLSqhDvlMZkwigUpjCvF7iSaPvpxWdkFabS ptJ+sx4iPBsZT98tXyKXC089vntfo2uT00hR1VrplvGK4gSshyncl+B9R/LvDFwj
frMeIjwbGU/fLV8ilwtPPb57X6Nrk9NIUdVa6ZbxiuIErIcp3JfgfUfy7wxcI/Uj 9SMyrUjnQ07CLMtWmtluYq/U/zxsAKZ2ifrXamcOGGzzimEmYDt/ND+MCoXUlDgK
Mq1I50NOwizLVprZbmKv1P88bACmdon612pnDhhs84phJmA7fzQ/jAqF1JQ4Crdz t3Mv7qDnoqTHVWU3d1KY+O7JyNPPKS43Bn8WLQuP0LODgtWnql5Kw9ZL6Wn2H205
L+6g56Kkx1VlN3dSmPjuycjTzykuNwZ/Fi0Lj9Czg4LVp6peSsPWS+lp9h9tOSzt LO2VB6/4ZeJAplNi3wnG8E86SbSF3kzfQENvABEBAAGJAbwEGAEKACYWIQQaVfCR
lQev+GXiQKZTYt8JxvBPOkm0hd5M30BDbwARAQABiQG8BBgBCgAmFiEEGlXwka0o rSjAf4MfpE15Bd4lx4rUVgUCZKxkKwIbDAUJA8JnAAAKCRB5Bd4lx4rUVtf3DACY
wH+DH6RNeQXeJceK1FYFAmSsZCsCGwwFCQPCZwAACgkQeQXeJceK1FbX9wwAmLBK sEpDwmWMTCTQqpjFrCu6xZfBof7Ujze6t/9aw4lgSQqiJA5uwUZO5qiXKWfpkfIX
Q8JljEwk0KqYxawrusWXwaH+1I83urf/WsOJYEkKoiQObsFGTuaolyln6ZHyF+gt 6C24p5a2Vu8bppeq/1ddyxVAbs0wZ0QDLoNM2Pvu4EBcxZPFWkPT2JV56m9ZKLPu
uKeWtlbvG6aXqv9XXcsVQG7NMGdEAy6DTNj77uBAXMWTxVpD09iVeepvWSiz7r7M vsyDMl+W42AYM4YqmTHEiNLw2c4Cwr26q7K8FBr3sj5ieJqtOSmdVamBJH/tXccd
gzJfluNgGDOGKpkxxIjS8NnOAsK9uquyvBQa97I+YniarTkpnVWpgSR/7V3HHf6Q /pDZoIoveKF0ra4hLh0isWL6ZUK3bMNp3xTw3tLYa/ZU7+8EX6EgUJXvzyEsf0d5
2aCKL3ihdK2uIS4dIrFi+mVCt2zDad8U8N7S2Gv2VO/vBF+hIFCV788hLH9HeX3f fd/vQT31fnuGtUKHQx4KiU4hXXPArwYt5XtumvrHXXHlyOK/bvGTL3la17IfnD3D
70E99X57hrVCh0MeColOIV1zwK8GLeV7bpr6x11x5cjiv27xky95WteyH5w9w/Xq 9epO7Q1DljIpf/Q9RhVfeYuzn0ftbKzoA3KBYmzn0lPgpLBvekgRXuBZLCneZaSy
Tu0NQ5YyKX/0PUYVX3mLs59H7Wys6ANygWJs59JT4KSwb3pIEV7gWSwp3mWkstlF 2UWbhOr936BUXrgi2sfKVmDRakc+/Wz50fr+1ZywGeSBH85Lfc+SKNCC8xbiKZA1
m4Tq/d+gVF64ItrHylZg0WpHPv1s+dH6/tWcsBnkgR/OS33PkijQgvMW4imQNRxg HGDKY5kh24ddfVf4rOVFlNe+/i1IWchDSZZjXJKI4lAlLZYAFXAWkVzysQKbp40=
ymOZIduHXX1X+KzlRZTXvv4tSFnIQ0mWY1ySiOJQJS2WABVwFpFc8rECm6eN =UiVm
=z4dc
-----END PGP PUBLIC KEY BLOCK----- -----END PGP PUBLIC KEY BLOCK-----
pub 793FD5751A0F0780 pub 793FD5751A0F0780
@ -6361,6 +6373,50 @@ cJR4YXWx
=IK4j =IK4j
-----END PGP PUBLIC KEY BLOCK----- -----END PGP PUBLIC KEY BLOCK-----
pub 79B3F4FD617DDBAD
uid Suresh Marru (IU Email) <smarru@iu.edu>
sub 30B0DD8C5845C0DF
-----BEGIN PGP PUBLIC KEY BLOCK-----
mQINBE6xY5EBEAC/c/7k2mDWzcA0GBzum21OGr/uLb72ZiOtsscVYgTONLHOT9Pi
k5ASMBVB7pKws/Rt2ArebDaQYOyhQXUX9UApAMR8vI8PIoghH/76FwyBD2V/ve6f
w6gCG/s6XfpCg/ZJQraFEYHak7a3fuwCIzJBqSYPr6uYP2ymzSXI4v5xl/dGMOyb
ribqO+Y2FD6nhDC2H/ZY1lMQg5UKqhxZ4E6wK8yYGdtwh0WBc4uFm4OMy3ZcI5o1
A9zoFpDnF/mwCqyhpmfYKra6M7U4oqLSU/Z331jm1R2NeMVgAbQ5LJL+XzlQoQvW
gd5BlUs7LxLgjUxnzeQX9FRR8p2F/tZElMXDFl9XxBJB5MqvEt3QEv/Z9DfUIEaM
QU+VL002ZtC16k2Uxtds4HyU4cDx3YPc2pBqzgKmJ2GHNEji8NQXJdTwUO0BnJU3
w8HqCdh0+vt9u5/BQsKxaNhUvXMkgcw1/g0P2w/C1qnp0l6ckyrkhXv3FDJ9EHn5
+RwOGV348NFS9Mm2x3Rt7T3ibJaNJ8izOCKfTgBxLUF6FMv3REuL6IzFxjxbGt6T
Clj94YLmaddUWTTX/gJ7vXvHNkDJmWmQYLUCQc+HegsW+oiYI+Vf/WPIoZerAv/9
0hgccztFdg0VThAPwtP+00Pq2L8K4BIOfFL3VBQh51QgZgza5PdxoZZ9awARAQAB
tCdTdXJlc2ggTWFycnUgKElVIEVtYWlsKSA8c21hcnJ1QGl1LmVkdT65Ag0ETrFj
kQEQALug8d9CzFOisqvpyoV1hwK8zqDVTf2QG1p5znfH48BD9ix9qhnKtOSaCY82
apj1FzmaFpM2eluLEgFC/TDqdlxFmJmnanfNEvnVV+aQt7hP34kPcBDCOKQONDw+
RiayOQwbYQh/KUEgnw5uAY1AgNIYgmLpatzPDhoeTh0ZLCD0o3vpczomF/cia0my
Q/5tGaegXJK6J4cEV34wTI1Jpkb/+8hO1CfudhgRjILgymHVAFHhauU6NMnbv5xD
SdQGvfR6pkdjPqc1sekH/GG8H9EdBWyn1AlheJ82ePjI74ZyOahTOseyKdgKc0gb
8lbjUFM/nZSGBROn2RoqfZM2j/kc4F3F3jOQLg2Ceg4cKk4gJseJUXTGqFI+0Akn
mRKH6sNYCXy8ufFh2Mwo+akYteNFRAFF/YOU1ubM9AO+GuTsMjmvrz57iwHL1Hht
XzW7oXXtJ9hzmjZFqV2qAYx4NSJIhCS0NoLVzByGkBBYToUKshNZQPja77bDSpy6
PdIZCX7hbzatmz8EQcpQxXX29gdbV0YEANQ1CrHD23iSCFXUAVKn3gEdGXDvWO4Z
fCc2SH/I+o30xsBCbuQsaM3LPyNiw7RFLZ+FpH0VCJKzgbUGvtaYjvE9egUj8RY5
Esq5AIE742KUYPN9+7ZnHplx7c2DikLi27xHKqCoh3LenojVABEBAAGJAh8EGAEC
AAkFAk6xY5ECGwwACgkQebP0/WF92616/Q/+LGTxCB39bC68jqkvBPXA9V4dAy0x
gnIUChjtijG0VLc3Ds/kkLkjUp8bH6Avdy0sbvfh2fwwR/m+lSVpispfudaytcPa
LEUwUxq3mu5Bz6C7H0TzsQGT4Uwm0kUeih/Ce9rfoGCgdrlTi7kZrGkzzJKg32C5
sEJu8OIMTMMnwfBOOlYmVPcdw+jG6a8KEP+ICLXawEk1/VMv4WgNHy9QFbOV89w1
YD/c5z9y+6DiPTTUgeSVbb34iTqTQkkmyODJtCcUeR8yrPpN8YptpI/8j9XmxDmj
Pvo9dzNa54p6cu2urqIrZFcDNDziBJ98jWBLGN8IKnsB0cI/bcnBoqwRTDHX//SH
ajyl5qtl3uF2Hhxx63KDyrZDGoJgfrAf5+ppOxH3WyLG78IFvCqDENSInThHPN4F
5z0Tw7BdlHqYOzxMNQ9hNYSkRtqYzx+eob4eb439vQ3i1ULmY8gAEFGGQV3e9QP7
cbQeJCkR5iqp6VFNeGt5tNkUwDUWBWTCNQ83b2JM8ksytkR0y70fb1g9862phEm1
VtwO5rCtQhG5055Em+j0qxS+kp2Xnv536PA3qPJMK9JrM5vfAKbP/g7RLyxrIesj
5hq1JxqyDaI4211/k6whi/v9dO8btNE/n7wQNeFw0uZJENjyB6L15Bja0PgLag88
bj0frksnOTPQBk4=
=9sMZ
-----END PGP PUBLIC KEY BLOCK-----
pub 79E193516BE7998F pub 79E193516BE7998F
sub 9F7335D63326E7F9 sub 9F7335D63326E7F9
-----BEGIN PGP PUBLIC KEY BLOCK----- -----BEGIN PGP PUBLIC KEY BLOCK-----

View File

@ -14,9 +14,12 @@
<trust file=".*-sources[.]jar" regex="true" reason="Android Studio downloads source jars but doesn't add checksums - fixes building in AS"/> <trust file=".*-sources[.]jar" regex="true" reason="Android Studio downloads source jars but doesn't add checksums - fixes building in AS"/>
</trusted-artifacts> </trusted-artifacts>
<ignored-keys> <ignored-keys>
<ignored-key id="1DE461528F1F1B2A" reason="Key couldn't be downloaded from any key server"/>
<ignored-key id="479D601F3A7B5C1A" reason="Key couldn't be downloaded from any key server"/>
<ignored-key id="A6EA2E2BF22E0543" reason="Key couldn't be downloaded from any key server"/> <ignored-key id="A6EA2E2BF22E0543" reason="Key couldn't be downloaded from any key server"/>
<ignored-key id="AC7A514BC9F9BB70" reason="Key couldn't be downloaded from any key server"/> <ignored-key id="AC7A514BC9F9BB70" reason="Key couldn't be downloaded from any key server"/>
<ignored-key id="BDD2A76422470515" reason="Key couldn't be downloaded from any key server"/> <ignored-key id="BDD2A76422470515" reason="Key couldn't be downloaded from any key server"/>
<ignored-key id="F6CE9695C9318406" reason="Key couldn't be downloaded from any key server"/>
</ignored-keys> </ignored-keys>
<trusted-keys> <trusted-keys>
<trusted-key id="02A36B6DB7056EB5E6FFEF893DA731F041734930" group="org.parceler"/> <trusted-key id="02A36B6DB7056EB5E6FFEF893DA731F041734930" group="org.parceler"/>
@ -11803,6 +11806,14 @@
<sha256 value="977a16e0c70ee01139463fd4cbd9efd7d7a767c0c8b3e72941b69cbdd2f085d3" origin="Generated by Gradle" reason="Artifact is not signed"/> <sha256 value="977a16e0c70ee01139463fd4cbd9efd7d7a767c0c8b3e72941b69cbdd2f085d3" origin="Generated by Gradle" reason="Artifact is not signed"/>
</artifact> </artifact>
</component> </component>
<component group="com.github.blikoon" name="QRCodeScanner" version="0.1.2">
<artifact name="QRCodeScanner-0.1.2.aar">
<sha256 value="be2f333f2739761358f032ac86c0120deb2c93c92a8ac619cce912aef20e2b79" origin="Generated by Gradle" reason="Artifact is not signed"/>
</artifact>
<artifact name="QRCodeScanner-0.1.2.pom">
<sha256 value="1ab22f1bd0c9010f102d625d81b3d4747b893117f2750f9094df8ec12f152c58" origin="Generated by Gradle" reason="Artifact is not signed"/>
</artifact>
</component>
<component group="com.github.chrisbanes" name="PhotoView" version="2.3.0"> <component group="com.github.chrisbanes" name="PhotoView" version="2.3.0">
<artifact name="PhotoView-2.3.0.aar"> <artifact name="PhotoView-2.3.0.aar">
<sha256 value="6c8989f2945d50ab38b3e0300064f1f8d2d75bbcae1434fe535d9fb6898e9ad6" origin="Generated by Gradle" reason="Artifact is not signed"/> <sha256 value="6c8989f2945d50ab38b3e0300064f1f8d2d75bbcae1434fe535d9fb6898e9ad6" origin="Generated by Gradle" reason="Artifact is not signed"/>
@ -14222,6 +14233,19 @@
<sha256 value="18b80f34a5e9fa1a5eec2250fd71e5465f2eb4b4d09e181940e38f1b6e064452" origin="Generated by Gradle" reason="Artifact is not signed"/> <sha256 value="18b80f34a5e9fa1a5eec2250fd71e5465f2eb4b4d09e181940e38f1b6e064452" origin="Generated by Gradle" reason="Artifact is not signed"/>
</artifact> </artifact>
</component> </component>
<component group="com.google.zxing" name="core" version="3.3.0">
<artifact name="core-3.3.0.jar">
<sha256 value="bba7724e02a997cec38213af77133ee8e24b0d5cf5fa7ecbc16a4fa93f11ee0d" origin="Generated by Gradle" reason="A key couldn't be downloaded"/>
</artifact>
<artifact name="core-3.3.0.pom">
<sha256 value="ca1c3e4c4848773d4e5afa301c12bc18aa4b26d2475ff6961ce026f2d940aabf" origin="Generated by Gradle" reason="A key couldn't be downloaded"/>
</artifact>
</component>
<component group="com.google.zxing" name="zxing-parent" version="3.3.0">
<artifact name="zxing-parent-3.3.0.pom">
<sha256 value="7c6951b21684f68ac4f6983d26e0f0b01ab5e7066f8b74b4acaff6f638ed1ff6" origin="Generated by Gradle" reason="A key couldn't be downloaded"/>
</artifact>
</component>
<component group="com.googlecode.juniversalchardet" name="juniversalchardet" version="1.0.3"> <component group="com.googlecode.juniversalchardet" name="juniversalchardet" version="1.0.3">
<artifact name="juniversalchardet-1.0.3.jar"> <artifact name="juniversalchardet-1.0.3.jar">
<sha256 value="757bfe906193b8b651e79dc26cd67d6b55d0770a2cdfb0381591504f779d4a76" origin="Generated by Gradle"/> <sha256 value="757bfe906193b8b651e79dc26cd67d6b55d0770a2cdfb0381591504f779d4a76" origin="Generated by Gradle"/>