"I"
for incoming message "O"
for
+ * outgoing message
+ * @param id transaction id
+ * @param payload freeform text
+ * @param session session number
+ * @param sequence sequence number
+ */
+
+ public MT999(String srcAddress, String dstAddress, String dir, String id, String relref, String payload,
+ String session, String sequence) {
+
+ if (srcAddress.length() != 12)
+ throw new IllegalArgumentException("srcAddress must be 12 characters");
+ if (dstAddress.length() != 12)
+ throw new IllegalArgumentException("dstAddress must be 12 characters");
+ if (dir.compareTo("I") != 0 && dir.compareTo("O") != 0)
+ throw new IllegalArgumentException("dir must be I or O");
+ if (id.length() < 1 || id.length() > 16)
+ throw new IllegalArgumentException("id must be between 1 and 12 characters");
+ if (relref.length() > 16)
+ throw new IllegalArgumentException("related reference must be at most 16 characters");
+ if (payload.length() < 1)
+ throw new IllegalArgumentException("payload must have a value");
+
+ if (session.length() != 4)
+ throw new IllegalArgumentException("session must be 4 digits");
+ if (sequence.length() != 6)
+ throw new IllegalArgumentException("sequence must be 6 digits");
+
+ mt999();
+
+ logicalTerminalAddress = srcAddress;
+ destinationAddress = dstAddress;
+ inputIdentifier = dir;
+
+ trn = id;
+ rr = relref;
+ narrative = payload;
+
+ sessionNumber = session;
+ sequenceNumber = sequence;
+ }
+
+ /**
+ * Construct MT999 message with defaults for session and sequence.
+ *
+ * @param srcAddress is sender's address
+ * @param dstAddress is receiver's address
+ * @param dir "I"
for incoming message "O"
for
+ * outgoing message
+ * @param id transaction id
+ * @param payload freeform text
+ */
+
+ public MT999(String srcAddress, String dstAddress, String dir, String id, String relref, String payload) {
+
+
+ if (srcAddress.length() != 12)
+ throw new IllegalArgumentException("srcAddress must be 12 characters");
+ if (dstAddress.length() != 12)
+ throw new IllegalArgumentException("dstAddress must be 12 characters");
+ if (dir.compareTo("I") != 0 && dir.compareTo("O") != 0)
+ throw new IllegalArgumentException("dir must be I or O");
+ if (id.length() < 1 || id.length() > 16)
+ throw new IllegalArgumentException("id must be between 1 and 12 characters");
+ if (relref.length() > 16)
+ throw new IllegalArgumentException("related reference must be at most 16 characters");
+ if (payload.length() < 1)
+ throw new IllegalArgumentException("payload must have a value");
+
+ mt999();
+
+ logicalTerminalAddress = srcAddress;
+ destinationAddress = dstAddress;
+ inputIdentifier = dir;
+
+ trn = id;
+ rr = relref;
+ narrative = payload;
+
+ sessionNumber = "0000";
+ sequenceNumber = "000000";
+ }
+
+ /**
+ * Convert MT999 message by composing.
+ *
+ * @param fmt rendering format
+ * @return string representation of MT999 message
+ */
+
+ public String toString(MTConstants.Format fmt) {
+ String result;
+ // FIXME: rework to stringbuffer
+ switch (fmt) {
+ case MTFIN:
+ // Basic Header Block
+ result = "{1:";
+ result += applicationIdentifier;
+ result += serviceIdentifier;
+ result += logicalTerminalAddress;
+ result += sessionNumber;
+ result += sequenceNumber;
+ result += "}";
+
+ // Application Header Block
+ result += "{2:";
+ result += inputIdentifier;
+ result += messageType;
+ result += destinationAddress;
+ result += messagePriority;
+ result += "}";
+
+ // no User Header Block
+
+ // Text Block
+ result += "{4:\n";
+ result += ":20:" + trn + "\n";
+ if (rr != null && rr.length() > 0)
+ result += ":21:" + rr +"\n";
+ result += ":79:\n" + narrative;
+ result += "\n-}";
+ return result;
+
+ case MTXML:
+ throw new UnsupportedOperationException("MTXML not yet implemented");
+ }
+
+ throw new AssertionError("this should never happen");
+ }
+
+ /**
+ * Convert MT999 message by composing.
+ *
+ * @return string representation of MT999 message
+ */
+
+ public String toString() {
+ return toString(MTConstants.Format.MTFIN);
+ }
+
+ // MT999 specifica
+
+ private void mt999() {
+ applicationIdentifier = "F"; // FIN
+ serviceIdentifier = "01"; // FIN
+ messageType = "999";
+ messagePriority = "N";
+ }
+
+}
diff --git a/test/java/foundation/pEp/jniadapter/test/speedtest/MTConstants.java b/test/java/foundation/pEp/jniadapter/test/speedtest/MTConstants.java
new file mode 100644
index 0000000..59b000f
--- /dev/null
+++ b/test/java/foundation/pEp/jniadapter/test/speedtest/MTConstants.java
@@ -0,0 +1,60 @@
+package foundation.pEp.jniadapter.test.speedtest;
+
+import java.util.regex.Pattern;
+
+public class MTConstants {
+
+ /**
+ * Rendering Format of a SWIFT message.
+ */
+
+ enum Format {
+ MTFIN, MTXML
+ }
+
+ /**
+ * SWIFTMessages have a Basic Header Block and an Application Header Block
+ */
+
+ static final String mt_regex = "(?ms)"
+ // Basic Header Block
+ + "\\{1:" //
+ + "(?+ * See SWIFT message structure, MT message format, MT999 + *
+ *+ * Copyright 2019, p≡p + * Security. + *
+ * + * @author Volker Birk + * @version %I% %G% + */ + +// FIXME: rework to stringbuffer + +public class MTMsgCodec { + public Engine pEp; + + /** + * Constructs a MessageCodec using p≡p engine. + * + * @param pEp_engine p≡p engine to use + */ + + public MTMsgCodec(Engine pEp_engine) { + pEp = pEp_engine; + } + + private final static String magicKeys = "pEpKeys"; + private final static String magicEnc = "pEpMessage"; + + private final static String pgp_regex = "(?ms)" + "-----BEGIN PGP (?pgp_text
without PGP header
+ */
+
+ protected static String stripFromPGP(String pgp_text) throws ParseException {
+
+ Matcher m = pgp_pattern.matcher(pgp_text);
+ if (!m.matches())
+ throw new ParseException("not a PGP block", 0);
+
+ return m.group("block");
+ }
+
+ /**
+ * Adds PGP header and footer.
+ *
+ * @param payload text to decorate
+ * @param pgp_type PGP data type
+ * @return payload
with added header and footer
+ */
+
+ protected static String addPGPHeader(String payload, String pgp_type) {
+ // FIXME: rework to stringbuffer
+ return "-----BEGIN PGP " + pgp_type + "-----\n\n" + payload + "\n-----END PGP " + pgp_type + "-----\n";
+ }
+
+ /**
+ * Decodes a BIC from an URI.
+ *
+ * @param uri the URI to decode from
+ * @throws ParseException if URI has not the correct form
+ * @return decoded BIC
+ */
+
+ public static String decodeBIC(String uri) throws ParseException {
+ Matcher m = uri_pattern.matcher(uri);
+ if (!m.matches())
+ throw new ParseException("not a valid URI", 0);
+
+ return m.group("bic");
+ }
+
+ /**
+ * Encodes a BIC into an URI.
+ *
+ * @param bic BIC to encode
+ * @return encoded URI
+ */
+
+ public static String encodeBIC(String bic) {
+ // return "payto://swift/" + bic
+ return bic + "@BIC";
+ }
+
+ /**
+ * Generates a list of transporting MT999 messages for a payload.
+ *
+ * @param from source address
+ * @param to destination address
+ * @param ii message direction
+ * @param trn message id
+ * @param payload payload to split
+ * @param magic magic string to mark as p≡p message
+ *
+ * @return array of String with MT999 messages
+ */
+
+ protected String[] transportMT999(String from, String to, String ii, String trn, String rr, String payload,
+ String magic) {
+
+ Vectorlongmsg
; in this case
+ * message direction is being taken from there, too
+ * @param config properties with configuration
+ * @return String with encoded p≡p for SWIFT message
+ * @throws UnsupportedOperationException if EncFormat
is other than
+ * None
, Inline
+ * or PEP
+ */
+
+ public String encode(Message msg, Properties config) {
+ if (msg.getLongmsg() == null || msg.getLongmsg().length() < 1)
+ throw new IllegalArgumentException("longmsg must contain the message");
+
+ String result = "";
+
+ String msgid = msg.getId() != null && msg.getId().length() > 0 ? msg.getId() : "23";
+ String dir = msg.getDir() == Message.Direction.Incoming ? "I" : "O";
+
+ if (msgid.length() > 12) {
+ if (msgid.substring(0, 3).compareTo("pEp.") == 0 && msgid.length() >= 15)
+ msgid = msgid.substring(4, 15);
+ else
+ msgid = msgid.substring(0, 11);
+ }
+
+ String from = msg.getFrom() != null && msg.getFrom().address.length() > 0 ? msg.getFrom().address : null;
+
+ String to = msg.getTo() != null && msg.getTo().size() > 0 && msg.getTo().elementAt(0).address.length() > 0
+ ? msg.getTo().elementAt(0).address
+ : null;
+
+ if (from != null) {
+ try {
+ from = decodeBIC(from);
+ if (from.length() != 12)
+ throw new IllegalArgumentException("from address must be URI with BIC12");
+ } catch (ParseException ex) {
+ throw new IllegalArgumentException("from address must be URI with BIC12");
+ }
+ }
+
+ if (to != null) {
+ try {
+ to = decodeBIC(to);
+ if (to.length() != 12)
+ throw new IllegalArgumentException("to address must be URI with BIC12");
+ } catch (ParseException ex) {
+ throw new IllegalArgumentException("to address must be URI with BIC12");
+ }
+ }
+
+ switch (msg.getEncFormat()) {
+ case None:
+ result = msg.getLongmsg(); // we send the message unmodified
+ if (result.substring(0, 3).compareTo("{1:") == 0) {
+ // probably SWIFT MTFIN
+
+ if (from == null || to == null || msgid == null) {
+ // parse SWIFT header
+ SWIFTMsg mh = new SWIFTMsg();
+
+ try {
+ mh.parseHeader(result);
+ } catch (ParseException ex) {
+ throw new UnsupportedOperationException("unsupported message format");
+ }
+
+ if (from == null)
+ from = mh.logicalTerminalAddress;
+ if (to == null)
+ to = mh.destinationAddress;
+ dir = mh.inputIdentifier;
+ }
+ } else if (result.substring(0, 1).compareTo("<") == 0) {
+ // probably XML
+
+ // FIXME: let's do the job for MTXML, too
+ return result;
+ } else { // we don't know this format, so let it be
+ return result;
+ }
+
+ if(msg.getAttachments() != null)
+ for (int i = 0; i < msg.getAttachments().size(); ++i) { // FIXME: can attachments become null?
+ Blob attach = msg.getAttachments().elementAt(i);
+ String magic;
+
+ if (attach.mime_type.compareToIgnoreCase("application/pgp-keys") == 0)
+ magic = magicKeys;
+ else
+ break; // don't know this MIME type
+
+ // we send an MT999 with the keys
+ String payload;
+ try {
+ payload = stripFromPGP(new String(attach.data, StandardCharsets.UTF_8));
+ } catch (ParseException ex) {
+ // cannot parse this
+ break;
+ }
+
+ String[] msgs = transportMT999(from, to, dir, msgid, "", payload, magic);
+
+ for (int j = 0; j < msgs.length; ++j) {
+ if (j > 0)
+ result += "\n";
+ result += msgs[j].toString();
+ }
+ }
+ break;
+
+ case PEP:
+ case PGPMIME:
+ case Inline:
+ if (from == null || to == null)
+ throw new IllegalArgumentException("from and to must be set to URIs with BIC12");
+
+ String pgp_txt;
+ Vector