remove logcat

This commit is contained in:
2026-05-14 05:24:27 +05:00
parent 1e95e82a61
commit 135f0659dd
5 changed files with 1 additions and 52 deletions
@@ -1,6 +1,5 @@
package sh.sar.basedbank.api.mib package sh.sar.basedbank.api.mib
import android.util.Log
import okhttp3.FormBody import okhttp3.FormBody
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Request import okhttp3.Request
@@ -40,7 +39,6 @@ class MibContactsClient {
.build() .build()
return client.newCall(request).execute().use { response -> return client.newCall(request).execute().use { response ->
Log.d(TAG, "getCategories: HTTP ${response.code}")
if (!response.isSuccessful) return emptyList() if (!response.isSuccessful) return emptyList()
parseCategories(response.body?.string() ?: return emptyList()) parseCategories(response.body?.string() ?: return emptyList())
} }
@@ -58,7 +56,6 @@ class MibContactsClient {
) )
} }
} catch (e: Exception) { } catch (e: Exception) {
Log.e(TAG, "parseCategories error: $e")
emptyList() emptyList()
} }
} }
@@ -89,7 +86,6 @@ class MibContactsClient {
.build() .build()
val (contacts, totalCount) = client.newCall(request).execute().use { response -> val (contacts, totalCount) = client.newCall(request).execute().use { response ->
Log.d(TAG, "fetchContacts page $page: HTTP ${response.code}")
if (!response.isSuccessful) return all if (!response.isSuccessful) return all
parseContacts(response.body?.string() ?: return all) parseContacts(response.body?.string() ?: return all)
} }
@@ -97,7 +93,6 @@ class MibContactsClient {
if (all.size >= totalCount || contacts.isEmpty()) break if (all.size >= totalCount || contacts.isEmpty()) break
page++ page++
} }
Log.d(TAG, "fetchContacts: loaded ${all.size} contacts")
return all return all
} }
@@ -127,7 +122,6 @@ class MibContactsClient {
} }
Pair(contacts, totalCount) Pair(contacts, totalCount)
} catch (e: Exception) { } catch (e: Exception) {
Log.e(TAG, "parseContacts error: $e")
Pair(emptyList(), 0) Pair(emptyList(), 0)
} }
} }
@@ -1,6 +1,5 @@
package sh.sar.basedbank.api.mib package sh.sar.basedbank.api.mib
import android.util.Log
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Request import okhttp3.Request
import java.util.concurrent.TimeUnit import java.util.concurrent.TimeUnit
@@ -35,7 +34,6 @@ class MibFinancingClient {
.build() .build()
val html = client.newCall(request).execute().use { response -> val html = client.newCall(request).execute().use { response ->
Log.d(TAG, "fetchFinancing: HTTP ${response.code}")
if (!response.isSuccessful) return emptyList() if (!response.isSuccessful) return emptyList()
response.body?.string() ?: return emptyList() response.body?.string() ?: return emptyList()
} }
@@ -69,7 +67,7 @@ class MibFinancingClient {
lastPayAmount = attrs["lastPayAmount"]?.toDoubleOrNull() ?: 0.0, lastPayAmount = attrs["lastPayAmount"]?.toDoubleOrNull() ?: 0.0,
currency = attrs["curCodeDesc"] ?: "MVR" currency = attrs["curCodeDesc"] ?: "MVR"
) )
}.toList().also { Log.d(TAG, "parsed ${it.size} financing deals") } }.toList()
} }
companion object { companion object {
@@ -1,6 +1,5 @@
package sh.sar.basedbank.api.mib package sh.sar.basedbank.api.mib
import android.util.Log
import okhttp3.FormBody import okhttp3.FormBody
import sh.sar.basedbank.util.Totp import sh.sar.basedbank.util.Totp
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
@@ -48,16 +47,12 @@ class MibLoginFlow(private val prefs: android.content.SharedPreferences) {
*/ */
fun login(username: String, passwordHash: String, otpSeed: String): List<MibAccount> { fun login(username: String, passwordHash: String, otpSeed: String): List<MibAccount> {
val appId = getOrCreateAppId() val appId = getOrCreateAppId()
Log.d(TAG, "login: appId=$appId")
val key1 = prefs.getString("mib_key1_$username", null) val key1 = prefs.getString("mib_key1_$username", null)
val key2 = prefs.getString("mib_key2_$username", null) val key2 = prefs.getString("mib_key2_$username", null)
Log.d(TAG, "login: stored keys present=${key1 != null && key2 != null}")
return if (key1 != null && key2 != null) { return if (key1 != null && key2 != null) {
Log.d(TAG, "login: taking regular login path")
regularLogin(username, passwordHash, appId, key1, key2) regularLogin(username, passwordHash, appId, key1, key2)
} else { } else {
Log.d(TAG, "login: taking first-time registration path")
firstTimeRegistration(username, passwordHash, otpSeed, appId) firstTimeRegistration(username, passwordHash, otpSeed, appId)
} }
} }
@@ -67,40 +62,29 @@ class MibLoginFlow(private val prefs: android.content.SharedPreferences) {
private fun firstTimeRegistration( private fun firstTimeRegistration(
username: String, passwordHash: String, otpSeed: String, appId: String username: String, passwordHash: String, otpSeed: String, appId: String
): List<MibAccount> { ): List<MibAccount> {
Log.d(TAG, "[reg] step 0: key exchange (sfunc=r)")
val (session1, _) = initialKeyExchange(appId, MibCrypto.DEFAULT_KEY, "r") val (session1, _) = initialKeyExchange(appId, MibCrypto.DEFAULT_KEY, "r")
Log.d(TAG, "[reg] step 0 done: xxid=${session1.xxid}")
Log.d(TAG, "[reg] step 1: getAuthType (A44)")
val userSalt = getAuthType(session1, username) val userSalt = getAuthType(session1, username)
Log.d(TAG, "[reg] step 1 done: userSalt length=${userSalt.length}")
Log.d(TAG, "[reg] step 2: registration init (C41)")
Log.d(TAG, "[reg] username='$username' userSalt='$userSalt'")
val clientSalt = randomAlpha(32) val clientSalt = randomAlpha(32)
val pgf03 = computePgf03(passwordHash, userSalt, clientSalt) val pgf03 = computePgf03(passwordHash, userSalt, clientSalt)
Log.d(TAG, "[reg] pgf03=$pgf03")
val regInitPayload = baseData(session1, "C41").apply { val regInitPayload = baseData(session1, "C41").apply {
put("uname", username) put("uname", username)
put("pgf03", pgf03) put("pgf03", pgf03)
put("clientSalt", clientSalt) put("clientSalt", clientSalt)
} }
val regInitResp = doRequest(session1, regInitPayload, "n") val regInitResp = doRequest(session1, regInitPayload, "n")
Log.d(TAG, "[reg] step 2 response: $regInitResp")
check(regInitResp.optBoolean("success", false)) { check(regInitResp.optBoolean("success", false)) {
regInitResp.optString("reasonText", "Registration init failed") regInitResp.optString("reasonText", "Registration init failed")
} }
Log.d(TAG, "[reg] step 3: OTP verify (C42)")
val otp = generateOtp(otpSeed) val otp = generateOtp(otpSeed)
Log.d(TAG, "[reg] generated OTP=$otp")
val otpPayload = baseData(session1, "C42").apply { val otpPayload = baseData(session1, "C42").apply {
put("otp", otp) put("otp", otp)
put("uname", username) put("uname", username)
put("otpType", "3") put("otpType", "3")
} }
val otpResp = doRequest(session1, otpPayload, "n") val otpResp = doRequest(session1, otpPayload, "n")
Log.d(TAG, "[reg] step 3 response: $otpResp")
check(otpResp.optBoolean("success", false)) { check(otpResp.optBoolean("success", false)) {
otpResp.optString("reasonText", "OTP verification failed") otpResp.optString("reasonText", "OTP verification failed")
} }
@@ -108,7 +92,6 @@ class MibLoginFlow(private val prefs: android.content.SharedPreferences) {
val keyData = otpResp.getJSONArray("data").getJSONObject(0) val keyData = otpResp.getJSONArray("data").getJSONObject(0)
val key1 = keyData.getString("key1") val key1 = keyData.getString("key1")
val key2 = keyData.getString("key2") val key2 = keyData.getString("key2")
Log.d(TAG, "[reg] stored key1/key2 for user=$username")
prefs.edit().putString("mib_key1_$username", key1).putString("mib_key2_$username", key2).apply() prefs.edit().putString("mib_key1_$username", key1).putString("mib_key2_$username", key2).apply()
return regularLogin(username, passwordHash, appId, key1, key2) return regularLogin(username, passwordHash, appId, key1, key2)
@@ -120,18 +103,12 @@ class MibLoginFlow(private val prefs: android.content.SharedPreferences) {
username: String, passwordHash: String, username: String, passwordHash: String,
appId: String, key1: String, key2: String appId: String, key1: String, key2: String
): List<MibAccount> { ): List<MibAccount> {
Log.d(TAG, "[login] step 4: key exchange (sfunc=i)")
val (session2, _) = initialKeyExchange(appId, key1, "i", key2) val (session2, _) = initialKeyExchange(appId, key1, "i", key2)
Log.d(TAG, "[login] step 4 done: xxid=${session2.xxid}")
Log.d(TAG, "[login] step 5: getAuthType (A44)")
val userSalt = getAuthType(session2, username) val userSalt = getAuthType(session2, username)
Log.d(TAG, "[login] step 5 done: userSalt length=${userSalt.length}")
Log.d(TAG, "[login] step 6: login init (A41)")
val clientSalt = randomAlpha(32) val clientSalt = randomAlpha(32)
val pgf03 = computePgf03(passwordHash, userSalt, clientSalt) val pgf03 = computePgf03(passwordHash, userSalt, clientSalt)
Log.d(TAG, "[login] pgf03 length=${pgf03.length}")
val loginPayload = baseData(session2, "A41").apply { val loginPayload = baseData(session2, "A41").apply {
put("uname", username) put("uname", username)
put("pgf03", pgf03) put("pgf03", pgf03)
@@ -140,17 +117,14 @@ class MibLoginFlow(private val prefs: android.content.SharedPreferences) {
put("requireBankData", 1) put("requireBankData", 1)
} }
val loginResp = doRequest(session2, loginPayload, "n") val loginResp = doRequest(session2, loginPayload, "n")
Log.d(TAG, "[login] step 6 response: success=${loginResp.optBoolean("success")} reasonCode=${loginResp.optString("reasonCode")} reasonText=${loginResp.optString("reasonText")}")
check(loginResp.optBoolean("success", false)) { check(loginResp.optBoolean("success", false)) {
loginResp.optString("reasonText", "Login init failed") loginResp.optString("reasonText", "Login init failed")
} }
val profiles = parseProfiles(loginResp) val profiles = parseProfiles(loginResp)
Log.d(TAG, "[login] parsed ${profiles.size} profiles")
lastSession = session2 lastSession = session2
lastProfiles = profiles lastProfiles = profiles
Log.d(TAG, "[login] step 7: fetch all profiles")
return fetchAllProfiles(session2, profiles) return fetchAllProfiles(session2, profiles)
} }
@@ -175,9 +149,7 @@ class MibLoginFlow(private val prefs: android.content.SharedPreferences) {
.build() .build()
val response = post(formBody) val response = post(formBody)
Log.d(TAG, "keyExchange($sfunc) raw response (first 80): ${response.take(80)}")
val respJson = MibCrypto.decrypt(response, encKey) val respJson = MibCrypto.decrypt(response, encKey)
Log.d(TAG, "keyExchange($sfunc) decrypted: success=${respJson.optBoolean("success")} reasonText=${respJson.optString("reasonText")}")
check(respJson.optBoolean("success", false)) { check(respJson.optBoolean("success", false)) {
respJson.optString("reasonText", "Key exchange failed") respJson.optString("reasonText", "Key exchange failed")
@@ -201,7 +173,6 @@ class MibLoginFlow(private val prefs: android.content.SharedPreferences) {
private fun doRequest(session: MibSession, data: JSONObject, sfunc: String): JSONObject { private fun doRequest(session: MibSession, data: JSONObject, sfunc: String): JSONObject {
val routePath = data.optString("routePath", "?") val routePath = data.optString("routePath", "?")
Log.d(TAG, "doRequest: routePath=$routePath xxid=${session.xxid.take(16)}...")
val encrypted = MibCrypto.encrypt(data, session.sessionKey) val encrypted = MibCrypto.encrypt(data, session.sessionKey)
val formBody = FormBody.Builder() val formBody = FormBody.Builder()
.add("xxid", session.xxid) .add("xxid", session.xxid)
@@ -209,9 +180,7 @@ class MibLoginFlow(private val prefs: android.content.SharedPreferences) {
.add("data", encrypted) .add("data", encrypted)
.build() .build()
val response = post(formBody) val response = post(formBody)
Log.d(TAG, "doRequest($routePath) raw response (first 80): ${response.take(80)}")
val result = MibCrypto.decrypt(response, session.sessionKey) val result = MibCrypto.decrypt(response, session.sessionKey)
Log.d(TAG, "doRequest($routePath) decrypted: success=${result.optBoolean("success")} reasonText=${result.optString("reasonText")}")
return result return result
} }
@@ -228,7 +197,6 @@ class MibLoginFlow(private val prefs: android.content.SharedPreferences) {
* subsequent WebView requests run under that profile. * subsequent WebView requests run under that profile.
*/ */
fun switchProfile(session: MibSession, profile: MibProfile) { fun switchProfile(session: MibSession, profile: MibProfile) {
Log.d(TAG, "switchProfile: profileId=${profile.profileId} cifType=${profile.cifType}")
val payload = baseData(session, "P47").apply { val payload = baseData(session, "P47").apply {
put("profileType", profile.profileType) put("profileType", profile.profileType)
put("profileId", profile.profileId) put("profileId", profile.profileId)
@@ -245,7 +213,6 @@ class MibLoginFlow(private val prefs: android.content.SharedPreferences) {
} }
val resp = doRequest(session, payload, "n") val resp = doRequest(session, payload, "n")
if (!resp.optBoolean("success", false)) { if (!resp.optBoolean("success", false)) {
Log.w(TAG, "P47 failed for profile ${profile.name}: ${resp.optString("reasonText")}")
continue continue
} }
val accountBalances = resp.optJSONArray("accountBalance") ?: continue val accountBalances = resp.optJSONArray("accountBalance") ?: continue
@@ -1,6 +1,5 @@
package sh.sar.basedbank.api.mib package sh.sar.basedbank.api.mib
import android.util.Log
import okhttp3.FormBody import okhttp3.FormBody
import okhttp3.OkHttpClient import okhttp3.OkHttpClient
import okhttp3.Request import okhttp3.Request
@@ -65,7 +64,6 @@ class MibTransferClient {
.build() .build()
return client.newCall(request).execute().use { response -> return client.newCall(request).execute().use { response ->
Log.d(TAG, "lookupIpsAccount: HTTP ${response.code}")
val bodyStr = response.body?.string() ?: "" val bodyStr = response.body?.string() ?: ""
val json = try { JSONObject(bodyStr) } catch (_: Exception) { null } val json = try { JSONObject(bodyStr) } catch (_: Exception) { null }
if (!response.isSuccessful || json == null || !json.optBoolean("success")) { if (!response.isSuccessful || json == null || !json.optBoolean("success")) {
@@ -92,7 +90,6 @@ class MibTransferClient {
.build() .build()
return client.newCall(request).execute().use { response -> return client.newCall(request).execute().use { response ->
Log.d(TAG, "lookupAccountName: HTTP ${response.code}")
val bodyStr = response.body?.string() ?: "" val bodyStr = response.body?.string() ?: ""
val json = try { JSONObject(bodyStr) } catch (_: Exception) { null } val json = try { JSONObject(bodyStr) } catch (_: Exception) { null }
if (!response.isSuccessful || json == null || !json.optBoolean("success")) { if (!response.isSuccessful || json == null || !json.optBoolean("success")) {
@@ -122,7 +119,6 @@ class MibTransferClient {
.build() .build()
return client.newCall(request).execute().use { response -> return client.newCall(request).execute().use { response ->
Log.d(TAG, "lookupAlias: HTTP ${response.code}")
val bodyStr = response.body?.string() ?: "" val bodyStr = response.body?.string() ?: ""
val json = try { JSONObject(bodyStr) } catch (_: Exception) { null } val json = try { JSONObject(bodyStr) } catch (_: Exception) { null }
if (!response.isSuccessful || json == null || !json.optBoolean("success")) { if (!response.isSuccessful || json == null || !json.optBoolean("success")) {
@@ -9,7 +9,6 @@ import android.os.Handler
import android.os.Looper import android.os.Looper
import android.text.Editable import android.text.Editable
import android.text.TextWatcher import android.text.TextWatcher
import android.util.Log
import androidx.fragment.app.Fragment import androidx.fragment.app.Fragment
import androidx.lifecycle.lifecycleScope import androidx.lifecycle.lifecycleScope
import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.Dispatchers
@@ -87,10 +86,8 @@ class CredentialsFragment : Fragment() {
val password = binding.etPassword.text.toString() val password = binding.etPassword.text.toString()
val otpSeed = binding.etOtpSeed.text.toString().trim() val otpSeed = binding.etOtpSeed.text.toString().trim()
Log.d(TAG, "Login button pressed for username=$username")
if (username.isEmpty() || password.isEmpty() || otpSeed.isEmpty()) { if (username.isEmpty() || password.isEmpty() || otpSeed.isEmpty()) {
Log.w(TAG, "Validation failed: empty fields")
binding.tvError.text = "Please fill in all fields" binding.tvError.text = "Please fill in all fields"
binding.tvError.visibility = View.VISIBLE binding.tvError.visibility = View.VISIBLE
return return
@@ -106,11 +103,9 @@ class CredentialsFragment : Fragment() {
viewLifecycleOwner.lifecycleScope.launch { viewLifecycleOwner.lifecycleScope.launch {
try { try {
Log.d(TAG, "Starting login flow on IO dispatcher")
val accounts = withContext(Dispatchers.IO) { val accounts = withContext(Dispatchers.IO) {
flow.login(username, passwordHash, otpSeed) flow.login(username, passwordHash, otpSeed)
} }
Log.d(TAG, "Login succeeded, got ${accounts.size} accounts")
CredentialStore(requireContext()).saveMibCredentials(username, passwordHash, otpSeed) CredentialStore(requireContext()).saveMibCredentials(username, passwordHash, otpSeed)
AccountCache.save(requireContext(), accounts) AccountCache.save(requireContext(), accounts)
val app = requireActivity().application as BasedBankApp val app = requireActivity().application as BasedBankApp
@@ -121,7 +116,6 @@ class CredentialsFragment : Fragment() {
intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK
startActivity(intent) startActivity(intent)
} catch (e: Exception) { } catch (e: Exception) {
Log.e(TAG, "Login failed: ${e.message}", e)
binding.tvError.text = e.message ?: "Login failed" binding.tvError.text = e.message ?: "Login failed"
binding.tvError.visibility = View.VISIBLE binding.tvError.visibility = View.VISIBLE
} finally { } finally {