gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[taler-taler-android] 01/02: [wallet] Don't allow entering invalid amoun


From: gnunet
Subject: [taler-taler-android] 01/02: [wallet] Don't allow entering invalid amounts
Date: Tue, 03 Jan 2023 15:28:19 +0100

This is an automated email from the git hooks/post-receive script.

torsten-grote pushed a commit to branch master
in repository taler-android.

commit 9bb3505277b8132c3fd0be52d9bbbc6078723ff2
Author: Torsten Grote <t@grobox.de>
AuthorDate: Tue Jan 3 11:22:42 2023 -0300

    [wallet] Don't allow entering invalid amounts
    
    #0007350
---
 taler-kotlin-android/build.gradle                  |  4 +-
 .../src/main/java/net/taler/common/Amount.kt       | 44 +++++++++++++++++-----
 .../java/net/taler/wallet/ReceiveFundsFragment.kt  |  4 +-
 .../java/net/taler/wallet/SendFundsFragment.kt     |  4 +-
 4 files changed, 41 insertions(+), 15 deletions(-)

diff --git a/taler-kotlin-android/build.gradle 
b/taler-kotlin-android/build.gradle
index efd305f..69b4f4d 100644
--- a/taler-kotlin-android/build.gradle
+++ b/taler-kotlin-android/build.gradle
@@ -21,6 +21,7 @@ plugins {
 }
 
 android {
+    namespace 'net.taler.common'
     compileSdkVersion 32
     buildToolsVersion "$build_tools_version"
 
@@ -49,9 +50,6 @@ android {
             excludes += ['META-INF/*.kotlin_module']
         }
     }
-
-    namespace 'net.taler.common'
-
 }
 
 dependencies {
diff --git a/taler-kotlin-android/src/main/java/net/taler/common/Amount.kt 
b/taler-kotlin-android/src/main/java/net/taler/common/Amount.kt
index 4a6e4b3..750a1de 100644
--- a/taler-kotlin-android/src/main/java/net/taler/common/Amount.kt
+++ b/taler-kotlin-android/src/main/java/net/taler/common/Amount.kt
@@ -25,8 +25,11 @@ import kotlin.math.floor
 import kotlin.math.pow
 import kotlin.math.roundToInt
 
-public class AmountParserException(msg: String? = null, cause: Throwable? = 
null) : Exception(msg, cause)
-public class AmountOverflowException(msg: String? = null, cause: Throwable? = 
null) : Exception(msg, cause)
+public class AmountParserException(msg: String? = null, cause: Throwable? = 
null) :
+    Exception(msg, cause)
+
+public class AmountOverflowException(msg: String? = null, cause: Throwable? = 
null) :
+    Exception(msg, cause)
 
 @Serializable(with = KotlinXAmountSerializer::class)
 public data class Amount(
@@ -50,7 +53,7 @@ public data class Amount(
      * of the base currency value.  For example, a fraction
      * of 50_000_000 would correspond to 50 cents.
      */
-    val fraction: Int
+    val fraction: Int,
 ) : Comparable<Amount> {
 
     public companion object {
@@ -63,8 +66,8 @@ public data class Amount(
         public const val MAX_FRACTION: Int = 99_999_999
 
         public fun fromDouble(currency: String, value: Double): Amount {
-            val intPart = Math.floor(value).toLong()
-            val fraPart = Math.floor((value - intPart) *  
FRACTIONAL_BASE).toInt()
+            val intPart = floor(value).toLong()
+            val fraPart = floor((value - intPart) * FRACTIONAL_BASE).toInt()
             return Amount(currency, intPart, fraPart)
         }
 
@@ -87,14 +90,34 @@ public data class Amount(
                 val fractionStr = valueSplit[1]
                 if (fractionStr.length > MAX_FRACTION_LENGTH)
                     throw AmountParserException("Fraction $fractionStr too 
long")
-                val fraction = "0.$fractionStr".toDoubleOrNull()
-                    ?.times(FRACTIONAL_BASE)
-                    ?.roundToInt()
-                checkFraction(fraction)
+                checkFraction(fractionStr.getFraction())
             } else 0
             return Amount(checkCurrency(currency), value, fraction)
         }
 
+        public fun isValidAmountStr(str: String): Boolean {
+            val split = str.split(".")
+            try {
+                checkValue(split[0].toLongOrNull())
+            } catch (e: AmountParserException) {
+                return false
+            }
+            // also check fraction, if it exists
+            if (split.size > 1) {
+                val fractionStr = split[1]
+                if (fractionStr.length > MAX_FRACTION_LENGTH) return false
+                val fraction = fractionStr.getFraction() ?: return false
+                return fraction <= MAX_FRACTION
+            }
+            return true
+        }
+
+        private fun String.getFraction(): Int? {
+            return "0.$this".toDoubleOrNull()
+                ?.times(FRACTIONAL_BASE)
+                ?.roundToInt()
+        }
+
         public fun min(currency: String): Amount = Amount(currency, 0, 1)
         public fun max(currency: String): Amount = Amount(currency, MAX_VALUE, 
MAX_FRACTION)
 
@@ -132,7 +155,8 @@ public data class Amount(
 
     public operator fun plus(other: Amount): Amount {
         check(currency == other.currency) { "Can only subtract from same 
currency" }
-        val resultValue = value + other.value + floor((fraction + 
other.fraction).toDouble() / FRACTIONAL_BASE).toLong()
+        val resultValue =
+            value + other.value + floor((fraction + other.fraction).toDouble() 
/ FRACTIONAL_BASE).toLong()
         if (resultValue > MAX_VALUE)
             throw AmountOverflowException()
         val resultFraction = (fraction + other.fraction) % FRACTIONAL_BASE
diff --git a/wallet/src/main/java/net/taler/wallet/ReceiveFundsFragment.kt 
b/wallet/src/main/java/net/taler/wallet/ReceiveFundsFragment.kt
index 647512c..8ae96ad 100644
--- a/wallet/src/main/java/net/taler/wallet/ReceiveFundsFragment.kt
+++ b/wallet/src/main/java/net/taler/wallet/ReceiveFundsFragment.kt
@@ -55,6 +55,7 @@ import androidx.fragment.app.activityViewModels
 import androidx.lifecycle.lifecycleScope
 import androidx.navigation.fragment.findNavController
 import net.taler.common.Amount
+import net.taler.common.Amount.Companion.isValidAmountStr
 import net.taler.wallet.exchanges.ExchangeItem
 
 class ReceiveFundsFragment : Fragment() {
@@ -136,7 +137,8 @@ private fun ReceiveFundsIntro(
                 keyboardOptions = KeyboardOptions.Default.copy(keyboardType = 
Decimal),
                 onValueChange = { input ->
                     isError = false
-                    text = input.filter { it.isDigit() || it == '.' }
+                    val filtered = input.filter { it.isDigit() || it == '.' }
+                    if (filtered.endsWith('.') || isValidAmountStr(filtered)) 
text = filtered
                 },
                 isError = isError,
                 label = {
diff --git a/wallet/src/main/java/net/taler/wallet/SendFundsFragment.kt 
b/wallet/src/main/java/net/taler/wallet/SendFundsFragment.kt
index 640fbf7..c5348a3 100644
--- a/wallet/src/main/java/net/taler/wallet/SendFundsFragment.kt
+++ b/wallet/src/main/java/net/taler/wallet/SendFundsFragment.kt
@@ -52,6 +52,7 @@ import androidx.fragment.app.Fragment
 import androidx.fragment.app.activityViewModels
 import androidx.navigation.fragment.findNavController
 import net.taler.common.Amount
+import net.taler.common.Amount.Companion.isValidAmountStr
 
 class SendFundsFragment : Fragment() {
     private val model: MainViewModel by activityViewModels()
@@ -126,7 +127,8 @@ private fun SendFundsIntro(
                 onValueChange = { input ->
                     isError = false
                     insufficientBalance = false
-                    text = input.filter { it.isDigit() || it == '.' }
+                    val filtered = input.filter { it.isDigit() || it == '.' }
+                    if (filtered.endsWith('.') || isValidAmountStr(filtered)) 
text = filtered
                 },
                 isError = isError || insufficientBalance,
                 label = {

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]