From 5897d50feddd6d31d480c4fa3c5d3b2596ff0ff6 Mon Sep 17 00:00:00 2001
From: Igor Skljar <39621064+it240884sii@users.noreply.github.com>
Date: Fri, 11 Sep 2026 21:23:14 +0300
Subject: [PATCH 1/2] Remove redundant isofield with id 96
Removed redundant ISO field definition for id 96.
---
jpos/src/main/resources/packager/cmf.xml | 5 -----
1 file changed, 5 deletions(-)
diff --git a/jpos/src/main/resources/packager/cmf.xml b/jpos/src/main/resources/packager/cmf.xml
index 5b6d8fbf82..a83f7502e9 100644
--- a/jpos/src/main/resources/packager/cmf.xml
+++ b/jpos/src/main/resources/packager/cmf.xml
@@ -763,11 +763,6 @@
name="Reserved for ISO use"
pad="false"
class="org.jpos.iso.IFB_LLLLBINARY"/>
-
Date: Fri, 11 Sep 2026 16:41:42 -0300
Subject: [PATCH 2/2] Fix reserved field 91 in CMF packagers
---
jpos/src/main/resources/packager/cmf-858.xml | 2 +-
jpos/src/main/resources/packager/cmf.xml | 5 +
jpos/src/main/resources/packager/cmfv3.xml | 8 +-
.../iso/packager/CMFFieldDefinitionsTest.java | 103 ++++++++++++++++++
4 files changed, 113 insertions(+), 5 deletions(-)
create mode 100644 jpos/src/test/java/org/jpos/iso/packager/CMFFieldDefinitionsTest.java
diff --git a/jpos/src/main/resources/packager/cmf-858.xml b/jpos/src/main/resources/packager/cmf-858.xml
index fdf67d2a55..e6b4db859a 100644
--- a/jpos/src/main/resources/packager/cmf-858.xml
+++ b/jpos/src/main/resources/packager/cmf-858.xml
@@ -763,7 +763,7 @@
name="Reserved for ISO use"
pad="false"
class="org.jpos.iso.IFB_LLLLBINARY"/>
-
+
-
+ class="org.jpos.iso.IFB_LLLLBINARY"/>
.
+ */
+
+package org.jpos.iso.packager;
+
+import java.io.InputStream;
+import java.util.Arrays;
+import java.util.HashSet;
+import java.util.Set;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import org.jpos.iso.IFB_LLLBINARY;
+import org.jpos.iso.IFB_LLLLBINARY;
+import org.jpos.iso.ISOBinaryField;
+import org.jpos.iso.ISOFieldPackager;
+import org.jpos.iso.ISOMsg;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.ValueSource;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+
+import static org.junit.jupiter.api.Assertions.assertArrayEquals;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertInstanceOf;
+import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+class CMFFieldDefinitionsTest {
+ @ParameterizedTest
+ @ValueSource(strings = {"cmf.xml", "cmfv3.xml", "cmf-858.xml"})
+ void topLevelFieldIdsAreUnique(String resource) throws Exception {
+ DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+ factory.setFeature("http://xml.org/sax/features/external-general-entities", false);
+ factory.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
+ factory.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
+ try (InputStream input = resource(resource)) {
+ Element root = factory.newDocumentBuilder().parse(input).getDocumentElement();
+ Set ids = new HashSet<>();
+ for (Node child = root.getFirstChild(); child != null; child = child.getNextSibling()) {
+ if (child instanceof Element field && field.hasAttribute("id"))
+ assertTrue(ids.add(field.getAttribute("id")),
+ resource + ": duplicate field " + field.getAttribute("id"));
+ }
+ }
+ }
+
+ @ParameterizedTest
+ @ValueSource(strings = {"cmf.xml", "cmfv3.xml", "cmf-858.xml"})
+ void reservedAndKeyManagementFieldsRoundTripAtTheirLimits(String resource) throws Exception {
+ GenericPackager packager;
+ try (InputStream input = resource(resource)) {
+ packager = new GenericPackager(input);
+ }
+ ISOFieldPackager reserved = packager.getFieldPackager(91);
+ ISOFieldPackager keys = packager.getFieldPackager(96);
+ assertInstanceOf(IFB_LLLLBINARY.class, reserved);
+ assertEquals(9999, reserved.getLength());
+ assertInstanceOf(IFB_LLLBINARY.class, keys);
+ assertEquals(999, keys.getLength());
+
+ byte[] reservedData = new byte[9999];
+ byte[] keyData = new byte[999];
+ Arrays.fill(reservedData, (byte) 0xA5);
+ Arrays.fill(keyData, (byte) 0x5A);
+ assertArrayEquals(new byte[] {(byte) 0x99, (byte) 0x99},
+ Arrays.copyOf(reserved.pack(new ISOBinaryField(91, reservedData)), 2));
+ assertArrayEquals(new byte[] {0x09, (byte) 0x99},
+ Arrays.copyOf(keys.pack(new ISOBinaryField(96, keyData)), 2));
+
+ ISOMsg message = new ISOMsg();
+ message.setPackager(packager);
+ message.setMTI("1200");
+ message.set(91, reservedData);
+ message.set(96, keyData);
+ byte[] packed = message.pack();
+ ISOMsg unpacked = new ISOMsg();
+ unpacked.setPackager(packager);
+ assertEquals(packed.length, unpacked.unpack(packed));
+ assertArrayEquals(reservedData, unpacked.getBytes(91));
+ assertArrayEquals(keyData, unpacked.getBytes(96));
+ }
+
+ private InputStream resource(String name) {
+ InputStream input = getClass().getResourceAsStream("/packager/" + name);
+ assertNotNull(input, name);
+ return input;
+ }
+}