diff --git a/fints4k/src/main/kotlin/net/dankito/fints/response/ResponseParser.kt b/fints4k/src/main/kotlin/net/dankito/fints/response/ResponseParser.kt index fc7bff78..ebe2f568 100644 --- a/fints4k/src/main/kotlin/net/dankito/fints/response/ResponseParser.kt +++ b/fints4k/src/main/kotlin/net/dankito/fints/response/ResponseParser.kt @@ -491,7 +491,7 @@ open class ResponseParser @JvmOverloads constructor( protected open fun parseTanResponse(segment: String, dataElementGroups: List): TanResponse { val binaryJobHashValue = if (dataElementGroups.size > 2) parseStringToNullIfEmpty(dataElementGroups[2]) else null - val binaryChallengeHHD_UC = if (dataElementGroups.size > 5) parseStringToNullIfEmpty(dataElementGroups[5]) else null + val binaryChallengeHHD_UC = if (dataElementGroups.size > 5 && dataElementGroups[5].isNotEmpty()) dataElementGroups[5] else null return TanResponse( parseCodeEnum(dataElementGroups[1], TanProcess.values()), diff --git a/fints4k/src/main/kotlin/net/dankito/fints/tan/TanImageDecoder.kt b/fints4k/src/main/kotlin/net/dankito/fints/tan/TanImageDecoder.kt index 95ed120c..ebd9a128 100644 --- a/fints4k/src/main/kotlin/net/dankito/fints/tan/TanImageDecoder.kt +++ b/fints4k/src/main/kotlin/net/dankito/fints/tan/TanImageDecoder.kt @@ -20,11 +20,11 @@ open class TanImageDecoder { val mimeType = challengeHHD_UC.substring(2, mimeTypeEnd) - val imageLength = getLength(bytes[mimeTypeEnd], bytes[mimeTypeEnd + 1]) val imageStart = mimeTypeEnd + 2 - val imageString = challengeHHD_UC.substring(imageStart, imageStart + imageLength) - val imageBytes = imageString.toByteArray(HbciCharset.DefaultCharset) + // sometimes it happened that imageStart + getLength(bytes[mimeTypeEnd], bytes[mimeTypeEnd + 1]) + // was greater than challengeHHD_UC.length + 1 -> ignore image length and simply return all bytes starting with imageStart + val imageBytes = bytes.copyOfRange(imageStart, bytes.size) return TanImage(mimeType, imageBytes) } catch (e: Exception) { diff --git a/fints4k/src/test/kotlin/net/dankito/fints/FinTsTestBase.kt b/fints4k/src/test/kotlin/net/dankito/fints/FinTsTestBase.kt index 32ca4318..323218c9 100644 --- a/fints4k/src/test/kotlin/net/dankito/fints/FinTsTestBase.kt +++ b/fints4k/src/test/kotlin/net/dankito/fints/FinTsTestBase.kt @@ -8,13 +8,21 @@ import net.dankito.fints.model.* import net.dankito.fints.response.segments.AccountType import net.dankito.fints.response.segments.ChangeTanMediaParameters import net.dankito.fints.response.segments.JobParameters +import java.io.File import java.math.BigDecimal +import java.nio.charset.Charset import java.util.* abstract class FinTsTestBase { companion object { + + const val TestFilesFolderName = "test_files/" + + const val TransactionsMt940Filename = "TransactionsMt940.txt" + + const val BankCode = "12345678" const val BankCountryCode = Laenderkennzeichen.Germany @@ -87,4 +95,14 @@ abstract class FinTsTestBase { return JobParameters("", 1, 1, 1, ":0:0") } + + /** + * testFilename has to be a file in src/test/resources/test_files/ folder + */ + protected open fun loadTestFile(testFilename: String, charset: Charset = Charsets.UTF_8): String { + val fileStream = FinTsTestBase::class.java.classLoader.getResourceAsStream(File(TestFilesFolderName, testFilename).path) + + return fileStream.reader(charset).readText() + } + } \ No newline at end of file diff --git a/fints4k/src/test/kotlin/net/dankito/fints/response/ResponseParserTest.kt b/fints4k/src/test/kotlin/net/dankito/fints/response/ResponseParserTest.kt index ea35dfdc..075c3a36 100644 --- a/fints4k/src/test/kotlin/net/dankito/fints/response/ResponseParserTest.kt +++ b/fints4k/src/test/kotlin/net/dankito/fints/response/ResponseParserTest.kt @@ -1,6 +1,7 @@ package net.dankito.fints.response import net.dankito.fints.FinTsTestBase +import net.dankito.fints.messages.HbciCharset import net.dankito.fints.messages.datenelemente.implementierte.Dialogsprache import net.dankito.fints.messages.datenelemente.implementierte.HbciVersion import net.dankito.fints.messages.datenelemente.implementierte.signatur.Sicherheitsfunktion @@ -11,6 +12,7 @@ import net.dankito.fints.messages.datenelementgruppen.implementierte.signatur.Si import net.dankito.fints.messages.segmente.id.ISegmentId import net.dankito.fints.messages.segmente.id.MessageSegmentId import net.dankito.fints.response.segments.* +import net.dankito.fints.tan.TanImageDecoder import org.assertj.core.api.Assertions.assertThat import org.junit.Assert import org.junit.Test @@ -102,6 +104,27 @@ class ResponseParserTest : FinTsTestBase() { assertThat(result.messageFeedback?.feedbacks?.map { it.message }).containsExactly("Nachricht nicht erwartet.", "Dialoginitialisierung abgebrochen.") } + @Test + fun `decode TanChallenge HHD_UC`() { + + // given + val response = loadTestFile("Decode_TanChallengeHhdUc_WithMaskedCharacter.txt", HbciCharset.DefaultCharset) + + + // when + val result = underTest.parse(response) + + + // then + assertThat(result.successful).isTrue() + + assertThat(result.tanResponse).isNotNull + + val decodedChallengeHhdUc = TanImageDecoder().decodeChallenge(result.tanResponse?.challengeHHD_UC ?: "") + assertThat(decodedChallengeHhdUc.decodingSuccessful).isTrue() + assertThat(decodedChallengeHhdUc.imageBytes.size).isEqualTo(3664) + } + @Test fun parseMessageHeader() { diff --git a/fints4k/src/test/kotlin/net/dankito/fints/transactions/Mt940AccountTransactionsParserTest.kt b/fints4k/src/test/kotlin/net/dankito/fints/transactions/Mt940AccountTransactionsParserTest.kt index 69fd83e2..efe03ea2 100644 --- a/fints4k/src/test/kotlin/net/dankito/fints/transactions/Mt940AccountTransactionsParserTest.kt +++ b/fints4k/src/test/kotlin/net/dankito/fints/transactions/Mt940AccountTransactionsParserTest.kt @@ -1,16 +1,12 @@ package net.dankito.fints.transactions +import net.dankito.fints.FinTsTestBase import net.dankito.fints.model.AccountData import org.assertj.core.api.Assertions.assertThat import org.junit.Test -class Mt940AccountTransactionsParserTest { - companion object { - const val TestFilesFolderName = "test_files/" - - const val TransactionsMt940FileRelativePath = TestFilesFolderName + "TransactionsMt940.txt" // TODO: place in common file - } +class Mt940AccountTransactionsParserTest : FinTsTestBase() { private val underTest = Mt940AccountTransactionsParser() @@ -20,8 +16,7 @@ class Mt940AccountTransactionsParserTest { fun parseTransactions() { // given - val fileStream = Mt940ParserTest::class.java.classLoader.getResourceAsStream(TransactionsMt940FileRelativePath) - val transactionsString = fileStream.reader().readText() + val transactionsString = loadTestFile(TransactionsMt940Filename) // when diff --git a/fints4k/src/test/kotlin/net/dankito/fints/transactions/Mt940ParserTest.kt b/fints4k/src/test/kotlin/net/dankito/fints/transactions/Mt940ParserTest.kt index a3563738..923b8c5f 100644 --- a/fints4k/src/test/kotlin/net/dankito/fints/transactions/Mt940ParserTest.kt +++ b/fints4k/src/test/kotlin/net/dankito/fints/transactions/Mt940ParserTest.kt @@ -15,9 +15,6 @@ import java.util.* class Mt940ParserTest : FinTsTestBase() { companion object { - const val TestFilesFolderName = "test_files/" - - const val TransactionsMt940FileRelativePath = TestFilesFolderName + "TransactionsMt940.txt" const val Currency = "EUR" @@ -134,8 +131,7 @@ class Mt940ParserTest : FinTsTestBase() { fun parseTransactions() { // given - val fileStream = Mt940ParserTest::class.java.classLoader.getResourceAsStream(TransactionsMt940FileRelativePath) - val transactionsString = fileStream.reader().readText() + val transactionsString = loadTestFile(TransactionsMt940Filename) // when diff --git a/fints4k/src/test/resources/test_files/Decode_TanChallengeHhdUc_WithMaskedCharacter.txt b/fints4k/src/test/resources/test_files/Decode_TanChallengeHhdUc_WithMaskedCharacter.txt new file mode 100644 index 00000000..5c15a027 Binary files /dev/null and b/fints4k/src/test/resources/test_files/Decode_TanChallengeHhdUc_WithMaskedCharacter.txt differ