Started to check for illegal SEPA characters and added replacing XML entities

This commit is contained in:
dankl 2019-10-27 23:39:24 +01:00 committed by dankito
parent 21e9a021c5
commit b48f97e3a5
5 changed files with 117 additions and 4 deletions

View File

@ -13,6 +13,8 @@ import kotlinx.android.synthetic.main.dialog_bank_transfer.*
import kotlinx.android.synthetic.main.dialog_bank_transfer.view.* import kotlinx.android.synthetic.main.dialog_bank_transfer.view.*
import net.dankito.banking.fints4java.android.R import net.dankito.banking.fints4java.android.R
import net.dankito.banking.fints4java.android.ui.MainWindowPresenter import net.dankito.banking.fints4java.android.ui.MainWindowPresenter
import net.dankito.fints.messages.segmente.implementierte.sepa.ISepaMessageCreator
import net.dankito.fints.messages.segmente.implementierte.sepa.SepaMessageCreator
import net.dankito.fints.model.BankTransferData import net.dankito.fints.model.BankTransferData
import net.dankito.fints.response.client.FinTsClientResponse import net.dankito.fints.response.client.FinTsClientResponse
import net.dankito.utils.android.extensions.asActivity import net.dankito.utils.android.extensions.asActivity
@ -30,6 +32,8 @@ open class BankTransferDialog : DialogFragment() {
protected var preselectedValues: BankTransferData? = null protected var preselectedValues: BankTransferData? = null
protected val sepaMessageCreator: ISepaMessageCreator = SepaMessageCreator()
open fun show(activity: AppCompatActivity, presenter: MainWindowPresenter, fullscreen: Boolean = false) { open fun show(activity: AppCompatActivity, presenter: MainWindowPresenter, fullscreen: Boolean = false) {
show(activity, presenter, null, fullscreen) show(activity, presenter, null, fullscreen)
@ -64,6 +68,7 @@ open class BankTransferDialog : DialogFragment() {
rootView.edtxtRemitteeBic.addTextChangedListener(otherEditTextChangedWatcher) rootView.edtxtRemitteeBic.addTextChangedListener(otherEditTextChangedWatcher)
rootView.edtxtAmount.addTextChangedListener(otherEditTextChangedWatcher) rootView.edtxtAmount.addTextChangedListener(otherEditTextChangedWatcher)
rootView.edtxtUsage.addTextChangedListener(otherEditTextChangedWatcher)
rootView.btnCancel.setOnClickListener { dismiss() } rootView.btnCancel.setOnClickListener { dismiss() }
@ -184,9 +189,11 @@ open class BankTransferDialog : DialogFragment() {
protected open fun checkIfRequiredDataEnteredOnUiThread() { protected open fun checkIfRequiredDataEnteredOnUiThread() {
val requiredDataEntered = val requiredDataEntered =
edtxtRemitteeName.text.toString().isNotEmpty() edtxtRemitteeName.text.toString().isNotEmpty()
&& sepaMessageCreator.containsOnlyAllowedCharacters(edtxtRemitteeName.text.toString()) // TODO: show error message for illegal characters
&& edtxtRemitteeIban.text.toString().isNotEmpty() // TODO: check if it is of length > 12, in Germany > 22? && edtxtRemitteeIban.text.toString().isNotEmpty() // TODO: check if it is of length > 12, in Germany > 22?
&& edtxtRemitteeBic?.text.toString().isNotEmpty() // TODO: check if it is of length is 8 or 11? && edtxtRemitteeBic?.text.toString().isNotEmpty() // TODO: check if it is of length is 8 or 11?
&& isAmountGreaterZero() && isAmountGreaterZero()
&& sepaMessageCreator.containsOnlyAllowedCharacters(edtxtUsage.text.toString()) // TODO: show error message for illegal characters
btnDoBankTransfer.isEnabled = requiredDataEntered btnDoBankTransfer.isEnabled = requiredDataEntered
} }

View File

@ -5,4 +5,8 @@ interface ISepaMessageCreator {
fun createXmlFile(filename: String, replacementStrings: Map<String, String>): String fun createXmlFile(filename: String, replacementStrings: Map<String, String>): String
fun containsOnlyAllowedCharacters(stringToTest: String): Boolean
fun convertToAllowedCharacters(input: String): String
} }

View File

@ -23,14 +23,14 @@ open class SepaEinzelueberweisung(
debitorBic, debitorBic,
mapOf( mapOf(
SepaMessageCreator.NumberOfTransactionsKey to "1", // TODO: may someday support more then one transaction per file SepaMessageCreator.NumberOfTransactionsKey to "1", // TODO: may someday support more then one transaction per file
"DebitorName" to debitor.name, "DebitorName" to messageCreator.convertToAllowedCharacters(debitor.name),
"DebitorIban" to debitor.iban!!, "DebitorIban" to debitor.iban!!,
"DebitorBic" to debitorBic, "DebitorBic" to debitorBic,
"CreditorName" to data.creditorName, "CreditorName" to messageCreator.convertToAllowedCharacters(data.creditorName),
"CreditorIban" to data.creditorIban, "CreditorIban" to data.creditorIban,
"CreditorBic" to data.creditorBic, "CreditorBic" to data.creditorBic,
"Amount" to data.amount.toString(), "Amount" to data.amount.toString(), // TODO: check if ',' or '.' should be used as decimal separator
"Usage" to data.usage, "Usage" to messageCreator.convertToAllowedCharacters(data.usage),
"RequestedExecutionDate" to RequestedExecutionDateValueForNotScheduledTransfers "RequestedExecutionDate" to RequestedExecutionDateValueForNotScheduledTransfers
), ),
messageCreator messageCreator

View File

@ -5,6 +5,7 @@ import org.slf4j.LoggerFactory
import java.io.File import java.io.File
import java.text.SimpleDateFormat import java.text.SimpleDateFormat
import java.util.* import java.util.*
import java.util.regex.Pattern
/** /**
@ -19,6 +20,10 @@ import java.util.*
open class SepaMessageCreator : ISepaMessageCreator { open class SepaMessageCreator : ISepaMessageCreator {
companion object { companion object {
const val AllowedSepaCharacters = "A-Za-z0-9\\?,\\-\\+\\./\\(\\) "
val AllowedSepaCharactersPattern: Pattern = Pattern.compile("^[$AllowedSepaCharacters]*$")
const val MessageIdKey = "MessageId" const val MessageIdKey = "MessageId"
const val CreationDateTimeKey = "CreationDateTime" const val CreationDateTimeKey = "CreationDateTime"
@ -33,6 +38,21 @@ open class SepaMessageCreator : ISepaMessageCreator {
} }
override fun containsOnlyAllowedCharacters(stringToTest: String): Boolean {
return AllowedSepaCharactersPattern.matcher(stringToTest).matches()
}
override fun convertToAllowedCharacters(input: String): String {
// TODO: add other replacement strings
return input
.replace("\"", "&quot;")
.replace("\'", "&apos;")
.replace("&", "&amp;")
.replace("<", "&lt;")
.replace(">", "&gt;")
}
override fun createXmlFile(filename: String, replacementStrings: Map<String, String>): String { override fun createXmlFile(filename: String, replacementStrings: Map<String, String>): String {
var xmlFile = loadXmlFile(filename) var xmlFile = loadXmlFile(filename)

View File

@ -0,0 +1,82 @@
package net.dankito.fints.messages.segmente.implementierte.sepa
import org.assertj.core.api.Assertions.assertThat
import org.junit.Test
class SepaMessageCreatorTest {
private val underTest = SepaMessageCreator()
@Test
fun containsOnlyAllowedCharacters_SimpleName() {
// when
val result = underTest.containsOnlyAllowedCharacters("Marieke Musterfrau")
// then
assertThat(result).isTrue()
}
@Test
fun containsOnlyAllowedCharacters_WithAllAllowedCharacters() {
// when
val result = underTest.containsOnlyAllowedCharacters("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789,.?+-/()")
// then
assertThat(result).isTrue()
}
@Test
fun `containsOnlyAllowedCharacters ! is an illegal character`() {
// when
val result = underTest.containsOnlyAllowedCharacters("!")
// then
assertThat(result).isFalse()
}
@Test
fun `containsOnlyAllowedCharacters € is an illegal character`() {
// when
val result = underTest.containsOnlyAllowedCharacters("")
// then
assertThat(result).isFalse()
}
@Test
fun `containsOnlyAllowedCharacters @ is an illegal character`() {
// when
val result = underTest.containsOnlyAllowedCharacters("@")
// then
assertThat(result).isFalse()
}
@Test
fun `containsOnlyAllowedCharacters colon is an illegal character`() {
// when
val result = underTest.containsOnlyAllowedCharacters(":")
// then
assertThat(result).isFalse()
}
@Test
fun `containsOnlyAllowedCharacters ö is an illegal character`() {
// when
val result = underTest.containsOnlyAllowedCharacters("ö")
// then
assertThat(result).isFalse()
}
}