From 998c6d0c0197e494488a19834b55e7ee011d6c6a Mon Sep 17 00:00:00 2001 From: dankito Date: Sat, 16 May 2020 14:45:59 +0200 Subject: [PATCH] Implemented extracting segment that is embedded in encrypted data segment HNVSD --- .../net/dankito/fints/messages/Separators.kt | 3 +++ .../dankito/fints/response/ResponseParser.kt | 23 ++++++++++++++++--- .../net/dankito/fints/util/MessageUtils.kt | 2 +- .../fints/response/ResponseParserTest.kt | 20 ++++++++++++++++ 4 files changed, 44 insertions(+), 4 deletions(-) diff --git a/fints4k/src/main/kotlin/net/dankito/fints/messages/Separators.kt b/fints4k/src/main/kotlin/net/dankito/fints/messages/Separators.kt index 003f235d..4c17b54b 100644 --- a/fints4k/src/main/kotlin/net/dankito/fints/messages/Separators.kt +++ b/fints4k/src/main/kotlin/net/dankito/fints/messages/Separators.kt @@ -10,6 +10,9 @@ class Separators { const val DataElementsSeparator = ":" + const val BinaryDataSeparatorChar = '@' + const val BinaryDataSeparator = BinaryDataSeparatorChar.toString() + const val MaskingCharacter = "?" val AllSeparators = listOf(DataElementsSeparator, DataElementGroupsSeparator, SegmentSeparator) 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 ecb9f1b8..fc7bff78 100644 --- a/fints4k/src/main/kotlin/net/dankito/fints/response/ResponseParser.kt +++ b/fints4k/src/main/kotlin/net/dankito/fints/response/ResponseParser.kt @@ -43,7 +43,9 @@ open class ResponseParser @JvmOverloads constructor( open fun parse(response: String): Response { try { - val segments = splitIntoPartsAndUnmask(response, Separators.SegmentSeparator) + val segments = splitIntoPartsAndUnmask(response, Separators.SegmentSeparator).toMutableList() + + extractSegmentEmbeddedInEncryptedData(segments) val parsedSegments = segments.mapNotNull { parseSegment(it) } @@ -55,6 +57,21 @@ open class ResponseParser @JvmOverloads constructor( } } + protected open fun extractSegmentEmbeddedInEncryptedData(elements: MutableList) { + ArrayList(elements).forEachIndexed { index, element -> + if (element?.startsWith(MessageSegmentId.EncryptionData.id) == true) { + val embeddedSegmentBinaryDataStartIndex = element.indexOf(Separators.BinaryDataSeparatorChar) + + if (embeddedSegmentBinaryDataStartIndex > 0) { + val inEncryptedDataSegmentEmbeddedSegment = extractBinaryData(element.substring(embeddedSegmentBinaryDataStartIndex)) + + elements.add(index + 1, inEncryptedDataSegmentEmbeddedSegment) + elements[index] = element.substring(0, embeddedSegmentBinaryDataStartIndex) + } + } + } + } + protected open fun parseSegment(segment: String): ReceivedSegment? { try { @@ -814,8 +831,8 @@ open class ResponseParser @JvmOverloads constructor( } protected open fun extractBinaryData(binaryData: String): String { - if (binaryData.startsWith('@')) { - val headerEndIndex = binaryData.indexOf('@', 2) + if (binaryData.startsWith(Separators.BinaryDataSeparatorChar)) { + val headerEndIndex = binaryData.indexOf(Separators.BinaryDataSeparatorChar, 2) if (headerEndIndex > -1) { return binaryData.substring(headerEndIndex + 1) diff --git a/fints4k/src/main/kotlin/net/dankito/fints/util/MessageUtils.kt b/fints4k/src/main/kotlin/net/dankito/fints/util/MessageUtils.kt index c3a452d6..391ba43d 100644 --- a/fints4k/src/main/kotlin/net/dankito/fints/util/MessageUtils.kt +++ b/fints4k/src/main/kotlin/net/dankito/fints/util/MessageUtils.kt @@ -31,7 +31,7 @@ open class MessageUtils { while (binaryDataMatcher.find()) { if (isEncryptionDataSegment(dataString, binaryDataMatcher) == false) { val startIndex = binaryDataMatcher.end() - val length = binaryDataMatcher.group().replace("@", "").toInt() + val length = binaryDataMatcher.group().replace(Separators.BinaryDataSeparator, "").toInt() binaryDataRanges.add(IntRange(startIndex, startIndex + length - 1)) } 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 6a52e20d..ea35dfdc 100644 --- a/fints4k/src/test/kotlin/net/dankito/fints/response/ResponseParserTest.kt +++ b/fints4k/src/test/kotlin/net/dankito/fints/response/ResponseParserTest.kt @@ -83,6 +83,26 @@ class ResponseParserTest : FinTsTestBase() { } + @Test + fun extractEmbeddedSegment() { + + // when + val result = underTest.parse("HNHBK:1:3+000000000249+300+0+1+0:1'" + + "HNVSK:998:3+PIN:1+998+1+2::0+1:20200512:153303+2:2:13:@8@\u0000\u0000\u0000\u0000\u0000\u0000\u0000\u0000:5:1+280:10070000:9999999999:V:0:0+0'" + + "HNVSD:999:1+@83@HIRMG:2:2+9120::Nachricht nicht erwartet.+9800::Dialoginitialisierung abgebrochen.''" + + "HNHBS:3:1+1'") + + // then + assertThat(result.receivedSegments).hasSize(5) + + assertCouldParseSegment(result, InstituteSegmentId.MessageFeedback, 2, 2) + + assertThat(result.messageFeedback).isNotNull + assertThat(result.messageFeedback?.isError).isTrue() + assertThat(result.messageFeedback?.feedbacks?.map { it.message }).containsExactly("Nachricht nicht erwartet.", "Dialoginitialisierung abgebrochen.") + } + + @Test fun parseMessageHeader() {