diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt
index 14c833a4..d0a56b9f 100644
--- a/RELEASE-NOTES.txt
+++ b/RELEASE-NOTES.txt
@@ -1,27 +1,25 @@
OpenAS2 Server
- Version 2.0.0
+ Version 2.1.0
RELEASE NOTES
-The OpenAS2 project is pleased to announce the release of OpenAS2 2.0.0
+The OpenAS2 project is pleased to announce the release of OpenAS2 2.1.0
-The release download file is: OpenAS2Server-2.0.0.zip
+The release download file is: OpenAS2Server-2.1.0.zip
The zip file contains a PDF document providing information on installing and using the application.
-This release is an enhancement and bug fix release that includes compatibility testing with other AS2 systems:
- 1. Add support for custom HTTP headers
- - configurable static headers as name/value pairs in the partnership
- - configurable dynamic headers with header values set from parsing the name of the file to be sent
- 2. Fix generator encoding for compression, encryption and signing
- 3. Support configurable control of canonicalization when signing
- 4. Support overriding digest "sha-1" algorithm name in signing to use "old" name without dash ("sha1")
- 5. Support AES128, AES192, AES256 ciphers
- 6. Support disabling the CMS algorithm protection OID for older AS2 systems that do not support it
- 7. Added "Troubleshooting.." section to documentation
+This release is an enhancement release:
+ 1. Add message tracking module to allow easy identification of sent and received messages based on state
+ - persists state change tracking of messages to H2 database
+ - allow user-plugin of custom tracking module(s)
+ 2. Enhanced documentation around certificate management
+ 3. Added properties element to config to allow easy custom config property access from java modules and helper classes
+ 4. Added support for parsing file name into partnership attributes using regular expressions
+ 5. Added script to support launching OpenAS2 as a daemon using the init.d paradigm
+ 6. Added system parameter to startup scripts to allow restricted HTTP headers that cause problems for some AS2 implementations
Upgrade Notes:
- 1. Canonicalization may affect existing working partnerships in prior versions of OpenAS2 if using a content transfer encoding other than "binary".
- If the partnership stops working then add the following attribute to the partnership:
-
+ 1. Add the new module to your existing config.xml (see classname="org.openas2.processor.msgtracking.DbTrackingModule" in release config.xml)
+ 2. If using a custom startup script, re-integrate your customisations into the new script
Java 1.5 or later is required.
NOTE FOR JAVA 1.5: Prior to java 1.6, the Javabeans Activation Framework is NOT included in the standard Java install. Download the 1.1.1 version and extract from the zip file from this web page: http://www.oracle.com/technetwork/java/javasebusiness/downloads/java-archive-downloads-java-plat-419418.html#jaf-1.1.1-fcs-oth-JPR
diff --git a/Server/bin/openas2.d b/Server/bin/openas2.d
new file mode 100755
index 00000000..6d15ca49
--- /dev/null
+++ b/Server/bin/openas2.d
@@ -0,0 +1,104 @@
+#!/bin/bash
+
+### BEGIN INIT INFO
+# Provides: openas2.d
+# Required-Start:
+# Required-Stop:
+# Default-Start: 2 3 4 5
+# Default-Stop: 0 1 6
+# Short-Description: Startup script to launch OpenAS2 appliction as a daemon
+# Description: This script can be used in any NIX based system that implements the init.d mechanism
+# The EXECUTABLE variable below must be set to point to the OpenAS2 startup script
+# See the OpenAS2HowTo.pdf for details on configuration checks for this mode of running OpenAS2
+### END INIT INFO
+
+SERVICE_NAME=OpenAS2
+EXECUTABLE=/opt/OpenAS2/bin/start-openas2.sh
+THIS_SCRIPT_NAME=`basename $0`
+THIS_SCRIPT_EXEC=$0
+if [ "$THIS_SCRIPT_NAME" = "$0" ]; then
+ THIS_SCRIPT_EXEC="/etc/init.d/$0"
+fi
+PID=$(ps -ef | grep java | grep org.openas2.app.OpenAS2Server | awk '{print $2}')
+
+case "$1" in
+ start)
+ echo "Starting $SERVICE_NAME ..."
+ if [ -z $PID ]; then
+ export OPENAS2_AS_DAEMON=true
+ $EXECUTABLE
+ RETVAL="$?"
+ if [ "$RETVAL" = 0 ]; then
+ echo "$SERVICE_NAME started ..."
+ exit 0
+ else
+ echo "ERROR $SERVICE_NAME could not be started. Review logs"
+ exit 1
+ fi
+ else
+ echo "$SERVICE_NAME is already running ..."
+ fi
+ ;;
+ stop|kill)
+ if [ ! -z $PID ]; then
+ echo "Attempting to stop $SERVICE_NAME..."
+ kill $PID
+ if [ "$?" = 0 ]; then
+ echo "$SERVICE_NAME terminated ..."
+ exit 0
+ else
+ echo "ERROR: $SERVICE_NAME failed to terminate. try force-stop"
+ exit 1
+ fi
+ else
+ echo "$SERVICE_NAME is not running ..."
+ exit 0
+ fi
+ ;;
+ force-stop)
+ if [ ! -z $PID ]; then
+ echo "Attempting to force termination of $SERVICE_NAME..."
+ kill -9 $PID
+ if [ "$?" = 0 ]; then
+ echo "$SERVICE_NAME terminated ..."
+ exit 0
+ else
+ echo "ERROR: $SERVICE_NAME failed to terminate. "
+ exit 1
+ fi
+ else
+ echo "$SERVICE_NAME is not running ..."
+ exit 0
+ fi
+ ;;
+ status)
+ if [ -z $PID ]; then
+ echo "$SERVICE_NAME is not running"
+ else
+ echo "$SERVICE_NAME is running"
+ fi
+ ;;
+ force-reload|restart|reload)
+ $THIS_SCRIPT_EXEC stop
+ if [ ! -z $PID ]; then
+ CNT=0
+ while ps -p $PID 2>/dev/null; do
+ sleep 1;CNT=$CNT+1;
+ CNT=$((CNT+1)); if [ $CNT -ge 5 ]; then break; fi
+ done
+ if ps -p $PID 2>/dev/null; then
+ echo "ERROR: Failed to stop $SERVICE_NAME"
+ exit 1
+ else
+ PID=""
+ fi
+ fi
+ $THIS_SCRIPT_EXEC start
+ ;;
+ *)
+ echo "Usage: $0 {start|stop|restart|reload|force-reload}"
+ exit 1
+ ;;
+
+esac
+
diff --git a/Server/bin/start-openas2.bat b/Server/bin/start-openas2.bat
index 2836d5c9..cf1da9a2 100755
--- a/Server/bin/start-openas2.bat
+++ b/Server/bin/start-openas2.bat
@@ -1,6 +1,13 @@
@echo off
rem Purpose: runs the OpenAS2 application
+rem Set some of the base system properties for the Java environment and logging
+rem remove -Dorg.apache.commons.logging.Log=org.openas2.logging.Log if using another logging package
+rem
+set EXTRA_PARMS=-Xms32m -Xmx384m -Dorg.apache.commons.logging.Log=org.openas2.logging.Log
+rem By default allow restricted HTTP headers
+set EXTRA_PARMS=%EXTRA_PARMS% -Dsun.net.http.allowRestrictedHeaders=true
+
rem Uncomment any of the following for enhanced debug
rem set EXTRA_PARMS=%EXTRA_PARMS% -Dmaillogger.debug.enabled=true
rem set EXTRA_PARMS=%EXTRA_PARMS% -DlogRxdMsgMimeBodyParts=true
@@ -54,11 +61,9 @@ if not "%JAVA%" == "" goto :Check_JAVA_END
)
set JAVA=%JAVA_HOME%\bin\java
:Check_JAVA_END
-
+set LIB_JARS=../lib/h2-1.4.192.jar;../lib/javax.mail.jar;../lib/bcpkix-jdk15on-154.jar;../lib/bcprov-jdk15on-154.jar;../lib/bcmail-jdk15on-154.jar;../lib/commons-logging-1.2.jar;../lib/openas2-server.jar
rem
-rem remove -Dorg.apache.commons.logging.Log=org.openas2.logging.Log if using another logging package
-rem
-"%JAVA%" "%EXTRA_PARMS% -Xms32m -Xmx384m -Dorg.apache.commons.logging.Log=org.openas2.logging.Log -cp .;../lib/javax.mail.jar;../lib/bcpkix-jdk15on-154.jar;../lib/bcprov-jdk15on-154.jar;../lib/bcmail-jdk15on-154.jar;../lib/commons-logging-1.2.jar;../lib/openas2-server.jar org.openas2.app.OpenAS2Server ../config/config.xml
+"%JAVA%" %EXTRA_PARMS% -cp .;%LIB_JARS% org.openas2.app.OpenAS2Server ../config/config.xml
:warn
:END
diff --git a/Server/bin/start-openas2.sh b/Server/bin/start-openas2.sh
index d42ef0ca..e6aa82a3 100755
--- a/Server/bin/start-openas2.sh
+++ b/Server/bin/start-openas2.sh
@@ -1,13 +1,22 @@
-#!/bin/sh
+#!/bin/bash
# purpose: runs the OpenAS2 application
x=`basename $0`
+binDir="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
keyStorePwd=$1
PWD_OVERRIDE=""
+
+# Set some of the base system properties for the Java environment and logging
+# remove -Dorg.apache.commons.logging.Log=org.openas2.logging.Log if using another logging package
+#
+EXTRA_PARMS="-Xms32m -Xmx384m -Dorg.apache.commons.logging.Log=org.openas2.logging.Log"
+# By default allow restricted HTTP headers
+EXTRA_PARMS="$EXTRA_PARMS -Dsun.net.http.allowRestrictedHeaders=true"
# Uncomment any of the following for enhanced debug
#EXTRA_PARMS="$EXTRA_PARMS -Dmaillogger.debug.enabled=true"
#EXTRA_PARMS="$EXTRA_PARMS -DlogRxdMsgMimeBodyParts=true"
#EXTRA_PARMS="$EXTRA_PARMS -DlogRxdMdnMimeBodyParts=true"
+#EXTRA_PARMS="$EXTRA_PARMS -Djavax.net.debug=SSL"
if [ ! -z $keyStorePwd ]; then
PWD_OVERRIDE="-Dorg.openas2.cert.Password=$keyStorePwd"
@@ -29,10 +38,16 @@ fi
if [ -z $JAVA_HOME ]; then
echo "ERROR: Cannot find JAVA_HOME"
- exit
+ exit 1
fi
+
+LIB_JARS="${binDir}/../lib/h2-1.4.192.jar:${binDir}/../lib/javax.mail.jar:${binDir}/../lib/bcpkix-jdk15on-154.jar:${binDir}/../lib/bcprov-jdk15on-154.jar:${binDir}/../lib/bcmail-jdk15on-154.jar:${binDir}/../lib/commons-logging-1.2.jar:${binDir}/../lib/openas2-server.jar"
JAVA_EXE=$JAVA_HOME/bin/java
#
-# remove -Dorg.apache.commons.logging.Log=org.openas2.logging.Log if using another logging package
-#
-$JAVA_EXE ${PWD_OVERRIDE} -Xms32m -Xmx384m -Dorg.apache.commons.logging.Log=org.openas2.logging.Log -cp .:../lib/javax.mail.jar:../lib/bcpkix-jdk15on-154.jar:../lib/bcprov-jdk15on-154.jar:../lib/bcmail-jdk15on-154.jar:../lib/commons-logging-1.2.jar:../lib/openas2-server.jar org.openas2.app.OpenAS2Server ../config/config.xml
+CMD="$JAVA_EXE ${PWD_OVERRIDE} ${EXTRA_PARMS} -cp .:${LIB_JARS} org.openas2.app.OpenAS2Server ${binDir}/../config/config.xml"
+if [ "true" = "$OPENAS2_AS_DAEMON" ]; then
+ $CMD &
+else
+ $CMD
+fi
+exit $?
\ No newline at end of file
diff --git a/Server/config/DB/openas2.mv.db b/Server/config/DB/openas2.mv.db
new file mode 100644
index 00000000..f7fe6aae
Binary files /dev/null and b/Server/config/DB/openas2.mv.db differ
diff --git a/Server/config/config.xml b/Server/config/config.xml
index b17653b4..8be660c1 100644
--- a/Server/config/config.xml
+++ b/Server/config/config.xml
@@ -1,4 +1,8 @@
+
-
+
+
+
@@ -56,6 +57,10 @@
Example for adding dynamic custom headers to Mime body part where filename is of form XXX-YYY.msg
+
+ Example for parsing filename into parameters that can be referenced this is a file name of the form XXXNNNN.edi where X is alphabetic and N are numerics
+
+
-->
diff --git a/Server/dist/OpenAS2Server-2.0.0.zip b/Server/dist/OpenAS2Server-2.1.0.zip
similarity index 70%
rename from Server/dist/OpenAS2Server-2.0.0.zip
rename to Server/dist/OpenAS2Server-2.1.0.zip
index 6237165f..183a4852 100644
Binary files a/Server/dist/OpenAS2Server-2.0.0.zip and b/Server/dist/OpenAS2Server-2.1.0.zip differ
diff --git a/Server/lib/h2-1.4.192.jar b/Server/lib/h2-1.4.192.jar
new file mode 100755
index 00000000..8936686e
Binary files /dev/null and b/Server/lib/h2-1.4.192.jar differ
diff --git a/Server/lib/openas2-server.jar b/Server/lib/openas2-server.jar
index b8c011c7..149df46c 100644
Binary files a/Server/lib/openas2-server.jar and b/Server/lib/openas2-server.jar differ
diff --git a/Server/src/org/openas2/BaseSession.java b/Server/src/org/openas2/BaseSession.java
index e014f2dd..65a4fbde 100644
--- a/Server/src/org/openas2/BaseSession.java
+++ b/Server/src/org/openas2/BaseSession.java
@@ -13,6 +13,7 @@
public abstract class BaseSession implements Session {
private Map components;
+ private String baseDirectory;
/**
* Creates a BaseSession
object, then calls the init()
method.
@@ -83,4 +84,13 @@ protected void initJavaMail() throws OpenAS2Exception {
"message/disposition-notification;; x-java-content-handler=org.openas2.util.DispositionDataContentHandler");
CommandMap.setDefaultCommandMap(mc);
}
+
+ public String getBaseDirectory() {
+ return baseDirectory;
+ }
+
+ public void setBaseDirectory(String dir) {
+ baseDirectory = dir;
+ }
+
}
diff --git a/Server/src/org/openas2/Session.java b/Server/src/org/openas2/Session.java
index 7d358b3b..6467b7c5 100644
--- a/Server/src/org/openas2/Session.java
+++ b/Server/src/org/openas2/Session.java
@@ -20,7 +20,7 @@
*/
public interface Session {
/** Official OpenAS2 release version */
- public static final String VERSION = "2.0.0";
+ public static final String VERSION = "2.1.0";
/** Official OpenAS2 title */
public static final String TITLE = "OpenAS2 v" + VERSION;
@@ -91,4 +91,9 @@ public interface Session {
* @see Component
*/
public Processor getProcessor() throws ComponentNotFoundException;
+
+ public String getBaseDirectory();
+
+ public void setBaseDirectory(String dir);
+
}
diff --git a/Server/src/org/openas2/XMLSession.java b/Server/src/org/openas2/XMLSession.java
index 30f581de..06d0dd18 100644
--- a/Server/src/org/openas2/XMLSession.java
+++ b/Server/src/org/openas2/XMLSession.java
@@ -4,6 +4,7 @@
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
+import java.util.Map;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
@@ -19,6 +20,7 @@
import org.openas2.partner.PartnershipFactory;
import org.openas2.processor.Processor;
import org.openas2.processor.ProcessorModule;
+import org.openas2.util.Properties;
import org.openas2.util.XMLUtil;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
@@ -34,6 +36,7 @@
*
*/
public class XMLSession extends BaseSession implements CommandRegistryFactory {
+ public static final String EL_PROPERTIES = "properties";
public static final String EL_CERTIFICATES = "certificates";
public static final String EL_CMDPROCESSOR = "commandProcessors";
public static final String EL_PROCESSOR = "processor";
@@ -42,7 +45,6 @@ public class XMLSession extends BaseSession implements CommandRegistryFactory {
public static final String EL_LOGGERS = "loggers";
public static final String PARAM_BASE_DIRECTORY = "basedir";
private CommandRegistry commandRegistry;
- private String baseDirectory;
private CommandManager cmdManager;
@@ -90,7 +92,9 @@ protected void load(InputStream in) throws ParserConfigurationException,
nodeName = rootNode.getNodeName();
- if (nodeName.equals(EL_CERTIFICATES)) {
+ if (nodeName.equals(EL_PROPERTIES)) {
+ loadProperties(rootNode);
+ } else if (nodeName.equals(EL_CERTIFICATES)) {
loadCertificates(rootNode);
} else if (nodeName.equals(EL_PROCESSOR)) {
loadProcessor(rootNode);
@@ -111,6 +115,12 @@ protected void load(InputStream in) throws ParserConfigurationException,
}
}
}
+
+ protected void loadProperties(Node propNode)
+ {
+ Map properties = XMLUtil.mapAttributes(propNode);
+ Properties.setProperties(properties);
+ }
protected void loadCertificates(Node rootNode) throws OpenAS2Exception {
CertificateFactory certFx = (CertificateFactory) XMLUtil.getComponent(
@@ -206,12 +216,4 @@ protected void loadProcessorModule(Processor proc, Node moduleNode)
proc.getModules().add(procmod);
}
- public String getBaseDirectory() {
- return baseDirectory;
- }
-
- public void setBaseDirectory(String dir) {
- baseDirectory = dir;
- }
-
}
diff --git a/Server/src/org/openas2/app/OpenAS2Server.java b/Server/src/org/openas2/app/OpenAS2Server.java
index 9740f109..a9ba151e 100644
--- a/Server/src/org/openas2/app/OpenAS2Server.java
+++ b/Server/src/org/openas2/app/OpenAS2Server.java
@@ -23,6 +23,8 @@
*/
public class OpenAS2Server {
protected BufferedWriter sysOut;
+ BaseCommandProcessor cmd = null;
+ XMLSession session = null;
public static void main(String[] args) {
@@ -31,10 +33,17 @@ public static void main(String[] args) {
}
public void start(String[] args) {
- BaseCommandProcessor cmd = null;
- XMLSession session = null;
int exitStatus = 0;
+ Runtime.getRuntime().addShutdownHook(new Thread()
+ {
+ @Override
+ public void run()
+ {
+ shutdown();
+ System.out.println("Shutdown due to process interruption!");
+ }
+ });
try {
Log logger = LogFactory.getLog(OpenAS2Server.class.getSimpleName());
@@ -94,29 +103,34 @@ public void start(String[] args) {
exitStatus = -1;
err.printStackTrace();
} finally {
+ shutdown();
+ System.exit(exitStatus);
+ }
+ }
- if (session != null) {
- try {
- session.getProcessor().stopActiveModules();
- } catch (OpenAS2Exception same) {
- same.terminate();
- }
+ public void shutdown()
+ {
+ if (session != null) {
+ try {
+ session.getProcessor().stopActiveModules();
+ } catch (OpenAS2Exception same) {
+ same.terminate();
}
+ }
- if (cmd != null) {
- try {
- cmd.deInit();
- } catch (OpenAS2Exception cdie) {
- cdie.terminate();
- }
+ if (cmd != null) {
+ try {
+ cmd.deInit();
+ } catch (OpenAS2Exception cdie) {
+ cdie.terminate();
}
+ }
- write("OpenAS2 has shut down\r\n");
+ write("OpenAS2 has shut down\r\n");
+
- System.exit(exitStatus);
- }
}
-
+
public void write(String msg) {
if (sysOut == null) {
sysOut = new BufferedWriter(new OutputStreamWriter(System.out));
diff --git a/Server/src/org/openas2/cert/PKCS12CertificateFactory.java b/Server/src/org/openas2/cert/PKCS12CertificateFactory.java
index ffc38294..480db371 100644
--- a/Server/src/org/openas2/cert/PKCS12CertificateFactory.java
+++ b/Server/src/org/openas2/cert/PKCS12CertificateFactory.java
@@ -171,13 +171,13 @@ public PrivateKey getPrivateKey(X509Certificate cert) throws OpenAS2Exception {
alias = ks.getCertificateAlias(cert);
if (alias == null) {
- throw new KeyNotFoundException(cert, null);
+ throw new KeyNotFoundException(cert, "-- alias null from getCertificateAlias(cert) call");
}
PrivateKey key = (PrivateKey) ks.getKey(alias, getPassword());
if (key == null) {
- throw new KeyNotFoundException(cert, null);
+ throw new KeyNotFoundException(cert, "-- key null from getKey(" + alias + ") call");
}
return key;
@@ -219,6 +219,16 @@ public void addPrivateKey(String alias, Key key, String password) throws OpenAS2
}
Certificate[] certChain = ks.getCertificateChain(alias);
+ if (certChain == null)
+ {
+ X509Certificate x509cert = (X509Certificate)ks.getCertificate(alias);
+ if (x509cert.getSubjectDN().equals(x509cert.getIssuerDN()))
+ {
+ // Trust chain is to itself
+ certChain = new X509Certificate[] { x509cert, x509cert };
+ if (logger.isInfoEnabled()) logger.info("Detected self-signed certificate and allowed import. Alias: " + alias);
+ }
+ }
ks.setKeyEntry(alias, key, password.toCharArray(), certChain);
save(getFilename(), getPassword());
diff --git a/Server/src/org/openas2/database/H2DBHandler.java b/Server/src/org/openas2/database/H2DBHandler.java
new file mode 100644
index 00000000..0864b4c8
--- /dev/null
+++ b/Server/src/org/openas2/database/H2DBHandler.java
@@ -0,0 +1,112 @@
+package org.openas2.database;
+
+import java.sql.Connection;
+import java.sql.DriverManager;
+import java.sql.SQLException;
+import java.sql.Statement;
+import java.util.concurrent.TimeUnit;
+
+import org.h2.jdbcx.JdbcConnectionPool;
+import org.openas2.OpenAS2Exception;
+
+public class H2DBHandler implements IDBHandler
+{
+ JdbcConnectionPool cp = null;
+
+ private String jdbcDriver = "org.h2.Driver";
+
+ private String connectString = "jdbc:h2:file:DB/openas2";
+
+ public H2DBHandler()
+ {
+ }
+
+ /**
+ * @param jdbcDriver
+ */
+ public H2DBHandler(String jdbcDriver)
+ {
+ setJdbcDriver(jdbcDriver);
+ }
+
+ /**
+ * @param jdbcDriver
+ */
+ public void setJdbcDriver(String jdbcDriver)
+ {
+ this.jdbcDriver = jdbcDriver;
+ }
+
+ public void createConnectionPool(String connectString, String userName, String pwd) throws OpenAS2Exception
+ {
+ // Check that a connection pool is not already running
+ if (cp != null)
+ {
+ throw new OpenAS2Exception(
+ "Connection pool already initialized. Cannot create a new connection pool. Stop current one first. DB connect string:"
+ + connectString + " :: Active pool connect string: " + this.connectString);
+ }
+ this.connectString = connectString;
+ // Load the Database Engine JDBC driver
+ // Class.forName(jdbcDriver);
+
+ cp = JdbcConnectionPool.create(connectString, userName, pwd);
+ }
+
+ public void destroyConnectionPool()
+ {
+ if (cp == null)
+ return;
+ cp.dispose();
+ cp = null;
+ }
+
+ public Connection getConnection() throws SQLException, OpenAS2Exception
+ {
+ // Check that a connection pool is running
+ if (cp == null)
+ {
+ throw new OpenAS2Exception("Connection pool not initialized.");
+ }
+ return cp.getConnection();
+ }
+
+ public Connection connect(String connectString, String userName, String password) throws Exception
+ {
+
+ // Load the Database Engine JDBC driver
+ Class.forName(jdbcDriver);
+ try
+ {
+
+ return DriverManager.getConnection(connectString, userName, password);
+ } catch (SQLException e)
+ {
+ throw new Exception("Failed to obtain connection to database: " + connectString, e);
+ }
+ }
+
+ public boolean shutdown(String connectString) throws SQLException, OpenAS2Exception
+ {
+ // Wait briefly if there are active connections
+ int waitCount = 0;
+ try
+ {
+ while (cp.getActiveConnections() > 0 && waitCount < 10)
+ {
+ TimeUnit.MILLISECONDS.sleep(100);
+ waitCount++;
+ }
+ } catch (InterruptedException e)
+ {
+ // Do nothing
+ }
+ Connection c = getConnection();
+ Statement st = c.createStatement();
+
+ boolean result = st.execute("SHUTDOWN");
+ c.close();
+ return result;
+ }
+
+}
diff --git a/Server/src/org/openas2/database/IDBHandler.java b/Server/src/org/openas2/database/IDBHandler.java
new file mode 100644
index 00000000..a12d52b4
--- /dev/null
+++ b/Server/src/org/openas2/database/IDBHandler.java
@@ -0,0 +1,21 @@
+package org.openas2.database;
+
+import java.sql.Connection;
+import java.sql.SQLException;
+
+import org.openas2.OpenAS2Exception;
+
+public interface IDBHandler
+{
+ public void setJdbcDriver(String jdbcDriver);
+
+ public void createConnectionPool(String connectString, String userName, String pwd) throws OpenAS2Exception;
+
+ public void destroyConnectionPool();
+
+ public Connection getConnection() throws SQLException, OpenAS2Exception;
+
+ public Connection connect(String connectString, String userName, String password) throws Exception;
+
+ public boolean shutdown(String connectString) throws SQLException, OpenAS2Exception;
+}
diff --git a/Server/src/org/openas2/lib/helper/BCCryptoHelper.java b/Server/src/org/openas2/lib/helper/BCCryptoHelper.java
index 5d94f303..29b959d8 100644
--- a/Server/src/org/openas2/lib/helper/BCCryptoHelper.java
+++ b/Server/src/org/openas2/lib/helper/BCCryptoHelper.java
@@ -428,10 +428,10 @@ public MimeBodyPart verifySignature(MimeBodyPart part, Certificate cert)
}
if (signer.verify(signerInfoVerifier))
{
- logSignerInfo("Verified signature for signer info", signer, part);
+ logSignerInfo("Verified signature for signer info", signer, part, x509Cert);
return signedPart.getContent();
}
- logSignerInfo("Failed to verify signature for signer info", signer, part);
+ logSignerInfo("Failed to verify signature for signer info", signer, part, x509Cert);
}
throw new SignatureException("Signature Verification failed");
}
@@ -749,7 +749,7 @@ public String printHeaders(Enumeration hdrs)
return(headers);
}
- public void logSignerInfo(String msgPrefix, SignerInformation signer, MimeBodyPart part)
+ public void logSignerInfo(String msgPrefix, SignerInformation signer, MimeBodyPart part, X509Certificate cert)
{
if (logger.isDebugEnabled())
{
@@ -764,6 +764,7 @@ public void logSignerInfo(String msgPrefix, SignerInformation signer, MimeBodyPa
+ "\n Signature: " + signer.getSignature()
+ "\n Unsigned attribs: " + signer.getUnsignedAttributes()
+ "\n Content-transfer-encoding: " + part.getEncoding()
+ + "\n Certificate: " + cert
);
} catch (Throwable e)
{
diff --git a/Server/src/org/openas2/logging/EmailLogger.java b/Server/src/org/openas2/logging/EmailLogger.java
index 0e5991ca..aaf7c535 100644
--- a/Server/src/org/openas2/logging/EmailLogger.java
+++ b/Server/src/org/openas2/logging/EmailLogger.java
@@ -137,8 +137,14 @@ protected String getShowDefaults() {
return VALUE_SHOW_TERMINATED;
}
- protected String getSubject(Level level, String msg) {
- StringBuffer subject = new StringBuffer("OpenAS2 Log (" + level.getName() + "): " + msg.substring(0, msg.indexOf("\n")));
+ protected String getSubject(Level level, String msg) throws OpenAS2Exception {
+ if (msg == null)
+ throw new OpenAS2Exception("Message string to extract subject is null");
+ String subj = "";
+ int newlineNdx = msg.indexOf("\n");
+ if (newlineNdx >= 1)
+ subj = msg.substring(0, newlineNdx);
+ StringBuffer subject = new StringBuffer("OpenAS2 Log (" + level.getName() + "): " + subj);
return subject.toString();
}
diff --git a/Server/src/org/openas2/message/AS2MessageMDN.java b/Server/src/org/openas2/message/AS2MessageMDN.java
index 6860c71f..0063491b 100644
--- a/Server/src/org/openas2/message/AS2MessageMDN.java
+++ b/Server/src/org/openas2/message/AS2MessageMDN.java
@@ -20,8 +20,9 @@ public class AS2MessageMDN extends BaseMessageMDN {
public static final String MDNA_DISPOSITION = "DISPOSITION";
public static final String MDNA_MIC = "MIC";
- public AS2MessageMDN(AS2Message msg) {
+ public AS2MessageMDN(AS2Message msg, boolean copyMsgHeaders) {
super(msg);
+ if (copyMsgHeaders) copyHeaders(msg.getHeaders());
setHeader("AS2-To", msg.getHeader("AS2-From"));
setHeader("AS2-From", msg.getHeader("AS2-To"));
}
diff --git a/Server/src/org/openas2/message/BaseMessage.java b/Server/src/org/openas2/message/BaseMessage.java
index 6453f91f..627f5b92 100644
--- a/Server/src/org/openas2/message/BaseMessage.java
+++ b/Server/src/org/openas2/message/BaseMessage.java
@@ -1,6 +1,7 @@
package org.openas2.message;
import java.io.ByteArrayOutputStream;
+import java.io.File;
import java.io.IOException;
import java.util.Enumeration;
import java.util.HashMap;
@@ -8,14 +9,19 @@
import javax.mail.Header;
import javax.mail.MessagingException;
+import javax.mail.internet.ContentDisposition;
import javax.mail.internet.InternetHeaders;
import javax.mail.internet.MimeBodyPart;
+import javax.mail.internet.ParseException;
+import org.apache.commons.logging.LogFactory;
import org.openas2.OpenAS2Exception;
+import org.openas2.Session;
import org.openas2.WrappedException;
import org.openas2.lib.helper.ICryptoHelper;
import org.openas2.params.InvalidParameterException;
import org.openas2.partner.Partnership;
+import org.openas2.processor.msgtracking.TrackingModule;
public abstract class BaseMessage implements Message {
@@ -37,6 +43,7 @@ public abstract class BaseMessage implements Message {
private String logMsg = null;
private String status = MSG_STATUS_MSG_INIT;
private Map customOuterMimeHeaders = new HashMap();
+ private String payloadFilename = null;
public BaseMessage() {
@@ -400,4 +407,65 @@ public void setCalculatedMIC(String calculatedMIC)
this.calculatedMIC = calculatedMIC;
}
+ public String getPayloadFilename()
+ {
+ return payloadFilename;
+ }
+
+ public void setPayloadFilename(String filename)
+ {
+ payloadFilename = filename;
+ }
+
+ public void trackMsgState(Session session)
+ {
+ // Log a start sending fail state but do not allow exceptions to stop the process
+ try
+ {
+ options.put("OPTIONAL_MODULE", "true");
+ session.getProcessor().handle(TrackingModule.DO_TRACK_MSG, this, options);
+ } catch (Exception et)
+ {
+ setLogMsg("Unable to persist message tracking state: " + org.openas2.logging.Log.getExceptionMsg(et));
+ LogFactory.getLog(BaseMessage.class.getSimpleName()).error(this, et);
+ }
+
+ }
+
+ public String extractPayloadFilename() throws ParseException
+ {
+ String s = getContentDisposition();
+ if (s == null || s.length() < 1)
+ return null;
+ // TODO: This should be a case insensitive lookup per RFC6266
+ String tmpFilename = null;
+
+ ContentDisposition cd = new ContentDisposition(s);
+ tmpFilename = cd.getParameter("filename");
+
+ if (tmpFilename == null || tmpFilename.length() < 1)
+ {
+ /* Try to extract manually */
+ int n = s.indexOf("filename=");
+ if (n > -1)
+ {
+ tmpFilename = s.substring(n);
+ tmpFilename = tmpFilename.replaceFirst("filename=", "");
+
+ int n1 = tmpFilename.indexOf(",");
+ if (n1 > -1)
+ s = s.substring(0, n1 - 1);
+ tmpFilename = tmpFilename.replaceAll("\"", "");
+ s = s.trim();
+ }
+ else
+ {
+ /* Try just using file separator */
+ int pos = s.lastIndexOf(File.separator);
+ if (pos >= 0)
+ tmpFilename = s.substring(pos + 1);
+ }
+ }
+ return tmpFilename;
+ }
}
diff --git a/Server/src/org/openas2/message/BaseMessageMDN.java b/Server/src/org/openas2/message/BaseMessageMDN.java
index 42463fd0..73c5590b 100644
--- a/Server/src/org/openas2/message/BaseMessageMDN.java
+++ b/Server/src/org/openas2/message/BaseMessageMDN.java
@@ -85,6 +85,14 @@ public InternetHeaders getHeaders() {
return headers;
}
+ public void copyHeaders(InternetHeaders srcHeaders) {
+ Enumeration headerEn = srcHeaders.getAllHeaders();
+ while (headerEn.hasMoreElements()) {
+ Header header = headerEn.nextElement();
+ setHeader(header.getName(), header.getValue());
+ }
+ }
+
public void setMessage(Message message) {
this.message = message;
}
@@ -141,8 +149,8 @@ public DataHistory getHistory() {
public String toString() {
StringBuffer buf = new StringBuffer();
- buf.append("MDN From:").append(getPartnership().getSenderIDs());
- buf.append("To:").append(getPartnership().getReceiverIDs());
+ buf.append("MDN From:").append(getPartnership().getReceiverIDs());
+ buf.append("To:").append(getPartnership().getSenderIDs());
Enumeration headerEn = getHeaders().getAllHeaders();
buf.append("\r\nHeaders:{");
diff --git a/Server/src/org/openas2/message/Message.java b/Server/src/org/openas2/message/Message.java
index 493f08c0..83418115 100644
--- a/Server/src/org/openas2/message/Message.java
+++ b/Server/src/org/openas2/message/Message.java
@@ -1,12 +1,15 @@
package org.openas2.message;
import java.io.Serializable;
+import java.util.HashMap;
import java.util.Map;
import javax.mail.internet.InternetHeaders;
import javax.mail.internet.MimeBodyPart;
+import javax.mail.internet.ParseException;
import org.openas2.OpenAS2Exception;
+import org.openas2.Session;
import org.openas2.params.InvalidParameterException;
import org.openas2.partner.Partnership;
@@ -22,8 +25,55 @@ public interface Message extends Serializable {
public static final String MSG_STATUS_MDN_VERIFY = "verifying_mdn";
public static final String MSG_STATUS_MDN_PROCESS_INIT = "init_processing_mdn";
public static final String MSG_STATUS_MSG_CLEANUP = "cleanup";
+
+ public static final String MSG_STATE_SEND_START = "msg_send_start";
+ public static final String MSG_STATE_SEND_EXCEPTION = "msg_send_exception";
+ public static final String MSG_STATE_SEND_FAIL = "msg_send_fail";
+ public static final String MSG_STATE_RECEIVE_START = "msg_receive_start";
+ public static final String MSG_STATE_RECEIVE_EXCEPTION = "msg_receive_exception";
+ public static final String MSG_STATE_RECEIVE_FAIL = "msg_receive_fail";
+ public static final String MSG_STATE_MDN_ERROR_RESPONSE_START = "msg_receive_error_sending_mdn_error";
+ public static final String MSG_STATE_MDN_SENDING_EXCEPTION = "mdn_sending_exception";
+ public static final String MSG_STATE_MDN_RECEIVING_EXCEPTION = "mdn_receiving_exception";
+ public static final String MSG_STATE_MDN_SEND_START = "mdn_send_start";
+ public static final String MSG_STATE_MDN_RECEIVE_START = "mdn_receive_start";
+ public static final String MSG_STATE_MSG_SENT_MDN_RECEIVED_ERROR = "msg_sent_mdn_received_error";
+ public static final String MSG_STATE_MSG_SENT_MDN_RECEIVED_OK = "msg_sent_mdn_received_ok";
+ public static final String MSG_STATE_MSG_RXD_MDN_SENDING_FAIL = "msg_rxd_mdn_sending_fail";
+ public static final String MSG_STATE_MSG_RXD_MDN_SENT_OK = "msg_rxd_mdn_sent_ok";
+ public static final String MSG_STATE_MIC_MISMATCH = "msg_sent_mdn_received_mic_mismatch";
+
+ public static Map STATE_MSGS = new HashMap()
+ {
+ private static final long serialVersionUID = 5L;
+
+ {
+ put(MSG_STATE_SEND_START, "Message sending started");
+ put(MSG_STATE_SEND_EXCEPTION, "Message sending exception occurred. Resend queued");
+ put(MSG_STATE_SEND_FAIL, "Message sending failed.");
+ put(MSG_STATE_RECEIVE_START, "Message receiving started");
+ put(MSG_STATE_RECEIVE_EXCEPTION, "Processing exception occurred receiving message. Resend queued");
+ put(MSG_STATE_RECEIVE_FAIL, "Failed to receive inbound message successfully.");
+ put(MSG_STATE_MDN_ERROR_RESPONSE_START,
+ "Error processing received message. Sending MDN error response to partner");
+ put(MSG_STATE_MDN_SENDING_EXCEPTION, "Processing exception sending MDN. Resend queued");
+ put(MSG_STATE_MDN_RECEIVING_EXCEPTION, "Processing exception receiving MDN. Resend queued");
+ put(MSG_STATE_MDN_SEND_START, "Message recieved. MDN sending started");
+ put(MSG_STATE_MDN_RECEIVE_START, "Message sent. MDN receiving started");
+ put(MSG_STATE_MSG_SENT_MDN_RECEIVED_ERROR,
+ "Message sent. Message MDN received indicates an error. Resend queued");
+ put(MSG_STATE_MSG_SENT_MDN_RECEIVED_OK, "Message sent. Message MDN success response received.");
+ put(MSG_STATE_MSG_RXD_MDN_SENDING_FAIL,
+ "Message was received but failed to successfully send an MDN response to partner");
+ put(MSG_STATE_MSG_RXD_MDN_SENT_OK, "Message received and MDN sent succesfully.");
+ }
+ };
public static final String SMIME_TYPE_COMPRESSED_DATA = "smime-type=compressed-data";
+
+ public String getPayloadFilename();
+ public void setPayloadFilename(String filename);
+ public String extractPayloadFilename() throws ParseException;
public void setStatus(String status);
@@ -118,6 +168,8 @@ public interface Message extends Serializable {
public String getLogMsg();
public void setLogMsg(String msg);
+
+ public void trackMsgState(Session session);
public String getCalculatedMIC();
diff --git a/Server/src/org/openas2/params/ComponentParameters.java b/Server/src/org/openas2/params/ComponentParameters.java
new file mode 100644
index 00000000..6212b733
--- /dev/null
+++ b/Server/src/org/openas2/params/ComponentParameters.java
@@ -0,0 +1,35 @@
+package org.openas2.params;
+
+import org.openas2.Component;
+
+public class ComponentParameters extends ParameterParser
+{
+ public static final String KEY_COMPONENT_PARAMETER = "component";
+ private Component target;
+
+ public ComponentParameters(Component target) {
+ super();
+ this.target = target;
+ }
+
+ public void setParameter(String key, String value) throws InvalidParameterException {
+ throw new InvalidParameterException("Set not supported", this, key, value);
+ }
+
+ public String getParameter(String key) throws InvalidParameterException {
+ if (key != null) {
+ return getTarget().getParameters().get(key);
+ } else {
+ throw new InvalidParameterException("Invalid area in key", this, key, null);
+ }
+ }
+
+ public void setTarget(Component component) {
+ target = component;
+ }
+
+ public Component getTarget() {
+ return target;
+ }
+
+}
diff --git a/Server/src/org/openas2/params/MessageParameters.java b/Server/src/org/openas2/params/MessageParameters.java
index 7d16856b..98e52a34 100644
--- a/Server/src/org/openas2/params/MessageParameters.java
+++ b/Server/src/org/openas2/params/MessageParameters.java
@@ -1,9 +1,8 @@
package org.openas2.params;
-import java.io.File;
import java.util.StringTokenizer;
-import javax.mail.internet.ContentDisposition;
+import javax.mail.internet.ParseException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -69,53 +68,17 @@ public String getParameter(String key) throws InvalidParameterException {
return getTarget().getHeader(areaID);
} else if (area.equals(KEY_CONTENT_FILENAME) && areaID.equals("filename")) {
String filename = "noContentDispositionFilename";
- String s = target.getContentDisposition();
- if (s == null || s.length() < 1)
- return filename;
- try {
- if (logger.isDebugEnabled())
- logger.debug("Attempting filename extraction from Content-disposition: " + s);
- // TODO: This should be a case insensitive lookup per RFC6266
- String tmpFilename = null;
-
- ContentDisposition cd = new ContentDisposition(s);
- tmpFilename = cd.getParameter("filename");
-
- if (tmpFilename == null || tmpFilename.length() < 1)
- {
- /* Try to extract manually */
- int n = s.indexOf("filename=");
- if (n > -1)
- {
- tmpFilename = s.substring(n);
- tmpFilename = tmpFilename.replaceFirst("filename=", "");
-
- int n1 = tmpFilename.indexOf(",");
- if (n1 > -1)
- s = s.substring(0, n1 - 1);
- tmpFilename = tmpFilename.replaceAll("\"", "");
- s = s.trim();
- }
- else
- {
- /* Try just using file separator */
- int pos = s.lastIndexOf(File.separator);
- if (pos >= 0)
- tmpFilename = s.substring(pos + 1);
- }
- }
-
- if (tmpFilename != null && tmpFilename.length() > 0)
- {
- if (logger.isDebugEnabled())
- logger.debug("Filename extracted from Content-disposition: " + tmpFilename);
- return tmpFilename;
- }
-
- } catch (Exception e) {
- e.printStackTrace();
+ String s = null;
+ try
+ {
+ s = getTarget().extractPayloadFilename();
+ } catch (ParseException e)
+ {
+ logger.warn("Failed to extract filename from content-disposition: " + org.openas2.logging.Log.getExceptionMsg(e), e);
}
- return filename;
+ if (s != null && s.length() > 0)
+ return s;
+ return filename;
} else {
throw new InvalidParameterException("Invalid area in key", this, key, null);
}
diff --git a/Server/src/org/openas2/partner/AS2Partnership.java b/Server/src/org/openas2/partner/AS2Partnership.java
index d4a521c2..11215d21 100644
--- a/Server/src/org/openas2/partner/AS2Partnership.java
+++ b/Server/src/org/openas2/partner/AS2Partnership.java
@@ -10,9 +10,12 @@ public interface AS2Partnership {
public static final String PA_AS2_RECEIPT_OPTION = "as2_receipt_option"; // URL destination for an async MDN
public static final String PA_MESSAGEID = "messageid"; // format to use for message-id if not default
public static final String PA_RESEND_MAX_RETRIES = "resend_max_retries"; // format to use for message-id if not default
- public static final String PA_CUSTOM_MIME_HEADERS = "custom_mime_headers";
- public static final String PA_ADD_CUSTOM_MIME_HEADERS_TO_HTTP = "add_custom_mime_headers_to_http";
- public static final String PA_CUSTOM_MIME_HEADER_NAMES_FROM_FILENAME = "custom_mime_header_names_from_filename";
- public static final String PA_CUSTOM_MIME_HEADER_NAME_DELIMITERS_IN_FILENAME = "custom_mime_header_name_delimiters_in_filename";
- public static final String PA_CUSTOM_MIME_HEADER_NAMES_REGEX_ON_FILENAME = "custom_mime_header_names_regex_on_filename";
+ public static final String PA_CUSTOM_MIME_HEADERS = "custom_mime_headers"; // list of nme/value pairs for setting custom mime headers
+ public static final String PA_ADD_CUSTOM_MIME_HEADERS_TO_HTTP = "add_custom_mime_headers_to_http"; // Add the custom mime headers (if any) to HTTP header if "true"
+ public static final String PA_CUSTOM_MIME_HEADER_NAMES_FROM_FILENAME = "custom_mime_header_names_from_filename"; // List of header names to be set from parsed filename
+ public static final String PA_CUSTOM_MIME_HEADER_NAME_DELIMITERS_IN_FILENAME = "custom_mime_header_name_delimiters_in_filename"; // Delimiters to split filename into values
+ public static final String PA_CUSTOM_MIME_HEADER_NAMES_REGEX_ON_FILENAME = "custom_mime_header_names_regex_on_filename"; // Regex to split filename into values
+
+ public static final String PA_ATTRIB_NAMES_FROM_FILENAME = "attribute_names_from_filename"; // List of attribute names to be set from parsed filename
+ public static final String PA_ATTRIB_VALUES_REGEX_ON_FILENAME = "attribute_values_regex_on_filename"; // Regex to split filename into values
}
diff --git a/Server/src/org/openas2/partner/BasePartnershipFactory.java b/Server/src/org/openas2/partner/BasePartnershipFactory.java
index ba9d594b..c077e9d0 100644
--- a/Server/src/org/openas2/partner/BasePartnershipFactory.java
+++ b/Server/src/org/openas2/partner/BasePartnershipFactory.java
@@ -4,9 +4,12 @@
import java.util.Iterator;
import java.util.List;
import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
import org.openas2.BaseComponent;
import org.openas2.OpenAS2Exception;
+import org.openas2.message.FileAttribute;
import org.openas2.message.Message;
import org.openas2.message.MessageMDN;
import org.openas2.params.MessageParameters;
@@ -15,11 +18,14 @@
public abstract class BasePartnershipFactory extends BaseComponent implements PartnershipFactory {
private List partnerships;
- public Partnership getPartnership(Partnership p) throws OpenAS2Exception {
+ public Partnership getPartnership(Partnership p, boolean reverseLookup) throws OpenAS2Exception {
Partnership ps = (p.getName() == null) ? null : getPartnership(p.getName());
if (ps == null) {
- ps = getPartnership(p.getSenderIDs(), p.getReceiverIDs());
+ if (reverseLookup)
+ ps = getPartnership(p.getReceiverIDs(), p.getSenderIDs());
+ else
+ ps = getPartnership(p.getSenderIDs(), p.getReceiverIDs());
}
if (ps == null) {
@@ -41,10 +47,36 @@ public List getPartnerships() {
return partnerships;
}
- public void updatePartnership(Message msg, boolean overwrite) throws OpenAS2Exception {
+ public void updatePartnership(Message msg, boolean overwrite) throws OpenAS2Exception
+ {
// Fill in any available partnership information
- Partnership partnership = getPartnership(msg.getPartnership());
+ Partnership partnership = getPartnership(msg.getPartnership(), false);
msg.getPartnership().copy(partnership);
+ // Now set dynamic parms based on file name if configured to
+ String filename = msg.getAttribute(FileAttribute.MA_FILENAME);
+ String filenameToParmsList = msg.getPartnership().getAttribute(AS2Partnership.PA_ATTRIB_NAMES_FROM_FILENAME);
+ if (filename != null && filenameToParmsList != null && filenameToParmsList.length() > 0)
+ {
+ String[] headerNames = filenameToParmsList.split("\\s*,\\s*");
+
+ String regex = msg.getPartnership().getAttribute(AS2Partnership.PA_ATTRIB_VALUES_REGEX_ON_FILENAME);
+ if (regex != null)
+ {
+ Pattern p = Pattern.compile(regex);
+ Matcher m = p.matcher(filename);
+ if (!m.find() || m.groupCount() != headerNames.length)
+ {
+ throw new OpenAS2Exception("Could not match filename (" + filename + ") to parameters required using the regex provided (" + regex + "): "
+ + (m.find() ? ("Mismatch in parameter count to extracted group count: " + headerNames.length
+ + "::" + m.groupCount()) : "No match found in filename"));
+ }
+ for (int i = 0; i < headerNames.length; i++)
+ {
+ msg.setAttribute(headerNames[i], m.group(i + 1));
+ }
+ }
+ }
+
// Set attributes
if (overwrite) {
@@ -57,7 +89,8 @@ public void updatePartnership(Message msg, boolean overwrite) throws OpenAS2Exce
public void updatePartnership(MessageMDN mdn, boolean overwrite) throws OpenAS2Exception {
// Fill in any available partnership information
- Partnership partnership = getPartnership(mdn.getPartnership());
+ // the MDN partnership should be the one used to send original message hence reverse lookup
+ Partnership partnership = getPartnership(mdn.getPartnership(), true);
mdn.getPartnership().copy(partnership);
}
diff --git a/Server/src/org/openas2/partner/Partnership.java b/Server/src/org/openas2/partner/Partnership.java
index 52dd5ec1..da811439 100644
--- a/Server/src/org/openas2/partner/Partnership.java
+++ b/Server/src/org/openas2/partner/Partnership.java
@@ -18,8 +18,9 @@ public class Partnership implements Serializable {
public static final String PID_EMAIL = "email"; // Email address
public static final String PA_PROTOCOL = "protocol"; // AS1 or AS2
public static final String PA_SUBJECT = "subject"; // Subject sent in messages
- public static final String PA_CONTENT_TRANSFER_ENCODING = "content_transfer_encoding"; // optional content transer enc value
+ public static final String PA_CONTENT_TRANSFER_ENCODING = "content_transfer_encoding"; // optional content transfer enc value
public static final String PA_REMOVE_PROTECTION_ATTRIB = "remove_cms_algorithm_protection_attrib"; // Some AS2 systems do not support the attribute
+ public static final String PA_SET_CONTENT_TRANSFER_ENCODING_OMBP = "set_content_transfer_encoding_on_outer_mime_bodypart"; // optional content transfer enc value
private Map attributes;
diff --git a/Server/src/org/openas2/partner/PartnershipFactory.java b/Server/src/org/openas2/partner/PartnershipFactory.java
index 2c0bdf4d..7abcf742 100644
--- a/Server/src/org/openas2/partner/PartnershipFactory.java
+++ b/Server/src/org/openas2/partner/PartnershipFactory.java
@@ -19,7 +19,7 @@ public interface PartnershipFactory extends Component {
public static final String COMPID_PARTNERSHIP_FACTORY = "partnershipfactory";
// throws an exception if the partnership doesn't exist
- public Partnership getPartnership(Partnership p) throws OpenAS2Exception;
+ public Partnership getPartnership(Partnership p, boolean reverseLookup) throws OpenAS2Exception;
// looks up and fills in any header info for a specific msg's partnership
public void updatePartnership(Message msg, boolean overwrite) throws OpenAS2Exception;
diff --git a/Server/src/org/openas2/processor/DefaultProcessor.java b/Server/src/org/openas2/processor/DefaultProcessor.java
index 037d2be4..0395dad3 100644
--- a/Server/src/org/openas2/processor/DefaultProcessor.java
+++ b/Server/src/org/openas2/processor/DefaultProcessor.java
@@ -73,6 +73,7 @@ public void handle(String action, Message msg, Map