summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--BKULocal/src/main/resources/log4j.properties2
-rw-r--r--BKULocal/src/main/webapp/errorresponse.css12
-rw-r--r--BKUOnline/src/main/webapp/errorresponse.css12
-rw-r--r--BKUWebStart/pom.xml14
-rw-r--r--BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/Configurator.java26
-rw-r--r--BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/Container.java11
-rw-r--r--BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/Launcher.java22
-rw-r--r--BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/LogSecurityManager.java9
-rw-r--r--BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/TLSServerCA.java9
-rw-r--r--BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/gui/AboutDialog.java7
-rw-r--r--BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/gui/PINManagementInvoker.java7
-rw-r--r--BKUWebStart/src/main/resources/log4j.properties20
-rw-r--r--BKUWebStart/src/test/java/at/gv/egiz/bku/webstart/ConfiguratorTest.java2
-rw-r--r--BKUWebStartPackage/pom.xml3
-rw-r--r--bkucommon/src/main/java/at/gv/egiz/bku/binding/DataUrl.java9
-rw-r--r--bkucommon/src/main/java/at/gv/egiz/bku/binding/DataUrlConnection.java2
-rw-r--r--bkucommon/src/main/java/at/gv/egiz/bku/binding/DataUrlConnectionImpl.java342
-rw-r--r--bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java29
-rw-r--r--bkucommon/src/main/java/at/gv/egiz/bku/binding/LegacyDataUrlConnectionImpl.java259
-rw-r--r--bkucommon/src/main/java/at/gv/egiz/bku/binding/XWWWFormUrlInputDecoder.java83
-rw-r--r--bkucommon/src/main/java/at/gv/egiz/bku/binding/XWWWFormUrlInputIterator.java376
-rw-r--r--bkucommon/src/main/java/at/gv/egiz/bku/binding/multipart/SLResultPart.java41
-rw-r--r--bkucommon/src/main/java/at/gv/egiz/bku/conf/CertValidatorImpl.java24
-rw-r--r--bkucommon/src/main/java/at/gv/egiz/bku/conf/IAIKCommonsLog.java144
-rw-r--r--bkucommon/src/main/java/at/gv/egiz/bku/conf/IAIKCommonsLogFactory.java59
-rw-r--r--bkucommon/src/main/java/at/gv/egiz/bku/slcommands/SLCommandFactory.java51
-rw-r--r--bkucommon/src/main/java/at/gv/egiz/bku/slcommands/SLMarshallerFactory.java172
-rw-r--r--bkucommon/src/main/java/at/gv/egiz/bku/slcommands/SLResult.java8
-rw-r--r--bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/AbstractAssocArrayInfobox.java13
-rw-r--r--bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/CreateXMLSignatureResultImpl.java15
-rw-r--r--bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/ErrorResultImpl.java6
-rw-r--r--bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/GetStatusCommandImpl.java2
-rw-r--r--bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/GetStatusResultImpl.java4
-rw-r--r--bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/IdentityLinkInfoboxImpl.java1
-rw-r--r--bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxReadResultFileImpl.java15
-rw-r--r--bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxReadResultImpl.java4
-rw-r--r--bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxUpdateResultImpl.java4
-rw-r--r--bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/NullOperationResultImpl.java4
-rw-r--r--bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/SLResultImpl.java94
-rw-r--r--bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/DataObject.java1
-rw-r--r--bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/Signature.java18
-rw-r--r--bkucommon/src/main/java/at/gv/egiz/bku/slexceptions/SLExceptionMessages.java6
-rw-r--r--bkucommon/src/main/java/at/gv/egiz/bku/slexceptions/SLVersionException.java28
-rw-r--r--bkucommon/src/main/resources/at/gv/egiz/bku/slcommands/schema/Core.20020225.xsd33
-rw-r--r--bkucommon/src/main/resources/at/gv/egiz/bku/slcommands/schema/Core.20020831.xsd10
-rw-r--r--bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages.properties7
-rw-r--r--bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages_en.properties4
-rw-r--r--bkucommon/src/test/java/at/gv/egiz/bku/binding/XWWWFormUrlInputIteratorTest.java152
-rw-r--r--bkucommon/src/test/java/at/gv/egiz/bku/slcommands/SLCommandFactoryTest.java7
-rw-r--r--bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/CreateXMLSignatureComandImplTest.java9
-rw-r--r--bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/ErrorResultImplTest.java2
-rw-r--r--bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/InfoboxReadComandImplTest.java9
-rw-r--r--bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/NullOperationResultImplTest.java2
-rw-r--r--bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/SVPersonendatenInfoboxImplTest.java15
-rw-r--r--utils/src/main/java/at/buergerkarte/namespaces/securitylayer/_1/TransformsInfoType.java21
-rw-r--r--utils/src/main/java/at/buergerkarte/namespaces/securitylayer/_20020225_/ErrorResponseType.java98
-rw-r--r--utils/src/main/java/at/buergerkarte/namespaces/securitylayer/_20020225_/ObjectFactory.java280
-rw-r--r--utils/src/main/java/at/buergerkarte/namespaces/securitylayer/_20020225_/package-info.java9
-rw-r--r--utils/src/main/java/at/buergerkarte/namespaces/securitylayer/_20020831_/ObjectFactory.java112
-rw-r--r--utils/src/main/java/at/gv/egiz/bku/utils/URLEncodingInputStream.java62
-rw-r--r--utils/src/main/java/at/gv/egiz/bku/utils/URLEncodingOutputStream.java134
-rw-r--r--utils/src/main/java/at/gv/egiz/bku/utils/URLEncodingWriter.java57
-rw-r--r--utils/src/main/java/at/gv/egiz/marshal/MarshallerFactory.java12
-rw-r--r--utils/src/main/java/at/gv/egiz/marshal/NamespacePrefix.java34
-rw-r--r--utils/src/main/java/at/gv/egiz/marshal/NamespacePrefixMapperImpl.java54
-rw-r--r--utils/src/main/java/at/gv/egiz/validation/ReportingValidationEventHandler.java (renamed from utils/src/main/java/at/gv/egiz/validation/ValidationEventLogger.java)13
-rw-r--r--utils/src/main/java/at/gv/egiz/xades/QualifyingPropertiesFactory.java8
-rw-r--r--utils/src/test/java/at/gv/egiz/bku/utils/URLEncodingOutputStreamTest.java147
-rw-r--r--utils/src/test/resources/BigRequest.xml1060
69 files changed, 3651 insertions, 670 deletions
diff --git a/BKULocal/src/main/resources/log4j.properties b/BKULocal/src/main/resources/log4j.properties
index 8dc8644c..86ddc7b4 100644
--- a/BKULocal/src/main/resources/log4j.properties
+++ b/BKULocal/src/main/resources/log4j.properties
@@ -15,7 +15,7 @@
# assume log4j to be configured by servlet container (java web start)
# loglever DEBUG, appender STDOUT
-#log4j.rootLogger=DEBUG, STDOUT
+log4j.rootLogger=DEBUG, STDOUT
# STDOUT appender
log4j.appender.STDOUT=org.apache.log4j.ConsoleAppender
diff --git a/BKULocal/src/main/webapp/errorresponse.css b/BKULocal/src/main/webapp/errorresponse.css
new file mode 100644
index 00000000..41402e71
--- /dev/null
+++ b/BKULocal/src/main/webapp/errorresponse.css
@@ -0,0 +1,12 @@
+@CHARSET "UTF-8";
+sl\:ErrorResponse {margin: 0.5em; display: block;}
+sl\:ErrorCode {display: inline;}
+sl\:Info {display: inline;}
+
+ErrorResponse:lang(de):before {content: "Bei der Verarbeitung der Anfrage durch die Bürgerkartenumgebung ist ein Fehler aufgetreten: "; font-weight: bolder;}
+ErrorResponse:before {content: "An error has occoured upon request processing by the citizen card software: "; font-weight: bold;}
+ErrorResponse {margin: 0.5em; display: block;}
+ErrorCode:lang(de):before {content: "Fehler-Code: ";}
+ErrorCode:before {content: "Error Code: ";}
+ErrorCode {display: block;}
+Info {display: block;} \ No newline at end of file
diff --git a/BKUOnline/src/main/webapp/errorresponse.css b/BKUOnline/src/main/webapp/errorresponse.css
new file mode 100644
index 00000000..41402e71
--- /dev/null
+++ b/BKUOnline/src/main/webapp/errorresponse.css
@@ -0,0 +1,12 @@
+@CHARSET "UTF-8";
+sl\:ErrorResponse {margin: 0.5em; display: block;}
+sl\:ErrorCode {display: inline;}
+sl\:Info {display: inline;}
+
+ErrorResponse:lang(de):before {content: "Bei der Verarbeitung der Anfrage durch die Bürgerkartenumgebung ist ein Fehler aufgetreten: "; font-weight: bolder;}
+ErrorResponse:before {content: "An error has occoured upon request processing by the citizen card software: "; font-weight: bold;}
+ErrorResponse {margin: 0.5em; display: block;}
+ErrorCode:lang(de):before {content: "Fehler-Code: ";}
+ErrorCode:before {content: "Error Code: ";}
+ErrorCode {display: block;}
+Info {display: block;} \ No newline at end of file
diff --git a/BKUWebStart/pom.xml b/BKUWebStart/pom.xml
index ca19a0b3..f51f1332 100644
--- a/BKUWebStart/pom.xml
+++ b/BKUWebStart/pom.xml
@@ -173,6 +173,12 @@
<version>1.0</version>
</dependency>
<dependency>
+ <groupId>iaik</groupId>
+ <artifactId>iaik_jce_full_signed</artifactId>
+ <scope>compile</scope>
+ </dependency>
+ <!--
+ <dependency>
<artifactId>utils</artifactId>
<groupId>at.gv.egiz</groupId>
<version>1.2.7-SNAPSHOT</version>
@@ -187,7 +193,8 @@
<groupId>commons-logging</groupId>
<artifactId>commons-logging</artifactId>
</dependency>
-
+ -->
+
<!-- Jetty 6.1.15+ required, see
| http://jira.codehaus.org/browse/JETTY-843
|-->
@@ -215,6 +222,11 @@
<artifactId>slf4j-log4j12</artifactId>
<version>1.5.8</version>
</dependency>
+ <dependency>
+ <groupId>log4j</groupId>
+ <artifactId>log4j</artifactId>
+ <scope>compile</scope>
+ </dependency>
<!-- javax.jnlp.* -->
<dependency>
diff --git a/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/Configurator.java b/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/Configurator.java
index 923a70d9..d8fe3e70 100644
--- a/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/Configurator.java
+++ b/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/Configurator.java
@@ -16,8 +16,9 @@
*/
package at.gv.egiz.bku.webstart;
-import at.gv.egiz.bku.utils.StreamUtil;
import iaik.asn1.CodingException;
+import iaik.utils.StreamCopier;
+
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
@@ -42,8 +43,10 @@ import java.util.jar.Manifest;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipOutputStream;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
+
+import org.apache.log4j.PropertyConfigurator;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
*
@@ -71,7 +74,7 @@ public class Configurator {
public static final String KEYSTORE_FILE = "keystore.ks";
public static final String PASSWD_FILE = ".secret";
- private static final Log log = LogFactory.getLog(Configurator.class);
+ private static final Logger log = LoggerFactory.getLogger(Configurator.class);
/** currently installed configuration version */
private String version;
@@ -110,6 +113,11 @@ public class Configurator {
} else {
initConfig(configDir);
}
+ // re-configure logging
+ // TODO: move to appropriate place
+ String log4jconfig = configDir.getPath() + File.separatorChar + "log4j.properties";
+ log.debug("Reconfiguring logging with " + log4jconfig);
+ PropertyConfigurator.configureAndWatch(log4jconfig);
}
/**
@@ -312,7 +320,7 @@ public class Configurator {
ZipEntry entry = new ZipEntry(relativePath.toString());
zip.putNextEntry(entry);
BufferedInputStream entryIS = new BufferedInputStream(new FileInputStream(dir));
- StreamUtil.copyStream(entryIS, zip);
+ new StreamCopier(entryIS, zip).copyStream();
entryIS.close();
zip.closeEntry();
dir.delete();
@@ -341,7 +349,7 @@ public class Configurator {
File confTemplateFile = new File(configDir, CONF_TEMPLATE_FILE);
InputStream is = Configurator.class.getClassLoader().getResourceAsStream(CONF_TEMPLATE_RESOURCE);
OutputStream os = new BufferedOutputStream(new FileOutputStream(confTemplateFile));
- StreamUtil.copyStream(is, os);
+ new StreamCopier(is, os).copyStream();
os.close();
unzip(confTemplateFile, configDir);
confTemplateFile.delete();
@@ -374,7 +382,7 @@ public class Configurator {
new File(certsDir, f.substring(0, f.lastIndexOf('/'))).mkdirs();
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(new File(certsDir, f)));
log.debug(f);
- StreamUtil.copyStream(Configurator.class.getClassLoader().getResourceAsStream(entry), bos);
+ new StreamCopier(Configurator.class.getClassLoader().getResourceAsStream(entry), bos).copyStream();
bos.close();
} else {
log.trace("ignore " + entry);
@@ -399,8 +407,8 @@ public class Configurator {
}
File f = new File(eF.getParent());
f.mkdirs();
- StreamUtil.copyStream(zipFile.getInputStream(entry),
- new FileOutputStream(eF));
+ new StreamCopier(zipFile.getInputStream(entry),
+ new FileOutputStream(eF)).copyStream();
}
zipFile.close();
}
diff --git a/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/Container.java b/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/Container.java
index 2feae267..4d1fe658 100644
--- a/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/Container.java
+++ b/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/Container.java
@@ -1,6 +1,7 @@
package at.gv.egiz.bku.webstart;
-import at.gv.egiz.bku.utils.StreamUtil;
+import iaik.utils.StreamCopier;
+
import java.awt.AWTPermission;
import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
@@ -24,20 +25,20 @@ import java.security.SecurityPermission;
import java.security.cert.Certificate;
import java.util.PropertyPermission;
import javax.smartcardio.CardPermission;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
import org.mortbay.jetty.Connector;
import org.mortbay.jetty.Server;
import org.mortbay.jetty.nio.SelectChannelConnector;
import org.mortbay.jetty.security.SslSocketConnector;
import org.mortbay.jetty.webapp.WebAppContext;
import org.mortbay.thread.QueuedThreadPool;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
public class Container {
public static final String HTTP_PORT_PROPERTY = "mocca.http.port";
public static final String HTTPS_PORT_PROPERTY = "mocca.http.port";
- private static Log log = LogFactory.getLog(Container.class);
+ private static Logger log = LoggerFactory.getLogger(Container.class);
static {
if (log.isDebugEnabled()) {
@@ -166,7 +167,7 @@ public class Container {
log.debug("copying BKULocal classpath resource to " + webapp);
InputStream is = getClass().getClassLoader().getResourceAsStream("BKULocal.war");
OutputStream os = new BufferedOutputStream(new FileOutputStream(webapp));
- StreamUtil.copyStream(is, os);
+ new StreamCopier(is, os).copyStream();
os.close();
return webapp.getPath();
}
diff --git a/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/Launcher.java b/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/Launcher.java
index 2bf42ccb..ef7edef1 100644
--- a/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/Launcher.java
+++ b/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/Launcher.java
@@ -10,8 +10,6 @@ import java.util.Locale;
import java.util.ResourceBundle;
import javax.jnlp.UnavailableServiceException;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
import com.sun.javaws.security.JavaWebStartSecurity;
import java.awt.AWTException;
@@ -37,6 +35,8 @@ import javax.jnlp.BasicService;
import javax.jnlp.ServiceManager;
import javax.swing.JFrame;
import org.mortbay.util.MultiException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
public class Launcher implements BKUControllerInterface, ActionListener {
public static final String HELP_COMMAND = "help";
@@ -71,9 +71,10 @@ public class Launcher implements BKUControllerInterface, ActionListener {
public static final String SHUTDOWN_COMMAND = "shutdown";
public static final String PIN_COMMAND = "pin";
public static final String ABOUT_COMMAND = "about";
+
+ private static Logger log = LoggerFactory.getLogger(Launcher.class);
- private static Log log = LogFactory.getLog(Launcher.class);
-
+
/** local bku uri */
public static final URL HTTP_SECURITY_LAYER_URL;
public static final URL HTTPS_SECURITY_LAYER_URL;
@@ -93,7 +94,7 @@ public class Launcher implements BKUControllerInterface, ActionListener {
cert = new URL(http, "/installCertificate");
help = new URL(http, "/help");
} catch (MalformedURLException ex) {
- log.error(ex);
+ log.error("Failed to create URL.", ex);
} finally {
HTTP_SECURITY_LAYER_URL = http;
HTTPS_SECURITY_LAYER_URL = https;
@@ -132,6 +133,7 @@ public class Launcher implements BKUControllerInterface, ActionListener {
public Launcher() {
+ log.info("Initializing Launcher");
if (log.isTraceEnabled()) {
SecurityManager sm = System.getSecurityManager();
if (sm instanceof JavaWebStartSecurity) {
@@ -147,7 +149,7 @@ public class Launcher implements BKUControllerInterface, ActionListener {
try {
initConfig();
} catch (Exception ex) {
- log.fatal("Failed to initialize configuration", ex);
+ log.error("Failed to initialize configuration", ex);
trayIcon.displayMessage(messages.getString(CAPTION_ERROR),
messages.getString(ERROR_CONFIG), TrayIcon.MessageType.ERROR);
throw ex;
@@ -156,12 +158,12 @@ public class Launcher implements BKUControllerInterface, ActionListener {
startServer();
initFinished();
} catch (BindException ex) {
- log.fatal("Failed to launch server, " + ex.getMessage(), ex);
+ log.error("Failed to launch server, " + ex.getMessage(), ex);
trayIcon.displayMessage(messages.getString(CAPTION_ERROR),
messages.getString(ERROR_BIND), TrayIcon.MessageType.ERROR);
throw ex;
} catch (MultiException ex) {
- log.fatal("Failed to launch server, " + ex.getMessage(), ex);
+ log.error("Failed to launch server, " + ex.getMessage(), ex);
if (ex.getThrowable(0) instanceof BindException) {
trayIcon.displayMessage(messages.getString(CAPTION_ERROR),
messages.getString(ERROR_BIND), TrayIcon.MessageType.ERROR);
@@ -172,7 +174,7 @@ public class Launcher implements BKUControllerInterface, ActionListener {
throw ex;
} catch (Exception ex) {
ex.printStackTrace();
- log.fatal("Failed to launch server, " + ex.getMessage(), ex);
+ log.error("Failed to launch server, " + ex.getMessage(), ex);
trayIcon.displayMessage(messages.getString(CAPTION_ERROR),
messages.getString(ERROR_START), TrayIcon.MessageType.ERROR);
throw ex;
@@ -379,7 +381,7 @@ public class Launcher implements BKUControllerInterface, ActionListener {
launcher.launch();
} catch (Exception ex) {
ex.printStackTrace();
- log.debug(ex);
+ log.debug("Caught exception " + ex.getMessage(), ex);
log.info("waiting to shutdown...");
Thread.sleep(5000);
log.info("exit");
diff --git a/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/LogSecurityManager.java b/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/LogSecurityManager.java
index 99fd403b..d589812e 100644
--- a/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/LogSecurityManager.java
+++ b/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/LogSecurityManager.java
@@ -20,8 +20,9 @@ import com.sun.javaws.security.JavaWebStartSecurity;
import java.io.FileDescriptor;
import java.net.InetAddress;
import java.security.Permission;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* JVM argument -Djava.security.debug=access,failure
@@ -31,7 +32,7 @@ import org.apache.commons.logging.LogFactory;
*/
public class LogSecurityManager extends SecurityManager {
- protected static final Log log = LogFactory.getLog(LogSecurityManager.class);
+ protected static final Logger log = LoggerFactory.getLogger(LogSecurityManager.class);
JavaWebStartSecurity sm;
public LogSecurityManager(JavaWebStartSecurity sm) {
@@ -182,6 +183,7 @@ public class LogSecurityManager extends SecurityManager {
}
}
+ @SuppressWarnings("deprecation")
@Override
public void checkMulticast(InetAddress maddr, byte ttl) {
try {
@@ -399,6 +401,7 @@ public class LogSecurityManager extends SecurityManager {
// protected Class[] getClassContext() {
// log.info("getClassContext"); return sm.getClassContext();
// }
+ @SuppressWarnings("deprecation")
@Override
public boolean getInCheck() {
log.info("getInCheck");
diff --git a/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/TLSServerCA.java b/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/TLSServerCA.java
index 08a06570..745042f8 100644
--- a/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/TLSServerCA.java
+++ b/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/TLSServerCA.java
@@ -16,8 +16,6 @@ import iaik.x509.extensions.SubjectAltName;
import iaik.x509.extensions.SubjectKeyIdentifier;
import java.io.IOException;
import java.math.BigInteger;
-import java.net.InetAddress;
-import java.net.UnknownHostException;
import java.security.GeneralSecurityException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
@@ -27,14 +25,15 @@ import java.util.Calendar;
import java.util.GregorianCalendar;
import java.util.Random;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
public class TLSServerCA {
public static final int CA_VALIDITY_Y = 3;
public static final String MOCCA_TLS_SERVER_ALIAS = "server";
public static final int SERVER_VALIDITY_Y = 3;
- private final static Log log = LogFactory.getLog(TLSServerCA.class);
+ private final static Logger log = LoggerFactory.getLogger(TLSServerCA.class);
private KeyPair caKeyPair;
private X509Certificate caCert;
diff --git a/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/gui/AboutDialog.java b/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/gui/AboutDialog.java
index 1e35af58..ba2c007d 100644
--- a/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/gui/AboutDialog.java
+++ b/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/gui/AboutDialog.java
@@ -11,7 +11,6 @@
package at.gv.egiz.bku.webstart.gui;
-import java.text.Format;
import java.text.MessageFormat;
import java.util.ResourceBundle;
@@ -21,6 +20,11 @@ import java.util.ResourceBundle;
*/
public class AboutDialog extends javax.swing.JDialog {
+ /**
+ *
+ */
+ private static final long serialVersionUID = 1L;
+
/** Creates new form AboutDialog */
public AboutDialog(java.awt.Frame parent, boolean modal, String version) {
super(parent, modal);
@@ -33,7 +37,6 @@ public class AboutDialog extends javax.swing.JDialog {
* WARNING: Do NOT modify this code. The content of this method is
* always regenerated by the Form Editor.
*/
- @SuppressWarnings("unchecked")
// <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
private void initComponents() {
diff --git a/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/gui/PINManagementInvoker.java b/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/gui/PINManagementInvoker.java
index 55e26313..1f14d751 100644
--- a/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/gui/PINManagementInvoker.java
+++ b/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/gui/PINManagementInvoker.java
@@ -21,8 +21,9 @@ import java.awt.TrayIcon;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.util.ResourceBundle;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
/**
* GUI is painted using SwingUtilities.invokeLater, but TrayIcon ActionListener Thread (== webstart thread) joined Jetty Thread
@@ -31,7 +32,7 @@ import org.apache.commons.logging.LogFactory;
*/
public class PINManagementInvoker implements Runnable {
- private static final Log log = LogFactory.getLog(PINManagementInvoker.class);
+ private static final Logger log = LoggerFactory.getLogger(PINManagementInvoker.class);
TrayIcon trayIcon;
ResourceBundle messages;
diff --git a/BKUWebStart/src/main/resources/log4j.properties b/BKUWebStart/src/main/resources/log4j.properties
index 76562ccf..81832418 100644
--- a/BKUWebStart/src/main/resources/log4j.properties
+++ b/BKUWebStart/src/main/resources/log4j.properties
@@ -13,23 +13,15 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-# loglever DEBUG, appender STDOUT
-log4j.rootLogger=DEBUG, file
-log4j.logger.org.mortbay.log=INFO
-log4j.logger.pki=INFO
-
-#log4j.additivity.pki=false
+# root log level INFO, appender file
+log4j.rootLogger=INFO, file
-# STDOUT appender
-log4j.appender.STDOUT=org.apache.log4j.ConsoleAppender
-log4j.appender.STDOUT.layout=org.apache.log4j.PatternLayout
-#log4j.appender.STDOUT.layout.ConversionPattern=%5p | %d{dd HH:mm:ss,SSS} | %20c | %10t | %m%n
-#log4j.appender.STDOUT.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n
-log4j.appender.STDOUT.layout.ConversionPattern=%-5p |%d | %t | %c %x- %m%n
+# jetty's log level
+log4j.logger.org.mortbay.log=INFO
-### FILE appender
+# file appender
log4j.appender.file=org.apache.log4j.DailyRollingFileAppender
log4j.appender.file.datePattern='.'yyyy-MM-dd
log4j.appender.file.File=${user.home}/.mocca/logs/webstart.log
log4j.appender.file.layout=org.apache.log4j.PatternLayout
-log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %-5p %c{1}:%L - %m%n \ No newline at end of file
+log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %-5p %c{2} - %m%n \ No newline at end of file
diff --git a/BKUWebStart/src/test/java/at/gv/egiz/bku/webstart/ConfiguratorTest.java b/BKUWebStart/src/test/java/at/gv/egiz/bku/webstart/ConfiguratorTest.java
index 0ea126cb..4f5798d5 100644
--- a/BKUWebStart/src/test/java/at/gv/egiz/bku/webstart/ConfiguratorTest.java
+++ b/BKUWebStart/src/test/java/at/gv/egiz/bku/webstart/ConfiguratorTest.java
@@ -8,8 +8,6 @@ package at.gv.egiz.bku.webstart;
import java.io.File;
import java.net.URI;
import java.util.zip.ZipOutputStream;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
diff --git a/BKUWebStartPackage/pom.xml b/BKUWebStartPackage/pom.xml
index 63725fc3..0b226785 100644
--- a/BKUWebStartPackage/pom.xml
+++ b/BKUWebStartPackage/pom.xml
@@ -1,3 +1,4 @@
+<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
@@ -22,7 +23,7 @@
<execution>
<phase>process-resources</phase>
<goals>
- <goal>jnlp-download-servlet</goal>
+ <goal>jnlp-single</goal>
</goals>
</execution>
</executions>
diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/binding/DataUrl.java b/bkucommon/src/main/java/at/gv/egiz/bku/binding/DataUrl.java
index 1db8c836..d3945253 100644
--- a/bkucommon/src/main/java/at/gv/egiz/bku/binding/DataUrl.java
+++ b/bkucommon/src/main/java/at/gv/egiz/bku/binding/DataUrl.java
@@ -16,7 +16,6 @@
*/
package at.gv.egiz.bku.binding;
-import at.gv.egiz.bku.conf.Configuration;
import at.gv.egiz.bku.conf.Configurator;
import java.net.MalformedURLException;
import java.net.URL;
@@ -89,13 +88,7 @@ public class DataUrl {
if (configuration != null) {
String className = configuration.getProperty(Configurator.DATAURLCONNECTION_CONFIG_P);
if (className != null) {
- try {
- log.info("set DataURLConnection class: " + className);
- Class c = Class.forName(className);
- connection = (DataUrlConnectionSPI) c.newInstance();
- } catch (Exception ex) {
- log.error("failed to instantiate DataURL connection " + className, ex);
- }
+ log.warn("Set DataURLConnection class not supported!");
}
}
}
diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/binding/DataUrlConnection.java b/bkucommon/src/main/java/at/gv/egiz/bku/binding/DataUrlConnection.java
index f954a017..384cf71c 100644
--- a/bkucommon/src/main/java/at/gv/egiz/bku/binding/DataUrlConnection.java
+++ b/bkucommon/src/main/java/at/gv/egiz/bku/binding/DataUrlConnection.java
@@ -62,7 +62,7 @@ public interface DataUrlConnection {
* @param transferEncoding may be null
*/
public void setHTTPFormParameter(String name, InputStream data, String contentType, String charSet, String transferEncoding);
-
+
/**
* @pre httpHeaders != null
* @throws java.net.SocketTimeoutException
diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/binding/DataUrlConnectionImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/binding/DataUrlConnectionImpl.java
index 4f2d2e00..b092ba41 100644
--- a/bkucommon/src/main/java/at/gv/egiz/bku/binding/DataUrlConnectionImpl.java
+++ b/bkucommon/src/main/java/at/gv/egiz/bku/binding/DataUrlConnectionImpl.java
@@ -18,10 +18,14 @@ package at.gv.egiz.bku.binding;
import java.io.IOException;
import java.io.InputStream;
+import java.io.InputStreamReader;
import java.io.OutputStream;
+import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.SocketTimeoutException;
import java.net.URL;
+import java.net.URLEncoder;
+import java.nio.charset.Charset;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.HashMap;
@@ -34,6 +38,7 @@ import java.util.Set;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLSocketFactory;
+import javax.xml.transform.stream.StreamResult;
import org.apache.commons.httpclient.methods.multipart.FilePart;
import org.apache.commons.httpclient.methods.multipart.Part;
@@ -47,32 +52,92 @@ import at.gv.egiz.bku.conf.Configurator;
import at.gv.egiz.bku.slcommands.SLResult;
import at.gv.egiz.bku.slcommands.SLResult.SLResultType;
import at.gv.egiz.bku.slexceptions.SLRuntimeException;
+import at.gv.egiz.bku.utils.URLEncodingWriter;
import at.gv.egiz.bku.utils.binding.Protocol;
/**
- * not thread-safe thus newInsance always returns a new object
+ * An implementation of the DataUrlConnectionSPI that supports
+ * <code>multipart/form-data</code> encoding and
+ * <code>application/x-www-form-urlencoded</code> for compatibility with legacy
+ * systems.
*
*/
public class DataUrlConnectionImpl implements DataUrlConnectionSPI {
private final static Log log = LogFactory.getLog(DataUrlConnectionImpl.class);
+
+ public static final byte[] B_DEFAULT_RESPONSETYPE = DEFAULT_RESPONSETYPE.getBytes(Charset.forName("UTF-8"));
+ /**
+ * Supported protocols are HTTP and HTTPS.
+ */
public final static Protocol[] SUPPORTED_PROTOCOLS = { Protocol.HTTP,
Protocol.HTTPS };
+ /**
+ * The X509 certificate of the DataURL server.
+ */
protected X509Certificate serverCertificate;
+
+ /**
+ * The protocol of the DataURL.
+ */
protected Protocol protocol;
+
+ /**
+ * Use <code>application/x-www-form-urlencoded</code> instead of
+ * standard conform <code>application/x-www-form-urlencoded</code>.
+ */
+ protected boolean urlEncoded = true;
+
+ /**
+ * The value of the DataURL.
+ */
protected URL url;
+
+ /**
+ * The URLConnection used for communication with the DataURL server.
+ */
private HttpURLConnection connection;
+
+ /**
+ * The HTTP request headers.
+ */
protected Map<String, String> requestHttpHeaders;
- protected ArrayList<Part> formParams;
+
+ /**
+ * The HTTP form parameters.
+ */
+ protected ArrayList<HTTPFormParameter> httpFormParameter;
+
+ /**
+ * The boundary for multipart/form-data requests.
+ */
protected String boundary;
+
+ /**
+ * The configuration properties.
+ */
protected Properties config = null;
+
+ /**
+ * The SSLSocketFactory for HTTPS connections.
+ */
protected SSLSocketFactory sslSocketFactory;
+
+ /**
+ * The HostnameVerifier for HTTPS connections.
+ */
protected HostnameVerifier hostnameVerifier;
+ /**
+ * The response of the DataURL server.
+ */
protected DataUrlResponse result;
+ /* (non-Javadoc)
+ * @see at.gv.egiz.bku.binding.DataUrlConnection#getProtocol()
+ */
public String getProtocol() {
if (protocol == null) {
return null;
@@ -80,13 +145,8 @@ public class DataUrlConnectionImpl implements DataUrlConnectionSPI {
return protocol.toString();
}
- /**
- * opens a connection sets the headers gets the server certificate
- *
- * @throws java.net.SocketTimeoutException
- * @throws java.io.IOException
- * @pre url != null
- * @pre httpHeaders != null
+ /* (non-Javadoc)
+ * @see at.gv.egiz.bku.binding.DataUrlConnection#connect()
*/
public void connect() throws SocketTimeoutException, IOException {
connection = (HttpURLConnection) url.openConnection();
@@ -104,9 +164,26 @@ public class DataUrlConnectionImpl implements DataUrlConnectionSPI {
https.setHostnameVerifier(hostnameVerifier);
}
} else {
- log.trace("No secure connection with: "+url+ " class="+connection.getClass());
+ log.trace("No secure connection with: " + url + " class="
+ + connection.getClass());
}
connection.setDoOutput(true);
+ // Transfer-Encoding: chunked is problematic ...
+ // e.g. https://issues.apache.org/bugzilla/show_bug.cgi?id=37794
+ // ... therefore disabled.
+ // connection.setChunkedStreamingMode(5*1024);
+ if (urlEncoded) {
+ log.debug("Setting DataURL Content-Type to "
+ + HttpUtil.APPLICATION_URL_ENCODED);
+ connection.addRequestProperty(HttpUtil.HTTP_HEADER_CONTENT_TYPE,
+ HttpUtil.APPLICATION_URL_ENCODED);
+ } else {
+ log.debug("Setting DataURL Content-Type to "
+ + HttpUtil.MULTIPART_FOTMDATA_BOUNDARY);
+ connection.addRequestProperty(HttpUtil.HTTP_HEADER_CONTENT_TYPE,
+ HttpUtil.MULTIPART_FOTMDATA + HttpUtil.SEPERATOR[0]
+ + HttpUtil.MULTIPART_FOTMDATA_BOUNDARY + "=" + boundary);
+ }
Set<String> headers = requestHttpHeaders.keySet();
Iterator<String> headerIt = headers.iterator();
while (headerIt.hasNext()) {
@@ -125,51 +202,128 @@ public class DataUrlConnectionImpl implements DataUrlConnectionSPI {
}
}
+ /* (non-Javadoc)
+ * @see at.gv.egiz.bku.binding.DataUrlConnection#getServerCertificate()
+ */
public X509Certificate getServerCertificate() {
return serverCertificate;
}
+ /* (non-Javadoc)
+ * @see at.gv.egiz.bku.binding.DataUrlConnection#setHTTPHeader(java.lang.String, java.lang.String)
+ */
public void setHTTPHeader(String name, String value) {
if (name != null && value != null) {
requestHttpHeaders.put(name, value);
}
}
+ /* (non-Javadoc)
+ * @see at.gv.egiz.bku.binding.DataUrlConnection#setHTTPFormParameter(java.lang.String, java.io.InputStream, java.lang.String, java.lang.String, java.lang.String)
+ */
public void setHTTPFormParameter(String name, InputStream data,
String contentType, String charSet, String transferEncoding) {
- InputStreamPartSource source = new InputStreamPartSource(null, data);
- FilePart formParam = new FilePart(name, source, contentType, charSet);
- if (transferEncoding != null) {
- formParam.setTransferEncoding(transferEncoding);
- } else {
- formParam.setTransferEncoding(null);
+ // if a content type is specified we have to switch to multipart/formdata encoding
+ if (contentType != null && contentType.length() > 0) {
+ urlEncoded = false;
}
- formParams.add(formParam);
+ httpFormParameter.add(new HTTPFormParameter(name, data, contentType,
+ charSet, transferEncoding));
}
- /**
- * send all formParameters
- *
- * @throws java.io.IOException
+
+
+ /* (non-Javadoc)
+ * @see at.gv.egiz.bku.binding.DataUrlConnection#transmit(at.gv.egiz.bku.slcommands.SLResult)
*/
public void transmit(SLResult slResult) throws IOException {
- SLResultPart slResultPart = new SLResultPart(slResult,
- XML_RESPONSE_ENCODING);
- if (slResult.getResultType() == SLResultType.XML) {
- slResultPart.setTransferEncoding(null);
- slResultPart.setContentType(slResult.getMimeType());
- slResultPart.setCharSet(XML_RESPONSE_ENCODING);
+ log.trace("Sending data");
+ if (urlEncoded) {
+ //
+ // application/x-www-form-urlencoded (legacy, SL < 1.2)
+ //
+
+ OutputStream os = connection.getOutputStream();
+ OutputStreamWriter streamWriter = new OutputStreamWriter(os, HttpUtil.DEFAULT_CHARSET);
+
+ // ResponseType
+ streamWriter.write(FORMPARAM_RESPONSETYPE);
+ streamWriter.write("=");
+ streamWriter.write(URLEncoder.encode(DEFAULT_RESPONSETYPE, "UTF-8"));
+ streamWriter.write("&");
+
+ // XMLResponse / Binary Response
+ if (slResult.getResultType() == SLResultType.XML) {
+ streamWriter.write(DataUrlConnection.FORMPARAM_XMLRESPONSE);
+ } else {
+ streamWriter.write(DataUrlConnection.FORMPARAM_BINARYRESPONSE);
+ }
+ streamWriter.write("=");
+ streamWriter.flush();
+ URLEncodingWriter urlEnc = new URLEncodingWriter(streamWriter);
+ slResult.writeTo(new StreamResult(urlEnc), false);
+ urlEnc.flush();
+
+ // transfer parameters
+ char[] cbuf = new char[512];
+ int len;
+ for (HTTPFormParameter formParameter : httpFormParameter) {
+ streamWriter.write("&");
+ streamWriter.write(URLEncoder.encode(formParameter.getName(), "UTF-8"));
+ streamWriter.write("=");
+ InputStreamReader reader = new InputStreamReader(formParameter.getData(),
+ (formParameter.getCharSet() != null)
+ ? formParameter.getCharSet()
+ : null);
+ while ((len = reader.read(cbuf)) != -1) {
+ urlEnc.write(cbuf, 0, len);
+ }
+ urlEnc.flush();
+ }
+ streamWriter.close();
+
} else {
- slResultPart.setTransferEncoding(null);
- slResultPart.setContentType(slResult.getMimeType());
- }
- formParams.add(slResultPart);
+ //
+ // multipart/form-data (conforming to SL 1.2)
+ //
- OutputStream os = connection.getOutputStream();
- log.trace("Sending data");
- Part[] parts = new Part[formParams.size()];
- Part.sendParts(os, formParams.toArray(parts), boundary.getBytes());
- os.close();
+ ArrayList<Part> parts = new ArrayList<Part>();
+
+ // ResponseType
+ StringPart responseType = new StringPart(FORMPARAM_RESPONSETYPE,
+ DEFAULT_RESPONSETYPE, "UTF-8");
+ responseType.setTransferEncoding(null);
+ parts.add(responseType);
+
+ // XMLResponse / Binary Response
+ SLResultPart slResultPart = new SLResultPart(slResult,
+ XML_RESPONSE_ENCODING);
+ if (slResult.getResultType() == SLResultType.XML) {
+ slResultPart.setTransferEncoding(null);
+ slResultPart.setContentType(slResult.getMimeType());
+ slResultPart.setCharSet(XML_RESPONSE_ENCODING);
+ } else {
+ slResultPart.setTransferEncoding(null);
+ slResultPart.setContentType(slResult.getMimeType());
+ }
+ parts.add(slResultPart);
+
+ // transfer parameters
+ for (HTTPFormParameter formParameter : httpFormParameter) {
+ InputStreamPartSource source = new InputStreamPartSource(null,
+ formParameter.getData());
+ FilePart part = new FilePart(formParameter.getName(), source,
+ formParameter.getContentType(), formParameter.getCharSet());
+ part.setTransferEncoding(formParameter.getTransferEncoding());
+ parts.add(part);
+ }
+
+ OutputStream os = connection.getOutputStream();
+ Part.sendParts(os, parts.toArray(new Part[parts.size()]), boundary.getBytes());
+ os.close();
+
+ }
+
// MultipartRequestEntity PostMethod
InputStream is = null;
try {
@@ -241,16 +395,9 @@ public class DataUrlConnectionImpl implements DataUrlConnectionSPI {
.put(HttpUtil.HTTP_HEADER_USER_AGENT, Configurator.USERAGENT_DEFAULT);
}
- requestHttpHeaders.put(HttpUtil.HTTP_HEADER_CONTENT_TYPE,
- HttpUtil.MULTIPART_FOTMDATA + HttpUtil.SEPERATOR[0]
- + HttpUtil.MULTIPART_FOTMDATA_BOUNDARY + "=" + boundary);
-
- formParams = new ArrayList<Part>();
- StringPart responseType = new StringPart(FORMPARAM_RESPONSETYPE,
- DEFAULT_RESPONSETYPE);
- responseType.setCharSet("UTF-8");
- responseType.setTransferEncoding(null);
- formParams.add(responseType);
+
+ httpFormParameter = new ArrayList<HTTPFormParameter>();
+
}
@Override
@@ -281,4 +428,107 @@ public class DataUrlConnectionImpl implements DataUrlConnectionSPI {
public void setHostnameVerifier(HostnameVerifier hostnameVerifier) {
this.hostnameVerifier = hostnameVerifier;
}
+
+ public class HTTPFormParameter {
+
+ private String name;
+
+ private InputStream data;
+
+ private String contentType;
+
+ private String charSet;
+
+ private String transferEncoding;
+
+ /**
+ * @param name
+ * @param data
+ * @param contentType
+ * @param charSet
+ * @param transferEncoding
+ */
+ public HTTPFormParameter(String name, InputStream data, String contentType,
+ String charSet, String transferEncoding) {
+ super();
+ this.name = name;
+ this.data = data;
+ this.contentType = contentType;
+ this.charSet = charSet;
+ this.transferEncoding = transferEncoding;
+ }
+
+ /**
+ * @return the name
+ */
+ public String getName() {
+ return name;
+ }
+
+ /**
+ * @param name the name to set
+ */
+ public void setName(String name) {
+ this.name = name;
+ }
+
+ /**
+ * @return the data
+ */
+ public InputStream getData() {
+ return data;
+ }
+
+ /**
+ * @param data the data to set
+ */
+ public void setData(InputStream data) {
+ this.data = data;
+ }
+
+ /**
+ * @return the contentType
+ */
+ public String getContentType() {
+ return contentType;
+ }
+
+ /**
+ * @param contentType the contentType to set
+ */
+ public void setContentType(String contentType) {
+ this.contentType = contentType;
+ }
+
+ /**
+ * @return the charSet
+ */
+ public String getCharSet() {
+ return charSet;
+ }
+
+ /**
+ * @param charSet the charSet to set
+ */
+ public void setCharSet(String charSet) {
+ this.charSet = charSet;
+ }
+
+ /**
+ * @return the transferEncoding
+ */
+ public String getTransferEncoding() {
+ return transferEncoding;
+ }
+
+ /**
+ * @param transferEncoding the transferEncoding to set
+ */
+ public void setTransferEncoding(String transferEncoding) {
+ this.transferEncoding = transferEncoding;
+ }
+
+
+
+ }
} \ No newline at end of file
diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java b/bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java
index ef603fc7..a1c4d5fc 100644
--- a/bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java
+++ b/bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java
@@ -22,6 +22,7 @@ import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.Reader;
+import java.io.Writer;
import java.net.URL;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
@@ -46,6 +47,7 @@ import javax.xml.transform.stream.StreamSource;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
+import at.gv.egiz.bku.slcommands.ErrorResult;
import at.gv.egiz.bku.slcommands.SLCommand;
import at.gv.egiz.bku.slcommands.SLCommandContext;
import at.gv.egiz.bku.slcommands.SLCommandFactory;
@@ -635,7 +637,6 @@ public class HTTPBindingProcessor extends AbstractBindingProcessor implements
throw new SLBindingException(2006);
}
InputDecoder id = InputDecoderFactory.getDecoder(cl, is);
- id.setContentType(cl);
if (id == null) {
log.error("Cannot get inputdecoder for is");
throw new SLException(2006);
@@ -730,9 +731,20 @@ public class HTTPBindingProcessor extends AbstractBindingProcessor implements
Templates templates) throws IOException {
log.debug("Writing error as result");
ErrorResultImpl error = new ErrorResultImpl(bindingProcessorError, locale);
- error.writeTo(new StreamResult(new OutputStreamWriter(os, encoding)), templates);
+ Writer writer = writeXMLDeclarationAndProcessingInstruction(os, encoding);
+ error.writeTo(new StreamResult(writer), templates, true);
}
+ protected Writer writeXMLDeclarationAndProcessingInstruction(OutputStream os, String encoding) throws IOException {
+ if (encoding == null) {
+ encoding = HttpUtil.DEFAULT_CHARSET;
+ }
+ OutputStreamWriter writer = new OutputStreamWriter(os, encoding);
+ writer.write("<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n");
+ writer.write("<?xml-stylesheet type=\"text/css\" href=\"errorresponse.css\"?>\n");
+ return writer;
+ }
+
@Override
public void writeResultTo(OutputStream os, String encoding)
throws IOException {
@@ -772,9 +784,16 @@ public class HTTPBindingProcessor extends AbstractBindingProcessor implements
return;
} else {
log.debug("Getting result from invoker");
- OutputStreamWriter osw = new OutputStreamWriter(os, encoding);
- slResult.writeTo(new StreamResult(osw), templates);
- osw.flush();
+ boolean fragment = false;
+ Writer writer;
+ if (slResult instanceof ErrorResult) {
+ writer = writeXMLDeclarationAndProcessingInstruction(os, encoding);
+ fragment = true;
+ } else {
+ writer = new OutputStreamWriter(os, encoding);
+ }
+ slResult.writeTo(new StreamResult(writer), templates, fragment);
+ writer.flush();
}
}
diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/binding/LegacyDataUrlConnectionImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/binding/LegacyDataUrlConnectionImpl.java
deleted file mode 100644
index cfccb7f1..00000000
--- a/bkucommon/src/main/java/at/gv/egiz/bku/binding/LegacyDataUrlConnectionImpl.java
+++ /dev/null
@@ -1,259 +0,0 @@
-package at.gv.egiz.bku.binding;
-
-
-import at.gv.egiz.bku.conf.Configurator;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-import java.io.StringWriter;
-import java.net.HttpURLConnection;
-import java.net.SocketTimeoutException;
-import java.net.URL;
-import java.net.URLEncoder;
-import java.security.cert.X509Certificate;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-import java.util.Properties;
-import java.util.Set;
-
-import javax.net.ssl.HostnameVerifier;
-import javax.net.ssl.HttpsURLConnection;
-import javax.net.ssl.SSLSocketFactory;
-import javax.xml.transform.stream.StreamResult;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-import at.gv.egiz.bku.slcommands.SLResult;
-import at.gv.egiz.bku.slcommands.SLResult.SLResultType;
-import at.gv.egiz.bku.slexceptions.SLRuntimeException;
-import at.gv.egiz.bku.utils.binding.Protocol;
-
-/**
- * not thread-safe thus newInsance always returns a new object
- *
- */
-public class LegacyDataUrlConnectionImpl implements DataUrlConnectionSPI {
-
- private final static Log log = LogFactory.getLog(LegacyDataUrlConnectionImpl.class);
-
- public final static Protocol[] SUPPORTED_PROTOCOLS = { Protocol.HTTP,
- Protocol.HTTPS };
- protected X509Certificate serverCertificate;
- protected Protocol protocol;
- protected URL url;
- private HttpURLConnection connection;
- protected Map<String, String> requestHttpHeaders;
- protected Map<String, String> formParams;
- protected String boundary;
- protected Properties config = null;
- protected SSLSocketFactory sslSocketFactory;
- protected HostnameVerifier hostnameVerifier;
-
- protected DataUrlResponse result;
-
- public String getProtocol() {
- if (protocol == null) {
- return null;
- }
- return protocol.toString();
- }
-
- /**
- * opens a connection sets the headers gets the server certificate
- *
- * @throws java.net.SocketTimeoutException
- * @throws java.io.IOException
- * @pre url != null
- * @pre httpHeaders != null
- */
- public void connect() throws SocketTimeoutException, IOException {
- connection = (HttpURLConnection) url.openConnection();
- if (connection instanceof HttpsURLConnection) {
- HttpsURLConnection https = (HttpsURLConnection) connection;
- if (sslSocketFactory != null) {
- log.debug("Setting custom ssl socket factory for ssl connection");
- https.setSSLSocketFactory(sslSocketFactory);
- }
- if (hostnameVerifier != null) {
- log.debug("Setting custom hostname verifier");
- https.setHostnameVerifier(hostnameVerifier);
- }
- }
- connection.setDoOutput(true);
- Set<String> headers = requestHttpHeaders.keySet();
- Iterator<String> headerIt = headers.iterator();
- while (headerIt.hasNext()) {
- String name = headerIt.next();
- connection.setRequestProperty(name, requestHttpHeaders.get(name));
- }
- log.trace("Connecting to: "+url);
- connection.connect();
- if (connection instanceof HttpsURLConnection) {
- HttpsURLConnection ssl = (HttpsURLConnection) connection;
- X509Certificate[] certs = (X509Certificate[]) ssl.getServerCertificates();
- if ((certs != null) && (certs.length >= 1)) {
- log.trace("Server certificate: "+certs[0]);
- serverCertificate = certs[0];
- }
- }
- }
-
- public X509Certificate getServerCertificate() {
- return serverCertificate;
- }
-
- public void setHTTPHeader(String name, String value) {
- if (name != null && value != null) {
- requestHttpHeaders.put(name, value);
- }
- }
-
- public void setHTTPFormParameter(String name, InputStream data,
- String contentType, String charSet, String transferEncoding) {
- StringBuilder sb = new StringBuilder();
- try {
- InputStreamReader reader = new InputStreamReader(data, (charSet != null) ? charSet : "UTF-8");
- char[] c = new char[512];
- for (int l; (l = reader.read(c)) != -1;) {
- sb.append(c, 0, l);
- }
- } catch (IOException e) {
- throw new SLRuntimeException("Failed to set HTTP form parameter.", e);
- }
- formParams.put(name, sb.toString());
- }
-
- /**
- * send all formParameters
- *
- * @throws java.io.IOException
- */
- public void transmit(SLResult slResult) throws IOException {
- StringWriter writer = new StringWriter();
- slResult.writeTo(new StreamResult(writer));
- formParams.put(
- (slResult.getResultType() == SLResultType.XML)
- ? DataUrlConnection.FORMPARAM_XMLRESPONSE
- : DataUrlConnection.FORMPARAM_BINARYRESPONSE,
- writer.toString());
-
- OutputStream os = connection.getOutputStream();
- OutputStreamWriter streamWriter = new OutputStreamWriter(os, HttpUtil.DEFAULT_CHARSET);
-
- log.trace("Sending data");
- Iterator<String> keys = formParams.keySet().iterator();
- while(keys.hasNext()) {
- String key = keys.next();
- streamWriter.write(URLEncoder.encode(key, "UTF-8"));
- streamWriter.write("=");
- streamWriter.write(URLEncoder.encode(formParams.get(key), "UTF-8"));
- if (keys.hasNext()) {
- streamWriter.write("&");
- }
- }
- streamWriter.flush();
- os.close();
-
- // MultipartRequestEntity PostMethod
- InputStream is = null;
- try {
- is = connection.getInputStream();
- } catch (IOException iox) {
- log.info(iox);
- }
- log.trace("Reading response");
- result = new DataUrlResponse(url.toString(), connection.getResponseCode(), is);
- Map<String, String> responseHttpHeaders = new HashMap<String, String>();
- Map<String, List<String>> httpHeaders = connection.getHeaderFields();
- for (Iterator<String> keyIt = httpHeaders.keySet().iterator(); keyIt
- .hasNext();) {
- String key = keyIt.next();
- StringBuffer value = new StringBuffer();
- for (String val : httpHeaders.get(key)) {
- value.append(val);
- value.append(HttpUtil.SEPERATOR[0]);
- }
- String valString = value.substring(0, value.length() - 1);
- if ((key != null) && (value.length() > 0)) {
- responseHttpHeaders.put(key, valString);
- }
- }
- result.setResponseHttpHeaders(responseHttpHeaders);
- }
-
- @Override
- public DataUrlResponse getResponse() throws IOException {
- return result;
- }
-
- /**
- * inits protocol, url, httpHeaders, formParams
- *
- * @param url
- * must not be null
- */
- @Override
- public void init(URL url) {
-
- for (int i = 0; i < SUPPORTED_PROTOCOLS.length; i++) {
- if (SUPPORTED_PROTOCOLS[i].toString().equalsIgnoreCase(url.getProtocol())) {
- protocol = SUPPORTED_PROTOCOLS[i];
- break;
- }
- }
- if (protocol == null) {
- throw new SLRuntimeException("Protocol " + url.getProtocol()
- + " not supported for data url");
- }
- this.url = url;
- requestHttpHeaders = new HashMap<String, String>();
- if ((config != null)
- && (config.getProperty(Configurator.USERAGENT_CONFIG_P) != null)) {
- log.debug("setting User-Agent header: " + config.getProperty(Configurator.USERAGENT_CONFIG_P));
- requestHttpHeaders.put(HttpUtil.HTTP_HEADER_USER_AGENT, config
- .getProperty(Configurator.USERAGENT_CONFIG_P));
- } else {
- requestHttpHeaders
- .put(HttpUtil.HTTP_HEADER_USER_AGENT, Configurator.USERAGENT_DEFAULT);
-
- }
- requestHttpHeaders.put(HttpUtil.HTTP_HEADER_CONTENT_TYPE,
- HttpUtil.APPLICATION_URL_ENCODED);
-
- formParams = new HashMap<String, String>();
- }
-
- @Override
- public DataUrlConnectionSPI newInstance() {
- DataUrlConnectionSPI uc = new LegacyDataUrlConnectionImpl();
- uc.setConfiguration(config);
- uc.setSSLSocketFactory(sslSocketFactory);
- uc.setHostnameVerifier(hostnameVerifier);
- return uc;
- }
-
- @Override
- public URL getUrl() {
- return url;
- }
-
- @Override
- public void setConfiguration(Properties config) {
- this.config = config;
- }
-
- @Override
- public void setSSLSocketFactory(SSLSocketFactory socketFactory) {
- this.sslSocketFactory = socketFactory;
- }
-
- @Override
- public void setHostnameVerifier(HostnameVerifier hostnameVerifier) {
- this.hostnameVerifier = hostnameVerifier;
- }
-} \ No newline at end of file
diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/binding/XWWWFormUrlInputDecoder.java b/bkucommon/src/main/java/at/gv/egiz/bku/binding/XWWWFormUrlInputDecoder.java
index f4ebe288..69c659e1 100644
--- a/bkucommon/src/main/java/at/gv/egiz/bku/binding/XWWWFormUrlInputDecoder.java
+++ b/bkucommon/src/main/java/at/gv/egiz/bku/binding/XWWWFormUrlInputDecoder.java
@@ -16,86 +16,43 @@
*/
package at.gv.egiz.bku.binding;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.net.URLDecoder;
-import java.util.Iterator;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.Map;
+import java.io.InputStream;
+import java.util.Iterator;
+import java.util.Map;
+
+import org.apache.commons.fileupload.ParameterParser;
-import org.apache.commons.fileupload.ParameterParser;
-
-import at.gv.egiz.bku.slexceptions.SLRuntimeException;
-import at.gv.egiz.bku.utils.StreamUtil;
-
-/**
- * Implementation based on Java's URLDecoder class
- *
- */
-// FIXME replace this code by a streaming variant
public class XWWWFormUrlInputDecoder implements InputDecoder {
-
- public final static String CHAR_SET = "charset";
- public final static String NAME_VAL_SEP = "=";
- public final static String SEP = "\\&";
-
- private String contentType;
- private InputStream dataStream;
- private String charset = "UTF-8";
-
- protected List<FormParameter> decodeInput(InputStream is) throws IOException {
- List<FormParameter> result = new LinkedList<FormParameter>();
- ByteArrayOutputStream bos = new ByteArrayOutputStream();
- StreamUtil.copyStream(is, bos);
- String inputString = new String(bos.toByteArray());
- String[] nameValuePairs = inputString.split(SEP);
- //inputString = URLDecoder.decode(inputString, charset);
- for (int i = 0; i < nameValuePairs.length; i++) {
- String[] fields = nameValuePairs[i].split(NAME_VAL_SEP, 2);
- if (fields.length != 2) {
- throw new SLRuntimeException("Invalid form encoding, missing value");
- }
- String name = URLDecoder.decode(fields[0], charset);
- String value =URLDecoder.decode(fields[1], charset);
- ByteArrayInputStream bais = new ByteArrayInputStream(value
- .getBytes(charset));
- FormParameterImpl fpi = new FormParameterImpl(contentType, name, bais, null);
- result.add(fpi);
- }
- return result;
- }
-
- @SuppressWarnings("unchecked")
+
+ /**
+ * The MIME type 'application/x-www-form-urlencoded'.
+ */
+ public static final String CONTENT_TYPE = "application/x-www-form-urlencoded";
+
+ /**
+ * The form parameter iterator.
+ */
+ protected XWWWFormUrlInputIterator iterator;
+
+ @SuppressWarnings("unchecked")
@Override
public void setContentType(String contentType) {
ParameterParser pp = new ParameterParser();
pp.setLowerCaseNames(true);
Map<String, String> params = pp.parse(contentType, new char[] { ':', ';' });
- if (!params.containsKey("application/x-www-form-urlencoded")) {
+ if (!params.containsKey(CONTENT_TYPE)) {
throw new IllegalArgumentException(
"not a url encoded content type specification: " + contentType);
}
- String cs = params.get(CHAR_SET);
- if (cs != null) {
- charset = cs;
- }
- this.contentType = contentType;
}
@Override
public Iterator<FormParameter> getFormParameterIterator() {
- try {
- return decodeInput(dataStream).iterator();
- } catch (IOException e) {
- throw new SLRuntimeException(e);
- }
+ return iterator;
}
@Override
public void setInputStream(InputStream is) {
- dataStream = is;
+ iterator = new XWWWFormUrlInputIterator(is);
}
}
diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/binding/XWWWFormUrlInputIterator.java b/bkucommon/src/main/java/at/gv/egiz/bku/binding/XWWWFormUrlInputIterator.java
new file mode 100644
index 00000000..f052ce05
--- /dev/null
+++ b/bkucommon/src/main/java/at/gv/egiz/bku/binding/XWWWFormUrlInputIterator.java
@@ -0,0 +1,376 @@
+package at.gv.egiz.bku.binding;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.FilterInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.nio.charset.Charset;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+
+public class XWWWFormUrlInputIterator implements Iterator<FormParameter> {
+
+ public static final byte NAME_VALUE_SEP = '=';
+
+ public static final byte PARAM_SEP = '&';
+
+ public static final Charset UTF_8 = Charset.forName("UTF-8");
+
+ /**
+ * The default buffer size.
+ */
+ protected static final int DEFAULT_BUFFER_SIZE = 4096;
+
+ /**
+ * Are we done with parsing the input.
+ */
+ protected boolean done = false;
+
+ /**
+ * The x-www-formdata-urlencoded input stream to be parsed.
+ */
+ protected final InputStream in;
+
+ /**
+ * The buffer size.
+ */
+ protected int bufferSize = DEFAULT_BUFFER_SIZE;
+
+ /**
+ * The read buffer.
+ */
+ protected final byte[] buf = new byte[bufferSize];
+
+ /**
+ * The read position.
+ */
+ protected int pos;
+
+ /**
+ * The number of valid bytes in the buffer;
+ */
+ protected int count;
+
+ /**
+ * The parameter returned by the last call of {@link #next()};
+ */
+ protected XWWWFormUrlEncodedParameter currentParameter;
+
+ /**
+ * An IOException that cannot be reported immediately.
+ */
+ protected IOException deferredIOException;
+
+ /**
+ * Creates a new instance of this x-www-formdata-urlencoded input iterator
+ * with the given InputStream <code>in</code> to be parsed.
+ *
+ * @param in the InputStream to be parsed
+ */
+ public XWWWFormUrlInputIterator(InputStream in) {
+ this.in = in;
+ }
+
+ /* (non-Javadoc)
+ * @see java.util.Iterator#hasNext()
+ */
+ @Override
+ public boolean hasNext() {
+ if (done) {
+ return false;
+ }
+ if (currentParameter != null) {
+ // we have to disconnect the current parameter
+ // to look for further parameters
+ try {
+ currentParameter.formParameterValue.disconnect();
+ // fill buffer if empty
+ if (pos >= count) {
+ if ((count = in.read(buf)) == -1) {
+ // done
+ done = true;
+ return false;
+ }
+ pos = 0;
+ }
+ } catch (IOException e) {
+ deferredIOException = e;
+ }
+ }
+ return true;
+ }
+
+ @Override
+ public FormParameter next() {
+ if (hasNext()) {
+ // skip separator
+ pos++;
+ currentParameter = new XWWWFormUrlEncodedParameter();
+ return currentParameter;
+ } else {
+ throw new NoSuchElementException();
+ }
+ }
+
+ @Override
+ public void remove() {
+ throw new UnsupportedOperationException();
+ }
+
+ public class XWWWFormUrlEncodedParameter implements FormParameter {
+
+ /**
+ * The list of header names.
+ */
+ // x-www-form-urlencoded parameters do not provide headers
+ protected final List<String> headers = Collections.emptyList();
+
+ /**
+ * The name of the form parameter.
+ */
+ protected String formParameterName;
+
+ /**
+ * The value of the form parameter.
+ */
+ protected URLDecodingInputStream formParameterValue;
+
+ public XWWWFormUrlEncodedParameter() {
+ // parse parameter name
+ URLDecodingInputStream urldec = new URLDecodingInputStream(in, NAME_VALUE_SEP);
+ InputStreamReader reader = new InputStreamReader(urldec, UTF_8);
+ try {
+ StringBuilder sb = new StringBuilder();
+ char[] b = new char[128];
+ for (int l = 0; (l = reader.read(b)) != -1;) {
+ sb.append(b, 0, l);
+ }
+ formParameterName = sb.toString();
+ // fill buffer if empty
+ if (pos >= count) {
+ if ((count = in.read(buf)) == -1) {
+ throw new IOException("Invalid URL encoding.");
+ }
+ pos = 0;
+ }
+ // skip separator
+ pos++;
+ } catch (IOException e) {
+ deferredIOException = e;
+ formParameterName = "";
+ }
+ formParameterValue = new URLDecodingInputStream(in, PARAM_SEP);
+ }
+
+ @Override
+ public String getFormParameterContentType() {
+ // x-www-form-urlencoded parameters do not specify a content type
+ return null;
+ }
+
+ @Override
+ public String getFormParameterName() {
+ return formParameterName;
+ }
+
+ @Override
+ public InputStream getFormParameterValue() {
+ if (deferredIOException != null) {
+ final IOException e = deferredIOException;
+ deferredIOException = null;
+ return new InputStream() {
+ @Override
+ public int read() throws IOException {
+ throw e;
+ }
+ };
+ } else {
+ return formParameterValue;
+ }
+ }
+
+ @Override
+ public Iterator<String> getHeaderNames() {
+ return headers.iterator();
+ }
+
+ @Override
+ public String getHeaderValue(String headerName) {
+ return null;
+ }
+
+ }
+
+ public class URLDecodingInputStream extends FilterInputStream {
+
+ /**
+ * Has this stream already been closed.
+ */
+ private boolean closed = false;
+
+ /**
+ * Has this stream been disconnected.
+ */
+ private boolean disconnected = false;
+
+ /**
+ * Read until this byte occurs.
+ */
+ protected final byte term;
+
+ /**
+ * Creates a new instance of this URLDecodingInputStream.
+ *
+ * @param in
+ * @param separator
+ */
+ protected URLDecodingInputStream(InputStream in, byte separator) {
+ super(in);
+ this.term = separator;
+ }
+
+ /* (non-Javadoc)
+ * @see java.io.FilterInputStream#read()
+ */
+ @Override
+ public int read() throws IOException {
+ if (closed) {
+ throw new IOException("The stream has already been closed.");
+ }
+ if (disconnected) {
+ return in.read();
+ }
+
+ if (pos >= count) {
+ if ((count = in.read(buf)) == -1) {
+ return -1;
+ }
+ pos = 0;
+ } if (buf[pos] == term) {
+ return -1;
+ } else if (buf[pos] == '+') {
+ pos++;
+ return ' ';
+ } else if (buf[pos] == '%') {
+ if (++pos == count) {
+ if ((count = in.read(buf)) == -1) {
+ throw new IOException("Invalid URL encoding.");
+ }
+ pos = 0;
+ }
+ int c1 = Character.digit(buf[pos], 16);
+ if (++pos == count) {
+ if ((count = in.read(buf)) == -1) {
+ throw new IOException("Invalid URL encoding.");
+ }
+ pos = 0;
+ }
+ int c2 = Character.digit(buf[pos], 16);
+ return ((c1 << 4) | c2);
+ } else {
+ return buf[pos++];
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see java.io.FilterInputStream#read(byte[], int, int)
+ */
+ @Override
+ public int read(byte[] b, int off, int len) throws IOException {
+ if (closed) {
+ throw new IOException("The stream has already been closed.");
+ }
+ if (disconnected) {
+ return in.read(b, off, len);
+ }
+
+ if ((off | len | (off + len) | (b.length - (off + len))) < 0) {
+ throw new IndexOutOfBoundsException();
+ } else if (len == 0) {
+ return 0;
+ }
+
+ if (pos >= count) {
+ if ((count = in.read(buf)) == -1) {
+ return -1;
+ }
+ pos = 0;
+ }
+ if (buf[pos] == term) {
+ return -1;
+ }
+
+ int l = 0;
+ for (;;) {
+ while (pos < count) {
+ if (l == len || buf[pos] == term) {
+ return l;
+ } else if (buf[pos] == '+') {
+ b[off] = ' ';
+ } else if (buf[pos] == '%') {
+ if (++pos == count && (count = in.read(buf)) == -1) {
+ throw new IOException("Invalid URL encoding.");
+ }
+ int c1 = Character.digit(buf[pos], 16);
+ if (++pos == count && (count = in.read(buf)) == -1) {
+ throw new IOException("Invalid URL encoding.");
+ }
+ int c2 = Character.digit(buf[pos], 16);
+ b[off] = (byte) ((c1 << 4) | c2);
+ } else {
+ b[off] = buf[pos];
+ }
+ pos++;
+ off++;
+ l++;
+ }
+ if ((count = in.read(buf)) == -1) {
+ return l;
+ }
+ pos = 0;
+ }
+ }
+
+ /**
+ * Disconnect from the InputStream and buffer all remaining data.
+ *
+ * @throws IOException
+ */
+ public void disconnect() throws IOException {
+ if (!disconnected) {
+ // don't waste space for a buffer if end of stream has already been
+ // reached
+ byte[] b = new byte[1];
+ if ((read(b)) != -1) {
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ os.write(b);
+ b = new byte[1024];
+ for (int l; (l = read(b, 0, b.length)) != -1;) {
+ os.write(b, 0, l);
+ }
+ super.in = new ByteArrayInputStream(os.toByteArray());
+ }
+ disconnected = true;
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see java.io.FilterInputStream#close()
+ */
+ @Override
+ public void close() throws IOException {
+ if (!hasNext()) {
+ // don't close the underlying stream until all parts are read
+ super.close();
+ }
+ disconnect();
+ closed = true;
+ }
+
+ }
+
+}
diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/binding/multipart/SLResultPart.java b/bkucommon/src/main/java/at/gv/egiz/bku/binding/multipart/SLResultPart.java
index 5585f02e..d896ea9f 100644
--- a/bkucommon/src/main/java/at/gv/egiz/bku/binding/multipart/SLResultPart.java
+++ b/bkucommon/src/main/java/at/gv/egiz/bku/binding/multipart/SLResultPart.java
@@ -16,37 +16,56 @@
*/
package at.gv.egiz.bku.binding.multipart;
+import at.gv.egiz.bku.binding.DataUrlConnection;
import at.gv.egiz.bku.slcommands.SLResult;
+import at.gv.egiz.bku.slcommands.SLResult.SLResultType;
+
import java.io.IOException;
+import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import javax.xml.transform.stream.StreamResult;
-import org.apache.commons.httpclient.methods.multipart.ByteArrayPartSource;
import org.apache.commons.httpclient.methods.multipart.FilePart;
+import org.apache.commons.httpclient.methods.multipart.PartSource;
-/**
- *
- * @author clemens
- */
public class SLResultPart extends FilePart {
protected SLResult slResult;
protected String encoding;
public SLResultPart(SLResult slResult, String encoding) {
- super("XMLResponse",
- new ByteArrayPartSource(null, "dummySource".getBytes()));
+ super((slResult.getResultType() == SLResultType.XML)
+ ? DataUrlConnection.FORMPARAM_XMLRESPONSE
+ : DataUrlConnection.FORMPARAM_BINARYRESPONSE,
+ new PartSource() {
+
+ @Override
+ public long getLength() {
+ // may return null, as sendData() is overridden
+ return 0;
+ }
+
+ @Override
+ public String getFileName() {
+ // return null, to prevent content-disposition header
+ return null;
+ }
+
+ @Override
+ public InputStream createInputStream() throws IOException {
+ // may return null, as sendData() is overridden below
+ return null;
+ }
+ }
+ );
this.slResult = slResult;
this.encoding = encoding;
}
@Override
protected void sendData(OutputStream out) throws IOException {
- slResult.writeTo(new StreamResult(new OutputStreamWriter(out, encoding)));
- // slResult.writeTo(new StreamResult(new OutputStreamWriter(System.out,
- // encoding)));
- // super.sendData(out);
+ slResult.writeTo(new StreamResult(new OutputStreamWriter(out, encoding)), false);
}
}
diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/conf/CertValidatorImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/conf/CertValidatorImpl.java
index 125233c1..3b2d1b99 100644
--- a/bkucommon/src/main/java/at/gv/egiz/bku/conf/CertValidatorImpl.java
+++ b/bkucommon/src/main/java/at/gv/egiz/bku/conf/CertValidatorImpl.java
@@ -1,7 +1,9 @@
package at.gv.egiz.bku.conf;
+import iaik.logging.LogConfigurationException;
import iaik.logging.TransactionId;
import iaik.logging.impl.TransactionIdImpl;
+import iaik.logging.LoggerConfig;
import iaik.pki.DefaultPKIConfiguration;
import iaik.pki.DefaultPKIProfile;
import iaik.pki.PKIConfiguration;
@@ -18,6 +20,7 @@ import iaik.x509.X509Certificate;
import java.io.File;
import java.util.Date;
+import java.util.Properties;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -37,6 +40,27 @@ public class CertValidatorImpl implements CertValidator {
* @see at.gv.egiz.bku.conf.CertValidator#init(java.io.File, java.io.File)
*/
public void init(File certDir, File caDir) {
+ // initialize IAIK logging for PKI module
+ log.debug("Configuring logging for IAIK PKI module");
+ iaik.logging.LogFactory.configure(new LoggerConfig() {
+
+ @Override
+ public Properties getProperties() throws LogConfigurationException {
+ return null;
+ }
+
+ @Override
+ public String getNodeId() {
+ return "pki";
+ }
+
+ @Override
+ public String getFactory() {
+ return IAIKCommonsLogFactory.class.getName();
+ }
+ });
+
+
// the parameters specifying the directory certstore
CertStoreParameters[] certStoreParameters = { new DefaultDirectoryCertStoreParameters(
"CS-001", certDir.getAbsolutePath(), true, false) };
diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/conf/IAIKCommonsLog.java b/bkucommon/src/main/java/at/gv/egiz/bku/conf/IAIKCommonsLog.java
new file mode 100644
index 00000000..1b7dd189
--- /dev/null
+++ b/bkucommon/src/main/java/at/gv/egiz/bku/conf/IAIKCommonsLog.java
@@ -0,0 +1,144 @@
+/**
+ *
+ */
+package at.gv.egiz.bku.conf;
+
+import iaik.logging.Log;
+import iaik.logging.TransactionId;
+
+/**
+ * @author mcentner
+ *
+ */
+public class IAIKCommonsLog implements Log {
+
+ /**
+ * The id that will be written to the log if the transactionid == null
+ */
+ public final static String NO_ID = "Null-ID";
+
+ protected org.apache.commons.logging.Log commonsLog;
+
+ protected String nodeId;
+
+ public IAIKCommonsLog(org.apache.commons.logging.Log log) {
+ this.commonsLog = log;
+ }
+
+ /* (non-Javadoc)
+ * @see iaik.logging.Log#debug(iaik.logging.TransactionId, java.lang.Object, java.lang.Throwable)
+ */
+ @Override
+ public void debug(TransactionId transactionId, Object message, Throwable t) {
+ if (commonsLog.isDebugEnabled()) {
+ commonsLog.debug(nodeId + ": "
+ + ((transactionId != null) ? transactionId.getLogID() : NO_ID) + ": "
+ + message, t);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see iaik.logging.Log#info(iaik.logging.TransactionId, java.lang.Object, java.lang.Throwable)
+ */
+ @Override
+ public void info(TransactionId transactionId, Object message, Throwable t) {
+ if (commonsLog.isInfoEnabled()) {
+ commonsLog.info(nodeId + ": "
+ + ((transactionId != null) ? transactionId.getLogID() : NO_ID) + ": "
+ + message, t);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see iaik.logging.Log#warn(iaik.logging.TransactionId, java.lang.Object, java.lang.Throwable)
+ */
+ @Override
+ public void warn(TransactionId transactionId, Object message, Throwable t) {
+ if (commonsLog.isWarnEnabled()) {
+ commonsLog.warn(nodeId + ": "
+ + ((transactionId != null) ? transactionId.getLogID() : NO_ID) + ": "
+ + message, t);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see iaik.logging.Log#error(iaik.logging.TransactionId, java.lang.Object, java.lang.Throwable)
+ */
+ @Override
+ public void error(TransactionId transactionId, Object message, Throwable t) {
+ if (commonsLog.isErrorEnabled()) {
+ commonsLog.error(nodeId + ": "
+ + ((transactionId != null) ? transactionId.getLogID() : NO_ID) + ": "
+ + message, t);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see iaik.logging.Log#fatal(iaik.logging.TransactionId, java.lang.Object, java.lang.Throwable)
+ */
+ @Override
+ public void fatal(TransactionId transactionId, Object message, Throwable t) {
+ if (commonsLog.isFatalEnabled()) {
+ commonsLog.fatal(nodeId + ": "
+ + ((transactionId != null) ? transactionId.getLogID() : NO_ID) + ": "
+ + message, t);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see iaik.logging.Log#setNodeId(java.lang.String)
+ */
+ @Override
+ public void setNodeId(String nodeId) {
+ this.nodeId = nodeId;
+ }
+
+ /* (non-Javadoc)
+ * @see iaik.logging.Log#getNodeId()
+ */
+ @Override
+ public String getNodeId() {
+ return nodeId;
+ }
+
+ /* (non-Javadoc)
+ * @see iaik.logging.Log#isDebugEnabled()
+ */
+ @Override
+ public boolean isDebugEnabled() {
+ return commonsLog.isDebugEnabled();
+ }
+
+ /* (non-Javadoc)
+ * @see iaik.logging.Log#isInfoEnabled()
+ */
+ @Override
+ public boolean isInfoEnabled() {
+ return commonsLog.isInfoEnabled();
+ }
+
+ /* (non-Javadoc)
+ * @see iaik.logging.Log#isWarnEnabled()
+ */
+ @Override
+ public boolean isWarnEnabled() {
+ return commonsLog.isWarnEnabled();
+ }
+
+ /* (non-Javadoc)
+ * @see iaik.logging.Log#isErrorEnabled()
+ */
+ @Override
+ public boolean isErrorEnabled() {
+ return commonsLog.isErrorEnabled();
+ }
+
+ /* (non-Javadoc)
+ * @see iaik.logging.Log#isFatalEnabled()
+ */
+ @Override
+ public boolean isFatalEnabled() {
+ return commonsLog.isFatalEnabled();
+ }
+
+}
diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/conf/IAIKCommonsLogFactory.java b/bkucommon/src/main/java/at/gv/egiz/bku/conf/IAIKCommonsLogFactory.java
new file mode 100644
index 00000000..14e2c757
--- /dev/null
+++ b/bkucommon/src/main/java/at/gv/egiz/bku/conf/IAIKCommonsLogFactory.java
@@ -0,0 +1,59 @@
+/**
+ *
+ */
+package at.gv.egiz.bku.conf;
+
+import org.apache.commons.logging.impl.WeakHashtable;
+
+import iaik.logging.Log;
+import iaik.logging.LogConfigurationException;
+import iaik.logging.LogFactory;
+
+/**
+ * @author mcentner
+ *
+ */
+public class IAIKCommonsLogFactory extends LogFactory {
+
+ protected WeakHashtable instances = new WeakHashtable();
+
+ /* (non-Javadoc)
+ * @see iaik.logging.LogFactory#getInstance(java.lang.String)
+ */
+ @Override
+ public Log getInstance(String name) throws LogConfigurationException {
+ org.apache.commons.logging.Log commonsLog = org.apache.commons.logging.LogFactory.getLog(name);
+ Log log = (Log) instances.get(commonsLog);
+ if (log == null) {
+ log = new IAIKCommonsLog(commonsLog);
+ log.setNodeId(node_id_);
+ instances.put(commonsLog, log);
+ }
+ return log;
+ }
+
+ /* (non-Javadoc)
+ * @see iaik.logging.LogFactory#getInstance(java.lang.Class)
+ */
+ @SuppressWarnings("unchecked")
+ @Override
+ public Log getInstance(Class clazz) throws LogConfigurationException {
+ org.apache.commons.logging.Log commonsLog = org.apache.commons.logging.LogFactory.getLog(clazz);
+ Log log = (Log) instances.get(commonsLog);
+ if (log == null) {
+ log = new IAIKCommonsLog(commonsLog);
+ log.setNodeId(node_id_);
+ instances.put(commonsLog, log);
+ }
+ return log;
+ }
+
+ /* (non-Javadoc)
+ * @see iaik.logging.LogFactory#release()
+ */
+ @Override
+ public void release() {
+ instances.clear();
+ }
+
+}
diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/SLCommandFactory.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/SLCommandFactory.java
index fe27bc54..8e3f6ece 100644
--- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/SLCommandFactory.java
+++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/SLCommandFactory.java
@@ -28,6 +28,7 @@ import javax.xml.bind.JAXBException;
import javax.xml.bind.UnmarshalException;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.ValidationEvent;
+import javax.xml.bind.ValidationEventLocator;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLEventReader;
import javax.xml.stream.XMLInputFactory;
@@ -46,11 +47,11 @@ import at.gv.egiz.bku.slexceptions.SLCommandException;
import at.gv.egiz.bku.slexceptions.SLExceptionMessages;
import at.gv.egiz.bku.slexceptions.SLRequestException;
import at.gv.egiz.bku.slexceptions.SLRuntimeException;
+import at.gv.egiz.bku.slexceptions.SLVersionException;
import at.gv.egiz.bku.utils.DebugReader;
import at.gv.egiz.slbinding.RedirectEventFilter;
import at.gv.egiz.slbinding.RedirectUnmarshallerListener;
-import at.gv.egiz.validation.ValidationEventLogger;
-import javax.xml.bind.ValidationEventHandler;
+import at.gv.egiz.validation.ReportingValidationEventHandler;
public class SLCommandFactory {
@@ -60,7 +61,9 @@ public class SLCommandFactory {
public static final String[] SCHEMA_FILES = new String[]{
"at/gv/egiz/bku/slcommands/schema/xml.xsd",
"at/gv/egiz/bku/slcommands/schema/xmldsig-core-schema.xsd",
- "at/gv/egiz/bku/slcommands/schema/Core-1.2.xsd"
+ "at/gv/egiz/bku/slcommands/schema/Core-1.2.xsd",
+ "at/gv/egiz/bku/slcommands/schema/Core.20020225.xsd",
+ "at/gv/egiz/bku/slcommands/schema/Core.20020831.xsd"
};
/**
* Logging facility.
@@ -169,7 +172,10 @@ public class SLCommandFactory {
String slPkg = at.buergerkarte.namespaces.securitylayer._1.ObjectFactory.class.getPackage().getName();
String xmldsigPkg = org.w3._2000._09.xmldsig_.ObjectFactory.class.getPackage().getName();
String cardChannelPkg = at.buergerkarte.namespaces.cardchannel.ObjectFactory.class.getPackage().getName();
- setJaxbContext(JAXBContext.newInstance(slPkg + ":" + xmldsigPkg + ":" + cardChannelPkg));
+ String slPkgLegacy1_0 = at.buergerkarte.namespaces.securitylayer._20020225_.ObjectFactory.class.getPackage().getName();
+ String slPkgLegacy1_1 = at.buergerkarte.namespaces.securitylayer._20020831_.ObjectFactory.class.getPackage().getName();
+ setJaxbContext(JAXBContext.newInstance(slPkg + ":" + xmldsigPkg + ":" + cardChannelPkg
+ + ":" + slPkgLegacy1_0 + ":" + slPkgLegacy1_1));
} catch (JAXBException e) {
log.error("Failed to setup JAXBContext security layer request.", e);
throw new SLRuntimeException(e);
@@ -248,26 +254,9 @@ public class SLCommandFactory {
SLRequestException {
Object object;
+ ReportingValidationEventHandler validationEventHandler = new ReportingValidationEventHandler();
try {
-// ValidatorHandler validator = slSchema.newValidatorHandler();
-// validator.getContentHandler();
-//
-// SAXParserFactory spf = SAXParserFactory.newInstance();
-// spf.setNamespaceAware(true);
-// XMLReader saxReader = spf.newSAXParser().getXMLReader();
-// //TODO extend validator to implement redirectContentHandler (validate+redirect)
-// saxReader.setContentHandler(validator);
-// //TODO get a InputSource
-// SAXSource saxSource = new SAXSource(saxReader, source);
-//
-// Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
-// //turn off duplicate jaxb validation
-// unmarshaller.setSchema(null);
-// unmarshaller.setListener(listener);
-// unmarshaller.unmarshal(saxSource);
-
-
XMLInputFactory inputFactory = XMLInputFactory.newInstance();
XMLEventReader eventReader = inputFactory.createXMLEventReader(source);
RedirectEventFilter redirectEventFilter = new RedirectEventFilter();
@@ -279,7 +268,7 @@ public class SLCommandFactory {
unmarshaller.setSchema(slSchema);
}
log.trace("Before unmarshal().");
- unmarshaller.setEventHandler(new ValidationEventLogger());
+ unmarshaller.setEventHandler(validationEventHandler);
object = unmarshaller.unmarshal(filteredReader);
log.trace("After unmarshal().");
} catch (UnmarshalException e) {
@@ -288,6 +277,13 @@ public class SLCommandFactory {
} else {
log.info("Failed to unmarshall security layer request." + e.getMessage());
}
+ if (validationEventHandler.getErrorEvent() != null) {
+ // Validation Error
+ ValidationEvent errorEvent = validationEventHandler.getErrorEvent();
+ ValidationEventLocator locator = errorEvent.getLocator();
+ throw new SLRequestException(3002,
+ SLExceptionMessages.EC3002_INVALID, new Object[]{errorEvent.getMessage()});
+ }
Throwable cause = e.getCause();
if (cause instanceof SAXParseException) {
throw new SLRequestException(3000,
@@ -328,10 +324,11 @@ public class SLCommandFactory {
* if an unexpected error occurs configuring the unmarshaller, if
* unmarshalling fails with an unexpected error or if the
* corresponding <code>SLCommand</code> could not be instantiated
+ * @throws SLVersionException
*/
@SuppressWarnings("unchecked")
public SLCommand createSLCommand(Source source, SLCommandContext context)
- throws SLCommandException, SLRuntimeException, SLRequestException {
+ throws SLCommandException, SLRuntimeException, SLRequestException, SLVersionException {
DebugReader dr = null;
if (log.isTraceEnabled() && source instanceof StreamSource) {
@@ -361,6 +358,12 @@ public class SLCommandFactory {
}
QName qName = ((JAXBElement) object).getName();
+ if (!SLCommand.NAMESPACE_URI.equals(qName.getNamespaceURI())) {
+ // security layer request version not supported
+ log.info("Unsupported security layer request version : " + qName.getNamespaceURI());
+ throw new SLVersionException(qName.getNamespaceURI());
+ }
+
Class<? extends SLCommand> implClass = getImplClass(qName);
if (implClass == null) {
// command not supported
diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/SLMarshallerFactory.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/SLMarshallerFactory.java
new file mode 100644
index 00000000..e0a375cf
--- /dev/null
+++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/SLMarshallerFactory.java
@@ -0,0 +1,172 @@
+/*
+* Copyright 2009 Federal Chancellery Austria and
+* Graz University of Technology
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package at.gv.egiz.bku.slcommands;
+
+import javax.xml.bind.JAXBContext;
+import javax.xml.bind.JAXBException;
+import javax.xml.bind.Marshaller;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import at.gv.egiz.bku.slexceptions.SLRuntimeException;
+import at.gv.egiz.marshal.MarshallerFactory;
+
+public class SLMarshallerFactory {
+
+ static Log log = LogFactory.getLog(SLMarshallerFactory.class);
+
+ /**
+ * The JAXBContext used for result marshaling.
+ * <p>
+ * Note: Different contexts are used for marshaling and unmarshaling of
+ * security layer requests and responses to avoid propagation of namespace
+ * declarations of legacy namespaces into marshaled results.
+ * </p>
+ * @see #jaxbContextLegacy
+ */
+ protected static JAXBContext context;
+
+ /**
+ * The JAXBContext used for marshaling of of results in the legacy namespace.
+ */
+ protected static JAXBContext legacyContext;
+
+ // ------------------- initialization on demand idiom -------------------
+ // see http://en.wikipedia.org/wiki/Initialization_on_demand_holder_idiom
+ // ----------------------------------------------------------------------
+
+ /**
+ * Private constructor called by {@link SLMarshallerFactoryInstanceHolder}.
+ */
+ private SLMarshallerFactory() {
+ // context is initialized immediately while the legacy context is initialized only on demand
+ try {
+ String slPkg = at.buergerkarte.namespaces.securitylayer._1.ObjectFactory.class.getPackage().getName();
+ String xmldsigPkg = org.w3._2000._09.xmldsig_.ObjectFactory.class.getPackage().getName();
+ String cardChannelPkg = at.buergerkarte.namespaces.cardchannel.ObjectFactory.class.getPackage().getName();
+ context = JAXBContext.newInstance(slPkg + ":" + xmldsigPkg + ":" + cardChannelPkg);
+ } catch (JAXBException e) {
+ log.error("Failed to setup JAXBContext security layer request.", e);
+ throw new SLRuntimeException(e);
+ }
+ }
+
+ /**
+ * The lazy instance holder for this SLMarshallerFactory.
+ */
+ private static class SLMarshallerFactoryInstanceHolder {
+ /**
+ * The instance returned by {@link SLMarshallerFactory#getInstance()}
+ */
+ private static final SLMarshallerFactory instance = new SLMarshallerFactory();
+ }
+
+ /**
+ * Get an instance of the <code>SLMarshallerFactory</code>.
+ */
+ public static SLMarshallerFactory getInstance() {
+ return SLMarshallerFactoryInstanceHolder.instance;
+ }
+
+ // ----------------------------------------------------------------------
+
+ /**
+ * Initialize the JAXBContext for the legacy namespace.
+ */
+ private static synchronized void ensureLegacyContext() {
+ // legacy marshaller is initialized only on demand
+ if (legacyContext == null) {
+ try {
+ String slPkgLegacy1_0 = at.buergerkarte.namespaces.securitylayer._20020225_.ObjectFactory.class.getPackage().getName();
+ String slPkgLegacy1_1 = at.buergerkarte.namespaces.securitylayer._20020831_.ObjectFactory.class.getPackage().getName();
+ String xmldsigPkg = org.w3._2000._09.xmldsig_.ObjectFactory.class.getPackage().getName();
+ String cardChannelPkg = at.buergerkarte.namespaces.cardchannel.ObjectFactory.class.getPackage().getName();
+ legacyContext = JAXBContext.newInstance(slPkgLegacy1_0 + ":" + slPkgLegacy1_1 + ":" + xmldsigPkg + ":" + cardChannelPkg);
+ } catch (JAXBException e) {
+ log.error("Failed to setup JAXBContext security layer request.", e);
+ throw new SLRuntimeException(e);
+ }
+ }
+ }
+
+ /**
+ * Creates an SL marshaller.
+ *
+ * @param formattedOutput
+ * <code>true</code> if the marshaller should produce formated
+ * output, <code>false</code> otherwise
+ * @return an SL marshaller
+ */
+ public Marshaller createMarshaller(boolean formattedOutput) {
+ return createMarshaller(formattedOutput, false);
+ }
+
+ /**
+ * Creates an SL marshaller.
+ *
+ * @param formattedOutput
+ * <code>true</code> if the marshaller should produce formated
+ * output, <code>false</code> otherwise
+ * @param fragment
+ * <code>true</code> if the marshaller should produce a XML fragment
+ * (omit XML declaration), <code>false</code> otherwise
+ * @return an SL marshaller
+ */
+ public Marshaller createMarshaller(boolean formattedOutput, boolean fragment) {
+ try {
+ return MarshallerFactory.createMarshaller(context, formattedOutput, fragment);
+ } catch (JAXBException e) {
+ log.fatal("Failed to marshall error response.", e);
+ throw new SLRuntimeException("Failed to marshall error response.", e);
+ }
+ }
+
+ /**
+ * Creates a legacy SL marshaller.
+ *
+ * @param formattedOutput
+ * <code>true</code> if the marshaller should produce formated
+ * output, <code>false</code> otherwise
+ * @return a legacy SL marshaller
+ */
+ public Marshaller createLegacyMarshaller(boolean formattedOutput) {
+ return createLegacyMarshaller(formattedOutput, false);
+ }
+
+ /**
+ * Creates a legacy SL marshaller.
+ *
+ * @param formattedOutput
+ * <code>true</code> if the marshaller should produce formated
+ * output, <code>false</code> otherwise
+ * @param fragment
+ * <code>true</code> if the marshaller should produce a XML fragment
+ * (omit XML declaration), <code>false</code> otherwise
+ * @return a legacy SL marshaller
+ */
+ public Marshaller createLegacyMarshaller(boolean formattedOutput, boolean fragment) {
+ try {
+ ensureLegacyContext();
+ return MarshallerFactory.createMarshaller(legacyContext, formattedOutput, fragment);
+ } catch (JAXBException e) {
+ log.fatal("Failed to marshall error response.", e);
+ throw new SLRuntimeException("Failed to marshall error response.", e);
+ }
+ }
+
+}
diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/SLResult.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/SLResult.java
index 7989a771..e9e483c5 100644
--- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/SLResult.java
+++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/SLResult.java
@@ -32,12 +32,14 @@ public interface SLResult {
*/
public String getMimeType();
- public void writeTo(Result aResult);
+ public void writeTo(Result aResult, boolean fragment);
/**
*
- * @param result
+ * @param result
+ * @param fragment TODO
* @param transformer may be null.
*/
- public void writeTo(Result result, Templates templates);
+ public void writeTo(Result result, Templates templates, boolean fragment);
+
} \ No newline at end of file
diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/AbstractAssocArrayInfobox.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/AbstractAssocArrayInfobox.java
index ce03dcf9..9a4536e6 100644
--- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/AbstractAssocArrayInfobox.java
+++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/AbstractAssocArrayInfobox.java
@@ -16,7 +16,6 @@
*/
package at.gv.egiz.bku.slcommands.impl;
-import at.gv.egiz.marshal.NamespacePrefixMapperImpl;
import java.io.ByteArrayOutputStream;
import java.util.Arrays;
import java.util.Collections;
@@ -24,7 +23,6 @@ import java.util.List;
import java.util.Map;
import java.util.regex.Pattern;
-import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
@@ -42,10 +40,8 @@ import at.buergerkarte.namespaces.securitylayer._1.InfoboxReadParamsAssocArrayTy
import at.buergerkarte.namespaces.securitylayer._1.InfoboxReadParamsAssocArrayType.ReadValue;
import at.gv.egiz.bku.slcommands.InfoboxReadResult;
import at.gv.egiz.bku.slcommands.SLCommandContext;
-import at.gv.egiz.bku.slcommands.SLCommandFactory;
+import at.gv.egiz.bku.slcommands.SLMarshallerFactory;
import at.gv.egiz.bku.slexceptions.SLCommandException;
-import at.gv.egiz.marshal.MarshallerFactory;
-import javax.xml.bind.PropertyException;
/**
* An abstract base class for {@link Infobox} implementations of type associative array.
@@ -255,13 +251,10 @@ public abstract class AbstractAssocArrayInfobox extends AbstractInfoboxImpl
}
protected byte[] marshallValue(Object jaxbElement) throws SLCommandException {
- SLCommandFactory commandFactory = SLCommandFactory.getInstance();
- JAXBContext jaxbContext = commandFactory.getJaxbContext();
- ByteArrayOutputStream result;
+ Marshaller marshaller = SLMarshallerFactory.getInstance().createMarshaller(false);
+ ByteArrayOutputStream result = new ByteArrayOutputStream();
try {
- Marshaller marshaller = MarshallerFactory.createMarshaller(jaxbContext);
- result = new ByteArrayOutputStream();
marshaller.marshal(jaxbElement, result);
} catch (JAXBException e) {
log.info("Failed to marshall infobox content.", e);
diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/CreateXMLSignatureResultImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/CreateXMLSignatureResultImpl.java
index b352a51e..19df4334 100644
--- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/CreateXMLSignatureResultImpl.java
+++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/CreateXMLSignatureResultImpl.java
@@ -16,8 +16,6 @@
*/
package at.gv.egiz.bku.slcommands.impl;
-import at.gv.egiz.marshal.NamespacePrefixMapperImpl;
-import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
@@ -33,10 +31,8 @@ import org.w3c.dom.Node;
import at.buergerkarte.namespaces.securitylayer._1.CreateXMLSignatureResponseType;
import at.buergerkarte.namespaces.securitylayer._1.ObjectFactory;
-import at.gv.egiz.bku.slcommands.SLCommandFactory;
+import at.gv.egiz.bku.slcommands.SLMarshallerFactory;
import at.gv.egiz.bku.slexceptions.SLRuntimeException;
-import at.gv.egiz.marshal.MarshallerFactory;
-import javax.xml.bind.PropertyException;
/**
* This calls implements the result of the security layer command <code>CreateXMLSignature</code>.
@@ -86,10 +82,9 @@ public class CreateXMLSignatureResultImpl extends SLResultImpl {
JAXBElement<CreateXMLSignatureResponseType> createCreateXMLSignatureResponse = factory.createCreateXMLSignatureResponse(createCreateXMLSignatureResponseType);
DocumentFragment fragment = doc.createDocumentFragment();
-
- JAXBContext jaxbContext = SLCommandFactory.getInstance().getJaxbContext();
+
+ Marshaller marshaller = SLMarshallerFactory.getInstance().createMarshaller(false);
try {
- Marshaller marshaller = MarshallerFactory.createMarshaller(jaxbContext);
marshaller.marshal(createCreateXMLSignatureResponse, fragment);
} catch (JAXBException e) {
log.error("Failed to marshall 'CreateXMLSignatureResponse'", e);
@@ -105,8 +100,8 @@ public class CreateXMLSignatureResultImpl extends SLResultImpl {
}
@Override
- public void writeTo(Result result, Templates templates) {
- writeTo(doc, result, templates);
+ public void writeTo(Result result, Templates templates, boolean fragment) {
+ writeTo(doc, result, templates, fragment);
}
}
diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/ErrorResultImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/ErrorResultImpl.java
index 5d0f0de0..aedde238 100644
--- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/ErrorResultImpl.java
+++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/ErrorResultImpl.java
@@ -56,11 +56,11 @@ public class ErrorResultImpl extends SLResultImpl implements ErrorResult {
}
@Override
- public void writeTo(Result result, Templates templates) {
+ public void writeTo(Result result, Templates templates, boolean fragment) {
if (locale == null) {
- writeErrorTo(slException, result, templates);
+ writeErrorTo(slException, result, templates, fragment);
} else {
- writeErrorTo(slException, result, templates, locale);
+ writeErrorTo(slException, result, templates, locale, fragment);
}
}
diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/GetStatusCommandImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/GetStatusCommandImpl.java
index 46bfe18b..0c2b96f9 100644
--- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/GetStatusCommandImpl.java
+++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/GetStatusCommandImpl.java
@@ -19,10 +19,8 @@ package at.gv.egiz.bku.slcommands.impl;
import at.buergerkarte.namespaces.securitylayer._1.GetStatusRequestType;
import at.gv.egiz.bku.slcommands.GetStatusCommand;
-import at.gv.egiz.bku.slcommands.SLCommandContext;
import at.gv.egiz.bku.slcommands.SLResult;
import at.gv.egiz.bku.slexceptions.SLCommandException;
-import at.gv.egiz.bku.slexceptions.SLException;
import at.gv.egiz.stal.ErrorResponse;
import at.gv.egiz.stal.STAL;
import at.gv.egiz.stal.STALResponse;
diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/GetStatusResultImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/GetStatusResultImpl.java
index fddd3b0b..fb1f627f 100644
--- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/GetStatusResultImpl.java
+++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/GetStatusResultImpl.java
@@ -45,8 +45,8 @@ public class GetStatusResultImpl extends SLResultImpl implements GetStatusResult
}
@Override
- public void writeTo(Result result, Templates templates) {
+ public void writeTo(Result result, Templates templates, boolean fragment) {
JAXBElement<GetStatusResponseType> response = of.createGetStatusResponse(responseType);
- writeTo(response, result, templates);
+ writeTo(response, result, templates, fragment);
}
}
diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/IdentityLinkInfoboxImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/IdentityLinkInfoboxImpl.java
index 7a82e43f..160e9589 100644
--- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/IdentityLinkInfoboxImpl.java
+++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/IdentityLinkInfoboxImpl.java
@@ -18,7 +18,6 @@ package at.gv.egiz.bku.slcommands.impl;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
-import java.io.OutputStream;
import java.net.MalformedURLException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxReadResultFileImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxReadResultFileImpl.java
index 75e44afa..422b424f 100644
--- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxReadResultFileImpl.java
+++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxReadResultFileImpl.java
@@ -16,8 +16,6 @@
*/
package at.gv.egiz.bku.slcommands.impl;
-import at.gv.egiz.marshal.NamespacePrefixMapperImpl;
-import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
@@ -39,10 +37,8 @@ import at.buergerkarte.namespaces.securitylayer._1.ObjectFactory;
import at.buergerkarte.namespaces.securitylayer._1.XMLContentType;
import at.gv.egiz.bku.slcommands.InfoboxReadResult;
import at.gv.egiz.bku.slcommands.SLCommand;
-import at.gv.egiz.bku.slcommands.SLCommandFactory;
+import at.gv.egiz.bku.slcommands.SLMarshallerFactory;
import at.gv.egiz.bku.slexceptions.SLRuntimeException;
-import at.gv.egiz.marshal.MarshallerFactory;
-import javax.xml.bind.PropertyException;
/**
* This class implements the result of the security layer command <code>InfoboxReadRequest</code>.
@@ -98,10 +94,9 @@ public class InfoboxReadResultFileImpl extends SLResultImpl implements
infoboxReadResponseType.setBinaryFileData(base64XMLContentType);
JAXBElement<InfoboxReadResponseType> infoboxReadResponse = factory.createInfoboxReadResponse(infoboxReadResponseType);
-
- JAXBContext context = SLCommandFactory.getInstance().getJaxbContext();
+
+ Marshaller marshaller = SLMarshallerFactory.getInstance().createMarshaller(false);
try {
- Marshaller marshaller = MarshallerFactory.createMarshaller(context);
marshaller.marshal(infoboxReadResponse, doc);
} catch (JAXBException e) {
log.error("Failed to marshal 'InfoboxReadResponse' document.", e);
@@ -158,8 +153,8 @@ public class InfoboxReadResultFileImpl extends SLResultImpl implements
}
@Override
- public void writeTo(Result result, Templates templates) {
- writeTo(xmlDocument, result, templates);
+ public void writeTo(Result result, Templates templates, boolean fragment) {
+ writeTo(xmlDocument, result, templates, fragment);
}
}
diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxReadResultImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxReadResultImpl.java
index e508941d..271ec955 100644
--- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxReadResultImpl.java
+++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxReadResultImpl.java
@@ -55,10 +55,10 @@ public class InfoboxReadResultImpl extends SLResultImpl implements InfoboxReadRe
}
@Override
- public void writeTo(Result result, Templates templates) {
+ public void writeTo(Result result, Templates templates, boolean fragment) {
ObjectFactory objectFactory = new ObjectFactory();
JAXBElement<InfoboxReadResponseType> response = objectFactory.createInfoboxReadResponse(infoboxReadResponse);
- writeTo(response, result, templates);
+ writeTo(response, result, templates, fragment);
}
}
diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxUpdateResultImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxUpdateResultImpl.java
index 15064756..e12536ba 100644
--- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxUpdateResultImpl.java
+++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxUpdateResultImpl.java
@@ -36,8 +36,8 @@ public class InfoboxUpdateResultImpl extends SLResultImpl implements
}
@Override
- public void writeTo(Result result, Templates templates) {
- writeTo(RESPONSE, result, templates);
+ public void writeTo(Result result, Templates templates, boolean fragment) {
+ writeTo(RESPONSE, result, templates, fragment);
}
}
diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/NullOperationResultImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/NullOperationResultImpl.java
index 05986f85..87733e39 100644
--- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/NullOperationResultImpl.java
+++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/NullOperationResultImpl.java
@@ -41,8 +41,8 @@ public class NullOperationResultImpl extends SLResultImpl implements NullOperati
}
@Override
- public void writeTo(Result result, Templates templates) {
- writeTo(RESPONSE, result, templates);
+ public void writeTo(Result result, Templates templates, boolean fragment) {
+ super.writeTo(RESPONSE, result, templates, fragment);
}
}
diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/SLResultImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/SLResultImpl.java
index 0452bddf..0077b7b2 100644
--- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/SLResultImpl.java
+++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/SLResultImpl.java
@@ -17,12 +17,14 @@
package at.gv.egiz.bku.slcommands.impl;
import java.io.UnsupportedEncodingException;
+import java.math.BigInteger;
import java.util.Locale;
-import javax.xml.bind.JAXBContext;
+import javax.xml.XMLConstants;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
+import javax.xml.transform.OutputKeys;
import javax.xml.transform.Result;
import javax.xml.transform.Templates;
import javax.xml.transform.Transformer;
@@ -41,17 +43,15 @@ import org.w3c.dom.Node;
import at.buergerkarte.namespaces.securitylayer._1.ErrorResponseType;
import at.buergerkarte.namespaces.securitylayer._1.ObjectFactory;
-import at.gv.egiz.marshal.NamespacePrefixMapperImpl;
-import at.gv.egiz.bku.slcommands.SLCommandFactory;
+import at.gv.egiz.bku.slcommands.SLMarshallerFactory;
import at.gv.egiz.bku.slcommands.SLResult;
import at.gv.egiz.bku.slexceptions.SLBindingException;
import at.gv.egiz.bku.slexceptions.SLCommandException;
import at.gv.egiz.bku.slexceptions.SLException;
import at.gv.egiz.bku.slexceptions.SLRuntimeException;
+import at.gv.egiz.bku.slexceptions.SLVersionException;
import at.gv.egiz.bku.utils.DebugOutputStream;
import at.gv.egiz.bku.utils.DebugWriter;
-import at.gv.egiz.marshal.MarshallerFactory;
-import javax.xml.bind.PropertyException;
/**
* This class serves as an abstract base class for the implementation of a
@@ -90,20 +90,18 @@ public abstract class SLResultImpl implements SLResult {
return resultingMimeType;
}
- private Marshaller getMarshaller() {
- try {
- JAXBContext context = SLCommandFactory.getInstance().getJaxbContext();
- Marshaller marshaller = MarshallerFactory.createMarshaller(context, true);
- return marshaller;
- } catch (JAXBException e) {
- log.fatal("Failed to marshall error response.", e);
- throw new SLRuntimeException("Failed to marshall error response.", e);
- }
+ @Override
+ public void writeTo(Result result, boolean fragment) {
+ writeTo(result, null, false);
}
+ @Override
+ public abstract void writeTo(Result result, Templates templates, boolean fragment);
+
private TransformerHandler getTransformerHandler(Templates templates, Result result) throws SLException {
try {
SAXTransformerFactory transformerFactory = (SAXTransformerFactory) SAXTransformerFactory.newInstance();
+ transformerFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true);
TransformerHandler transformerHandler = transformerFactory.newTransformerHandler(templates);
transformerHandler.setResult(result);
return transformerHandler;
@@ -119,12 +117,6 @@ public abstract class SLResultImpl implements SLResult {
}
}
- @Override
- public void writeTo(Result result) {
- writeTo(result, null);
- }
-
-
/**
* Writes the given <code>response</code> to the SAX <code>result</code> using
* the given transform <code>templates</code>.
@@ -133,7 +125,7 @@ public abstract class SLResultImpl implements SLResult {
* @param result
* @param templates
*/
- protected void writeTo(JAXBElement<?> response, Result result, Templates templates) {
+ protected void writeTo(JAXBElement<?> response, Result result, Templates templates, boolean fragment) {
DebugWriter dw = null;
DebugOutputStream ds = null;
@@ -154,11 +146,11 @@ public abstract class SLResultImpl implements SLResult {
try {
transformerHandler = getTransformerHandler(templates, result);
} catch (SLException e) {
- writeErrorTo(e, result, templates);
+ writeErrorTo(e, result, templates, fragment);
}
}
- Marshaller marshaller = getMarshaller();
+ Marshaller marshaller = SLMarshallerFactory.getInstance().createMarshaller(true);
try {
if (transformerHandler != null) {
marshaller.marshal(response, transformerHandler);
@@ -168,7 +160,7 @@ public abstract class SLResultImpl implements SLResult {
} catch (JAXBException e) {
log.info("Failed to marshall " + response.getName() + " result." , e);
SLCommandException commandException = new SLCommandException(4000);
- writeErrorTo(commandException, result, templates);
+ writeErrorTo(commandException, result, templates, fragment);
}
if (ds != null) {
@@ -185,7 +177,7 @@ public abstract class SLResultImpl implements SLResult {
}
- protected void writeTo(Node node, Result result, Templates templates) {
+ protected void writeTo(Node node, Result result, Templates templates, boolean fragment) {
DebugWriter dw = null;
DebugOutputStream ds = null;
@@ -205,24 +197,30 @@ public abstract class SLResultImpl implements SLResult {
try {
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
+ if (fragment) {
+ transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
+ }
transformer.transform(new DOMSource(node), result);
} catch (TransformerConfigurationException e) {
log.error("Failed to create Transformer.", e);
- writeErrorTo(new SLException(4000), result, null);
+ writeErrorTo(new SLException(4000), result, null, fragment);
} catch (TransformerException e) {
log.error("Failed to transform result.", e);
- writeErrorTo(new SLException(4000), result, null);
+ writeErrorTo(new SLException(4000), result, null, fragment);
}
} else {
try {
Transformer transformer = templates.newTransformer();
+ if (fragment) {
+ transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");
+ }
transformer.transform(new DOMSource(node), result);
} catch (TransformerConfigurationException e) {
log.info("Failed to create transformer.", e);
- writeErrorTo(new SLException(2008), result, templates);
+ writeErrorTo(new SLException(2008), result, templates, fragment);
} catch (TransformerException e) {
log.error("Failed to transform result.", e);
- writeErrorTo(new SLException(2008), result, templates);
+ writeErrorTo(new SLException(2008), result, templates, fragment);
}
}
@@ -240,11 +238,11 @@ public abstract class SLResultImpl implements SLResult {
}
- protected void writeErrorTo(SLException slException, Result result, Templates templates) {
- writeErrorTo(slException, result, templates, Locale.getDefault());
+ protected void writeErrorTo(SLException slException, Result result, Templates templates, boolean fragment) {
+ writeErrorTo(slException, result, templates, Locale.getDefault(), fragment);
}
- protected void writeErrorTo(SLException slException, Result result, Templates templates, Locale locale) {
+ protected void writeErrorTo(SLException slException, Result result, Templates templates, Locale locale, boolean fragment) {
TransformerHandler transformerHandler = null;
if (templates != null) {
@@ -256,13 +254,33 @@ public abstract class SLResultImpl implements SLResult {
}
}
- ObjectFactory factory = new ObjectFactory();
- ErrorResponseType responseType = factory.createErrorResponseType();
- responseType.setErrorCode(slException.getErrorCode());
- responseType.setInfo(slException.getLocalizedMessage(locale));
- JAXBElement<ErrorResponseType> response = factory.createErrorResponse(responseType);
+ Object response;
+
+ Marshaller marshaller;
+ if (slException instanceof SLVersionException
+ && ("http://www.buergerkarte.at/namespaces/securitylayer/20020225#"
+ .equals(((SLVersionException) slException).getNamespaceURI()) ||
+ "http://www.buergerkarte.at/namespaces/securitylayer/20020831#"
+ .equals(((SLVersionException) slException).getNamespaceURI()))) {
+ // issue ErrorResponse in the legacy namespace
+ at.buergerkarte.namespaces.securitylayer._20020225_.ObjectFactory factory
+ = new at.buergerkarte.namespaces.securitylayer._20020225_.ObjectFactory();
+ at.buergerkarte.namespaces.securitylayer._20020225_.ErrorResponseType errorResponseType = factory
+ .createErrorResponseType();
+ errorResponseType.setErrorCode(BigInteger.valueOf(slException
+ .getErrorCode()));
+ errorResponseType.setInfo(slException.getLocalizedMessage(locale));
+ response = factory.createErrorResponse(errorResponseType);
+ marshaller = SLMarshallerFactory.getInstance().createLegacyMarshaller(true, fragment);
+ } else {
+ ObjectFactory factory = new ObjectFactory();
+ ErrorResponseType responseType = factory.createErrorResponseType();
+ responseType.setErrorCode(slException.getErrorCode());
+ responseType.setInfo(slException.getLocalizedMessage(locale));
+ response = factory.createErrorResponse(responseType);
+ marshaller = SLMarshallerFactory.getInstance().createMarshaller(true, fragment);
+ }
- Marshaller marshaller = getMarshaller();
try {
if (transformerHandler != null) {
marshaller.marshal(response, transformerHandler);
diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/DataObject.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/DataObject.java
index b64306aa..2088a684 100644
--- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/DataObject.java
+++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/DataObject.java
@@ -81,7 +81,6 @@ import at.gv.egiz.bku.viewer.ValidationException;
import at.gv.egiz.bku.viewer.Validator;
import at.gv.egiz.bku.viewer.ValidatorFactory;
import at.gv.egiz.dom.DOMUtils;
-import at.gv.egiz.marshal.NamespacePrefix;
import at.gv.egiz.marshal.NamespacePrefixMapperImpl;
import at.gv.egiz.slbinding.impl.XMLContentType;
import javax.xml.namespace.NamespaceContext;
diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/Signature.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/Signature.java
index 9182e824..26ddb153 100644
--- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/Signature.java
+++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/Signature.java
@@ -16,7 +16,6 @@
*/
package at.gv.egiz.bku.slcommands.impl.xsect;
-import at.gv.egiz.stal.HashDataInput;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
@@ -31,9 +30,7 @@ import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
-import java.util.HashMap;
import java.util.List;
-import java.util.Map;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
@@ -87,8 +84,6 @@ import at.gv.egiz.bku.utils.urldereferencer.StreamData;
import at.gv.egiz.bku.utils.urldereferencer.URLDereferencer;
import at.gv.egiz.bku.utils.urldereferencer.URLDereferencerContext;
import at.gv.egiz.dom.DOMUtils;
-import at.gv.egiz.marshal.NamespacePrefix;
-import at.gv.egiz.marshal.NamespacePrefixMapperImpl;
import at.gv.egiz.slbinding.impl.XMLContentType;
import at.gv.egiz.stal.STAL;
import at.gv.egiz.xades.QualifyingPropertiesException;
@@ -327,6 +322,8 @@ public class Signature {
*/
public void buildXMLSignature() throws SLCommandException {
+ String signatureId = ctx.getIdValueFactory().createIdValue("Signature");
+
List<XMLObject> objects = new ArrayList<XMLObject>();
List<Reference> references = new ArrayList<Reference>();
@@ -340,7 +337,7 @@ public class Signature {
}
}
- addXAdESObjectAndReference(objects, references);
+ addXAdESObjectAndReference(objects, references, signatureId);
XMLSignatureFactory signatureFactory = ctx.getSignatureFactory();
AlgorithmMethodFactory algorithmMethodFactory = ctx.getAlgorithmMethodFactory();
@@ -369,7 +366,6 @@ public class Signature {
ki = kif.newKeyInfo(Collections.singletonList(x509Data));
}
- String signatureId = ctx.getIdValueFactory().createIdValue("Signature");
String signatureValueId = ctx.getIdValueFactory().createIdValue("SignatureValue");
xmlSignature = signatureFactory.newXMLSignature(si, ki, objects, signatureId, signatureValueId);
@@ -588,7 +584,7 @@ public class Signature {
* @param references
* the list of <code>ds:References</code> to add the created
* <code>ds:Reference</code> to
- *
+ * @param signatureId TODO
* @throws SLCommandException
* if creating and adding the XAdES
* <code>QualifyingProperties</code> fails
@@ -596,7 +592,7 @@ public class Signature {
* if <code>objects</code> or <code>references</code> is
* <code>null</code>
*/
- private void addXAdESObjectAndReference(List<XMLObject> objects, List<Reference> references) throws SLCommandException {
+ private void addXAdESObjectAndReference(List<XMLObject> objects, List<Reference> references, String signatureId) throws SLCommandException {
QualifyingPropertiesFactory factory = QualifyingPropertiesFactory.getInstance();
@@ -630,9 +626,11 @@ public class Signature {
}
}
+ String target = "#" + signatureId;
+
JAXBElement<QualifyingPropertiesType> qualifyingProperties;
try {
- qualifyingProperties = factory.createQualifyingProperties111(date, signingCertificates, idValue, dataObjectFormats);
+ qualifyingProperties = factory.createQualifyingProperties111(target, date, signingCertificates, idValue, dataObjectFormats);
} catch (QualifyingPropertiesException e) {
log.error("Failed to create QualifyingProperties.", e);
throw new SLCommandException(4000);
diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slexceptions/SLExceptionMessages.java b/bkucommon/src/main/java/at/gv/egiz/bku/slexceptions/SLExceptionMessages.java
index 5ce5cba1..73ac8d1b 100644
--- a/bkucommon/src/main/java/at/gv/egiz/bku/slexceptions/SLExceptionMessages.java
+++ b/bkucommon/src/main/java/at/gv/egiz/bku/slexceptions/SLExceptionMessages.java
@@ -47,4 +47,10 @@ public final class SLExceptionMessages {
public static final String EC4011_NOTIMPLEMENTED = "ec4011.notimplemented";
+ //
+ // Legacy error codes
+ //
+
+ public static final String LEC2901_NOTIMPLEMENTED = "lec2901.notimplemented";
+
}
diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slexceptions/SLVersionException.java b/bkucommon/src/main/java/at/gv/egiz/bku/slexceptions/SLVersionException.java
new file mode 100644
index 00000000..45501746
--- /dev/null
+++ b/bkucommon/src/main/java/at/gv/egiz/bku/slexceptions/SLVersionException.java
@@ -0,0 +1,28 @@
+package at.gv.egiz.bku.slexceptions;
+
+public class SLVersionException extends SLException {
+
+ private static final long serialVersionUID = 1L;
+
+ protected String namespaceURI;
+
+ public SLVersionException(String namespaceURI) {
+ super(2901, SLExceptionMessages.LEC2901_NOTIMPLEMENTED, new Object[] {namespaceURI});
+ this.namespaceURI = namespaceURI;
+ }
+
+ public SLVersionException(int errorCode, String namespaceURI) {
+ super(errorCode);
+ this.namespaceURI = namespaceURI;
+ }
+
+ public SLVersionException(int errorCode, String namespaceURI, String message, Object[] arguments) {
+ super(errorCode, message, arguments);
+ this.namespaceURI = namespaceURI;
+ }
+
+ public String getNamespaceURI() {
+ return namespaceURI;
+ }
+
+}
diff --git a/bkucommon/src/main/resources/at/gv/egiz/bku/slcommands/schema/Core.20020225.xsd b/bkucommon/src/main/resources/at/gv/egiz/bku/slcommands/schema/Core.20020225.xsd
new file mode 100644
index 00000000..76d1d7cb
--- /dev/null
+++ b/bkucommon/src/main/resources/at/gv/egiz/bku/slcommands/schema/Core.20020225.xsd
@@ -0,0 +1,33 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsd:schema targetNamespace="http://www.buergerkarte.at/namespaces/securitylayer/20020225#" xmlns="http://www.buergerkarte.at/namespaces/securitylayer/20020225#" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" elementFormDefault="qualified" attributeFormDefault="unqualified" version="1.1.0">
+ <xsd:element name="CreateCMSSignatureRequest" type="xsd:anyType"/>
+ <xsd:element name="CreateCMSSignatureResponse" type="xsd:anyType"/>
+ <xsd:element name="CreateXMLSignatureRequest" type="xsd:anyType"/>
+ <xsd:element name="CreateXMLSignatureResponse" type="xsd:anyType"/>
+ <xsd:element name="VerifyCMSSignatureRequest" type="xsd:anyType"/>
+ <xsd:element name="VerifyCMSSignatureResponse" type="xsd:anyType"/>
+ <xsd:element name="VerifyXMLSignatureRequest" type="xsd:anyType"/>
+ <xsd:element name="VerifyXMLSignatureResponse" type="xsd:anyType"/>
+ <xsd:element name="InfoboxAvailableRequest" type="xsd:anyType"/>
+ <xsd:element name="InfoboxAvailableResponse" type="xsd:anyType"/>
+ <xsd:element name="InfoboxReadRequest" type="xsd:anyType"/>
+ <xsd:element name="InfoboxReadResponse" type="xsd:anyType"/>
+ <xsd:element name="InfoboxUpdateRequest" type="xsd:anyType"/>
+ <xsd:element name="InfoboxUpdateResponse" type="xsd:anyType"/>
+ <xsd:element name="CreateSessionKeyRequest" type="xsd:anyType"/>
+ <xsd:element name="CreateSessionKeyResponse" type="xsd:anyType"/>
+ <xsd:element name="CreateSymmetricSecretRequest" type="xsd:anyType"/>
+ <xsd:element name="CreateSymmetricSecretResponse" type="xsd:anyType"/>
+ <xsd:element name="GetPropertiesRequest" type="xsd:anyType"/>
+ <xsd:element name="GetPropertiesResponse" type="xsd:anyType"/>
+ <xsd:element name="GetStatusRequest" type="xsd:anyType"/>
+ <xsd:element name="GetStatusResponse" type="xsd:anyType"/>
+ <!--########## Error Response ###-->
+ <xsd:element name="ErrorResponse" type="ErrorResponseType"/>
+ <xsd:complexType name="ErrorResponseType">
+ <xsd:sequence>
+ <xsd:element name="ErrorCode" type="xsd:integer"/>
+ <xsd:element name="Info" type="xsd:string"/>
+ </xsd:sequence>
+ </xsd:complexType>
+</xsd:schema>
diff --git a/bkucommon/src/main/resources/at/gv/egiz/bku/slcommands/schema/Core.20020831.xsd b/bkucommon/src/main/resources/at/gv/egiz/bku/slcommands/schema/Core.20020831.xsd
new file mode 100644
index 00000000..6759d791
--- /dev/null
+++ b/bkucommon/src/main/resources/at/gv/egiz/bku/slcommands/schema/Core.20020831.xsd
@@ -0,0 +1,10 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<xsd:schema targetNamespace="http://www.buergerkarte.at/namespaces/securitylayer/20020831#" xmlns:dsig="http://www.w3.org/2000/09/xmldsig#" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns="http://www.buergerkarte.at/namespaces/securitylayer/20020831#" xmlns:sl10="http://www.buergerkarte.at/namespaces/securitylayer/20020225#" elementFormDefault="qualified" attributeFormDefault="unqualified" version="1.1.0">
+ <xsd:element name="CreateXMLSignatureRequest" type="xsd:anyType"/>
+ <xsd:element name="CreateXMLSignatureResponse" type="xsd:anyType"/>
+ <xsd:element name="VerifyCMSSignatureRequest" type="xsd:anyType"/>
+ <xsd:element name="VerifyCMSSignatureResponse" type="xsd:anyType"/>
+ <xsd:element name="VerifyXMLSignatureRequest" type="xsd:anyType"/>
+ <xsd:element name="VerifyXMLSignatureResponse" type="xsd:anyType"/>
+ <xsd:element name="GetPropertiesResponse" type="xsd:anyType"/>
+</xsd:schema>
diff --git a/bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages.properties b/bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages.properties
index 73409c8b..db56184e 100644
--- a/bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages.properties
+++ b/bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages.properties
@@ -95,5 +95,10 @@ ec4000.infobox.invalid=Die Infobox '{0}' enthält ungültige Daten.
ec4000.idlink.transfomation.failed=Die komprimierte Personenbindung konnte mit dem Stylesheet {0} nicht transformiert werden.
ec4002.infobox.unknown=Unbekannter Infoboxbezeichner {0}.
ec4003.not.resolved=Zu signierendes Datum kann nicht aufgelöst werden (URI={0}).
-ec4011.notimplemented=Befehl {0} ist nicht implementiert.
+ec4011.notimplemented=Befehl {0} ist nicht implementiert.
+
+# Legacy error messages
+#
+
+lec2901.notimplemented=Die in der Anfrage verwendete Version des Security-Layer Protokolls ({0}) wird nicht mehr unterstützt.
diff --git a/bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages_en.properties b/bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages_en.properties
index 91ca20e8..6c67ba87 100644
--- a/bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages_en.properties
+++ b/bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages_en.properties
@@ -96,3 +96,7 @@ ec4000.idlink.transfomation.failed=Failed to transform CompressedIdentityLink wi
ec4002.infobox.unknown=Unknown info box identifier {0}.
ec4003.not.resolved=Data to be signed cannot be resolved from URI={0}.
ec4011.notimplemented=Command {0} not implemented.
+
+# Legacy error codes
+#
+lec2901.notimplemented=The version ({0}) of the security-layer protocol used in the request is not supported.
diff --git a/bkucommon/src/test/java/at/gv/egiz/bku/binding/XWWWFormUrlInputIteratorTest.java b/bkucommon/src/test/java/at/gv/egiz/bku/binding/XWWWFormUrlInputIteratorTest.java
new file mode 100644
index 00000000..703e4460
--- /dev/null
+++ b/bkucommon/src/test/java/at/gv/egiz/bku/binding/XWWWFormUrlInputIteratorTest.java
@@ -0,0 +1,152 @@
+package at.gv.egiz.bku.binding;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.net.URLEncoder;
+import java.nio.charset.Charset;
+
+import org.junit.Ignore;
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+public class XWWWFormUrlInputIteratorTest {
+
+ @Test
+ public void testOneParam() throws IOException {
+
+ final String name = "name";
+ final String value = "value";
+
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ OutputStreamWriter w = new OutputStreamWriter(os, Charset.forName("UTF-8"));
+ w.write(name);
+ w.write("=");
+ w.write(value);
+ w.flush();
+ w.close();
+
+ ByteArrayInputStream in = new ByteArrayInputStream(os.toByteArray());
+ XWWWFormUrlInputIterator decoder = new XWWWFormUrlInputIterator(in);
+
+ assertTrue(decoder.hasNext());
+ FormParameter param = decoder.next();
+ assertNotNull(param);
+ assertEquals(name, param.getFormParameterName());
+ InputStream vis = param.getFormParameterValue();
+ assertNotNull(vis);
+ InputStreamReader r = new InputStreamReader(vis);
+ char[] buf = new char[value.length() + 1];
+ int len = r.read(buf);
+ assertEquals(value.length(), len);
+ assertEquals(value, new String(buf, 0, len));
+ assertFalse(decoder.hasNext());
+ Exception ex = null;
+ try {
+ decoder.next();
+ } catch (Exception e) {
+ ex = e;
+ }
+ assertNotNull(ex);
+
+ }
+
+ @Test
+ public void testTwoParam() throws IOException {
+
+ final String name1 = "name";
+ final String value1 = "value";
+ final String name2 = "Name_2";
+ final String value2 = "Value 2";
+
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ OutputStreamWriter w = new OutputStreamWriter(os, Charset.forName("UTF-8"));
+ w.write(name1);
+ w.write("=");
+ w.write(value1);
+ w.write("&");
+ w.write(URLEncoder.encode(name2, "UTF-8"));
+ w.write("=");
+ w.write(URLEncoder.encode(value2, "UTF-8"));
+ w.flush();
+ w.close();
+
+ ByteArrayInputStream in = new ByteArrayInputStream(os.toByteArray());
+ XWWWFormUrlInputIterator decoder = new XWWWFormUrlInputIterator(in);
+
+ assertTrue(decoder.hasNext());
+ FormParameter param = decoder.next();
+ assertNotNull(param);
+ assertEquals(name1, param.getFormParameterName());
+ InputStream vis = param.getFormParameterValue();
+ assertNotNull(vis);
+ InputStreamReader r = new InputStreamReader(vis);
+ char[] buf = new char[value1.length() + 1];
+ int len = r.read(buf);
+ assertEquals(value1.length(), len);
+ assertEquals(value1, new String(buf, 0, len));
+
+ assertTrue(decoder.hasNext());
+ param = decoder.next();
+ assertNotNull(param);
+ assertEquals(name2, param.getFormParameterName());
+ vis = param.getFormParameterValue();
+ assertNotNull(vis);
+ r = new InputStreamReader(vis);
+ buf = new char[value2.length() + 1];
+ len = r.read(buf);
+ assertEquals(value2.length(), len);
+ assertEquals(value2, new String(buf, 0, len));
+
+ assertFalse(decoder.hasNext());
+ }
+
+ @Test
+ public void testURLEnc() throws IOException {
+
+ String name = "name";
+ byte[] value = new byte[128];
+ for (int i = 0; i < value.length; i++) {
+ value[i] = (byte) i;
+ }
+
+ String encValue = URLEncoder.encode(new String(value, "UTF-8"), "ASCII");
+ System.out.println(encValue);
+
+ ByteArrayOutputStream os = new ByteArrayOutputStream();
+ OutputStreamWriter w = new OutputStreamWriter(os, Charset.forName("UTF-8"));
+ w.write(name);
+ w.write("=");
+ w.write(encValue);
+ w.flush();
+ w.close();
+
+ ByteArrayInputStream in = new ByteArrayInputStream(os.toByteArray());
+ XWWWFormUrlInputIterator decoder = new XWWWFormUrlInputIterator(in);
+
+ assertTrue(decoder.hasNext());
+ FormParameter param = decoder.next();
+ assertNotNull(param);
+ assertEquals(name, param.getFormParameterName());
+ InputStream vis = param.getFormParameterValue();
+ assertNotNull(vis);
+ byte[] buf = new byte[value.length];
+ int len = vis.read(buf);
+ assertArrayEquals(value, buf);
+ assertEquals(value.length, len);
+ assertFalse(decoder.hasNext());
+ Exception ex = null;
+ try {
+ decoder.next();
+ } catch (Exception e) {
+ ex = e;
+ }
+ assertNotNull(ex);
+
+ }
+
+
+}
diff --git a/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/SLCommandFactoryTest.java b/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/SLCommandFactoryTest.java
index cd931878..7a087b38 100644
--- a/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/SLCommandFactoryTest.java
+++ b/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/SLCommandFactoryTest.java
@@ -33,6 +33,7 @@ import org.springframework.context.support.ClassPathXmlApplicationContext;
import at.gv.egiz.bku.slexceptions.SLCommandException;
import at.gv.egiz.bku.slexceptions.SLRequestException;
import at.gv.egiz.bku.slexceptions.SLRuntimeException;
+import at.gv.egiz.bku.slexceptions.SLVersionException;
import at.gv.egiz.stal.dummy.DummySTAL;
public class SLCommandFactoryTest {
@@ -54,7 +55,7 @@ public class SLCommandFactoryTest {
}
@Test
- public void createNullOperationCommand() throws SLCommandException, SLRuntimeException, SLRequestException {
+ public void createNullOperationCommand() throws SLCommandException, SLRuntimeException, SLRequestException, SLVersionException {
Reader requestReader = new StringReader(
"<NullOperationRequest xmlns=\"http://www.buergerkarte.at/namespaces/securitylayer/1.2#\"/>");
Source source = new StreamSource(requestReader);
@@ -65,7 +66,7 @@ public class SLCommandFactoryTest {
}
@Test(expected=SLCommandException.class)
- public void createUnsupportedCommand() throws SLCommandException, SLRuntimeException, SLRequestException {
+ public void createUnsupportedCommand() throws SLCommandException, SLRuntimeException, SLRequestException, SLVersionException {
Reader requestReader = new StringReader(
"<CreateCMSSignatureRequest xmlns=\"http://www.buergerkarte.at/namespaces/securitylayer/1.2#\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"http://www.buergerkarte.at/namespaces/securitylayer/1.2# file:/home/clemens/IAIK/BKU2/svn/bku/utils/src/main/schema/Core-1.2.xsd\" Structure=\"detached\"><KeyboxIdentifier></KeyboxIdentifier><DataObject><MetaInfo><MimeType></MimeType></MetaInfo><Content><Base64Content></Base64Content></Content></DataObject></CreateCMSSignatureRequest>");
Source source = new StreamSource(requestReader);
@@ -75,7 +76,7 @@ public class SLCommandFactoryTest {
}
@Test(expected=SLRequestException.class)
- public void createMalformedCommand() throws SLCommandException, SLRuntimeException, SLRequestException {
+ public void createMalformedCommand() throws SLCommandException, SLRuntimeException, SLRequestException, SLVersionException {
Reader requestReader = new StringReader(
"<NullOperationRequest xmlns=\"http://www.buergerkarte.at/namespaces/securitylayer/1.2#\">" +
"missplacedContent" +
diff --git a/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/CreateXMLSignatureComandImplTest.java b/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/CreateXMLSignatureComandImplTest.java
index 8fdec375..4e9b4cd7 100644
--- a/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/CreateXMLSignatureComandImplTest.java
+++ b/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/CreateXMLSignatureComandImplTest.java
@@ -41,6 +41,7 @@ import at.gv.egiz.bku.slcommands.impl.xsect.STALProvider;
import at.gv.egiz.bku.slexceptions.SLCommandException;
import at.gv.egiz.bku.slexceptions.SLRequestException;
import at.gv.egiz.bku.slexceptions.SLRuntimeException;
+import at.gv.egiz.bku.slexceptions.SLVersionException;
import at.gv.egiz.stal.STAL;
import at.gv.egiz.stal.dummy.DummySTAL;
//@Ignore
@@ -66,7 +67,7 @@ public class CreateXMLSignatureComandImplTest {
}
@Test
- public void testCreateXMLSignatureRequest() throws SLCommandException, SLRuntimeException, SLRequestException {
+ public void testCreateXMLSignatureRequest() throws SLCommandException, SLRuntimeException, SLRequestException, SLVersionException {
InputStream inputStream = getClass().getClassLoader().getResourceAsStream("at/gv/egiz/bku/slcommands/createxmlsignaturerequest/CreateXMLSignatureRequest.xml");
assertNotNull(inputStream);
@@ -76,11 +77,11 @@ public class CreateXMLSignatureComandImplTest {
assertTrue(command instanceof CreateXMLSignatureCommand);
SLResult result = command.execute();
- result.writeTo(new StreamResult(System.out));
+ result.writeTo(new StreamResult(System.out), false);
}
// @Test(expected=SLCommandException.class)
- public void testInfboxReadRequestInvalid1() throws SLCommandException, SLRuntimeException, SLRequestException {
+ public void testInfboxReadRequestInvalid1() throws SLCommandException, SLRuntimeException, SLRequestException, SLVersionException {
InputStream inputStream = getClass().getClassLoader().getResourceAsStream("at/gv/egiz/bku/slcommands/infoboxreadcommand/IdentityLink.Binary.Invalid-1.xml");
assertNotNull(inputStream);
@@ -90,7 +91,7 @@ public class CreateXMLSignatureComandImplTest {
}
// @Test(expected=SLCommandException.class)
- public void testInfboxReadRequestInvalid2() throws SLCommandException, SLRuntimeException, SLRequestException {
+ public void testInfboxReadRequestInvalid2() throws SLCommandException, SLRuntimeException, SLRequestException, SLVersionException {
InputStream inputStream = getClass().getClassLoader().getResourceAsStream("at/gv/egiz/bku/slcommands/infoboxreadcommand/IdentityLink.Binary.Invalid-2.xml");
assertNotNull(inputStream);
diff --git a/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/ErrorResultImplTest.java b/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/ErrorResultImplTest.java
index f10ca520..aa2bcd62 100644
--- a/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/ErrorResultImplTest.java
+++ b/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/ErrorResultImplTest.java
@@ -36,7 +36,7 @@ public class ErrorResultImplTest {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
StreamResult result = new StreamResult(stream);
- errorResult.writeTo(result);
+ errorResult.writeTo(result, false);
System.out.println(stream.toString());
diff --git a/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/InfoboxReadComandImplTest.java b/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/InfoboxReadComandImplTest.java
index b0d11d47..bfc784f7 100644
--- a/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/InfoboxReadComandImplTest.java
+++ b/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/InfoboxReadComandImplTest.java
@@ -39,6 +39,7 @@ import at.gv.egiz.bku.slcommands.SLResult;
import at.gv.egiz.bku.slexceptions.SLCommandException;
import at.gv.egiz.bku.slexceptions.SLRequestException;
import at.gv.egiz.bku.slexceptions.SLRuntimeException;
+import at.gv.egiz.bku.slexceptions.SLVersionException;
import at.gv.egiz.stal.STAL;
import at.gv.egiz.stal.dummy.DummySTAL;
@@ -63,7 +64,7 @@ public class InfoboxReadComandImplTest {
}
@Test
- public void testInfboxReadRequest() throws SLCommandException, SLRuntimeException, SLRequestException {
+ public void testInfboxReadRequest() throws SLCommandException, SLRuntimeException, SLRequestException, SLVersionException {
InputStream inputStream = getClass().getClassLoader().getResourceAsStream("at/gv/egiz/bku/slcommands/infoboxreadcommand/IdentityLink.Binary.xml");
assertNotNull(inputStream);
@@ -73,11 +74,11 @@ public class InfoboxReadComandImplTest {
assertTrue(command instanceof InfoboxReadCommand);
SLResult result = command.execute();
- result.writeTo(new StreamResult(System.out));
+ result.writeTo(new StreamResult(System.out), false);
}
@Test(expected=SLCommandException.class)
- public void testInfboxReadRequestInvalid1() throws SLCommandException, SLRuntimeException, SLRequestException {
+ public void testInfboxReadRequestInvalid1() throws SLCommandException, SLRuntimeException, SLRequestException, SLVersionException {
InputStream inputStream = getClass().getClassLoader().getResourceAsStream("at/gv/egiz/bku/slcommands/infoboxreadcommand/IdentityLink.Binary.Invalid-1.xml");
assertNotNull(inputStream);
@@ -87,7 +88,7 @@ public class InfoboxReadComandImplTest {
assertTrue(command instanceof InfoboxReadCommand);
}
- public void testInfboxReadRequestInvalid2() throws SLCommandException, SLRuntimeException, SLRequestException {
+ public void testInfboxReadRequestInvalid2() throws SLCommandException, SLRuntimeException, SLRequestException, SLVersionException {
InputStream inputStream = getClass().getClassLoader().getResourceAsStream("at/gv/egiz/bku/slcommands/infoboxreadcommand/IdentityLink.Binary.Invalid-2.xml");
assertNotNull(inputStream);
diff --git a/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/NullOperationResultImplTest.java b/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/NullOperationResultImplTest.java
index 8632b67c..e9b0775f 100644
--- a/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/NullOperationResultImplTest.java
+++ b/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/NullOperationResultImplTest.java
@@ -33,7 +33,7 @@ public class NullOperationResultImplTest {
ByteArrayOutputStream stream = new ByteArrayOutputStream();
StreamResult result = new StreamResult(stream);
- nullOperationResult.writeTo(result);
+ nullOperationResult.writeTo(result, false);
System.out.println(stream.toString());
diff --git a/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/SVPersonendatenInfoboxImplTest.java b/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/SVPersonendatenInfoboxImplTest.java
index f9c60b86..a17f0797 100644
--- a/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/SVPersonendatenInfoboxImplTest.java
+++ b/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/SVPersonendatenInfoboxImplTest.java
@@ -23,7 +23,6 @@ import iaik.asn1.CodingException;
import java.io.IOException;
import java.io.InputStream;
-import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
@@ -42,10 +41,12 @@ import at.gv.egiz.bku.slcommands.InfoboxReadCommand;
import at.gv.egiz.bku.slcommands.SLCommand;
import at.gv.egiz.bku.slcommands.SLCommandContext;
import at.gv.egiz.bku.slcommands.SLCommandFactory;
+import at.gv.egiz.bku.slcommands.SLMarshallerFactory;
import at.gv.egiz.bku.slcommands.SLResult;
import at.gv.egiz.bku.slexceptions.SLCommandException;
import at.gv.egiz.bku.slexceptions.SLRequestException;
import at.gv.egiz.bku.slexceptions.SLRuntimeException;
+import at.gv.egiz.bku.slexceptions.SLVersionException;
import at.gv.egiz.stal.STAL;
import at.gv.egiz.stal.dummy.DummySTAL;
@@ -93,9 +94,7 @@ public class SVPersonendatenInfoboxImplTest {
JAXBElement<AttributeList> ehic = new ObjectFactory().createEHIC(attributeList);
- JAXBContext jaxbContext = SLCommandFactory.getInstance().getJaxbContext();
-
- Marshaller marshaller = jaxbContext.createMarshaller();
+ Marshaller marshaller = SLMarshallerFactory.getInstance().createMarshaller(false);
marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
@@ -105,7 +104,7 @@ public class SVPersonendatenInfoboxImplTest {
@Ignore
@Test
- public void testInfboxReadRequest() throws SLCommandException, SLRuntimeException, SLRequestException {
+ public void testInfboxReadRequest() throws SLCommandException, SLRuntimeException, SLRequestException, SLVersionException {
InputStream inputStream = getClass().getClassLoader().getResourceAsStream("at/gv/egiz/bku/slcommands/infoboxreadcommand/IdentityLink.Binary.xml");
assertNotNull(inputStream);
@@ -115,12 +114,12 @@ public class SVPersonendatenInfoboxImplTest {
assertTrue(command instanceof InfoboxReadCommand);
SLResult result = command.execute();
- result.writeTo(new StreamResult(System.out));
+ result.writeTo(new StreamResult(System.out), false);
}
@Ignore
@Test(expected=SLCommandException.class)
- public void testInfboxReadRequestInvalid1() throws SLCommandException, SLRuntimeException, SLRequestException {
+ public void testInfboxReadRequestInvalid1() throws SLCommandException, SLRuntimeException, SLRequestException, SLVersionException {
InputStream inputStream = getClass().getClassLoader().getResourceAsStream("at/gv/egiz/bku/slcommands/infoboxreadcommand/IdentityLink.Binary.Invalid-1.xml");
assertNotNull(inputStream);
@@ -131,7 +130,7 @@ public class SVPersonendatenInfoboxImplTest {
}
@Ignore
- public void testInfboxReadRequestInvalid2() throws SLCommandException, SLRuntimeException, SLRequestException {
+ public void testInfboxReadRequestInvalid2() throws SLCommandException, SLRuntimeException, SLRequestException, SLVersionException {
InputStream inputStream = getClass().getClassLoader().getResourceAsStream("at/gv/egiz/bku/slcommands/infoboxreadcommand/IdentityLink.Binary.Invalid-2.xml");
assertNotNull(inputStream);
diff --git a/utils/src/main/java/at/buergerkarte/namespaces/securitylayer/_1/TransformsInfoType.java b/utils/src/main/java/at/buergerkarte/namespaces/securitylayer/_1/TransformsInfoType.java
index 5ee40b95..e4a8f48e 100644
--- a/utils/src/main/java/at/buergerkarte/namespaces/securitylayer/_1/TransformsInfoType.java
+++ b/utils/src/main/java/at/buergerkarte/namespaces/securitylayer/_1/TransformsInfoType.java
@@ -24,11 +24,15 @@
package at.buergerkarte.namespaces.securitylayer._1;
+import javax.xml.bind.JAXBElement;
import javax.xml.bind.annotation.XmlAccessType;
import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlAnyElement;
import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlElementRef;
import javax.xml.bind.annotation.XmlType;
import org.w3._2000._09.xmldsig_.TransformsType;
+import org.w3c.dom.Element;
/**
@@ -58,8 +62,9 @@ import org.w3._2000._09.xmldsig_.TransformsType;
})
public class TransformsInfoType {
- @XmlElement(name = "Transforms", namespace = "http://www.w3.org/2000/09/xmldsig#")
- protected TransformsType transforms;
+ @XmlElementRef(name = "Transforms", namespace = "http://www.w3.org/2000/09/xmldsig#", type = JAXBElement.class)
+ @XmlAnyElement(lax = true)
+ protected Object transforms;
@XmlElement(name = "FinalDataMetaInfo", required = true)
protected MetaInfoType finalDataMetaInfo;
@@ -68,10 +73,12 @@ public class TransformsInfoType {
*
* @return
* possible object is
- * {@link TransformsType }
+ * {@link JAXBElement }{@code <}{@link String }{@code >}
+ * {@link Object }
+ * {@link Element }
*
*/
- public TransformsType getTransforms() {
+ public Object getTransforms() {
return transforms;
}
@@ -80,10 +87,12 @@ public class TransformsInfoType {
*
* @param value
* allowed object is
- * {@link TransformsType }
+ * {@link JAXBElement }{@code <}{@link String }{@code >}
+ * {@link Object }
+ * {@link Element }
*
*/
- public void setTransforms(TransformsType value) {
+ public void setTransforms(Object value) {
this.transforms = value;
}
diff --git a/utils/src/main/java/at/buergerkarte/namespaces/securitylayer/_20020225_/ErrorResponseType.java b/utils/src/main/java/at/buergerkarte/namespaces/securitylayer/_20020225_/ErrorResponseType.java
new file mode 100644
index 00000000..69b5cd9d
--- /dev/null
+++ b/utils/src/main/java/at/buergerkarte/namespaces/securitylayer/_20020225_/ErrorResponseType.java
@@ -0,0 +1,98 @@
+//
+// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.0.2-b01-fcs
+// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>
+// Any modifications to this file will be lost upon recompilation of the source schema.
+// Generated on: 2009.09.07 at 09:47:31 AM CEST
+//
+
+
+package at.buergerkarte.namespaces.securitylayer._20020225_;
+
+import java.math.BigInteger;
+import javax.xml.bind.annotation.XmlAccessType;
+import javax.xml.bind.annotation.XmlAccessorType;
+import javax.xml.bind.annotation.XmlElement;
+import javax.xml.bind.annotation.XmlType;
+
+
+/**
+ * <p>Java class for ErrorResponseType complex type.
+ *
+ * <p>The following schema fragment specifies the expected content contained within this class.
+ *
+ * <pre>
+ * &lt;complexType name="ErrorResponseType">
+ * &lt;complexContent>
+ * &lt;restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ * &lt;sequence>
+ * &lt;element name="ErrorCode" type="{http://www.w3.org/2001/XMLSchema}integer"/>
+ * &lt;element name="Info" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ * &lt;/sequence>
+ * &lt;/restriction>
+ * &lt;/complexContent>
+ * &lt;/complexType>
+ * </pre>
+ *
+ *
+ */
+@XmlAccessorType(XmlAccessType.FIELD)
+@XmlType(name = "ErrorResponseType", propOrder = {
+ "errorCode",
+ "info"
+})
+public class ErrorResponseType {
+
+ @XmlElement(name = "ErrorCode", required = true)
+ protected BigInteger errorCode;
+ @XmlElement(name = "Info", required = true)
+ protected String info;
+
+ /**
+ * Gets the value of the errorCode property.
+ *
+ * @return
+ * possible object is
+ * {@link BigInteger }
+ *
+ */
+ public BigInteger getErrorCode() {
+ return errorCode;
+ }
+
+ /**
+ * Sets the value of the errorCode property.
+ *
+ * @param value
+ * allowed object is
+ * {@link BigInteger }
+ *
+ */
+ public void setErrorCode(BigInteger value) {
+ this.errorCode = value;
+ }
+
+ /**
+ * Gets the value of the info property.
+ *
+ * @return
+ * possible object is
+ * {@link String }
+ *
+ */
+ public String getInfo() {
+ return info;
+ }
+
+ /**
+ * Sets the value of the info property.
+ *
+ * @param value
+ * allowed object is
+ * {@link String }
+ *
+ */
+ public void setInfo(String value) {
+ this.info = value;
+ }
+
+}
diff --git a/utils/src/main/java/at/buergerkarte/namespaces/securitylayer/_20020225_/ObjectFactory.java b/utils/src/main/java/at/buergerkarte/namespaces/securitylayer/_20020225_/ObjectFactory.java
new file mode 100644
index 00000000..a02f9ca1
--- /dev/null
+++ b/utils/src/main/java/at/buergerkarte/namespaces/securitylayer/_20020225_/ObjectFactory.java
@@ -0,0 +1,280 @@
+//
+// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.0.2-b01-fcs
+// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>
+// Any modifications to this file will be lost upon recompilation of the source schema.
+// Generated on: 2009.09.07 at 09:47:31 AM CEST
+//
+
+
+package at.buergerkarte.namespaces.securitylayer._20020225_;
+
+import javax.xml.bind.JAXBElement;
+import javax.xml.bind.annotation.XmlElementDecl;
+import javax.xml.bind.annotation.XmlRegistry;
+import javax.xml.namespace.QName;
+
+
+/**
+ * This object contains factory methods for each
+ * Java content interface and Java element interface
+ * generated in the at.buergerkarte.namespaces.securitylayer._20020225_ package.
+ * <p>An ObjectFactory allows you to programatically
+ * construct new instances of the Java representation
+ * for XML content. The Java representation of XML
+ * content can consist of schema derived interfaces
+ * and classes representing the binding of schema
+ * type definitions, element declarations and model
+ * groups. Factory methods for each of these are
+ * provided in this class.
+ *
+ */
+@XmlRegistry
+public class ObjectFactory {
+
+ private final static QName _CreateXMLSignatureRequest_QNAME = new QName("http://www.buergerkarte.at/namespaces/securitylayer/20020225#", "CreateXMLSignatureRequest");
+ private final static QName _InfoboxUpdateRequest_QNAME = new QName("http://www.buergerkarte.at/namespaces/securitylayer/20020225#", "InfoboxUpdateRequest");
+ private final static QName _ErrorResponse_QNAME = new QName("http://www.buergerkarte.at/namespaces/securitylayer/20020225#", "ErrorResponse");
+ private final static QName _VerifyXMLSignatureResponse_QNAME = new QName("http://www.buergerkarte.at/namespaces/securitylayer/20020225#", "VerifyXMLSignatureResponse");
+ private final static QName _CreateSessionKeyResponse_QNAME = new QName("http://www.buergerkarte.at/namespaces/securitylayer/20020225#", "CreateSessionKeyResponse");
+ private final static QName _GetPropertiesRequest_QNAME = new QName("http://www.buergerkarte.at/namespaces/securitylayer/20020225#", "GetPropertiesRequest");
+ private final static QName _GetPropertiesResponse_QNAME = new QName("http://www.buergerkarte.at/namespaces/securitylayer/20020225#", "GetPropertiesResponse");
+ private final static QName _InfoboxAvailableResponse_QNAME = new QName("http://www.buergerkarte.at/namespaces/securitylayer/20020225#", "InfoboxAvailableResponse");
+ private final static QName _InfoboxAvailableRequest_QNAME = new QName("http://www.buergerkarte.at/namespaces/securitylayer/20020225#", "InfoboxAvailableRequest");
+ private final static QName _CreateSessionKeyRequest_QNAME = new QName("http://www.buergerkarte.at/namespaces/securitylayer/20020225#", "CreateSessionKeyRequest");
+ private final static QName _InfoboxUpdateResponse_QNAME = new QName("http://www.buergerkarte.at/namespaces/securitylayer/20020225#", "InfoboxUpdateResponse");
+ private final static QName _CreateXMLSignatureResponse_QNAME = new QName("http://www.buergerkarte.at/namespaces/securitylayer/20020225#", "CreateXMLSignatureResponse");
+ private final static QName _GetStatusResponse_QNAME = new QName("http://www.buergerkarte.at/namespaces/securitylayer/20020225#", "GetStatusResponse");
+ private final static QName _CreateCMSSignatureRequest_QNAME = new QName("http://www.buergerkarte.at/namespaces/securitylayer/20020225#", "CreateCMSSignatureRequest");
+ private final static QName _CreateSymmetricSecretRequest_QNAME = new QName("http://www.buergerkarte.at/namespaces/securitylayer/20020225#", "CreateSymmetricSecretRequest");
+ private final static QName _VerifyXMLSignatureRequest_QNAME = new QName("http://www.buergerkarte.at/namespaces/securitylayer/20020225#", "VerifyXMLSignatureRequest");
+ private final static QName _CreateSymmetricSecretResponse_QNAME = new QName("http://www.buergerkarte.at/namespaces/securitylayer/20020225#", "CreateSymmetricSecretResponse");
+ private final static QName _CreateCMSSignatureResponse_QNAME = new QName("http://www.buergerkarte.at/namespaces/securitylayer/20020225#", "CreateCMSSignatureResponse");
+ private final static QName _VerifyCMSSignatureResponse_QNAME = new QName("http://www.buergerkarte.at/namespaces/securitylayer/20020225#", "VerifyCMSSignatureResponse");
+ private final static QName _InfoboxReadResponse_QNAME = new QName("http://www.buergerkarte.at/namespaces/securitylayer/20020225#", "InfoboxReadResponse");
+ private final static QName _VerifyCMSSignatureRequest_QNAME = new QName("http://www.buergerkarte.at/namespaces/securitylayer/20020225#", "VerifyCMSSignatureRequest");
+ private final static QName _InfoboxReadRequest_QNAME = new QName("http://www.buergerkarte.at/namespaces/securitylayer/20020225#", "InfoboxReadRequest");
+ private final static QName _GetStatusRequest_QNAME = new QName("http://www.buergerkarte.at/namespaces/securitylayer/20020225#", "GetStatusRequest");
+
+ /**
+ * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: at.buergerkarte.namespaces.securitylayer._20020225_
+ *
+ */
+ public ObjectFactory() {
+ }
+
+ /**
+ * Create an instance of {@link ErrorResponseType }
+ *
+ */
+ public ErrorResponseType createErrorResponseType() {
+ return new ErrorResponseType();
+ }
+
+ /**
+ * Create an instance of {@link JAXBElement }{@code <}{@link Object }{@code >}}
+ *
+ */
+ @XmlElementDecl(namespace = "http://www.buergerkarte.at/namespaces/securitylayer/20020225#", name = "CreateXMLSignatureRequest")
+ public JAXBElement<Object> createCreateXMLSignatureRequest(Object value) {
+ return new JAXBElement<Object>(_CreateXMLSignatureRequest_QNAME, Object.class, null, value);
+ }
+
+ /**
+ * Create an instance of {@link JAXBElement }{@code <}{@link Object }{@code >}}
+ *
+ */
+ @XmlElementDecl(namespace = "http://www.buergerkarte.at/namespaces/securitylayer/20020225#", name = "InfoboxUpdateRequest")
+ public JAXBElement<Object> createInfoboxUpdateRequest(Object value) {
+ return new JAXBElement<Object>(_InfoboxUpdateRequest_QNAME, Object.class, null, value);
+ }
+
+ /**
+ * Create an instance of {@link JAXBElement }{@code <}{@link ErrorResponseType }{@code >}}
+ *
+ */
+ @XmlElementDecl(namespace = "http://www.buergerkarte.at/namespaces/securitylayer/20020225#", name = "ErrorResponse")
+ public JAXBElement<ErrorResponseType> createErrorResponse(ErrorResponseType value) {
+ return new JAXBElement<ErrorResponseType>(_ErrorResponse_QNAME, ErrorResponseType.class, null, value);
+ }
+
+ /**
+ * Create an instance of {@link JAXBElement }{@code <}{@link Object }{@code >}}
+ *
+ */
+ @XmlElementDecl(namespace = "http://www.buergerkarte.at/namespaces/securitylayer/20020225#", name = "VerifyXMLSignatureResponse")
+ public JAXBElement<Object> createVerifyXMLSignatureResponse(Object value) {
+ return new JAXBElement<Object>(_VerifyXMLSignatureResponse_QNAME, Object.class, null, value);
+ }
+
+ /**
+ * Create an instance of {@link JAXBElement }{@code <}{@link Object }{@code >}}
+ *
+ */
+ @XmlElementDecl(namespace = "http://www.buergerkarte.at/namespaces/securitylayer/20020225#", name = "CreateSessionKeyResponse")
+ public JAXBElement<Object> createCreateSessionKeyResponse(Object value) {
+ return new JAXBElement<Object>(_CreateSessionKeyResponse_QNAME, Object.class, null, value);
+ }
+
+ /**
+ * Create an instance of {@link JAXBElement }{@code <}{@link Object }{@code >}}
+ *
+ */
+ @XmlElementDecl(namespace = "http://www.buergerkarte.at/namespaces/securitylayer/20020225#", name = "GetPropertiesRequest")
+ public JAXBElement<Object> createGetPropertiesRequest(Object value) {
+ return new JAXBElement<Object>(_GetPropertiesRequest_QNAME, Object.class, null, value);
+ }
+
+ /**
+ * Create an instance of {@link JAXBElement }{@code <}{@link Object }{@code >}}
+ *
+ */
+ @XmlElementDecl(namespace = "http://www.buergerkarte.at/namespaces/securitylayer/20020225#", name = "GetPropertiesResponse")
+ public JAXBElement<Object> createGetPropertiesResponse(Object value) {
+ return new JAXBElement<Object>(_GetPropertiesResponse_QNAME, Object.class, null, value);
+ }
+
+ /**
+ * Create an instance of {@link JAXBElement }{@code <}{@link Object }{@code >}}
+ *
+ */
+ @XmlElementDecl(namespace = "http://www.buergerkarte.at/namespaces/securitylayer/20020225#", name = "InfoboxAvailableResponse")
+ public JAXBElement<Object> createInfoboxAvailableResponse(Object value) {
+ return new JAXBElement<Object>(_InfoboxAvailableResponse_QNAME, Object.class, null, value);
+ }
+
+ /**
+ * Create an instance of {@link JAXBElement }{@code <}{@link Object }{@code >}}
+ *
+ */
+ @XmlElementDecl(namespace = "http://www.buergerkarte.at/namespaces/securitylayer/20020225#", name = "InfoboxAvailableRequest")
+ public JAXBElement<Object> createInfoboxAvailableRequest(Object value) {
+ return new JAXBElement<Object>(_InfoboxAvailableRequest_QNAME, Object.class, null, value);
+ }
+
+ /**
+ * Create an instance of {@link JAXBElement }{@code <}{@link Object }{@code >}}
+ *
+ */
+ @XmlElementDecl(namespace = "http://www.buergerkarte.at/namespaces/securitylayer/20020225#", name = "CreateSessionKeyRequest")
+ public JAXBElement<Object> createCreateSessionKeyRequest(Object value) {
+ return new JAXBElement<Object>(_CreateSessionKeyRequest_QNAME, Object.class, null, value);
+ }
+
+ /**
+ * Create an instance of {@link JAXBElement }{@code <}{@link Object }{@code >}}
+ *
+ */
+ @XmlElementDecl(namespace = "http://www.buergerkarte.at/namespaces/securitylayer/20020225#", name = "InfoboxUpdateResponse")
+ public JAXBElement<Object> createInfoboxUpdateResponse(Object value) {
+ return new JAXBElement<Object>(_InfoboxUpdateResponse_QNAME, Object.class, null, value);
+ }
+
+ /**
+ * Create an instance of {@link JAXBElement }{@code <}{@link Object }{@code >}}
+ *
+ */
+ @XmlElementDecl(namespace = "http://www.buergerkarte.at/namespaces/securitylayer/20020225#", name = "CreateXMLSignatureResponse")
+ public JAXBElement<Object> createCreateXMLSignatureResponse(Object value) {
+ return new JAXBElement<Object>(_CreateXMLSignatureResponse_QNAME, Object.class, null, value);
+ }
+
+ /**
+ * Create an instance of {@link JAXBElement }{@code <}{@link Object }{@code >}}
+ *
+ */
+ @XmlElementDecl(namespace = "http://www.buergerkarte.at/namespaces/securitylayer/20020225#", name = "GetStatusResponse")
+ public JAXBElement<Object> createGetStatusResponse(Object value) {
+ return new JAXBElement<Object>(_GetStatusResponse_QNAME, Object.class, null, value);
+ }
+
+ /**
+ * Create an instance of {@link JAXBElement }{@code <}{@link Object }{@code >}}
+ *
+ */
+ @XmlElementDecl(namespace = "http://www.buergerkarte.at/namespaces/securitylayer/20020225#", name = "CreateCMSSignatureRequest")
+ public JAXBElement<Object> createCreateCMSSignatureRequest(Object value) {
+ return new JAXBElement<Object>(_CreateCMSSignatureRequest_QNAME, Object.class, null, value);
+ }
+
+ /**
+ * Create an instance of {@link JAXBElement }{@code <}{@link Object }{@code >}}
+ *
+ */
+ @XmlElementDecl(namespace = "http://www.buergerkarte.at/namespaces/securitylayer/20020225#", name = "CreateSymmetricSecretRequest")
+ public JAXBElement<Object> createCreateSymmetricSecretRequest(Object value) {
+ return new JAXBElement<Object>(_CreateSymmetricSecretRequest_QNAME, Object.class, null, value);
+ }
+
+ /**
+ * Create an instance of {@link JAXBElement }{@code <}{@link Object }{@code >}}
+ *
+ */
+ @XmlElementDecl(namespace = "http://www.buergerkarte.at/namespaces/securitylayer/20020225#", name = "VerifyXMLSignatureRequest")
+ public JAXBElement<Object> createVerifyXMLSignatureRequest(Object value) {
+ return new JAXBElement<Object>(_VerifyXMLSignatureRequest_QNAME, Object.class, null, value);
+ }
+
+ /**
+ * Create an instance of {@link JAXBElement }{@code <}{@link Object }{@code >}}
+ *
+ */
+ @XmlElementDecl(namespace = "http://www.buergerkarte.at/namespaces/securitylayer/20020225#", name = "CreateSymmetricSecretResponse")
+ public JAXBElement<Object> createCreateSymmetricSecretResponse(Object value) {
+ return new JAXBElement<Object>(_CreateSymmetricSecretResponse_QNAME, Object.class, null, value);
+ }
+
+ /**
+ * Create an instance of {@link JAXBElement }{@code <}{@link Object }{@code >}}
+ *
+ */
+ @XmlElementDecl(namespace = "http://www.buergerkarte.at/namespaces/securitylayer/20020225#", name = "CreateCMSSignatureResponse")
+ public JAXBElement<Object> createCreateCMSSignatureResponse(Object value) {
+ return new JAXBElement<Object>(_CreateCMSSignatureResponse_QNAME, Object.class, null, value);
+ }
+
+ /**
+ * Create an instance of {@link JAXBElement }{@code <}{@link Object }{@code >}}
+ *
+ */
+ @XmlElementDecl(namespace = "http://www.buergerkarte.at/namespaces/securitylayer/20020225#", name = "VerifyCMSSignatureResponse")
+ public JAXBElement<Object> createVerifyCMSSignatureResponse(Object value) {
+ return new JAXBElement<Object>(_VerifyCMSSignatureResponse_QNAME, Object.class, null, value);
+ }
+
+ /**
+ * Create an instance of {@link JAXBElement }{@code <}{@link Object }{@code >}}
+ *
+ */
+ @XmlElementDecl(namespace = "http://www.buergerkarte.at/namespaces/securitylayer/20020225#", name = "InfoboxReadResponse")
+ public JAXBElement<Object> createInfoboxReadResponse(Object value) {
+ return new JAXBElement<Object>(_InfoboxReadResponse_QNAME, Object.class, null, value);
+ }
+
+ /**
+ * Create an instance of {@link JAXBElement }{@code <}{@link Object }{@code >}}
+ *
+ */
+ @XmlElementDecl(namespace = "http://www.buergerkarte.at/namespaces/securitylayer/20020225#", name = "VerifyCMSSignatureRequest")
+ public JAXBElement<Object> createVerifyCMSSignatureRequest(Object value) {
+ return new JAXBElement<Object>(_VerifyCMSSignatureRequest_QNAME, Object.class, null, value);
+ }
+
+ /**
+ * Create an instance of {@link JAXBElement }{@code <}{@link Object }{@code >}}
+ *
+ */
+ @XmlElementDecl(namespace = "http://www.buergerkarte.at/namespaces/securitylayer/20020225#", name = "InfoboxReadRequest")
+ public JAXBElement<Object> createInfoboxReadRequest(Object value) {
+ return new JAXBElement<Object>(_InfoboxReadRequest_QNAME, Object.class, null, value);
+ }
+
+ /**
+ * Create an instance of {@link JAXBElement }{@code <}{@link Object }{@code >}}
+ *
+ */
+ @XmlElementDecl(namespace = "http://www.buergerkarte.at/namespaces/securitylayer/20020225#", name = "GetStatusRequest")
+ public JAXBElement<Object> createGetStatusRequest(Object value) {
+ return new JAXBElement<Object>(_GetStatusRequest_QNAME, Object.class, null, value);
+ }
+
+}
diff --git a/utils/src/main/java/at/buergerkarte/namespaces/securitylayer/_20020225_/package-info.java b/utils/src/main/java/at/buergerkarte/namespaces/securitylayer/_20020225_/package-info.java
new file mode 100644
index 00000000..084f6b11
--- /dev/null
+++ b/utils/src/main/java/at/buergerkarte/namespaces/securitylayer/_20020225_/package-info.java
@@ -0,0 +1,9 @@
+//
+// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.0.2-b01-fcs
+// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>
+// Any modifications to this file will be lost upon recompilation of the source schema.
+// Generated on: 2009.09.07 at 09:47:31 AM CEST
+//
+
+@javax.xml.bind.annotation.XmlSchema(namespace = "http://www.buergerkarte.at/namespaces/securitylayer/20020225#", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED)
+package at.buergerkarte.namespaces.securitylayer._20020225_;
diff --git a/utils/src/main/java/at/buergerkarte/namespaces/securitylayer/_20020831_/ObjectFactory.java b/utils/src/main/java/at/buergerkarte/namespaces/securitylayer/_20020831_/ObjectFactory.java
new file mode 100644
index 00000000..17f6d4b4
--- /dev/null
+++ b/utils/src/main/java/at/buergerkarte/namespaces/securitylayer/_20020831_/ObjectFactory.java
@@ -0,0 +1,112 @@
+//
+// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.0.2-b01-fcs
+// See <a href="http://java.sun.com/xml/jaxb">http://java.sun.com/xml/jaxb</a>
+// Any modifications to this file will be lost upon recompilation of the source schema.
+// Generated on: 2009.09.07 at 09:47:31 AM CEST
+//
+
+
+package at.buergerkarte.namespaces.securitylayer._20020831_;
+
+import javax.xml.bind.JAXBElement;
+import javax.xml.bind.annotation.XmlElementDecl;
+import javax.xml.bind.annotation.XmlRegistry;
+import javax.xml.namespace.QName;
+
+
+/**
+ * This object contains factory methods for each
+ * Java content interface and Java element interface
+ * generated in the at.buergerkarte.namespaces.securitylayer._20020831_ package.
+ * <p>An ObjectFactory allows you to programatically
+ * construct new instances of the Java representation
+ * for XML content. The Java representation of XML
+ * content can consist of schema derived interfaces
+ * and classes representing the binding of schema
+ * type definitions, element declarations and model
+ * groups. Factory methods for each of these are
+ * provided in this class.
+ *
+ */
+@XmlRegistry
+public class ObjectFactory {
+
+ private final static QName _CreateXMLSignatureRequest_QNAME = new QName("http://www.buergerkarte.at/namespaces/securitylayer/20020831#", "CreateXMLSignatureRequest");
+ private final static QName _GetPropertiesResponse_QNAME = new QName("http://www.buergerkarte.at/namespaces/securitylayer/20020831#", "GetPropertiesResponse");
+ private final static QName _VerifyXMLSignatureResponse_QNAME = new QName("http://www.buergerkarte.at/namespaces/securitylayer/20020831#", "VerifyXMLSignatureResponse");
+ private final static QName _VerifyXMLSignatureRequest_QNAME = new QName("http://www.buergerkarte.at/namespaces/securitylayer/20020831#", "VerifyXMLSignatureRequest");
+ private final static QName _VerifyCMSSignatureResponse_QNAME = new QName("http://www.buergerkarte.at/namespaces/securitylayer/20020831#", "VerifyCMSSignatureResponse");
+ private final static QName _CreateXMLSignatureResponse_QNAME = new QName("http://www.buergerkarte.at/namespaces/securitylayer/20020831#", "CreateXMLSignatureResponse");
+ private final static QName _VerifyCMSSignatureRequest_QNAME = new QName("http://www.buergerkarte.at/namespaces/securitylayer/20020831#", "VerifyCMSSignatureRequest");
+
+ /**
+ * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: at.buergerkarte.namespaces.securitylayer._20020831_
+ *
+ */
+ public ObjectFactory() {
+ }
+
+ /**
+ * Create an instance of {@link JAXBElement }{@code <}{@link Object }{@code >}}
+ *
+ */
+ @XmlElementDecl(namespace = "http://www.buergerkarte.at/namespaces/securitylayer/20020831#", name = "CreateXMLSignatureRequest")
+ public JAXBElement<Object> createCreateXMLSignatureRequest(Object value) {
+ return new JAXBElement<Object>(_CreateXMLSignatureRequest_QNAME, Object.class, null, value);
+ }
+
+ /**
+ * Create an instance of {@link JAXBElement }{@code <}{@link Object }{@code >}}
+ *
+ */
+ @XmlElementDecl(namespace = "http://www.buergerkarte.at/namespaces/securitylayer/20020831#", name = "GetPropertiesResponse")
+ public JAXBElement<Object> createGetPropertiesResponse(Object value) {
+ return new JAXBElement<Object>(_GetPropertiesResponse_QNAME, Object.class, null, value);
+ }
+
+ /**
+ * Create an instance of {@link JAXBElement }{@code <}{@link Object }{@code >}}
+ *
+ */
+ @XmlElementDecl(namespace = "http://www.buergerkarte.at/namespaces/securitylayer/20020831#", name = "VerifyXMLSignatureResponse")
+ public JAXBElement<Object> createVerifyXMLSignatureResponse(Object value) {
+ return new JAXBElement<Object>(_VerifyXMLSignatureResponse_QNAME, Object.class, null, value);
+ }
+
+ /**
+ * Create an instance of {@link JAXBElement }{@code <}{@link Object }{@code >}}
+ *
+ */
+ @XmlElementDecl(namespace = "http://www.buergerkarte.at/namespaces/securitylayer/20020831#", name = "VerifyXMLSignatureRequest")
+ public JAXBElement<Object> createVerifyXMLSignatureRequest(Object value) {
+ return new JAXBElement<Object>(_VerifyXMLSignatureRequest_QNAME, Object.class, null, value);
+ }
+
+ /**
+ * Create an instance of {@link JAXBElement }{@code <}{@link Object }{@code >}}
+ *
+ */
+ @XmlElementDecl(namespace = "http://www.buergerkarte.at/namespaces/securitylayer/20020831#", name = "VerifyCMSSignatureResponse")
+ public JAXBElement<Object> createVerifyCMSSignatureResponse(Object value) {
+ return new JAXBElement<Object>(_VerifyCMSSignatureResponse_QNAME, Object.class, null, value);
+ }
+
+ /**
+ * Create an instance of {@link JAXBElement }{@code <}{@link Object }{@code >}}
+ *
+ */
+ @XmlElementDecl(namespace = "http://www.buergerkarte.at/namespaces/securitylayer/20020831#", name = "CreateXMLSignatureResponse")
+ public JAXBElement<Object> createCreateXMLSignatureResponse(Object value) {
+ return new JAXBElement<Object>(_CreateXMLSignatureResponse_QNAME, Object.class, null, value);
+ }
+
+ /**
+ * Create an instance of {@link JAXBElement }{@code <}{@link Object }{@code >}}
+ *
+ */
+ @XmlElementDecl(namespace = "http://www.buergerkarte.at/namespaces/securitylayer/20020831#", name = "VerifyCMSSignatureRequest")
+ public JAXBElement<Object> createVerifyCMSSignatureRequest(Object value) {
+ return new JAXBElement<Object>(_VerifyCMSSignatureRequest_QNAME, Object.class, null, value);
+ }
+
+}
diff --git a/utils/src/main/java/at/gv/egiz/bku/utils/URLEncodingInputStream.java b/utils/src/main/java/at/gv/egiz/bku/utils/URLEncodingInputStream.java
new file mode 100644
index 00000000..28ef6b88
--- /dev/null
+++ b/utils/src/main/java/at/gv/egiz/bku/utils/URLEncodingInputStream.java
@@ -0,0 +1,62 @@
+/**
+ *
+ */
+package at.gv.egiz.bku.utils;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.CharBuffer;
+
+/**
+ * @author mcentner
+ *
+ */
+public class URLEncodingInputStream extends InputStream {
+
+ private char[] buffer = new char[1];
+
+ private CharBuffer charBuffer = CharBuffer.wrap(buffer);
+
+ protected Readable in;
+
+ /**
+ * @param in
+ */
+ public URLEncodingInputStream(Readable in) {
+ this.in = in;
+ }
+
+ /* (non-Javadoc)
+ * @see java.io.InputStream#read()
+ */
+ @Override
+ public int read() throws IOException {
+ charBuffer.rewind();
+ if (in.read(charBuffer) == -1) {
+ return -1;
+ }
+ if (buffer[0] == '+') {
+ return ' ';
+ } else if (buffer[0] == '%') {
+ charBuffer.rewind();
+ if (in.read(charBuffer) == -1) {
+ throw new IOException("Invalid URL encoding.");
+ }
+ int c1 = Character.digit(buffer[0], 16);
+ charBuffer.rewind();
+ if (in.read(charBuffer) == -1) {
+ throw new IOException("Invalid URL encoding.");
+ }
+ int c2 = Character.digit(buffer[0], 16);
+ if (c1 == -1 || c2 == -1) {
+ throw new IOException("Invalid URL encoding.");
+ }
+ return ((c1 << 4) | c2);
+ } else {
+ return buffer[0];
+ }
+ }
+
+
+
+}
diff --git a/utils/src/main/java/at/gv/egiz/bku/utils/URLEncodingOutputStream.java b/utils/src/main/java/at/gv/egiz/bku/utils/URLEncodingOutputStream.java
new file mode 100644
index 00000000..df42df6d
--- /dev/null
+++ b/utils/src/main/java/at/gv/egiz/bku/utils/URLEncodingOutputStream.java
@@ -0,0 +1,134 @@
+/*
+* Copyright 2008 Federal Chancellery Austria and
+* Graz University of Technology
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package at.gv.egiz.bku.utils;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.nio.CharBuffer;
+import java.util.BitSet;
+
+/**
+ * An URLEncoding <a
+ * href="http://tools.ietf.org/html/rfc3986#section-2.1">RFC3986, Section 2.1</a>
+ * OutputStream.
+ *
+ * @author mcentner
+ */
+public class URLEncodingOutputStream extends OutputStream {
+
+ private static final int MAX_BUFFER_SIZE = 512;
+
+ private static final BitSet UNRESERVED = new BitSet(256);
+
+ static {
+ for (int i = '0'; i <= '9'; i++) {
+ UNRESERVED.set(i);
+ }
+ for (int i = 'a'; i <= 'z'; i++) {
+ UNRESERVED.set(i);
+ }
+ for (int i = 'A'; i <= 'Z'; i++) {
+ UNRESERVED.set(i);
+ }
+ UNRESERVED.set('-');
+ UNRESERVED.set('_');
+ UNRESERVED.set('.');
+ UNRESERVED.set('*');
+ UNRESERVED.set(' ');
+ }
+
+ private static final char[] HEX = new char[] {
+ '0', '1', '2', '3', '4', '5', '6', '7',
+ '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
+ };
+
+ private char[] buf;
+
+ protected Appendable out;
+
+ /**
+ * Creates a new instance of this URLEncodingOutputStream that writes to the
+ * given Appendable.
+ * <p>
+ * Note: According to
+ * http://www.w3.org/TR/html40/appendix/notes.html#non-ascii-chars the input
+ * for the {@link #write()} methods should be the UTF-8.
+ * </p>
+ *
+ * @param out
+ */
+ public URLEncodingOutputStream(Appendable out) {
+ this.out = out;
+ }
+
+ /* (non-Javadoc)
+ * @see java.io.OutputStream#write(int)
+ */
+ @Override
+ public void write(int b) throws IOException {
+ b &= 0xFF;
+ if (UNRESERVED.get(b)) {
+ if (b == ' ') {
+ out.append('+');
+ } else {
+ out.append((char) b);
+ }
+ } else {
+ out.append('%').append(HEX[b >>> 4]).append(HEX[b & 0xF]);
+ }
+
+ }
+
+ /* (non-Javadoc)
+ * @see java.io.OutputStream#write(byte[], int, int)
+ */
+ @Override
+ public void write(byte[] b, int off, int len) throws IOException {
+
+ // ensure a buffer at least double the size of end - start + 1
+ // but max
+ int sz = Math.min(len + 1, MAX_BUFFER_SIZE);
+ if (buf == null || buf.length < sz) {
+ buf = new char[sz];
+ }
+
+ int bPos = 0;
+ for (int i = 0; i < len; i++) {
+ if (bPos + 3 > buf.length) {
+ // flush buffer
+ out.append(CharBuffer.wrap(buf, 0, bPos));
+ bPos = 0;
+ }
+ int c = 0xFF & b[off + i];
+ if (UNRESERVED.get(c)) {
+ if (c == ' ') {
+ buf[bPos++] = '+';
+ } else {
+ buf[bPos++] = (char) c;
+ }
+ } else {
+ buf[bPos++] = '%';
+ buf[bPos++] = HEX[c >>> 4];
+ buf[bPos++] = HEX[c & 0xF];
+ }
+ }
+ out.append(CharBuffer.wrap(buf, 0, bPos));
+
+ }
+
+
+}
diff --git a/utils/src/main/java/at/gv/egiz/bku/utils/URLEncodingWriter.java b/utils/src/main/java/at/gv/egiz/bku/utils/URLEncodingWriter.java
new file mode 100644
index 00000000..3ba90265
--- /dev/null
+++ b/utils/src/main/java/at/gv/egiz/bku/utils/URLEncodingWriter.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright 2008 Federal Chancellery Austria and
+ * Graz University of Technology
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */package at.gv.egiz.bku.utils;
+
+import java.io.IOException;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.nio.charset.Charset;
+
+/**
+ * An URLEncoding <a
+ * href="http://tools.ietf.org/html/rfc3986#section-2.1">RFC3986, Section
+ * 2.1</a> Writer, that uses an UTF-8 encoding according to <a href
+ * ="http://www.w3.org/TR/html40/appendix/notes.html#non-ascii-chars"
+ * >http://www.w3.org/TR/html40/appendix/notes.html#non-ascii-chars</a> for
+ * writing non-ASCII characters.
+ *
+ * @author mcentner
+ */
+public class URLEncodingWriter extends Writer {
+
+ protected OutputStreamWriter osw;
+
+ public URLEncodingWriter(Appendable out) {
+ URLEncodingOutputStream urlEnc = new URLEncodingOutputStream(out);
+ osw = new OutputStreamWriter(urlEnc, Charset.forName("UTF-8"));
+ }
+
+ @Override
+ public void close() throws IOException {
+ osw.close();
+ }
+
+ @Override
+ public void flush() throws IOException {
+ osw.flush();
+ }
+
+ @Override
+ public void write(char[] cbuf, int off, int len) throws IOException {
+ osw.write(cbuf, off, len);
+ }
+
+}
diff --git a/utils/src/main/java/at/gv/egiz/marshal/MarshallerFactory.java b/utils/src/main/java/at/gv/egiz/marshal/MarshallerFactory.java
index ccebcc81..3ac0a86e 100644
--- a/utils/src/main/java/at/gv/egiz/marshal/MarshallerFactory.java
+++ b/utils/src/main/java/at/gv/egiz/marshal/MarshallerFactory.java
@@ -31,13 +31,17 @@ public class MarshallerFactory {
private static final Log log = LogFactory.getLog(MarshallerFactory.class);
- public static Marshaller createMarshaller(JAXBContext ctx, boolean formattedOutput) throws JAXBException {
+ public static Marshaller createMarshaller(JAXBContext ctx, boolean formattedOutput, boolean fragment) throws JAXBException {
Marshaller m = ctx.createMarshaller();
try {
if (formattedOutput) {
log.trace("setting marshaller property FORMATTED_OUTPUT");
m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE);
}
+ if (fragment) {
+ log.trace("setting marshaller property FRAGMENT");
+ m.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE);
+ }
log.trace("setting marshaller property NamespacePrefixMapper");
m.setProperty("com.sun.xml.bind.namespacePrefixMapper", new NamespacePrefixMapperImpl());
} catch (PropertyException ex) {
@@ -45,8 +49,12 @@ public class MarshallerFactory {
}
return m;
}
+
+ public static Marshaller createMarshaller(JAXBContext ctx, boolean formattedOutput) throws JAXBException {
+ return createMarshaller(ctx, formattedOutput, false);
+ }
public static Marshaller createMarshaller(JAXBContext ctx) throws JAXBException {
- return createMarshaller(ctx, false);
+ return createMarshaller(ctx, false, false);
}
}
diff --git a/utils/src/main/java/at/gv/egiz/marshal/NamespacePrefix.java b/utils/src/main/java/at/gv/egiz/marshal/NamespacePrefix.java
deleted file mode 100644
index 3ae1d0ff..00000000
--- a/utils/src/main/java/at/gv/egiz/marshal/NamespacePrefix.java
+++ /dev/null
@@ -1,34 +0,0 @@
-/*
- * Copyright 2008 Federal Chancellery Austria and
- * Graz University of Technology
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package at.gv.egiz.marshal;
-
-/**
- *
- * @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at>
- */
-public interface NamespacePrefix {
- String CARDCHANNEL_PREFIX = "cc";
- String ECDSA_PREFIX = "ecdsa";
- String PERSONDATA_PREFIX = "pr";
- String SAML10_PREFIX = "saml";
- String SL_PREFIX = "sl";
- String XADES_PREFIX = "xades";
- String XMLDSIG_PREFIX = "dsig";
- String XSI_PREFIX = "xsi";
-
-}
diff --git a/utils/src/main/java/at/gv/egiz/marshal/NamespacePrefixMapperImpl.java b/utils/src/main/java/at/gv/egiz/marshal/NamespacePrefixMapperImpl.java
index 519f6b1f..e0698977 100644
--- a/utils/src/main/java/at/gv/egiz/marshal/NamespacePrefixMapperImpl.java
+++ b/utils/src/main/java/at/gv/egiz/marshal/NamespacePrefixMapperImpl.java
@@ -17,6 +17,9 @@
package at.gv.egiz.marshal;
//import com.sun.xml.internal.bind.marshaller.NamespacePrefixMapper;
+import java.util.HashMap;
+import java.util.Map;
+
import com.sun.xml.bind.marshaller.NamespacePrefixMapper;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
@@ -29,45 +32,32 @@ public class NamespacePrefixMapperImpl extends NamespacePrefixMapper {
private static final Log log = LogFactory.getLog(NamespacePrefixMapperImpl.class);
+ protected static final Map<String, String> prefixMap = new HashMap<String, String>();
+
+ static {
+ prefixMap.put("http://www.w3.org/2001/XMLSchema-instance", "xsi");
+ prefixMap.put("http://www.w3.org/2000/09/xmldsig#", "dsig");
+ prefixMap.put("http://www.buergerkarte.at/namespaces/securitylayer/1.2#", "sl");
+ prefixMap.put("http://www.buergerkarte.at/cardchannel", "cc");
+ prefixMap.put("http://www.w3.org/2001/04/xmldsig-more#", "ecdsa");
+ prefixMap.put("http://reference.e-government.gv.at/namespace/persondata/20020228#", "pr");
+ prefixMap.put("urn:oasis:names:tc:SAML:1.0:assertion", "saml");
+ prefixMap.put("http://uri.etsi.org/01903/v1.1.1#", "xades");
+ prefixMap.put("http://www.buergerkarte.at/namespaces/securitylayer/20020225#", "sl10");
+ prefixMap.put("http://www.buergerkarte.at/namespaces/securitylayer/20020831#", "sl11");
+ }
+
+
@Override
public String getPreferredPrefix(String namespaceUri, String suggestion, boolean requirePrefix) {
if (log.isTraceEnabled()) {
log.trace("prefix for namespace " + namespaceUri + " requested");
}
- if ("http://www.w3.org/2001/XMLSchema-instance".equals(namespaceUri)) {
- return NamespacePrefix.XSI_PREFIX;
- }
-
- if ("http://www.w3.org/2000/09/xmldsig#".equals(namespaceUri)) {
- return NamespacePrefix.XMLDSIG_PREFIX;
- }
-
- if ("http://www.buergerkarte.at/namespaces/securitylayer/1.2#".equals(namespaceUri)) {
- return NamespacePrefix.SL_PREFIX;
- }
-
- if ("http://www.buergerkarte.at/cardchannel".equals(namespaceUri)) {
- return NamespacePrefix.CARDCHANNEL_PREFIX;
- }
-
- if ("http://www.w3.org/2001/04/xmldsig-more#".equals(namespaceUri)) {
- return NamespacePrefix.ECDSA_PREFIX;
- }
-
- if ("http://reference.e-government.gv.at/namespace/persondata/20020228#".equals(namespaceUri)) {
- return NamespacePrefix.PERSONDATA_PREFIX;
- }
-
- if ("urn:oasis:names:tc:SAML:1.0:assertion".equals(namespaceUri)) {
- return NamespacePrefix.SAML10_PREFIX;
- }
-
- if ("http://uri.etsi.org/01903/v1.1.1#".equals(namespaceUri)) {
- return NamespacePrefix.XADES_PREFIX;
- }
- return suggestion;
+ String prefix = prefixMap.get(namespaceUri);
+
+ return (prefix != null) ? prefix : suggestion;
}
/**
diff --git a/utils/src/main/java/at/gv/egiz/validation/ValidationEventLogger.java b/utils/src/main/java/at/gv/egiz/validation/ReportingValidationEventHandler.java
index 0fafdd7f..6543c333 100644
--- a/utils/src/main/java/at/gv/egiz/validation/ValidationEventLogger.java
+++ b/utils/src/main/java/at/gv/egiz/validation/ReportingValidationEventHandler.java
@@ -25,9 +25,11 @@ import org.apache.commons.logging.LogFactory;
*
* @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at>
*/
-public class ValidationEventLogger implements ValidationEventHandler {
+public class ReportingValidationEventHandler implements ValidationEventHandler {
- protected static final Log log = LogFactory.getLog(ValidationEventLogger.class);
+ protected static final Log log = LogFactory.getLog(ReportingValidationEventHandler.class);
+
+ protected ValidationEvent errorEvent;
/**
*
@@ -43,13 +45,20 @@ public class ValidationEventLogger implements ValidationEventHandler {
return true;
case ValidationEvent.ERROR:
log.warn(event.getMessage());
+ errorEvent = event;
return false;
case ValidationEvent.FATAL_ERROR:
log.error(event.getMessage());
+ errorEvent = event;
return false;
default:
log.debug(event.getMessage());
return false;
}
}
+
+ public ValidationEvent getErrorEvent() {
+ return errorEvent;
+ }
+
}
diff --git a/utils/src/main/java/at/gv/egiz/xades/QualifyingPropertiesFactory.java b/utils/src/main/java/at/gv/egiz/xades/QualifyingPropertiesFactory.java
index 71ca1db9..82cba624 100644
--- a/utils/src/main/java/at/gv/egiz/xades/QualifyingPropertiesFactory.java
+++ b/utils/src/main/java/at/gv/egiz/xades/QualifyingPropertiesFactory.java
@@ -16,8 +16,6 @@
*/
package at.gv.egiz.xades;
-import at.gv.egiz.marshal.MarshallerFactory;
-import at.gv.egiz.marshal.NamespacePrefixMapperImpl;
import java.math.BigInteger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
@@ -51,6 +49,8 @@ import org.w3._2000._09.xmldsig_.DigestMethodType;
import org.w3._2000._09.xmldsig_.X509IssuerSerialType;
import org.w3c.dom.Node;
+import at.gv.egiz.marshal.MarshallerFactory;
+
public class QualifyingPropertiesFactory {
public static String NS_URI_V1_1_1 = "http://uri.etsi.org/01903/v1.1.1#";
@@ -155,7 +155,7 @@ public class QualifyingPropertiesFactory {
return dataObjectFormatType;
}
- public JAXBElement<QualifyingPropertiesType> createQualifyingProperties111(Date signingTime, List<X509Certificate> certificates, String idValue, List<DataObjectFormatType> dataObjectFormats) throws QualifyingPropertiesException {
+ public JAXBElement<QualifyingPropertiesType> createQualifyingProperties111(String target, Date signingTime, List<X509Certificate> certificates, String idValue, List<DataObjectFormatType> dataObjectFormats) throws QualifyingPropertiesException {
GregorianCalendar gregorianCalendar = new GregorianCalendar();
gregorianCalendar.setTimeZone(TimeZone.getTimeZone("UTC"));
@@ -206,6 +206,8 @@ public class QualifyingPropertiesFactory {
QualifyingPropertiesType qualifyingPropertiesType = qpFactory.createQualifyingPropertiesType();
qualifyingPropertiesType.setSignedProperties(signedPropertiesType);
+ qualifyingPropertiesType.setTarget(target);
+
return qpFactory.createQualifyingProperties(qualifyingPropertiesType);
}
diff --git a/utils/src/test/java/at/gv/egiz/bku/utils/URLEncodingOutputStreamTest.java b/utils/src/test/java/at/gv/egiz/bku/utils/URLEncodingOutputStreamTest.java
new file mode 100644
index 00000000..e92b9584
--- /dev/null
+++ b/utils/src/test/java/at/gv/egiz/bku/utils/URLEncodingOutputStreamTest.java
@@ -0,0 +1,147 @@
+/*
+* Copyright 2008 Federal Chancellery Austria and
+* Graz University of Technology
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+* http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package at.gv.egiz.bku.utils;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.net.URLEncoder;
+import java.nio.charset.Charset;
+
+import org.junit.BeforeClass;
+import org.junit.Ignore;
+import org.junit.Test;
+
+public class URLEncodingOutputStreamTest {
+
+ private static String buf;
+
+ private static Charset UTF_8 = Charset.forName("UTF-8");
+
+ @BeforeClass
+ public static void setUpClass() throws IOException {
+
+ ClassLoader cl = URLEncodingOutputStreamTest.class.getClassLoader();
+ InputStream is = cl.getResourceAsStream("BigRequest.xml");
+
+ assertNotNull(is);
+
+ InputStreamReader reader = new InputStreamReader(is, UTF_8);
+
+ StringBuilder sb = new StringBuilder();
+
+ char[] b = new char[512];
+ for (int l; (l = reader.read(b)) != -1;) {
+ sb.append(b, 0, l);
+ }
+
+ buf = sb.toString();
+
+ }
+
+ @Test
+ public void testCompareResults() throws IOException {
+
+ String out1;
+ String out2;
+
+ // new
+ StringWriter writer = new StringWriter();
+ URLEncodingOutputStream urlEnc = new URLEncodingOutputStream(writer);
+ OutputStreamWriter streamWriter = new OutputStreamWriter(urlEnc, UTF_8);
+ streamWriter.append(buf);
+ streamWriter.flush();
+ out1 = writer.toString();
+
+ // URLEncoder
+ out2 = URLEncoder.encode(buf, UTF_8.name());
+
+ for (int i = 0; i < out1.length(); i++) {
+ if (out1.charAt(i) != out2.charAt(i)) {
+ System.out.println(i + ": " + out1.substring(i));
+ System.out.println(i + ": " + out2.substring(i));
+ }
+ }
+
+ assertEquals(out1, out2);
+
+ }
+
+ @Ignore
+ @Test
+ public void testURLEncodingOutputStream() throws IOException {
+
+ NullWriter writer = new NullWriter();
+
+ URLEncodingOutputStream urlEnc = new URLEncodingOutputStream(writer);
+ OutputStreamWriter streamWriter = new OutputStreamWriter(urlEnc, UTF_8);
+
+ long t0, t1, dt = 0;
+ for (int run = 0; run < 1000; run++) {
+ t0 = System.currentTimeMillis();
+ streamWriter.append(buf);
+ t1 = System.currentTimeMillis();
+ if (run > 1) {
+ dt += t1 - t0;
+ }
+ }
+ System.out.println("Time " + dt + "ms");
+
+ }
+
+ @Ignore
+ @Test
+ public void testURLEncodingNaive() throws IOException {
+
+ String in = new String(buf);
+
+ long t0, t1, dt = 0;
+ for (int run = 0; run < 1000; run++) {
+ t0 = System.currentTimeMillis();
+ URLEncoder.encode(in, "UTF-8");
+ t1 = System.currentTimeMillis();
+ if (run > 1) {
+ dt += t1 - t0;
+ }
+ }
+ System.out.println("Time (naive) " + dt + "ms");
+
+ }
+
+ public class NullWriter extends Writer {
+
+ @Override
+ public void close() throws IOException {
+ }
+
+ @Override
+ public void flush() throws IOException {
+ }
+
+ @Override
+ public void write(char[] cbuf, int off, int len) throws IOException {
+ }
+
+ }
+
+}
diff --git a/utils/src/test/resources/BigRequest.xml b/utils/src/test/resources/BigRequest.xml
new file mode 100644
index 00000000..90eb1eb8
--- /dev/null
+++ b/utils/src/test/resources/BigRequest.xml
@@ -0,0 +1,1060 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<sl:CreateXMLSignatureRequest
+ xmlns:sl="http://www.buergerkarte.at/namespaces/securitylayer/1.2#">
+<sl:KeyboxIdentifier>SecureSignatureKeypair</sl:KeyboxIdentifier>
+ <sl:DataObjectInfo Structure="enveloping">
+ <sl:DataObject>
+ <sl:Base64Content>TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3RldHVyIGFkaXBpc2Np
+bmcgZWxpdC4gTnVsbGFtIHZ1bHB1dGF0ZSwgcmlzdXMgaW1wZXJkaWV0IGNvbnNl
+cXVhdCB2YXJpdXMsIHJpc3VzIGR1aSB0ZW1wdXMgbGVvLCBub24gbGFjaW5pYSBl
+bmltIG51bmMgYSBzZW0uIERvbmVjIHBvcnRhLCBpcHN1bSB0aW5jaWR1bnQgdWx0
+cmljZXMgaW50ZXJkdW0sIGZlbGlzIGF1Z3VlIHNvZGFsZXMgYW50ZSwgdmVsIG9y
+bmFyZSBsaWJlcm8gbnVsbGEgZXQgcHVydXMuIENyYXMgdGVtcHVzIHZhcml1cyBw
+b3J0YS4gRG9uZWMgaWQgcHVydXMgdXQgdmVsaXQgYmliZW5kdW0gbHVjdHVzIGJs
+YW5kaXQgc2l0IGFtZXQgbmVxdWUuIENsYXNzIGFwdGVudCB0YWNpdGkgc29jaW9z
+cXUgYWQgbGl0b3JhIHRvcnF1ZW50IHBlciBjb251YmlhIG5vc3RyYSwgcGVyIGlu
+Y2VwdG9zIGhpbWVuYWVvcy4gQ3JhcyBmYWNpbGlzaXMgdGVtcHVzIGZlcm1lbnR1
+bS4gRG9uZWMgZmVybWVudHVtIG1hc3NhIGV0IHNhcGllbiBwb3N1ZXJlIHZlbmVu
+YXRpcy4gSW4gcXVpcyB1cm5hIG9yY2kuIER1aXMgYSBsaWJlcm8gb3JjaS4gTnVs
+bGEgcG9ydHRpdG9yIGF1Z3VlIHZpdGFlIGxpZ3VsYSB0ZW1wb3Igc2VkIHJ1dHJ1
+bSBtaSBjdXJzdXMuIEFlbmVhbiBpYWN1bGlzIG5pc2kgYXQgaXBzdW0gY29uc2Vj
+dGV0dXIgZWdldCB2YXJpdXMgbWFnbmEgc29sbGljaXR1ZGluLiBVdCBmYWNpbGlz
+aXMgdGVsbHVzIGEgbmVxdWUgZWdlc3RhcyBwbGFjZXJhdC4gRG9uZWMgdG9ydG9y
+IHZlbGl0LCB0aW5jaWR1bnQgYSBtb2xsaXMgY3Vyc3VzLCBsdWN0dXMgYWxpcXVh
+bSBsaWJlcm8uIER1aXMgbm9uIHRlbGx1cyBwcmV0aXVtIHRlbGx1cyB2YXJpdXMg
+ZWxlaWZlbmQgaW4gc2VkIHNlbS4gU3VzcGVuZGlzc2UgZmVybWVudHVtIHRlbGx1
+cyBpZCBmZWxpcyB0ZW1wdXMgdml2ZXJyYS4gRG9uZWMgcG9ydHRpdG9yIHRpbmNp
+ZHVudCBtYXVyaXMgbmVjIGV1aXNtb2QuCgpQcmFlc2VudCB1bGxhbWNvcnBlciB0
+cmlzdGlxdWUgbG9yZW0sIGV0IHBsYWNlcmF0IG51bmMgZWxlbWVudHVtIHV0LiBN
+b3JiaSBldCBhZGlwaXNjaW5nIHNlbS4gTmFtIHZlbCBuaWJoIGV1IGxlbyBjb25k
+aW1lbnR1bSByaG9uY3VzIHF1aXMgc2VkIHVybmEuIFBoYXNlbGx1cyBpZCBqdXN0
+byB1dCBvcmNpIHZlc3RpYnVsdW0gc2NlbGVyaXNxdWUuIE5hbSBtb2xsaXMgdG9y
+dG9yIHB1cnVzLiBQZWxsZW50ZXNxdWUgaWFjdWxpcyBzZW1wZXIgbWFsZXN1YWRh
+LiBJbnRlZ2VyIGJsYW5kaXQgZmVsaXMgYXQgbG9yZW0gZXVpc21vZCB2ZW5lbmF0
+aXMuIE1hZWNlbmFzIG5lYyBlbGVpZmVuZCBsZW8uIERvbmVjIGxvYm9ydGlzLCBy
+aXN1cyBuZWMgdGVtcHVzIHZvbHV0cGF0LCBudWxsYSBlbGl0IGx1Y3R1cyBhcmN1
+LCBhYyBwb3N1ZXJlIGxhY3VzIG1hc3NhIGluIG1pLiBNYWVjZW5hcyBzaXQgYW1l
+dCBudW5jIG5lYyB0ZWxsdXMgZWdlc3RhcyB2ZXN0aWJ1bHVtIHZpdGFlIGV0IGVs
+aXQuIE51bGxhbSBjb25zZWN0ZXR1ciBydXRydW0gdGVsbHVzIGFjIGFjY3Vtc2Fu
+LiBDdXJhYml0dXIgZ3JhdmlkYSBhdWd1ZSBldCBtZXR1cyBjdXJzdXMgZWxlaWZl
+bmQuIENyYXMgb2RpbyBhcmN1LCB0aW5jaWR1bnQgdXQgZWdlc3RhcyB2ZWwsIGdy
+YXZpZGEgaW4gZXJvcy4gTnVuYyBldCBtYWxlc3VhZGEgcXVhbS4gTWF1cmlzIGFj
+IHRlbGx1cyBhcmN1LgoKQ3JhcyBuaXNsIHNhcGllbiwgdGluY2lkdW50IGVnZXQg
+ZWxlaWZlbmQgdmVsLCBwcmV0aXVtIGlkIGxlY3R1cy4gQWxpcXVhbSB0b3J0b3Ig
+dXJuYSwgcG9zdWVyZSBpZCBydXRydW0gbHVjdHVzLCBhdWN0b3Igc2VkIGFudGUu
+IFByb2luIGZlcm1lbnR1bSwgbmliaCBhIHZvbHV0cGF0IHZvbHV0cGF0LCBlcm9z
+IGRvbG9yIHNjZWxlcmlzcXVlIG1hZ25hLCB0ZW1wdXMgc29sbGljaXR1ZGluIGxp
+YmVybyBkb2xvciBydXRydW0gZXN0LiBNYXVyaXMgcXVpcyBqdXN0byBhcmN1LiBQ
+cm9pbiB2ZWhpY3VsYSBhZGlwaXNjaW5nIGVyb3Mgbm9uIGNvbmRpbWVudHVtLiBO
+dW5jIHN1c2NpcGl0LCBsZWN0dXMgZXUgaWFjdWxpcyBtb2xlc3RpZSwgbWkgZG9s
+b3IgcG9ydGEgZG9sb3IsIGV1IHNhZ2l0dGlzIG1hc3NhIGlwc3VtIGluIG1pLiBO
+dW5jIHNlbXBlciBzY2VsZXJpc3F1ZSBsb3JlbSwgYSBzb2RhbGVzIHRvcnRvciBw
+b3J0dGl0b3IgaWQuIE51bGxhIG1hdHRpcywgdG9ydG9yIG5lYyBpYWN1bGlzIHBy
+ZXRpdW0sIGVyYXQgbGFjdXMgdnVscHV0YXRlIGR1aSwgdnVscHV0YXRlIGZhY2ls
+aXNpcyBkb2xvciB0dXJwaXMgdXQgZmVsaXMuIE1hZWNlbmFzIHZpdGFlIHNlbSBl
+dCBuaWJoIHNhZ2l0dGlzIHRpbmNpZHVudCBxdWlzIGluIHRvcnRvci4gQWxpcXVh
+bSBpZCBzb2RhbGVzIHJpc3VzLiBJbnRlZ2VyIGZhY2lsaXNpcywgc2FwaWVuIHV0
+IHNhZ2l0dGlzIGNvbnNlY3RldHVyLCBkaWFtIGxvcmVtIHZpdmVycmEgZG9sb3Is
+IHF1aXMgY29tbW9kbyBuaWJoIGVyYXQgcXVpcyBtZXR1cy4gUHJvaW4gZGljdHVt
+IHJpc3VzIG1hdXJpcy4gTnVuYyBldSB1cm5hIHNpdCBhbWV0IHZlbGl0IHBsYWNl
+cmF0IGVsZWlmZW5kLiBBZW5lYW4gc2l0IGFtZXQgcHVydXMgbnVuYy4gUHJvaW4g
+bm9uIG5lcXVlIGEgdGVsbHVzIG1hdHRpcyBlZ2VzdGFzIGF0IHV0IG51bmMuIERv
+bmVjIG5vbiBhbnRlIHZpdGFlIG9yY2kgcGVsbGVudGVzcXVlIHNjZWxlcmlzcXVl
+LiBNYWVjZW5hcyBhYyBpYWN1bGlzIGZlbGlzLiBVdCBhZGlwaXNjaW5nIHN1c2Np
+cGl0IGRpYW0gdXQgcG9ydGEuIERvbmVjIHZlc3RpYnVsdW0gbGFjaW5pYSBtYWdu
+YSwgaWQgcnV0cnVtIG5pc2kgdmVuZW5hdGlzIHNlZC4KCk51bGxhIHNhZ2l0dGlz
+IHBoYXJldHJhIGFudGUgZXUgb3JuYXJlLiBBbGlxdWFtIGV1IGRvbG9yIHV0IHVy
+bmEgY29uZGltZW50dW0gcnV0cnVtLiBJbnRlZ2VyIHN1c2NpcGl0LCB2ZWxpdCBu
+ZWMgc29sbGljaXR1ZGluIGN1cnN1cywgbGVjdHVzIHF1YW0gc2NlbGVyaXNxdWUg
+bWksIGlkIGF1Y3RvciBzYXBpZW4gdG9ydG9yIHNlZCB0ZWxsdXMuIERvbmVjIHRp
+bmNpZHVudCB0aW5jaWR1bnQgbGVjdHVzLCBxdWlzIHNvZGFsZXMgcHVydXMgaW1w
+ZXJkaWV0IGV0LiBOdWxsYSBmYWNpbGlzaS4gTnVsbGFtIGlhY3VsaXMgZWxlbWVu
+dHVtIGZlbGlzLCBlZ2V0IG1hdHRpcyBkb2xvciB0cmlzdGlxdWUgYWMuIFNlZCBl
+Z2V0IHNlbSBuZXF1ZS4gVXQgZmVybWVudHVtLCBtaSBxdWlzIHZvbHV0cGF0IHZl
+bmVuYXRpcywgbGFjdXMgbmVxdWUgY29udmFsbGlzIGVzdCwgdml0YWUgc3VzY2lw
+aXQgdHVycGlzIGFudGUgYXQgcmlzdXMuIE51bmMgZmVybWVudHVtLCBtYWduYSBx
+dWlzIHZlbmVuYXRpcyBldWlzbW9kLCBlbGl0IHZlbGl0IGZlcm1lbnR1bSBqdXN0
+bywgYSBkaWN0dW0gbGlndWxhIGp1c3RvIGFjIGxvcmVtLiBTZWQgZWdldCB0b3J0
+b3IgbWFnbmEsIHZpdmVycmEgaW50ZXJkdW0gbGVvLiBRdWlzcXVlIGluIGxhY3Vz
+IGV0IGxlY3R1cyBhZGlwaXNjaW5nIGNvbnNlY3RldHVyIGluIHF1aXMgZXN0LiBN
+YXVyaXMgZXQgZG9sb3IgZXQgbmVxdWUgbW9sZXN0aWUgY29uc2VjdGV0dXIgZXVp
+c21vZCBldSBlbGl0LiBOdWxsYSBmYWNpbGlzaS4gUHJvaW4gYWMgdmVsaXQgaXBz
+dW0sIHV0IHRyaXN0aXF1ZSBtYWduYS4gVmVzdGlidWx1bSBwb3N1ZXJlIG1hbGVz
+dWFkYSBuaXNsIHNpdCBhbWV0IGFsaXF1YW0uIFN1c3BlbmRpc3NlIHNlZCBpcHN1
+bSBpZCB0ZWxsdXMgcG9ydGEgcG9zdWVyZSBlZ2V0IHNpdCBhbWV0IHR1cnBpcy4g
+TnVuYyBhYyBkb2xvciB2ZWwgdXJuYSBkYXBpYnVzIGZlcm1lbnR1bSBuZWMgdmVo
+aWN1bGEgdXJuYS4gRnVzY2UgdGluY2lkdW50IG1ldHVzIGV1IGlwc3VtIG1hdHRp
+cyB0cmlzdGlxdWUuIFNlZCBmYXVjaWJ1cyBmcmluZ2lsbGEgYWRpcGlzY2luZy4g
+Q3JhcyBwaGFyZXRyYSwgYW50ZSBzZWQgYWNjdW1zYW4gcmhvbmN1cywgZWxpdCBk
+b2xvciBsYWNpbmlhIG1hdXJpcywgYXQgbGFvcmVldCBsaWJlcm8gYXVndWUgYXQg
+bmlzbC4KClByb2luIGEgbGVvIHV0IHRvcnRvciBwb3J0YSBsdWN0dXMuIFZlc3Rp
+YnVsdW0gYW50ZSBpcHN1bSBwcmltaXMgaW4gZmF1Y2lidXMgb3JjaSBsdWN0dXMg
+ZXQgdWx0cmljZXMgcG9zdWVyZSBjdWJpbGlhIEN1cmFlOyBVdCBzZWQgbnVuYyB2
+ZWwgbWV0dXMgc3VzY2lwaXQgY29uZ3VlIGF0IGEgZG9sb3IuIE51bmMgZXUgdG9y
+dG9yIGxvcmVtLCBuZWMgY29uZ3VlIGxpYmVyby4gTW9yYmkgbGFvcmVldCBsZWN0
+dXMgbmlzbCwgdml0YWUgcmhvbmN1cyBlbGl0LiBTdXNwZW5kaXNzZSBldCBxdWFt
+IHF1aXMgZHVpIGxhY2luaWEgc29kYWxlcyBuZWMgZXUgbGlndWxhLiBQZWxsZW50
+ZXNxdWUgbm9uIGlwc3VtIGxlbywgc2l0IGFtZXQgbW9sZXN0aWUgZHVpLiBTZWQg
+YSBhdWd1ZSBlZ2V0IG1hdXJpcyBncmF2aWRhIG1hbGVzdWFkYSBldCBxdWlzIGlw
+c3VtLiBBbGlxdWFtIGFjIG5pYmggbGlndWxhLCBpbiBwb3J0dGl0b3IgZWxpdC4g
+TWF1cmlzIHR1cnBpcyBvcmNpLCBhY2N1bXNhbiBpbiBpbnRlcmR1bSBhdCwgZmFj
+aWxpc2lzIHZpdGFlIHR1cnBpcy4gUXVpc3F1ZSBtYXR0aXMgcGVsbGVudGVzcXVl
+IGVyb3MgdmVsIHZpdmVycmEuIFZlc3RpYnVsdW0gbGFvcmVldCBjb25ndWUgYWxp
+cXVhbS4gRG9uZWMgcG9zdWVyZSBtYXVyaXMgbmVjIGxpYmVybyBvcm5hcmUgZXQg
+ZWdlc3RhcyBhbnRlIHB1bHZpbmFyLiBDdXJhYml0dXIgYW50ZSBhbnRlLCBtb2xl
+c3RpZSB1dCBiaWJlbmR1bSB2aXRhZSwgcnV0cnVtIHZlbCByaXN1cy4gRG9uZWMg
+ZXQgbmVxdWUgcHVydXMsIHNpdCBhbWV0IGFkaXBpc2NpbmcgZmVsaXMuIFBlbGxl
+bnRlc3F1ZSBkaWduaXNzaW0gdmVzdGlidWx1bSBzYXBpZW4gbmVjIGZyaW5naWxs
+YS4gUHJvaW4gbmVjIHB1cnVzIGV0IGVzdCBldWlzbW9kIHBoYXJldHJhLiBQZWxs
+ZW50ZXNxdWUgZGFwaWJ1cyBkYXBpYnVzIG1ldHVzIHZlbCBmYWNpbGlzaXMuIFZp
+dmFtdXMgdmVsIGVsaXQgbnVuYy4KCkV0aWFtIGFjIGVuaW0gZWdldCBtYXVyaXMg
+ZmF1Y2lidXMgZGFwaWJ1cy4gTW9yYmkgdml0YWUgbGVjdHVzIG5lcXVlLiBNYXVy
+aXMgc2FwaWVuIG1ldHVzLCBzdXNjaXBpdCBzaXQgYW1ldCBlZ2VzdGFzIHZpdGFl
+LCBwaGFyZXRyYSBhIG1hc3NhLiBVdCB2YXJpdXMsIHRvcnRvciBzZWQgZnJpbmdp
+bGxhIHBsYWNlcmF0LCBuZXF1ZSBkaWFtIGNvbmd1ZSBudW5jLCBpZCBhbGlxdWV0
+IG5pc2kgcmlzdXMgdXQgdXJuYS4gVml2YW11cyBwbGFjZXJhdCBwb3J0YSBhcmN1
+IHZpdGFlIGFjY3Vtc2FuLiBNYXVyaXMgaGVuZHJlcml0LCBlbmltIHZpdGFlIGFs
+aXF1YW0gcG9ydHRpdG9yLCBwdXJ1cyBuZXF1ZSBncmF2aWRhIG1hZ25hLCBub24g
+cHJldGl1bSBuZXF1ZSBsZWN0dXMgc2l0IGFtZXQgdG9ydG9yLiBEdWlzIHN1c2Np
+cGl0IG9ybmFyZSBvZGlvIHZpdGFlIHBoYXJldHJhLiBEb25lYyBlbGVpZmVuZCwg
+ZHVpIG5vbiBncmF2aWRhIGNvbnZhbGxpcywgb2RpbyBhcmN1IGJsYW5kaXQgbWFn
+bmEsIG5vbiBwb3J0YSBsZW8gbGliZXJvIHBvcnRhIG1hZ25hLiBEdWlzIGVzdCB1
+cm5hLCBsdWN0dXMgZXUgaW50ZXJkdW0gbmVjLCBpYWN1bGlzIG5lYyBlbGl0LiBD
+dXJhYml0dXIgZmFjaWxpc2lzIHRlbXB1cyB0ZW1wdXMuIFNlZCBzZW0gdXJuYSwg
+dml2ZXJyYSBldSBpbXBlcmRpZXQgc2l0IGFtZXQsIGludGVyZHVtIGV0IGp1c3Rv
+LiBJbiBoYWMgaGFiaXRhc3NlIHBsYXRlYSBkaWN0dW1zdC4gRG9uZWMgdGluY2lk
+dW50IG1hc3NhIHV0IGR1aSBmZXJtZW50dW0gcG9zdWVyZSBldCBuZWMgdHVycGlz
+LiBFdGlhbSBmZXJtZW50dW0gcG9ydGEgbWF1cmlzLiBTdXNwZW5kaXNzZSBsYWN1
+cyBsaWJlcm8sIHByZXRpdW0gaW4gZWdlc3RhcyB2ZWwsIHNhZ2l0dGlzIGV0IG1h
+c3NhLiBOdWxsYSBhbGlxdWFtIGxhb3JlZXQgc2FwaWVuLCBhdCBwZWxsZW50ZXNx
+dWUgZXJvcyB2ZW5lbmF0aXMgcXVpcy4gSW50ZWdlciBhY2N1bXNhbiwgbGFjdXMg
+dXQgZGFwaWJ1cyBlZ2VzdGFzLCByaXN1cyBuaXNsIHNlbXBlciB0dXJwaXMsIHNp
+dCBhbWV0IHZpdmVycmEgZmVsaXMgdHVycGlzIHNlZCB2ZWxpdC4KCkRvbmVjIHZl
+aGljdWxhLCB0ZWxsdXMgcXVpcyBtb2xlc3RpZSBiaWJlbmR1bSwgYXVndWUgbmlz
+bCB0ZW1wdXMgbG9yZW0sIHNpdCBhbWV0IGNvbmRpbWVudHVtIGp1c3RvIGF1Z3Vl
+IHNpdCBhbWV0IGFudGUuIE51bGxhbSB0b3J0b3Igc2VtLCBtYXR0aXMgYWMgcG9y
+dHRpdG9yIHZpdGFlLCBpYWN1bGlzIHNlZCBkdWkuIEN1bSBzb2NpaXMgbmF0b3F1
+ZSBwZW5hdGlidXMgZXQgbWFnbmlzIGRpcyBwYXJ0dXJpZW50IG1vbnRlcywgbmFz
+Y2V0dXIgcmlkaWN1bHVzIG11cy4gRXRpYW0gaW4gc2VtIGlwc3VtLiBJbiBldSBt
+b2xlc3RpZSBtZXR1cy4gVml2YW11cyBsYW9yZWV0IGZhdWNpYnVzIG5pYmgsIGEg
+c2VtcGVyIG5pYmggZnJpbmdpbGxhIHV0LiBNYWVjZW5hcyBsYW9yZWV0LCBwdXJ1
+cyBldSBzb2xsaWNpdHVkaW4gcGhhcmV0cmEsIGp1c3RvIHRlbGx1cyBjb21tb2Rv
+IGF1Z3VlLCBpbiBmYXVjaWJ1cyBsZW8ganVzdG8gbmVjIG5pc2wuIE5hbSBldSBw
+cmV0aXVtIGVzdC4gRnVzY2Ugc2l0IGFtZXQgcXVhbSBsb3JlbSwgdXQgc29kYWxl
+cyB0ZWxsdXMuIE51bmMgZWxlbWVudHVtLCBzZW0gc2NlbGVyaXNxdWUgaWFjdWxp
+cyBpbnRlcmR1bSwgZXJvcyBkdWkgb3JuYXJlIG9yY2ksIHNlZCBwbGFjZXJhdCBy
+aXN1cyBlcmF0IGVnZXQgYXJjdS4gTW9yYmkgYWMgbWV0dXMgaWQgbGlndWxhIHBv
+cnRhIGdyYXZpZGEuIE51bmMgY29udmFsbGlzIGRpYW0gaW4gbmlzaSBncmF2aWRh
+IGFjIGNvbW1vZG8gbGFjdXMgZGlnbmlzc2ltLiBDdW0gc29jaWlzIG5hdG9xdWUg
+cGVuYXRpYnVzIGV0IG1hZ25pcyBkaXMgcGFydHVyaWVudCBtb250ZXMsIG5hc2Nl
+dHVyIHJpZGljdWx1cyBtdXMuIEV0aWFtIHF1aXMgdmVsaXQgZXUgZmVsaXMgbHVj
+dHVzIHBlbGxlbnRlc3F1ZSBub24gZWdlc3RhcyBuZXF1ZS4gTnVuYyBuaWJoIHRl
+bGx1cywgcGxhY2VyYXQgbm9uIGZlcm1lbnR1bSBhdCwgb3JuYXJlIHF1aXMgZGlh
+bS4gU3VzcGVuZGlzc2Ugc2l0IGFtZXQgcHVydXMgcXVpcyBkdWkgY29uc2VxdWF0
+IHByZXRpdW0uIEZ1c2NlIGV0IG1hZ25hIG5pc2ksIHZlbCB2ZXN0aWJ1bHVtIGVy
+b3MuIEluIGZhdWNpYnVzLCBsYWN1cyBlZ2V0IGZhdWNpYnVzIGZldWdpYXQsIGxp
+Z3VsYSBlbmltIHZlc3RpYnVsdW0gbG9yZW0sIGEgdml2ZXJyYSBsb3JlbSBlc3Qg
+dml0YWUgcXVhbS4gTnVuYyBwdXJ1cyBuaXNsLCB2YXJpdXMgZXQgdGVtcG9yIHVs
+dHJpY2llcywgaWFjdWxpcyBhIGxpYmVyby4gQ2xhc3MgYXB0ZW50IHRhY2l0aSBz
+b2Npb3NxdSBhZCBsaXRvcmEgdG9ycXVlbnQgcGVyIGNvbnViaWEgbm9zdHJhLCBw
+ZXIgaW5jZXB0b3MgaGltZW5hZW9zLgoKRnVzY2UgdmVsIGp1c3RvIHNpdCBhbWV0
+IHF1YW0gbWFsZXN1YWRhIG9ybmFyZSBzaXQgYW1ldCBldCBhbnRlLiBOdWxsYW0g
+cmhvbmN1cyBwb3J0YSBzZW0gcXVpcyBtYWxlc3VhZGEuIENsYXNzIGFwdGVudCB0
+YWNpdGkgc29jaW9zcXUgYWQgbGl0b3JhIHRvcnF1ZW50IHBlciBjb251YmlhIG5v
+c3RyYSwgcGVyIGluY2VwdG9zIGhpbWVuYWVvcy4gRG9uZWMgYW50ZSBvZGlvLCB0
+aW5jaWR1bnQgYWMgbW9sbGlzIGluLCB1bHRyaWNlcyBuZWMgZHVpLiBOdW5jIGN1
+cnN1cyBtYWduYSBuZWMgcHVydXMgZnJpbmdpbGxhIGEgbW9sZXN0aWUgcHVydXMg
+bG9ib3J0aXMuIEZ1c2NlIHJ1dHJ1bSwgbG9yZW0gZWdldCB1bGxhbWNvcnBlciBm
+cmluZ2lsbGEsIGR1aSBsaWd1bGEgc29sbGljaXR1ZGluIHJpc3VzLCB2aXRhZSBw
+b3N1ZXJlIG5lcXVlIGZlbGlzIHZpdGFlIHF1YW0uIEN1cmFiaXR1ciBjb25kaW1l
+bnR1bSBsaWJlcm8gYXQgb3JjaSBhdWN0b3IgZXUgY29tbW9kbyBsaWJlcm8gc29s
+bGljaXR1ZGluLiBDcmFzIHNlZCBwdXJ1cyBtaSwgc2VkIGNvbnZhbGxpcyBuaWJo
+LiBOdWxsYW0gYWMgbG9yZW0gYSBpcHN1bSBsYWNpbmlhIHVsbGFtY29ycGVyIGlk
+IHF1aXMgdG9ydG9yLiBNb3JiaSBlbGVpZmVuZCwgbnVsbGEgdmVsIHZlbmVuYXRp
+cyBjb25kaW1lbnR1bSwgbGVjdHVzIHRvcnRvciB2ZW5lbmF0aXMgcmlzdXMsIGEg
+bHVjdHVzIGxhY3VzIGlwc3VtIHV0IHNhcGllbi4KCk1hdXJpcyBsYW9yZWV0IG51
+bmMgc2l0IGFtZXQgZW5pbSBkaWN0dW0gbG9ib3J0aXMuIE1hdXJpcyBydXRydW0s
+IGVsaXQgdXQgbW9sZXN0aWUgb3JuYXJlLCB0b3J0b3IgZXJvcyB2YXJpdXMgbnVu
+YywgdHJpc3RpcXVlIHBlbGxlbnRlc3F1ZSB0dXJwaXMgYXVndWUgaW4gYW50ZS4g
+QWVuZWFuIGZlbGlzIGR1aSwgZnJpbmdpbGxhIGluIGFsaXF1YW0gYXQsIG9ybmFy
+ZSB1dCBudWxsYS4gSW4gbWkgbnVuYywgc2VtcGVyIGluIGNvbmRpbWVudHVtIG5v
+biwgY29uZ3VlIGFjIG1hdXJpcy4gQ3VyYWJpdHVyIGltcGVyZGlldCByaG9uY3Vz
+IHNlbSwgbW9sZXN0aWUgYWRpcGlzY2luZyBpcHN1bSBzb2xsaWNpdHVkaW4gYS4g
+Vml2YW11cyB1dCBpcHN1bSBxdWlzIHR1cnBpcyBhbGlxdWV0IHRpbmNpZHVudCBh
+Y2N1bXNhbiBhYyBxdWFtLiBDdXJhYml0dXIgcG9ydHRpdG9yLCBtYXVyaXMgYWMg
+bHVjdHVzIHZpdmVycmEsIHB1cnVzIGVzdCBhZGlwaXNjaW5nIHNhcGllbiwgc2l0
+IGFtZXQgYWxpcXVhbSBxdWFtIG51bGxhIGF0IGVyYXQuIFZpdmFtdXMgdGVtcHVz
+LCBqdXN0byBhIHByZXRpdW0gZGljdHVtLCBpcHN1bSBudW5jIGxhb3JlZXQgdGVs
+bHVzLCBuZWMgdGVtcHVzIHNlbSBuaXNpIGFjIHF1YW0uIFZpdmFtdXMgaW4gbWFz
+c2EgZW5pbS4gUXVpc3F1ZSBuZWMgdG9ydG9yIHZpdGFlIG51bGxhIHVsdHJpY2Vz
+IGNvbnZhbGxpcy4gTnVsbGFtIHRvcnRvciBtYXVyaXMsIGF1Y3RvciB2aXRhZSB0
+ZW1wb3IgZXQsIGF1Y3RvciBuZWMgc2FwaWVuLiBRdWlzcXVlIHVsbGFtY29ycGVy
+IHZpdmVycmEgdmVuZW5hdGlzLiBNYWVjZW5hcyBxdWlzIGdyYXZpZGEgbWFzc2Eu
+IEludGVnZXIgdml0YWUganVzdG8gbGVjdHVzLCBhYyBtYWxlc3VhZGEgcXVhbS4g
+TWFlY2VuYXMgc2l0IGFtZXQgbmVxdWUgbnVsbGEsIG5lYyBpbXBlcmRpZXQgaXBz
+dW0uIFNlZCB0ZW1wdXMgYmliZW5kdW0gc2FwaWVuLCBub24gZnJpbmdpbGxhIG51
+bmMgZWxlbWVudHVtIGV1LiBOdW5jIGF1Y3RvciBhbGlxdWV0IGxlbywgYmliZW5k
+dW0gcHJldGl1bSBkaWFtIHBsYWNlcmF0IGFjLiBOYW0gaW4gZW5pbSBkdWkuIFNl
+ZCBldCBuaWJoIG5vbiBudW5jIHBsYWNlcmF0IHBoYXJldHJhLiBTZWQgb2RpbyBs
+ZW8sIGNvbmRpbWVudHVtIGV1IHN1c2NpcGl0IGV1LCBtb2xsaXMgZWdldCBuaXNp
+LgoKUHJvaW4gb3JuYXJlLCBpcHN1bSB2aXRhZSBsYW9yZWV0IHZhcml1cywgbGFj
+dXMgbGVvIHBoYXJldHJhIG1hdXJpcywgc2VkIGNvbnZhbGxpcyBsaWJlcm8gbWV0
+dXMgcmhvbmN1cyBvcmNpLiBNYXVyaXMgcnV0cnVtIGxlbyB2ZWwgYW50ZSBlZ2Vz
+dGFzIGEgYWRpcGlzY2luZyBlc3QgdmVuZW5hdGlzLiBJbiBldSBtaSB1dCBlbGl0
+IHRyaXN0aXF1ZSB2ZWhpY3VsYS4gTnVuYyBwb3N1ZXJlLCBlbmltIHF1aXMgc3Vz
+Y2lwaXQgYWNjdW1zYW4sIGVsaXQgbGVvIHNlbXBlciBudW5jLCBub24gbGFvcmVl
+dCBhbnRlIG5pYmggc2l0IGFtZXQgbWF1cmlzLiBBbGlxdWFtIGFjIHF1YW0gcXVp
+cyBuaXNsIHNvbGxpY2l0dWRpbiBtb2xlc3RpZSBpZCBhYyBudWxsYS4gSW50ZWdl
+ciBldSBkb2xvciBpcHN1bS4gUGhhc2VsbHVzIGludGVyZHVtIHZlaGljdWxhIHNl
+bXBlci4gU3VzcGVuZGlzc2UgbmVjIGFyY3UgYWMgZXN0IGlhY3VsaXMgdmVoaWN1
+bGEuIE1hZWNlbmFzIHNlbXBlciBsaWJlcm8gaWFjdWxpcyBsb3JlbSBmZXVnaWF0
+IGF1Y3Rvci4gQWxpcXVhbSBibGFuZGl0IHNlbXBlciBibGFuZGl0LiBVdCBlZ2Vz
+dGFzIGVyb3Mgc2VkIG5pc2kgZGFwaWJ1cyBhIHNlbXBlciBtZXR1cyBkYXBpYnVz
+LiBNb3JiaSB2dWxwdXRhdGUgbGFvcmVldCB2ZWxpdCwgZXUgYmliZW5kdW0gYXJj
+dSBjb21tb2RvIG5vbi4gTWFlY2VuYXMgZmVsaXMgbnVuYywgdm9sdXRwYXQgaWQg
+dmVzdGlidWx1bSB2aXRhZSwgdmVzdGlidWx1bSB2aXRhZSBhbnRlLgoKU2VkIG51
+bmMgaXBzdW0sIGF1Y3RvciB2ZWwgZmV1Z2lhdCBzaXQgYW1ldCwgaW50ZXJkdW0g
+YXQgbGlndWxhLiBNYXVyaXMgcXVpcyBuaXNpIGVnZXQgbGVjdHVzIGdyYXZpZGEg
+c2VtcGVyIGluIHF1aXMgZW5pbS4gTnVsbGEgYXVjdG9yIGVsZW1lbnR1bSBqdXN0
+bywgbm9uIGJpYmVuZHVtIGR1aSBmZXJtZW50dW0gYWMuIEZ1c2NlIGxvcmVtIGF1
+Z3VlLCBjb21tb2RvIG5vbiB0aW5jaWR1bnQgc2l0IGFtZXQsIGFjY3Vtc2FuIHNl
+ZCBtZXR1cy4gTmFtIHNhcGllbiBlbmltLCBkaWduaXNzaW0gZXQgdmFyaXVzIGV1
+LCBsdWN0dXMgYXQgb3JjaS4gTnVsbGFtIGxpYmVybyBvcmNpLCBiaWJlbmR1bSBh
+IGxhY2luaWEgYWMsIHZ1bHB1dGF0ZSBmYXVjaWJ1cyBtaS4gTW9yYmkgY29uZGlt
+ZW50dW0gZmVybWVudHVtIGRpZ25pc3NpbS4gTG9yZW0gaXBzdW0gZG9sb3Igc2l0
+IGFtZXQsIGNvbnNlY3RldHVyIGFkaXBpc2NpbmcgZWxpdC4gUXVpc3F1ZSBldCBu
+ZXF1ZSBlcmF0LCB1dCB2b2x1dHBhdCBsZW8uIFZlc3RpYnVsdW0gdmVsIGxpZ3Vs
+YSBuZXF1ZS4gTnVuYyBwaGFyZXRyYSBsaWJlcm8gaW4gbWF1cmlzIGRhcGlidXMg
+aW4gbGFvcmVldCBkdWkgbHVjdHVzLiBQaGFzZWxsdXMgdmVsaXQgbmlzaSwgZGlj
+dHVtIGF0IHZvbHV0cGF0IG5lYywgaGVuZHJlcml0IGZhY2lsaXNpcyBlc3QuIFN1
+c3BlbmRpc3NlIG1hdXJpcyBwdXJ1cywgZGlnbmlzc2ltIHNpdCBhbWV0IHRpbmNp
+ZHVudCBhYywgaWFjdWxpcyBpZCBzZW0uIER1aXMgcmlzdXMganVzdG8sIGZyaW5n
+aWxsYSBhdCB2dWxwdXRhdGUgYXQsIGxvYm9ydGlzIG5vbiBhcmN1LiBBbGlxdWFt
+IGVyYXQgdm9sdXRwYXQuCgpWaXZhbXVzIGxlY3R1cyBtaSwgdWxsYW1jb3JwZXIg
+ZXQgZmV1Z2lhdCBzaXQgYW1ldCwgZ3JhdmlkYSBxdWlzIHZlbGl0LiBDcmFzIHRp
+bmNpZHVudCBtZXR1cyByaXN1cywgZWdldCB0cmlzdGlxdWUgYXJjdS4gTnVuYyBl
+Z2V0IGxlbyBhIGVsaXQgdGVtcG9yIHBvcnR0aXRvci4gQ3VtIHNvY2lpcyBuYXRv
+cXVlIHBlbmF0aWJ1cyBldCBtYWduaXMgZGlzIHBhcnR1cmllbnQgbW9udGVzLCBu
+YXNjZXR1ciByaWRpY3VsdXMgbXVzLiBQcmFlc2VudCB0ZW1wdXMgbnVuYyBlZ2V0
+IG5pYmggY29uc2VjdGV0dXIgYWMgY29udmFsbGlzIGVuaW0gc2FnaXR0aXMuIEFs
+aXF1YW0gaXBzdW0gdXJuYSwgZmF1Y2lidXMgYWMgdHJpc3RpcXVlIHZlbCwgbGFv
+cmVldCBhIGxlby4gUGhhc2VsbHVzIGNvbmRpbWVudHVtIGVuaW0gZWdldCBpcHN1
+bSB2b2x1dHBhdCB1dCBhY2N1bXNhbiBuaWJoIHBlbGxlbnRlc3F1ZS4gTnVsbGFt
+IGxhb3JlZXQsIHRvcnRvciBpbiB1bGxhbWNvcnBlciBmcmluZ2lsbGEsIGR1aSBv
+ZGlvIHNjZWxlcmlzcXVlIHB1cnVzLCB1dCBpYWN1bGlzIGVyYXQgcmlzdXMgYWMg
+bnVsbGEuIEFsaXF1YW0gZWdlc3RhcyBsYWNpbmlhIGFsaXF1YW0uIE1hdXJpcyBi
+bGFuZGl0LCB0b3J0b3IgcXVpcyBtb2xsaXMgcGVsbGVudGVzcXVlLCBudWxsYSBt
+YWduYSB2ZXN0aWJ1bHVtIGVyYXQsIGV0IHRyaXN0aXF1ZSBsaWd1bGEgc2VtIGVn
+ZXQgdGVsbHVzLiBWZXN0aWJ1bHVtIGZlbGlzIHRvcnRvciwgc2VtcGVyIGluIHN1
+c2NpcGl0IGVnZXQsIHRpbmNpZHVudCB2ZWwgdmVsaXQuCgpNYWVjZW5hcyBzZW0g
+dGVsbHVzLCBiaWJlbmR1bSBhYyBjdXJzdXMgdXQsIGZldWdpYXQgdmVsIHRvcnRv
+ci4gU2VkIHZlbmVuYXRpcyBmZWxpcyBhIGF1Z3VlIHByZXRpdW0gZXUgbGFvcmVl
+dCBkdWkgbWF0dGlzLiBNYWVjZW5hcyByaG9uY3VzIHZlc3RpYnVsdW0gbWFnbmEg
+ZWdldCBjb252YWxsaXMuIE51bGxhIGZhY2lsaXNpLiBGdXNjZSBpbnRlcmR1bSBk
+aWN0dW0gbGVvIG5lYyBhZGlwaXNjaW5nLiBOdW5jIHZpdGFlIGxvcmVtIHF1YW0u
+IEluIHVsdHJpY2llcyBzZW0gZXUgbGlndWxhIGVsZWlmZW5kIGluIHNhZ2l0dGlz
+IGFyY3UgcnV0cnVtLiBOdWxsYW0gZGlhbSBqdXN0bywgZmVybWVudHVtIG5lYyBs
+dWN0dXMgZXUsIGltcGVyZGlldCBuZWMgbGliZXJvLiBJbnRlZ2VyIGhlbmRyZXJp
+dCB0ZW1wb3IgZGFwaWJ1cy4gU3VzcGVuZGlzc2UgcG90ZW50aS4gRG9uZWMgdXQg
+YXJjdSBuZWMgbG9yZW0gbHVjdHVzIHZhcml1cyB2aXRhZSBhIG51bmMuIEZ1c2Nl
+IGEgc2FwaWVuIGxhb3JlZXQgdGVsbHVzIGFkaXBpc2NpbmcgdmVzdGlidWx1bS4g
+QWxpcXVhbSB2YXJpdXMgZGljdHVtIG1pIGVnZXQgZmV1Z2lhdC4gRXRpYW0gc2Vk
+IGxlbyBldCBtYXVyaXMgZmV1Z2lhdCBldWlzbW9kLiBTdXNwZW5kaXNzZSBxdWlz
+IG1hZ25hIG1hZ25hLCBhIHRpbmNpZHVudCBvcmNpLiBMb3JlbSBpcHN1bSBkb2xv
+ciBzaXQgYW1ldCwgY29uc2VjdGV0dXIgYWRpcGlzY2luZyBlbGl0LiBEb25lYyBu
+aXNpIHR1cnBpcywgYWxpcXVldCBldSBzb2xsaWNpdHVkaW4gdml0YWUsIGxhb3Jl
+ZXQgbmVjIG5pc2kuIFZlc3RpYnVsdW0gdHJpc3RpcXVlLCB2ZWxpdCB2aXRhZSB1
+bGxhbWNvcnBlciBjb25kaW1lbnR1bSwgbGVjdHVzIG9yY2kgcG9ydHRpdG9yIGFy
+Y3UsIGV1IHBsYWNlcmF0IGZlbGlzIHB1cnVzIG5lYyBvcmNpLiBOYW0gaXBzdW0g
+YXVndWUsIHNjZWxlcmlzcXVlIGF0IGxhY2luaWEgc2l0IGFtZXQsIG1hdHRpcyBh
+IGVyYXQuIFBoYXNlbGx1cyBhIG1hZ25hIHF1aXMgbGFjdXMgdmFyaXVzIHBsYWNl
+cmF0LgoKUHJvaW4gb3JuYXJlIHZpdmVycmEgcGxhY2VyYXQuIFNlZCBpYWN1bGlz
+IHVsdHJpY2VzIG1hZ25hLCBjb252YWxsaXMgYXVjdG9yIG1pIHRyaXN0aXF1ZSB2
+ZWwuIFBlbGxlbnRlc3F1ZSBhYyBuaXNpIHNpdCBhbWV0IG5pc2kgYWxpcXVhbSB0
+aW5jaWR1bnQgYWMgdXQgaXBzdW0uIFByYWVzZW50IGEgdGVsbHVzIG5vbiBudW5j
+IGlhY3VsaXMgYWRpcGlzY2luZy4gUXVpc3F1ZSBmYWNpbGlzaXMganVzdG8gZWdl
+dCBtZXR1cyBncmF2aWRhIHVsbGFtY29ycGVyLiBEb25lYyBzYWdpdHRpcywgdG9y
+dG9yIGV1aXNtb2QgYWxpcXVhbSBpbnRlcmR1bSwgYXVndWUgYXVndWUgbGFvcmVl
+dCBlbGl0LCBpbiBjb21tb2RvIHVybmEgbGFjdXMgdmVsIGVzdC4gVmVzdGlidWx1
+bSBkdWkgbmliaCwgdmFyaXVzIGEgaW50ZXJkdW0gYSwgcG9ydGEgdXQgbWV0dXMu
+IFV0IGxlY3R1cyB1cm5hLCBwb3N1ZXJlIGluIGx1Y3R1cyBldCwgcnV0cnVtIGEg
+ZXJhdC4gU3VzcGVuZGlzc2UgY3Vyc3VzLCB0b3J0b3Igdml0YWUgc2NlbGVyaXNx
+dWUgdHJpc3RpcXVlLCBkb2xvciBlcmF0IGRpZ25pc3NpbSBsZWN0dXMsIG5lYyBz
+b2RhbGVzIG1hdXJpcyB0ZWxsdXMgdmVsIHB1cnVzLiBEdWlzIGVsaXQgbWF1cmlz
+LCBhY2N1bXNhbiB1dCBwb3N1ZXJlIHZ1bHB1dGF0ZSwgbWFsZXN1YWRhIGV0IGFu
+dGUuIE1vcmJpIGJsYW5kaXQgbGFjdXMgYXQgbWF1cmlzIHNhZ2l0dGlzIHJ1dHJ1
+bS4gUGhhc2VsbHVzIGRvbG9yIG1hdXJpcywgY29uc2VxdWF0IHZlbCBmYXVjaWJ1
+cyB2ZWwsIHB1bHZpbmFyIG5lYyBhcmN1LiBOYW0gY29tbW9kbywgcHVydXMgdml0
+YWUgbW9sbGlzIHNjZWxlcmlzcXVlLCBzYXBpZW4gdHVycGlzIGJpYmVuZHVtIGFu
+dGUsIGV1IGZhY2lsaXNpcyBpcHN1bSBpcHN1bSBuZWMgbmVxdWUuIENsYXNzIGFw
+dGVudCB0YWNpdGkgc29jaW9zcXUgYWQgbGl0b3JhIHRvcnF1ZW50IHBlciBjb251
+YmlhIG5vc3RyYSwgcGVyIGluY2VwdG9zIGhpbWVuYWVvcy4gUGVsbGVudGVzcXVl
+IGNvbnZhbGxpcyBkaWduaXNzaW0gbWFnbmEgc2l0IGFtZXQgdnVscHV0YXRlLiBT
+ZWQgY29uZGltZW50dW0gdmVoaWN1bGEgbWF0dGlzLiBWaXZhbXVzIHRpbmNpZHVu
+dCBmYWNpbGlzaXMgaXBzdW0sIGV0IHBvcnRhIHJpc3VzIHVsdHJpY2VzIHZpdGFl
+LiBRdWlzcXVlIG5vbiBjb25zZXF1YXQgbmlzbC4gQ3VyYWJpdHVyIGp1c3RvIG51
+bGxhLCBiaWJlbmR1bSBpbiB2ZW5lbmF0aXMgZWdldCwgcG9zdWVyZSBlZ2V0IHNl
+bS4KClBlbGxlbnRlc3F1ZSBzaXQgYW1ldCByaXN1cyB2ZWwgbGliZXJvIGV1aXNt
+b2Qgc3VzY2lwaXQgdmVsIHNpdCBhbWV0IG1ldHVzLiBEb25lYyBncmF2aWRhLCBs
+ZW8gcXVpcyBpbnRlcmR1bSBjb25ndWUsIHF1YW0gbGVjdHVzIHRyaXN0aXF1ZSBu
+aXNpLCBldSB1bHRyaWNlcyBzZW0gdHVycGlzIHRpbmNpZHVudCBlc3QuIFByYWVz
+ZW50IHB1bHZpbmFyIGNvbnZhbGxpcyB1cm5hIHZpdGFlIGlhY3VsaXMuIFV0IGNv
+bnZhbGxpcyBwdWx2aW5hciBmYWNpbGlzaXMuIEN1bSBzb2NpaXMgbmF0b3F1ZSBw
+ZW5hdGlidXMgZXQgbWFnbmlzIGRpcyBwYXJ0dXJpZW50IG1vbnRlcywgbmFzY2V0
+dXIgcmlkaWN1bHVzIG11cy4gQWVuZWFuIGV0IGVyYXQgZG9sb3IsIGFjIHBvc3Vl
+cmUgbWV0dXMuIFNlZCBjb25kaW1lbnR1bSBhZGlwaXNjaW5nIGlwc3VtLCBlZ2V0
+IHVsdHJpY2llcyBqdXN0byBmZXJtZW50dW0gc2l0IGFtZXQuIE5hbSBmZXJtZW50
+dW0gbGVvIHZpdGFlIGxlY3R1cyBtYXR0aXMgaW1wZXJkaWV0LiBFdGlhbSBkb2xv
+ciBsYWN1cywgbWF0dGlzIGF0IHRlbXB1cyBldSwgY29uZ3VlIHZlbCB2ZWxpdC4g
+UHJhZXNlbnQgYmxhbmRpdCB2aXZlcnJhIHJob25jdXMuIFBlbGxlbnRlc3F1ZSB2
+aXRhZSBsYWN1cyBsZW8uCgpRdWlzcXVlIGlkIGxvcmVtIHF1aXMgdHVycGlzIGx1
+Y3R1cyBjb25zZXF1YXQgaW4gc2l0IGFtZXQgZXN0LiBDdXJhYml0dXIgdHJpc3Rp
+cXVlLCBhcmN1IGEgY3Vyc3VzIHZvbHV0cGF0LCBudWxsYSBlc3QgYXVjdG9yIHRl
+bGx1cywgbmVjIGZhY2lsaXNpcyBuaWJoIGF1Z3VlIG5lYyBvcmNpLiBNYXVyaXMg
+ZmV1Z2lhdCwgZXN0IGFjIGF1Y3RvciBldWlzbW9kLCBvZGlvIG5pYmggYWNjdW1z
+YW4gbmVxdWUsIGluIGZlcm1lbnR1bSBvcmNpIG1hc3NhIHZpdGFlIGF1Z3VlLiBQ
+ZWxsZW50ZXNxdWUgcXVpcyBtaSBhcmN1LCBub24gaW1wZXJkaWV0IGlwc3VtLiBO
+dWxsYW0gZGFwaWJ1cyBoZW5kcmVyaXQgZmVsaXMsIGFjIHVsbGFtY29ycGVyIHRv
+cnRvciBwaGFyZXRyYSBldC4gTnVsbGEgYWNjdW1zYW4sIGxhY3VzIHNlZCBlbGVt
+ZW50dW0gaW50ZXJkdW0sIG1pIGFyY3UgdmVzdGlidWx1bSBuZXF1ZSwgZWdldCBm
+YWNpbGlzaXMgZXJvcyBudW5jIGF0IGVsaXQuIFN1c3BlbmRpc3NlIGV1IG1hdXJp
+cyBzdXNjaXBpdCBwdXJ1cyBkaWN0dW0gaWFjdWxpcy4gUHJhZXNlbnQgc2l0IGFt
+ZXQgbnVuYyBuZWMgbGFjdXMgZmFjaWxpc2lzIHBvcnRhLiBNYXVyaXMgbnVuYyBp
+cHN1bSwgc29sbGljaXR1ZGluIHNlZCBwb3N1ZXJlIGluLCBmZXJtZW50dW0gYWMg
+dGVsbHVzLiBOdWxsYSBmcmluZ2lsbGEgc2NlbGVyaXNxdWUgZXJhdCBpZCBwbGFj
+ZXJhdC4KCkludGVnZXIgZnJpbmdpbGxhIGZlcm1lbnR1bSB0dXJwaXMgZWdldCBs
+YW9yZWV0LiBTdXNwZW5kaXNzZSBwb3N1ZXJlIGVzdCBhYyBlcm9zIGNvbnNlcXVh
+dCBub24gZGlnbmlzc2ltIHB1cnVzIGFsaXF1ZXQuIE1hdXJpcyBwcmV0aXVtIHZl
+bmVuYXRpcyBwdWx2aW5hci4gVXQgbmVxdWUgbWV0dXMsIGN1cnN1cyBpZCBkaWdu
+aXNzaW0gc2l0IGFtZXQsIGNvbmRpbWVudHVtIGVnZXQgZXJvcy4gQWxpcXVhbSBl
+cmF0IHZvbHV0cGF0LiBFdGlhbSBwb3J0YSBhbGlxdWFtIG5pc2ksIHNpdCBhbWV0
+IGNvbnNlY3RldHVyIHB1cnVzIGxvYm9ydGlzIG5lYy4gVmVzdGlidWx1bSB0aW5j
+aWR1bnQgcGxhY2VyYXQgcXVhbSBhYyBjdXJzdXMuIFByYWVzZW50IGxhb3JlZXQg
+ZXJvcyBub24gbmVxdWUgcmhvbmN1cyBhYyBoZW5kcmVyaXQgZHVpIHRlbXBvci4g
+Q3JhcyBzb2RhbGVzIGVsaXQgdml0YWUgdXJuYSBpbnRlcmR1bSBhY2N1bXNhbi4g
+TnVsbGFtIG5lYyBsYW9yZWV0IGFyY3UuIERvbmVjIGZyaW5naWxsYSBzY2VsZXJp
+c3F1ZSByaXN1cywgbmVjIHNhZ2l0dGlzIG9kaW8gYWNjdW1zYW4gbm9uLiBRdWlz
+cXVlIHJ1dHJ1bSBzb2RhbGVzIG9kaW8uIE1hdXJpcyBmYWNpbGlzaXMsIG5pYmgg
+cXVpcyBlbGVpZmVuZCBzb2xsaWNpdHVkaW4sIGR1aSBvZGlvIGF1Y3RvciBvcmNp
+LCBldSBwb3J0dGl0b3IgYXJjdSBudW5jIGFjIGxpZ3VsYS4gSW4gc2VkIG1pIG5l
+cXVlLiBNYXVyaXMgZWdlc3RhcywgdGVsbHVzIHNlZCBldWlzbW9kIGVnZXN0YXMs
+IGVyb3MgbGlndWxhIGdyYXZpZGEgcmlzdXMsIGF0IGFsaXF1YW0gbGVvIGxpZ3Vs
+YSB1dCBvZGlvLiBBbGlxdWFtIHZlbCB2YXJpdXMgc2FwaWVuLiBFdGlhbSBldSBs
+ZW8gZXJvcywgcXVpcyBjb25zZXF1YXQgbWkuIE51bGxhbSBzb2RhbGVzIHBlbGxl
+bnRlc3F1ZSBvZGlvIG5vbiB0cmlzdGlxdWUuCgpBbGlxdWFtIGVyYXQgdm9sdXRw
+YXQuIEFlbmVhbiBsYW9yZWV0LCBudW5jIGVnZXQgbW9sbGlzIGF1Y3RvciwgbWkg
+bGlndWxhIGxvYm9ydGlzIGR1aSwgYSB1bHRyaWNpZXMgcXVhbSB2ZWxpdCB1dCBz
+YXBpZW4uIFV0IHZlbCBpYWN1bGlzIG5pYmguIEV0aWFtIHV0IHJpc3VzIGR1aS4g
+TWF1cmlzIGF0IGp1c3RvIGZlbGlzLiBNYXVyaXMgaWFjdWxpcyBiaWJlbmR1bSB2
+ZWxpdCBlZ2V0IGRhcGlidXMuIEFsaXF1YW0gZXJhdCB2b2x1dHBhdC4gTnVsbGEg
+c2l0IGFtZXQgb3JjaSBhbnRlLCBhIGVnZXN0YXMgc2FwaWVuLiBNb3JiaSB1bGxh
+bWNvcnBlciBsZWN0dXMgdmVsIG1hdXJpcyB2ZXN0aWJ1bHVtIG1hbGVzdWFkYS4g
+Q3JhcyB2ZWwgbGVjdHVzIGlwc3VtLiBEdWlzIGVnZXN0YXMgdmVuZW5hdGlzIHBy
+ZXRpdW0uIE1vcmJpIHNlZCB0b3J0b3IgZXUgb2RpbyBzdXNjaXBpdCBydXRydW0u
+IFNlZCB1bHRyaWNlcyBtYXNzYSBmZXJtZW50dW0gbGFjdXMgdGVtcHVzIHBoYXJl
+dHJhLiBJbiBldCBtYXVyaXMgcXVhbSwgaWQgZnJpbmdpbGxhIG1ldHVzLgoKQWVu
+ZWFuIG5lYyB2ZWxpdCBkdWkuIE51bGxhbSBlZ2VzdGFzIG1pIGV1IGlwc3VtIHVs
+dHJpY2VzIGVnZXQgdmVuZW5hdGlzIHZlbGl0IGxhY2luaWEuIFZpdmFtdXMgbmVj
+IGxpZ3VsYSBzaXQgYW1ldCBqdXN0byBhZGlwaXNjaW5nIHZhcml1cyB1dCB1dCBw
+dXJ1cy4gQWVuZWFuIGx1Y3R1cyBuaXNsIGVnZXQgbmlzbCB1bHRyaWNlcyBpbXBl
+cmRpZXQuIFZpdmFtdXMgYSBuaWJoIGF0IGVsaXQgc29kYWxlcyBldWlzbW9kLiBB
+ZW5lYW4gaGVuZHJlcml0IG5pc2kgdmVsIG1ldHVzIGNvbnZhbGxpcyB2dWxwdXRh
+dGUuIE1vcmJpIHVybmEgdHVycGlzLCB0ZW1wb3IgYXQgcHVsdmluYXIgdmVsLCBj
+b25zZWN0ZXR1ciBldSBtZXR1cy4gTmFtIGZyaW5naWxsYSBtYXVyaXMgc2VkIG9y
+Y2kgcG9ydGEgYWMgbW9sbGlzIG51bGxhIGJsYW5kaXQuIEluIHVsdHJpY2llcyB2
+ZWxpdCBhdWN0b3IgYXJjdSBncmF2aWRhIGZlcm1lbnR1bS4gVXQgdmVsIG5lcXVl
+IGV0IHZlbGl0IHByZXRpdW0gYmxhbmRpdCBldSBpbiBhbnRlLiBWZXN0aWJ1bHVt
+IHV0IGR1aSBtYWduYS4gTmFtIGV0IGxhY3VzIGlwc3VtLCBzZWQgdGluY2lkdW50
+IHRlbGx1cy4gRG9uZWMgZWxlbWVudHVtIGVsZWlmZW5kIHRvcnRvciB1dCB2ZXN0
+aWJ1bHVtLgoKRXRpYW0gdm9sdXRwYXQgbWV0dXMgc2VkIGxvcmVtIGRhcGlidXMg
+bGFjaW5pYS4gQ2xhc3MgYXB0ZW50IHRhY2l0aSBzb2Npb3NxdSBhZCBsaXRvcmEg
+dG9ycXVlbnQgcGVyIGNvbnViaWEgbm9zdHJhLCBwZXIgaW5jZXB0b3MgaGltZW5h
+ZW9zLiBWZXN0aWJ1bHVtIGEgYmxhbmRpdCBuaWJoLiBQaGFzZWxsdXMgZXQgbG9y
+ZW0gdmVsIGVyb3MgaWFjdWxpcyB1bHRyaWNpZXMuIFNlZCBzaXQgYW1ldCBtYWdu
+YSBzaXQgYW1ldCBlc3QgbW9sZXN0aWUgcHJldGl1bSBzZWQgbmVjIG9yY2kuIFN1
+c3BlbmRpc3NlIHBvdGVudGkuIE51bGxhIGNvbnZhbGxpcyBhbnRlIHZpdGFlIGRv
+bG9yIGNvbnZhbGxpcyBub24gdmFyaXVzIG5lcXVlIHBlbGxlbnRlc3F1ZS4gQ3Jh
+cyBldWlzbW9kIG1hc3NhIGEgZXJvcyBhbGlxdWFtIHVsdHJpY2VzLiBTZWQgdml0
+YWUgcHVydXMgdXQgbmlzaSBmYXVjaWJ1cyBmZXVnaWF0LiBQcmFlc2VudCBhIGxl
+Y3R1cyBldCB2ZWxpdCBlZ2VzdGFzIHBoYXJldHJhIGV0IHNpdCBhbWV0IGRvbG9y
+LiBEdWlzIHF1aXMgbGFjaW5pYSBvZGlvLiBTZWQgc2VkIGVuaW0gbGVvLiBEb25l
+YyBwdWx2aW5hciBzb2xsaWNpdHVkaW4gbmVxdWUgdXQgZnJpbmdpbGxhLiBFdGlh
+bSBtYWxlc3VhZGEgbmlzbCBkaWN0dW0gZXJhdCBkaWN0dW0gZGFwaWJ1cy4gRnVz
+Y2UgZmFjaWxpc2lzLCBtaSB2ZWwgdmFyaXVzIG9ybmFyZSwgdG9ydG9yIG51bGxh
+IG9ybmFyZSBlcm9zLCBhdCBldWlzbW9kIG5pYmggbmlzaSBldCBhdWd1ZS4gTWFl
+Y2VuYXMgZWdldCBzYXBpZW4gbWkuIFNlZCBzZWQgbnVsbGEgbGVjdHVzLiBOdW5j
+IGRpZ25pc3NpbSBsdWN0dXMgbGVjdHVzLCBhdCBhbGlxdWV0IGRvbG9yIHZlbmVu
+YXRpcyBxdWlzLiBVdCBwdWx2aW5hciwgdG9ydG9yIHNpdCBhbWV0IHNjZWxlcmlz
+cXVlIHBoYXJldHJhLCBmZWxpcyBsZW8gcHJldGl1bSBmZWxpcywgZXQgbWF0dGlz
+IHNhcGllbiBtYXVyaXMgbWF0dGlzIG51bGxhLgoKU3VzcGVuZGlzc2UgcG90ZW50
+aS4gTnVuYyBxdWlzIHB1bHZpbmFyIHF1YW0uIER1aXMgZGFwaWJ1cyBiaWJlbmR1
+bSBmYWNpbGlzaXMuIE51bGxhbSBsb2JvcnRpcyBlcmF0IHNpdCBhbWV0IHF1YW0g
+YWRpcGlzY2luZyBldSBtb2xlc3RpZSB0b3J0b3IgYWNjdW1zYW4uIFByYWVzZW50
+IHB1bHZpbmFyIGVuaW0gZXUganVzdG8gZGFwaWJ1cyBpbiB2aXZlcnJhIG1hdXJp
+cyBjb21tb2RvLiBFdGlhbSBtb2xsaXMgY29uc2VxdWF0IHZlbGl0LCBub24gbW9s
+ZXN0aWUgZXJvcyBjb25kaW1lbnR1bSBhYy4gRXRpYW0gdml0YWUgZXJhdCBuZWMg
+ZWxpdCBjb25ndWUgY29uZGltZW50dW0gYSB1bGxhbWNvcnBlciB0dXJwaXMuIFZl
+c3RpYnVsdW0gYW50ZSBpcHN1bSBwcmltaXMgaW4gZmF1Y2lidXMgb3JjaSBsdWN0
+dXMgZXQgdWx0cmljZXMgcG9zdWVyZSBjdWJpbGlhIEN1cmFlOyBWZXN0aWJ1bHVt
+IHZpdGFlIGxvcmVtIGV0IGxlY3R1cyBjb252YWxsaXMgY29uc2VjdGV0dXIuIFN1
+c3BlbmRpc3NlIHNpdCBhbWV0IGZlbGlzIG5vbiBtZXR1cyBtYXR0aXMgbG9ib3J0
+aXMuIE1vcmJpIGV1IG51bGxhIHRvcnRvci4gTWFlY2VuYXMgaGVuZHJlcml0IG9y
+Y2kgc2l0IGFtZXQgbGlndWxhIGludGVyZHVtIGV0IGlhY3VsaXMgbnVsbGEgcGxh
+Y2VyYXQuIE5hbSBkaWN0dW0gbGFjdXMgYXQgYXJjdSByaG9uY3VzIGVsZWlmZW5k
+LiBJbiBoYWMgaGFiaXRhc3NlIHBsYXRlYSBkaWN0dW1zdC4KCkN1cmFiaXR1ciBh
+YyB2ZW5lbmF0aXMgZHVpLiBDbGFzcyBhcHRlbnQgdGFjaXRpIHNvY2lvc3F1IGFk
+IGxpdG9yYSB0b3JxdWVudCBwZXIgY29udWJpYSBub3N0cmEsIHBlciBpbmNlcHRv
+cyBoaW1lbmFlb3MuIEludGVnZXIgYXVjdG9yIHBvcnRhIG5lcXVlIHZlbCBwZWxs
+ZW50ZXNxdWUuIEFlbmVhbiBhYyBwdXJ1cyBxdWlzIHZlbGl0IGlhY3VsaXMgcG9y
+dHRpdG9yIGluIGluIHNlbS4gRHVpcyB0aW5jaWR1bnQgcmlzdXMgaW4gcmlzdXMg
+ZmF1Y2lidXMgYSBhbGlxdWFtIGRpYW0gYXVjdG9yLiBOdWxsYW0gc2VtIGF1Z3Vl
+LCBhZGlwaXNjaW5nIHNlZCB0aW5jaWR1bnQgcXVpcywgbW9sZXN0aWUgc2VkIGxp
+YmVyby4gVmVzdGlidWx1bSBjb21tb2RvIG9kaW8gdGVtcG9yIG51bGxhIG9ybmFy
+ZSBwbGFjZXJhdC4gTW9yYmkgZG9sb3IgbWFzc2EsIGJpYmVuZHVtIGluIGVsZWlm
+ZW5kIGlkLCBtb2xlc3RpZSB1dCBqdXN0by4gUXVpc3F1ZSB2YXJpdXMgbnVuYyBz
+aXQgYW1ldCBuaXNsIGRhcGlidXMgZmFjaWxpc2lzLiBEb25lYyB1dCBlcmF0IG1p
+LiBEdWlzIGVnZXQgY29uc2VjdGV0dXIgbWFnbmEuIE1hdXJpcyBlZ2VzdGFzIHNl
+bXBlciBlZ2VzdGFzLiBTZWQgZXQganVzdG8gc2VkIG51bGxhIGJsYW5kaXQgYWNj
+dW1zYW4gYXQgbm9uIGxlby4gSW4gZWdldCBlc3QgaXBzdW0uIE51bGxhIHRlbGx1
+cyBsaWd1bGEsIGFsaXF1ZXQgc2l0IGFtZXQgdnVscHV0YXRlIHZpdGFlLCBtb2xs
+aXMgZXUgZXJhdC4KCkFlbmVhbiBhYyBhdWd1ZSBvZGlvLiBQcm9pbiBtb2xsaXMs
+IGRvbG9yIHV0IGZldWdpYXQgc3VzY2lwaXQsIGR1aSBhbnRlIGNvbnNlY3RldHVy
+IG9kaW8sIHZpdGFlIGNvbmRpbWVudHVtIHRlbGx1cyBudWxsYSBhYyBmZWxpcy4g
+UGVsbGVudGVzcXVlIGVnZXN0YXMgdWx0cmljZXMgbnVuYywgZXUgc2FnaXR0aXMg
+c2FwaWVuIGV1aXNtb2Qgdml0YWUuIEludGVnZXIgc29sbGljaXR1ZGluIGZldWdp
+YXQgbGVvIG5lYyBjb25zZWN0ZXR1ci4gUHJhZXNlbnQgc2l0IGFtZXQgc2VtIGVy
+YXQsIG5lYyB2b2x1dHBhdCBsYWN1cy4gRXRpYW0gYSBsYWN1cyBudWxsYSwgbm9u
+IGludGVyZHVtIGVyYXQuIE1hZWNlbmFzIHF1aXMgZGljdHVtIGxlY3R1cy4gUGVs
+bGVudGVzcXVlIGFjIGxpYmVybyB2ZWwgZWxpdCB0cmlzdGlxdWUgc2VtcGVyLiBR
+dWlzcXVlIGV1IHN1c2NpcGl0IGR1aS4gSW4gaGFjIGhhYml0YXNzZSBwbGF0ZWEg
+ZGljdHVtc3QuIENyYXMgZXUgcG9ydGEgcXVhbS4gQ3VyYWJpdHVyIHBoYXJldHJh
+LCBmZWxpcyB1dCByaG9uY3VzIHRpbmNpZHVudCwgbnVsbGEgYXVndWUgcGxhY2Vy
+YXQgc2FwaWVuLCBpZCB2ZXN0aWJ1bHVtIG5pc2wgbmVxdWUgYXQgZGlhbS4KClF1
+aXNxdWUgbGFvcmVldCBkYXBpYnVzIGx1Y3R1cy4gTW9yYmkgZXJhdCBvZGlvLCBt
+YXR0aXMgc2l0IGFtZXQgdWx0cmljaWVzIGV1LCBpbnRlcmR1bSBldCBudWxsYS4g
+TmFtIHZ1bHB1dGF0ZSwgbWV0dXMgbm9uIGVsZW1lbnR1bSBoZW5kcmVyaXQsIHVy
+bmEgcHVydXMgcGhhcmV0cmEgZWxpdCwgdml0YWUgc29kYWxlcyBwdXJ1cyBsaWd1
+bGEgbm9uIHF1YW0uIEV0aWFtIGlkIGxpZ3VsYSB0aW5jaWR1bnQgbGVvIHBlbGxl
+bnRlc3F1ZSBibGFuZGl0LiBVdCBhbnRlIHVybmEsIHZlc3RpYnVsdW0gc2VkIGVs
+ZW1lbnR1bSBhYywgcGVsbGVudGVzcXVlIHNpdCBhbWV0IHRvcnRvci4gRnVzY2Ug
+dmVuZW5hdGlzIGNvbW1vZG8gYW50ZSBhdCB0ZW1wb3IuIE51bGxhIGluIG9kaW8g
+bGVjdHVzLiBEb25lYyBsYWNpbmlhIGRhcGlidXMgdmVoaWN1bGEuIFN1c3BlbmRp
+c3NlIHNjZWxlcmlzcXVlIG9kaW8gdXQgbG9yZW0gZGlnbmlzc2ltIGlkIHByZXRp
+dW0gdG9ydG9yIHN1c2NpcGl0LiBOdWxsYW0gZmVsaXMgYW50ZSwgZmVybWVudHVt
+IGVnZXQgc29sbGljaXR1ZGluIHNpdCBhbWV0LCBjb21tb2RvIGF0IGVuaW0uIERv
+bmVjIGFsaXF1ZXQgbWF1cmlzIGluIGVsaXQgYXVjdG9yIGF0IGNvbnZhbGxpcyBx
+dWFtIHVsbGFtY29ycGVyLiBEdWlzIGVuaW0gbmliaCwgdnVscHV0YXRlIGluIGZh
+Y2lsaXNpcyBpZCwgYWRpcGlzY2luZyBpbnRlcmR1bSBsYWN1cy4gQWVuZWFuIHNv
+bGxpY2l0dWRpbiBjb25ndWUgY29uc2VjdGV0dXIuIFByYWVzZW50IGxvYm9ydGlz
+IG5pc2wgZXQgbWV0dXMgZXVpc21vZCBjb25ndWUuIFN1c3BlbmRpc3NlIGlkIHRl
+bXB1cyBpcHN1bS4KCkRvbmVjIGV1IGF1Y3RvciBzYXBpZW4uIEluIHBsYWNlcmF0
+IGF1Y3RvciBtYXNzYSB1dCBwbGFjZXJhdC4gVml2YW11cyBhdCB0dXJwaXMgZWxp
+dC4gRG9uZWMgY29uZ3VlIHJob25jdXMgZXN0IGEgdml2ZXJyYS4gTnVuYyBub24g
+b2RpbyBlbmltLiBDdW0gc29jaWlzIG5hdG9xdWUgcGVuYXRpYnVzIGV0IG1hZ25p
+cyBkaXMgcGFydHVyaWVudCBtb250ZXMsIG5hc2NldHVyIHJpZGljdWx1cyBtdXMu
+IE1hZWNlbmFzIHF1aXMgbWFzc2EgbGliZXJvLCBxdWlzIGVsZW1lbnR1bSBtYXVy
+aXMuIFZlc3RpYnVsdW0gYW50ZSBpcHN1bSBwcmltaXMgaW4gZmF1Y2lidXMgb3Jj
+aSBsdWN0dXMgZXQgdWx0cmljZXMgcG9zdWVyZSBjdWJpbGlhIEN1cmFlOyBWZXN0
+aWJ1bHVtIHZhcml1cyB2ZWxpdCBhIG9yY2kgZ3JhdmlkYSB1bHRyaWNpZXMgc2Vk
+IHZlbCBsaWd1bGEuIFZlc3RpYnVsdW0gcHJldGl1bSB2ZWhpY3VsYSBhbGlxdWV0
+LiBTdXNwZW5kaXNzZSBhdWN0b3IgY29uZ3VlIG1hZ25hLCBhYyBjb252YWxsaXMg
+ZGlhbSB1bGxhbWNvcnBlciB2ZWwuCgpBZW5lYW4gcGxhY2VyYXQgbW9sbGlzIGlw
+c3VtLCBuZWMgdWxsYW1jb3JwZXIgcXVhbSBoZW5kcmVyaXQgZWdldC4gQWVuZWFu
+IHNlZCBpcHN1bSBhIGFyY3UgbG9ib3J0aXMgdGluY2lkdW50LiBDbGFzcyBhcHRl
+bnQgdGFjaXRpIHNvY2lvc3F1IGFkIGxpdG9yYSB0b3JxdWVudCBwZXIgY29udWJp
+YSBub3N0cmEsIHBlciBpbmNlcHRvcyBoaW1lbmFlb3MuIEV0aWFtIGNvbnZhbGxp
+cyB0b3J0b3Igc2FnaXR0aXMgbmlzbCBwb3J0YSBmZXJtZW50dW0uIFZpdmFtdXMg
+YWNjdW1zYW4gbHVjdHVzIGNvbmd1ZS4gTWF1cmlzIGV0IGxlY3R1cyBsb3JlbS4g
+TnVuYyBldCBudW5jIGV0IGF1Z3VlIGdyYXZpZGEgYmliZW5kdW0uIE51bGxhbSBz
+dXNjaXBpdCBhcmN1IGV0IG1hdXJpcyBpYWN1bGlzIHZpdGFlIGNvbmd1ZSBuaXNs
+IHRlbXB1cy4gQ2xhc3MgYXB0ZW50IHRhY2l0aSBzb2Npb3NxdSBhZCBsaXRvcmEg
+dG9ycXVlbnQgcGVyIGNvbnViaWEgbm9zdHJhLCBwZXIgaW5jZXB0b3MgaGltZW5h
+ZW9zLiBDcmFzIGRvbG9yIHRlbGx1cywgbHVjdHVzIHNlZCBpbXBlcmRpZXQgZXUs
+IGFjY3Vtc2FuIG5lYyBsb3JlbS4gQ3JhcyBxdWlzIGlwc3VtIGFudGUuIFZlc3Rp
+YnVsdW0gYW50ZSBpcHN1bSBwcmltaXMgaW4gZmF1Y2lidXMgb3JjaSBsdWN0dXMg
+ZXQgdWx0cmljZXMgcG9zdWVyZSBjdWJpbGlhIEN1cmFlOyBRdWlzcXVlIHZpdGFl
+IGRpYW0gYXVndWUsIGV1IHVsdHJpY2VzIGFyY3UuIFByYWVzZW50IGFudGUgdmVs
+aXQsIHZlaGljdWxhIGVnZXQgY3Vyc3VzIGV0LCBjb25zZXF1YXQgc2l0IGFtZXQg
+dG9ydG9yLiBNYWVjZW5hcyB1bHRyaWNlcyBsaWd1bGEgaW4gb2RpbyB2ZWhpY3Vs
+YSB0aW5jaWR1bnQuIEFlbmVhbiB1bHRyaWNpZXMgaXBzdW0gdXQgc2VtIHZ1bHB1
+dGF0ZSB2aXRhZSBwdWx2aW5hciBkaWFtIGNvbnNlY3RldHVyLiBOYW0gdmVsIGVn
+ZXN0YXMgZXJvcy4KClByb2luIHVybmEgbmliaCwgYWxpcXVldCBuZWMgc2FnaXR0
+aXMgYSwgY29uZ3VlIHNlZCBqdXN0by4gTWF1cmlzIHJpc3VzIG5lcXVlLCBibGFu
+ZGl0IGN1cnN1cyBzZW1wZXIgZXUsIGZlcm1lbnR1bSBlZ2V0IHB1cnVzLiBDdXJh
+Yml0dXIgaW4gbGFjdXMgYXVndWUsIHNpdCBhbWV0IGNvbmRpbWVudHVtIG1pLiBN
+YXVyaXMgZXUgc2VtIGlwc3VtLCBpbiB1bHRyaWNlcyBtZXR1cy4gUXVpc3F1ZSBm
+cmluZ2lsbGEgc2VtIGEgbmlzaSBjb21tb2RvIHZhcml1cy4gTnVuYyB1bHRyaWNl
+cyBwbGFjZXJhdCBwbGFjZXJhdC4gVml2YW11cyBub24gbGVjdHVzIGRvbG9yLCBl
+Z2V0IGhlbmRyZXJpdCBhdWd1ZS4gTmFtIHV0IG1hdHRpcyBwdXJ1cy4gSW50ZWdl
+ciB2ZWwgdXJuYSBldCB0ZWxsdXMgbGFjaW5pYSBmYWNpbGlzaXMgcGVsbGVudGVz
+cXVlIHV0IHRlbGx1cy4gRXRpYW0gbGFvcmVldCByaXN1cyBxdWlzIGVsaXQgZGlj
+dHVtIGlkIHRyaXN0aXF1ZSBsZW8gc2VtcGVyLiBVdCBvcm5hcmUgbmlzbCBldSBu
+aXNsIHVsbGFtY29ycGVyIGluIHNvbGxpY2l0dWRpbiBtYXVyaXMgZ3JhdmlkYS4g
+RXRpYW0gaW4gdGluY2lkdW50IHZlbGl0LiBVdCB0ZW1wdXMgdHVycGlzIHZpdGFl
+IHVybmEgc2FnaXR0aXMgdmVsIHBvcnRhIHNlbSB2b2x1dHBhdC4gRHVpcyBub24g
+anVzdG8gbWV0dXMsIHRlbXBvciBmYXVjaWJ1cyBxdWFtLiBBbGlxdWFtIGluIGxh
+Y3VzIG5lYyBtaSB2ZXN0aWJ1bHVtIGZyaW5naWxsYS4gUHJhZXNlbnQgdGVtcG9y
+IGxlY3R1cyBhdCBtZXR1cyBwb3J0YSB1dCBjb25ndWUgZHVpIGZyaW5naWxsYS4K
+Ck5hbSBhYyBsZWN0dXMgc2VtLCBhdCB2aXZlcnJhIHJpc3VzLiBDcmFzIHNpdCBh
+bWV0IHNvZGFsZXMgbWFzc2EuIFF1aXNxdWUgY29uc2VjdGV0dXIgbGlndWxhIHBv
+c3VlcmUgdHVycGlzIGV1aXNtb2QgaW50ZXJkdW0uIFV0IGV1IHRlbGx1cyBldSBt
+YXNzYSB1bHRyaWNpZXMgYmliZW5kdW0gdml0YWUgaWQgbWV0dXMuIEN1cmFiaXR1
+ciBpbXBlcmRpZXQgY29uc2VxdWF0IHRpbmNpZHVudC4gVXQgZW5pbSBxdWFtLCBj
+b25zZWN0ZXR1ciBhdCBwb3J0dGl0b3IgaW4sIHZhcml1cyBldSBtYWduYS4gTnVu
+YyBhcmN1IGVsaXQsIHNvZGFsZXMgbm9uIGRhcGlidXMgdnVscHV0YXRlLCBsYWNp
+bmlhIGlkIGZlbGlzLiBDdXJhYml0dXIgbHVjdHVzLCByaXN1cyBxdWlzIHZpdmVy
+cmEgY29udmFsbGlzLCBtYXNzYSBqdXN0byB0ZW1wdXMgbGliZXJvLCB2aXRhZSBw
+b3J0dGl0b3IgbGlndWxhIHZlbGl0IGEgdHVycGlzLiBOdW5jIHZpdmVycmEsIG1l
+dHVzIGEgbWFsZXN1YWRhIGNvbnZhbGxpcywgbmVxdWUgYW50ZSBiaWJlbmR1bSBu
+aXNsLCBlZ2V0IGltcGVyZGlldCBlbmltIGxlY3R1cyBldSBlbmltLiBQZWxsZW50
+ZXNxdWUgZW5pbSBuaXNsLCBhZGlwaXNjaW5nIGVnZXQgbW9sZXN0aWUgYXQsIGNv
+bnNlY3RldHVyIGV1IG9yY2kuIFNlZCBwb3J0YSB1bGxhbWNvcnBlciBlc3QsIG5l
+YyBkaWN0dW0gdHVycGlzIHNlbXBlciBzaXQgYW1ldC4KClF1aXNxdWUgcG9ydGEg
+bWkgYWMgdmVsaXQgcmhvbmN1cyBhIHZlaGljdWxhIGxlbyBjb25zZXF1YXQuIE1v
+cmJpIGxhb3JlZXQgbWF1cmlzIGVsaXQuIEZ1c2NlIHNlbXBlciByaXN1cyB2ZWwg
+bGFjdXMgZWdlc3RhcyByaG9uY3VzLiBQZWxsZW50ZXNxdWUgdGluY2lkdW50IG51
+bGxhIGp1c3RvLCB2aXRhZSB2ZWhpY3VsYSBsaWJlcm8uIE1hdXJpcyBkYXBpYnVz
+IGR1aSBpbiBtYWduYSB0cmlzdGlxdWUgc2l0IGFtZXQgZmFjaWxpc2lzIHJpc3Vz
+IGxvYm9ydGlzLiBBZW5lYW4gc2l0IGFtZXQgZG9sb3Igdml0YWUgbG9yZW0gZXVp
+c21vZCBjb252YWxsaXMuIE51bGxhbSBzaXQgYW1ldCBhZGlwaXNjaW5nIGp1c3Rv
+LiBWaXZhbXVzIHZlc3RpYnVsdW0gb3JuYXJlIHN1c2NpcGl0LiBWZXN0aWJ1bHVt
+IG1hbGVzdWFkYSB1bHRyaWNlcyB2ZWxpdCBub24gZmV1Z2lhdC4gVmVzdGlidWx1
+bSBhbnRlIGlwc3VtIHByaW1pcyBpbiBmYXVjaWJ1cyBvcmNpIGx1Y3R1cyBldCB1
+bHRyaWNlcyBwb3N1ZXJlIGN1YmlsaWEgQ3VyYWU7IE1hdXJpcyBhcmN1IGlwc3Vt
+LCBjb21tb2RvIGluIGlhY3VsaXMgc2VkLCBjb25zZXF1YXQgdXQgYXVndWUuIEFs
+aXF1YW0gbGliZXJvIG1hdXJpcywgYWxpcXVldCBhdCBjb25kaW1lbnR1bSBub24s
+IGhlbmRyZXJpdCBuZWMgZXJhdC4gSW4gdXQgbWF1cmlzIGxvcmVtLiBWaXZhbXVz
+IGVnZXQgbGlndWxhIGlkIG5pc2kgc29sbGljaXR1ZGluIHBsYWNlcmF0IGlkIG5l
+YyB0ZWxsdXMuIE51bGxhIG5vbiBmYXVjaWJ1cyBsb3JlbS4gTnVsbGEgbm9uIG5p
+YmggZXUgZW5pbSB2aXZlcnJhIGNvbnNlY3RldHVyLiBNb3JiaSBsaWJlcm8gbmlz
+bCwgY29udmFsbGlzIGlkIGFsaXF1YW0gaWQsIHN1c2NpcGl0IGFjIGRpYW0uIENs
+YXNzIGFwdGVudCB0YWNpdGkgc29jaW9zcXUgYWQgbGl0b3JhIHRvcnF1ZW50IHBl
+ciBjb251YmlhIG5vc3RyYSwgcGVyIGluY2VwdG9zIGhpbWVuYWVvcy4gSW50ZWdl
+ciBlZ2V0IGFudGUgc2FwaWVuLiBTZWQgbm9uIGF1Y3RvciBtYXNzYS4KCk1hZWNl
+bmFzIHRpbmNpZHVudCBncmF2aWRhIGNvbnZhbGxpcy4gVmVzdGlidWx1bSBldCBp
+YWN1bGlzIGxpYmVyby4gU2VkIHVybmEgb3JjaSwgY29udmFsbGlzIGluIGNvbnNl
+cXVhdCBpZCwgdWx0cmljaWVzIHF1aXMgc2VtLiBFdGlhbSBhbGlxdWV0IHNhZ2l0
+dGlzIGltcGVyZGlldC4gTWF1cmlzIG5lYyBuZXF1ZSBxdWFtLiBNb3JiaSB0aW5j
+aWR1bnQgbW9sbGlzIHZlbGl0IGVnZXQgdWx0cmljZXMuIERvbmVjIGF0IHR1cnBp
+cyBtYWduYSwgZXUgcGxhY2VyYXQgZXJvcy4gUXVpc3F1ZSB0b3J0b3IgbmlzbCwg
+dGluY2lkdW50IGV1IGltcGVyZGlldCBxdWlzLCBwb3N1ZXJlIG5lYyBlbGl0LiBD
+dW0gc29jaWlzIG5hdG9xdWUgcGVuYXRpYnVzIGV0IG1hZ25pcyBkaXMgcGFydHVy
+aWVudCBtb250ZXMsIG5hc2NldHVyIHJpZGljdWx1cyBtdXMuIFF1aXNxdWUgYWxp
+cXVldCBsYW9yZWV0IGRpY3R1bS4KClF1aXNxdWUgdmVsIGJpYmVuZHVtIGxlby4g
+RXRpYW0gZXQgbWF1cmlzIGxhY3VzLCBzZWQgc29sbGljaXR1ZGluIG5pc2kuIFF1
+aXNxdWUgaWQgcmlzdXMgaW4gbG9yZW0gbWF0dGlzIGRpY3R1bS4gU3VzcGVuZGlz
+c2UgcG90ZW50aS4gRG9uZWMgbmVjIGp1c3RvIGFyY3UsIHV0IHBlbGxlbnRlc3F1
+ZSBzZW0uIFN1c3BlbmRpc3NlIHBvdGVudGkuIFBlbGxlbnRlc3F1ZSBlZ2V0IG5p
+c2kgaWQgbmlzbCBsYWNpbmlhIGltcGVyZGlldC4gTmFtIGNvbnNlY3RldHVyIGZh
+Y2lsaXNpcyBsZW8gbmVjIHRlbXBvci4gRHVpcyBmZXJtZW50dW0gbGFvcmVldCB0
+dXJwaXMgZXQgcHJldGl1bS4gQ2xhc3MgYXB0ZW50IHRhY2l0aSBzb2Npb3NxdSBh
+ZCBsaXRvcmEgdG9ycXVlbnQgcGVyIGNvbnViaWEgbm9zdHJhLCBwZXIgaW5jZXB0
+b3MgaGltZW5hZW9zLiBBZW5lYW4gbGFvcmVldCBlc3Qgc2l0IGFtZXQgZWxpdCBm
+ZXVnaWF0IGRhcGlidXMuIEV0aWFtIHRlbXB1cyBzdXNjaXBpdCB2ZWxpdCwgb3Ju
+YXJlIGRhcGlidXMgaXBzdW0gcG9ydGEgbm9uLiBOdW5jIHV0IGRvbG9yIHV0IGR1
+aSBwb3J0YSBhY2N1bXNhbi4gSW50ZWdlciBkaWN0dW0sIHNlbSBub24gc3VzY2lw
+aXQgc29sbGljaXR1ZGluLCB0b3J0b3IgZXJhdCBsYW9yZWV0IHRlbGx1cywgc2l0
+IGFtZXQgcHJldGl1bSBkb2xvciBtaSB1dCBpcHN1bS4gVml2YW11cyBhdWN0b3Ig
+ZGlhbSBkaWN0dW0gc2FwaWVuIGZlcm1lbnR1bSBhZGlwaXNjaW5nLiBQaGFzZWxs
+dXMgc2NlbGVyaXNxdWUgb2RpbyBxdWlzIG9yY2kgY3Vyc3VzIGV0IHRlbXBvciBz
+ZW0gdGluY2lkdW50LiBJbiBoYWMgaGFiaXRhc3NlIHBsYXRlYSBkaWN0dW1zdC4g
+QWVuZWFuIHNvZGFsZXMsIGVzdCBldCBtYXR0aXMgc29kYWxlcywgbG9yZW0gZGlh
+bSBkYXBpYnVzIHF1YW0sIGFjIHByZXRpdW0gbGFjdXMgbGVjdHVzIGV1IHNhcGll
+bi4gRG9uZWMgYWRpcGlzY2luZyBsb2JvcnRpcyBtaSBlZ2V0IHZlc3RpYnVsdW0u
+CgpNYWVjZW5hcyBhdCBhbnRlIGVsaXQuIEluIHRlbXB1cyBydXRydW0gZXN0LCB2
+aXRhZSBlbGVtZW50dW0gbnVuYyBtb2xlc3RpZSBhYy4gQWxpcXVhbSB1dCBlbmlt
+IGFyY3UsIG5lYyBzb2RhbGVzIG51bGxhLiBVdCBkaWduaXNzaW0gYWRpcGlzY2lu
+ZyBvcm5hcmUuIER1aXMgZGljdHVtIGNvbW1vZG8gaXBzdW0sIGEgb3JuYXJlIHJp
+c3VzIG1hbGVzdWFkYSBzZWQuIEV0aWFtIGlkIGFyY3UgbWF1cmlzLCBuZWMgcGhh
+cmV0cmEgc2FwaWVuLiBMb3JlbSBpcHN1bSBkb2xvciBzaXQgYW1ldCwgY29uc2Vj
+dGV0dXIgYWRpcGlzY2luZyBlbGl0LiBBZW5lYW4gcnV0cnVtIGxlY3R1cyBzZWQg
+dHVycGlzIHBvcnR0aXRvciBoZW5kcmVyaXQuIEludGVnZXIgbWV0dXMgbGVvLCBs
+dWN0dXMgYWMgbGFjaW5pYSBpbiwgZWxlaWZlbmQgZXQgbmVxdWUuIFBlbGxlbnRl
+c3F1ZSBiaWJlbmR1bSBudWxsYSBzaXQgYW1ldCB0ZWxsdXMgZXVpc21vZCB2ZWwg
+c2NlbGVyaXNxdWUgbWFnbmEgcnV0cnVtLiBBZW5lYW4gdWx0cmljZXMgY29udmFs
+bGlzIG5pc2wsIGlkIG9ybmFyZSB0ZWxsdXMgYXVjdG9yIGV1LiBRdWlzcXVlIGxv
+Ym9ydGlzIGF1Y3RvciBqdXN0bywgc2l0IGFtZXQgdGluY2lkdW50IGR1aSBsYWNp
+bmlhIG5lYy4gTnVsbGFtIGNvbmd1ZSBudW5jIGF0IGZlbGlzIHBvcnR0aXRvciBy
+dXRydW0gbm9uIGF0IGVuaW0uCgpVdCBjb252YWxsaXMgY29uZGltZW50dW0gbGFj
+dXMgc2VkIGZhY2lsaXNpcy4gQWxpcXVhbSBwcmV0aXVtIGxpZ3VsYSBlZ2V0IG1h
+Z25hIHBsYWNlcmF0IHZvbHV0cGF0LiBEb25lYyBub24gbG9yZW0gcGVsbGVudGVz
+cXVlIGlwc3VtIGxvYm9ydGlzIHVsbGFtY29ycGVyLiBTdXNwZW5kaXNzZSB2b2x1
+dHBhdCBmZXJtZW50dW0gbWFsZXN1YWRhLiBQcmFlc2VudCBtb2xlc3RpZSBtYWxl
+c3VhZGEgbG9yZW0sIHNpdCBhbWV0IGVsZWlmZW5kIG1hc3NhIGVsZWlmZW5kIG5l
+Yy4gTnVsbGEgZmFjaWxpc2lzIHRpbmNpZHVudCBlcmF0LCBpbiBwb3J0dGl0b3Ig
+ZXJvcyBzYWdpdHRpcyBpZC4gU2VkIGxvYm9ydGlzLCBsaWJlcm8gYXVjdG9yIGlu
+dGVyZHVtIGhlbmRyZXJpdCwgZmVsaXMgcXVhbSB2ZXN0aWJ1bHVtIG5pYmgsIGVn
+ZXQgaW1wZXJkaWV0IG1hZ25hIGxpZ3VsYSBhdCBudWxsYS4gQWxpcXVhbSBlcmF0
+IHZvbHV0cGF0LiBBbGlxdWFtIG5lYyBuaXNsIHZlbGl0LiBOdW5jIGRhcGlidXMg
+ZGlnbmlzc2ltIG1hc3NhIGFjIGx1Y3R1cy4gTWF1cmlzIG5vbiBvZGlvIHB1cnVz
+LiBEdWlzIGVyYXQgYW50ZSwgY29uc2VjdGV0dXIgcXVpcyBjb21tb2RvIGEsIGlh
+Y3VsaXMgc2VkIGVzdC4gQ3VyYWJpdHVyIGp1c3RvIGp1c3RvLCBiaWJlbmR1bSBp
+biBzZW1wZXIgdmVsLCBmYXVjaWJ1cyBpbiBuaWJoLiBFdGlhbSBtYWduYSBhcmN1
+LCBldWlzbW9kIGF0IHRpbmNpZHVudCBxdWlzLCBzb2xsaWNpdHVkaW4gZXQgbGVj
+dHVzLiBOdWxsYW0gcHVydXMgbWV0dXMsIGZlcm1lbnR1bSBlZ2V0IHVsdHJpY2ll
+cyBuZWMsIGNvbmd1ZSBhIG5pYmguIFBoYXNlbGx1cyBhIGxhY3VzIGlwc3VtLCBp
+ZCBzb2xsaWNpdHVkaW4gdmVsaXQuCgpQaGFzZWxsdXMgbm9uIHZlbGl0IG9yY2ks
+IGFjIGZldWdpYXQgbGFjdXMuIEN1cmFiaXR1ciBzZWQgc2FwaWVuIG1hZ25hLiBJ
+biB2ZWwgcHVsdmluYXIgZmVsaXMuIE1hdXJpcyBxdWlzIGRpYW0gcXVpcyBtYXNz
+YSB2YXJpdXMgdmFyaXVzLiBQcmFlc2VudCB1dCBhdWd1ZSBsZW8sIGV0IGZhY2ls
+aXNpcyBtYXNzYS4gSW50ZWdlciBhdCB2ZWxpdCBvcmNpLCBuZWMgbW9sZXN0aWUg
+ZXN0LiBNb3JiaSBwb3J0YSBibGFuZGl0IHR1cnBpcyBhdCBmcmluZ2lsbGEuIFNl
+ZCBsYW9yZWV0IG9kaW8gdXQgZWxpdCBmZXJtZW50dW0gc2VkIGFjY3Vtc2FuIHRv
+cnRvciB2b2x1dHBhdC4gVmVzdGlidWx1bSBhbnRlIGlwc3VtIHByaW1pcyBpbiBm
+YXVjaWJ1cyBvcmNpIGx1Y3R1cyBldCB1bHRyaWNlcyBwb3N1ZXJlIGN1YmlsaWEg
+Q3VyYWU7IEV0aWFtIGlkIG1hc3NhIHZpdGFlIGVyb3MgaWFjdWxpcyBmYWNpbGlz
+aXMgc2VkIGFjIHNlbS4gRXRpYW0gdG9ydG9yIHF1YW0sIG1hbGVzdWFkYSBpbiBz
+b2RhbGVzIGEsIHZ1bHB1dGF0ZSB0aW5jaWR1bnQgcXVhbS4gTnVsbGEgZmFjaWxp
+c2kuIERvbmVjIGNvbmRpbWVudHVtIHZhcml1cyB1bHRyaWNlcy4gRnVzY2UgYmxh
+bmRpdCwgdmVsaXQgdml0YWUgc2NlbGVyaXNxdWUgZXVpc21vZCwgbmliaCBudWxs
+YSBpbnRlcmR1bSBhcmN1LCB2ZWwgdnVscHV0YXRlIGZlbGlzIGVzdCBpbiB0b3J0
+b3IuIFNlZCB1dCB1cm5hIGZlcm1lbnR1bSBkaWFtIGVsZWlmZW5kIGxvYm9ydGlz
+LgoKQWxpcXVhbSBub24gbnVuYyBvZGlvLiBBbGlxdWFtIGlkIGRpYW0gdmVsIG1p
+IHBvc3VlcmUgYXVjdG9yLiBQcmFlc2VudCB0ZW1wb3IgdGVsbHVzIHF1aXMgb2Rp
+byB0aW5jaWR1bnQgcG9zdWVyZS4gSW50ZWdlciBhIG1hc3NhIHB1cnVzLCBhYyBn
+cmF2aWRhIG1pLiBEb25lYyB2YXJpdXMgbmVxdWUgZXUgZXJvcyBzY2VsZXJpc3F1
+ZSBibGFuZGl0LiBNYWVjZW5hcyBjb25kaW1lbnR1bSB2b2x1dHBhdCBvZGlvIHBy
+ZXRpdW0gY29udmFsbGlzLiBEdWlzIHBvc3VlcmUgdmVoaWN1bGEgdm9sdXRwYXQu
+IFNlZCB0aW5jaWR1bnQgc2FwaWVuIGV1IGRpYW0gY3Vyc3VzIHZpdGFlIG9ybmFy
+ZSBxdWFtIGFkaXBpc2NpbmcuIE5hbSBmYXVjaWJ1cyB0aW5jaWR1bnQgZWxlaWZl
+bmQuIEFlbmVhbiBmYWNpbGlzaXMgY29uc2VxdWF0IHR1cnBpcywgYWMgbG9ib3J0
+aXMgdmVsaXQgZGljdHVtIHF1aXMuIE1hdXJpcyBpbXBlcmRpZXQgY29udmFsbGlz
+IGxpZ3VsYSBtYXR0aXMgY29uZ3VlLiBOdWxsYW0gdWx0cmljaWVzIGNvbmd1ZSBs
+YWN1cyBldCBwcmV0aXVtLiBQcmFlc2VudCBlcm9zIGFyY3UsIGxvYm9ydGlzIHV0
+IHBvcnR0aXRvciB1dCwgaW50ZXJkdW0gZXUgbGliZXJvLiBOYW0gbmVjIG9yY2kg
+ZXJhdC4gQ3JhcyBoZW5kcmVyaXQgY29uc2VjdGV0dXIgbWFzc2EsIGlkIGxvYm9y
+dGlzIGFyY3UgZXVpc21vZCBpZC4gU3VzcGVuZGlzc2UgcG90ZW50aS4gTnVsbGFt
+IGVnZXN0YXMsIGVyb3MgYWMgc3VzY2lwaXQgbW9sZXN0aWUsIG5lcXVlIHRlbGx1
+cyBhZGlwaXNjaW5nIG1hdXJpcywgbm9uIGNvbW1vZG8gZmVsaXMgb2RpbyB1dCBz
+ZW0uIE51bGxhbSBzYWdpdHRpcyBncmF2aWRhIHByZXRpdW0uIEZ1c2NlIHJ1dHJ1
+bSBjdXJzdXMgc2NlbGVyaXNxdWUuIFF1aXNxdWUgY29udmFsbGlzLCBkb2xvciBp
+biBwdWx2aW5hciBhbGlxdWV0LCBzYXBpZW4gaXBzdW0gdGVtcG9yIGR1aSwgaWQg
+dHJpc3RpcXVlIGVzdCBtYXVyaXMgYXVjdG9yIGp1c3RvLgoKQWVuZWFuIGFsaXF1
+ZXQgbWV0dXMgZXUgbWFnbmEgdHJpc3RpcXVlIGV1IGZlcm1lbnR1bSBtYWduYSB1
+bGxhbWNvcnBlci4gQWVuZWFuIHNjZWxlcmlzcXVlIGJsYW5kaXQgZWxlaWZlbmQu
+IEludGVnZXIgYSBvcm5hcmUgb2Rpby4gTWFlY2VuYXMgZWxlaWZlbmQgaGVuZHJl
+cml0IGFudGUgaWQgbW9sZXN0aWUuIE1hdXJpcyByaG9uY3VzIHBsYWNlcmF0IGFs
+aXF1YW0uIFN1c3BlbmRpc3NlIGEgZWxpdCBkaWFtLCBldCBwaGFyZXRyYSBlc3Qu
+IER1aXMgZWxlbWVudHVtIG9yY2kgZXUgYW50ZSBtYXR0aXMgYWMgY29uZ3VlIG5p
+c2wgYWxpcXVldC4gSW50ZWdlciBzaXQgYW1ldCBkb2xvciBldCBtYXVyaXMgZWxl
+aWZlbmQgbGFvcmVldC4gU2VkIGFsaXF1ZXQgcHJldGl1bSBudWxsYSwgaW4gZWxl
+aWZlbmQgYXVndWUgcnV0cnVtIHF1aXMuIFF1aXNxdWUgZGFwaWJ1cyBuaXNsIHZp
+dGFlIHRlbGx1cyBpbnRlcmR1bSBldSBibGFuZGl0IGFyY3UgY29uc2VxdWF0LiBF
+dGlhbSBzZWQgcHVydXMgcmlzdXMuIEZ1c2NlIHR1cnBpcyBsaWJlcm8sIGFsaXF1
+YW0gbmVjIGxhY2luaWEgYXQsIGJsYW5kaXQgbmVjIG51bmMuIFByYWVzZW50IHZp
+dmVycmEsIGxvcmVtIGFjIHBvcnR0aXRvciBtYWxlc3VhZGEsIGxvcmVtIHZlbGl0
+IHNvbGxpY2l0dWRpbiB2ZWxpdCwgc2l0IGFtZXQgdGluY2lkdW50IHVybmEgZHVp
+IHZpdGFlIGxlby4KCkRvbmVjIHZpdGFlIGZlbGlzIHF1aXMgZW5pbSB2dWxwdXRh
+dGUgcmhvbmN1cy4gUHJhZXNlbnQgZWxlbWVudHVtIHRyaXN0aXF1ZSBjb25ndWUu
+IERvbmVjIHF1aXMgbWV0dXMgbmliaC4gTWFlY2VuYXMgYXJjdSBhbnRlLCBsYWNp
+bmlhIGluIGRhcGlidXMgaWQsIGZlcm1lbnR1bSBzZWQgZXJhdC4gTW9yYmkgYWRp
+cGlzY2luZyBncmF2aWRhIG1hZ25hLCB1dCBwb3N1ZXJlIG9kaW8gZmV1Z2lhdCB2
+aXRhZS4gU3VzcGVuZGlzc2UgcG9ydGEgbHVjdHVzIGxhb3JlZXQuIEFsaXF1YW0g
+aW4gZXJhdCBzaXQgYW1ldCBvZGlvIHZlaGljdWxhIG9ybmFyZSBxdWlzIGF0IGR1
+aS4gU3VzcGVuZGlzc2Ugbm9uIGxvcmVtIHZpdGFlIGxpZ3VsYSBsdWN0dXMgY29u
+c2VjdGV0dXIgYWMgaWQgcHVydXMuIE51bmMgdXQgbmlzaSBqdXN0by4gTnVsbGFt
+IGVnZXQgc2FwaWVuIGNvbW1vZG8gZHVpIHN1c2NpcGl0IHBlbGxlbnRlc3F1ZS4g
+Vml2YW11cyBzZW1wZXIgbWkgc2VkIGFyY3Ugc2VtcGVyIHZhcml1cy4gQ3JhcyBh
+bGlxdWV0IHZlc3RpYnVsdW0gc2FwaWVuLCBhIGludGVyZHVtIG1pIHVsbGFtY29y
+cGVyIHZlbC4gTW9yYmkgcHVydXMgZGlhbSwgb3JuYXJlIG5vbiB0ZW1wb3Igbm9u
+LCBjb252YWxsaXMgbmVjIGVuaW0uIE51bGxhbSB0cmlzdGlxdWUgdnVscHV0YXRl
+IGxlbyBuZWMgZmFjaWxpc2lzLiBQZWxsZW50ZXNxdWUgaGFiaXRhbnQgbW9yYmkg
+dHJpc3RpcXVlIHNlbmVjdHVzIGV0IG5ldHVzIGV0IG1hbGVzdWFkYSBmYW1lcyBh
+YyB0dXJwaXMgZWdlc3Rhcy4KCk1vcmJpIGltcGVyZGlldCB2ZWhpY3VsYSBjb25n
+dWUuIE1hdXJpcyBxdWlzIG51bGxhIG9kaW8sIGEgZmF1Y2lidXMgdXJuYS4gTnVs
+bGEgZXQgZXJvcyBkb2xvci4gRnVzY2UgYSBmYXVjaWJ1cyBpcHN1bS4gTWF1cmlz
+IGZlcm1lbnR1bSBmZXVnaWF0IGRpZ25pc3NpbS4gVXQgYSBqdXN0byBlbGl0LCBu
+b24gYXVjdG9yIHF1YW0uIFNlZCBsYWN1cyBhdWd1ZSwgcGxhY2VyYXQgYXQgYWxp
+cXVhbSBub24sIG1hdHRpcyBpZCBtaS4gQWVuZWFuIGEgbGFvcmVldCBlcm9zLiBD
+cmFzIHVsdHJpY2llcyBlbGl0IGluIG51bmMgc3VzY2lwaXQgaWQgc29sbGljaXR1
+ZGluIGVuaW0gY29uZGltZW50dW0uIFBoYXNlbGx1cyBkaWduaXNzaW0gbmlzaSBx
+dWlzIGxlbyBpbnRlcmR1bSBwaGFyZXRyYS4gRG9uZWMgc2l0IGFtZXQgbGVvIGEg
+ZHVpIHZpdmVycmEgbW9sZXN0aWUuIEN1cmFiaXR1ciBsb2JvcnRpcyBzYXBpZW4g
+cXVpcyBuZXF1ZSBwdWx2aW5hciBhdCBmcmluZ2lsbGEgbmlzaSB2ZWhpY3VsYS4K
+ClByYWVzZW50IG5vbiBwdXJ1cyB0ZWxsdXMuIEludGVnZXIgaWFjdWxpcyBkYXBp
+YnVzIG5pc2wsIHRyaXN0aXF1ZSB2ZXN0aWJ1bHVtIG1pIG1hbGVzdWFkYSBzaXQg
+YW1ldC4gU2VkIGxvYm9ydGlzIGhlbmRyZXJpdCBsb2JvcnRpcy4gUXVpc3F1ZSB0
+ZW1wb3IsIGFyY3UgYWMgdGVtcHVzIGF1Y3RvciwgbmVxdWUgcXVhbSBkaWN0dW0g
+cXVhbSwgdml0YWUgZ3JhdmlkYSBsaWd1bGEgbmliaCBldSBhdWd1ZS4gQWVuZWFu
+IGV1aXNtb2QgdGVtcG9yIGlwc3VtIGEgaGVuZHJlcml0LiBDcmFzIGRvbG9yIGxp
+Z3VsYSwgZmF1Y2lidXMgYWMgaGVuZHJlcml0IGVnZXQsIGFsaXF1YW0gYSBuaXNs
+LiBJbnRlZ2VyIG5lYyBjb25zZXF1YXQganVzdG8uIEludGVnZXIgcGhhcmV0cmEg
+c2NlbGVyaXNxdWUgbGVvLiBBZW5lYW4gZXVpc21vZCB2ZWhpY3VsYSBhbnRlIG5v
+biBwaGFyZXRyYS4gVmVzdGlidWx1bSBzb2xsaWNpdHVkaW4ganVzdG8gZXUgc2Vt
+IGxhb3JlZXQgaW4gdGVtcHVzIG5lcXVlIGNvbW1vZG8uCgpVdCBpbiBhcmN1IGFu
+dGUuIEN1cmFiaXR1ciB1bHRyaWNpZXMgdmVsaXQgZGlhbS4gQWxpcXVhbSB2ZWxp
+dCBlcm9zLCB2b2x1dHBhdCBxdWlzIGN1cnN1cyBpZCwgdmVoaWN1bGEgYWMgdG9y
+dG9yLiBOdWxsYSBwcmV0aXVtLCBlcmF0IGlkIGZhY2lsaXNpcyBibGFuZGl0LCBy
+aXN1cyB0ZWxsdXMgYWxpcXVldCBvcmNpLCB2ZWwgY29uZGltZW50dW0gbmliaCBl
+bGl0IHZpdGFlIGVsaXQuIFBoYXNlbGx1cyB1bGxhbWNvcnBlciBjb25zZWN0ZXR1
+ciBhbnRlIHNpdCBhbWV0IGx1Y3R1cy4gTnVsbGEgdXQgbnVsbGEgZWdldCBlcm9z
+IGRpY3R1bSBwZWxsZW50ZXNxdWUgdmVsIHV0IG51bGxhLiBEb25lYyBsYW9yZWV0
+IHZpdmVycmEgbWFnbmEgdXQgaW50ZXJkdW0uIFZpdmFtdXMgcHVsdmluYXIgc2Fw
+aWVuIGNvbnZhbGxpcyBtYWduYSBzb2RhbGVzIGVnZXQgZWdlc3RhcyBlc3QgaW1w
+ZXJkaWV0LiBRdWlzcXVlIGZhY2lsaXNpcyBhbGlxdWFtIHNvZGFsZXMuIEV0aWFt
+IGZlcm1lbnR1bSwgb2RpbyBhYyBzZW1wZXIgc2NlbGVyaXNxdWUsIHB1cnVzIGVu
+aW0gaW1wZXJkaWV0IGF1Z3VlLCBzaXQgYW1ldCBkaWduaXNzaW0gc2FwaWVuIHRv
+cnRvciBuZWMgbWF1cmlzLiBTdXNwZW5kaXNzZSBlbGVpZmVuZCBjb21tb2RvIG51
+bmMgcXVpcyBjb25zZWN0ZXR1ci4gRG9uZWMgZWdldCB0cmlzdGlxdWUgbGVvLgoK
+U3VzcGVuZGlzc2Ugc29sbGljaXR1ZGluIHBoYXJldHJhIHNlbXBlci4gU2VkIGp1
+c3RvIGVzdCwgZmF1Y2lidXMgaWQgY3Vyc3VzIGEsIHBlbGxlbnRlc3F1ZSBpbiBt
+aS4gTWF1cmlzIHNhZ2l0dGlzLCBpcHN1bSBjdXJzdXMgYmxhbmRpdCBpbXBlcmRp
+ZXQsIGVzdCBlc3QgbHVjdHVzIHJpc3VzLCBxdWlzIGZlcm1lbnR1bSBsZW8gb3Jj
+aSBhIG9kaW8uIE51bmMgc2l0IGFtZXQgdmVsaXQgaXBzdW0uIE5hbSBldWlzbW9k
+IHB1bHZpbmFyIG1ldHVzLCBhYyBhZGlwaXNjaW5nIGR1aSB1bGxhbWNvcnBlciBh
+LiBWZXN0aWJ1bHVtIGFudGUgaXBzdW0gcHJpbWlzIGluIGZhdWNpYnVzIG9yY2kg
+bHVjdHVzIGV0IHVsdHJpY2VzIHBvc3VlcmUgY3ViaWxpYSBDdXJhZTsgU2VkIG1v
+bGVzdGllIHRpbmNpZHVudCBkb2xvciwgc2VkIHByZXRpdW0gbWFnbmEgY29uc2Vj
+dGV0dXIgdXQuIExvcmVtIGlwc3VtIGRvbG9yIHNpdCBhbWV0LCBjb25zZWN0ZXR1
+ciBhZGlwaXNjaW5nIGVsaXQuIEFsaXF1YW0gbGVjdHVzIGxpZ3VsYSwgaW50ZXJk
+dW0gYXQgbG9ib3J0aXMgaWQsIGNvbnZhbGxpcyBzaXQgYW1ldCBzZW0uIFNlZCBl
+Z2V0IG5lcXVlIGluIGFyY3UgdWx0cmljZXMgZmV1Z2lhdC4gUHJvaW4gdnVscHV0
+YXRlIGxlbyBlZ2V0IGVyb3MgZGFwaWJ1cyBhbGlxdWV0LiBGdXNjZSBmYWNpbGlz
+aXMgY29uc2VxdWF0IGRpYW0sIHNlZCB2ZXN0aWJ1bHVtIG1pIHVsdHJpY2llcyBl
+Z2V0LiBVdCBwb3N1ZXJlIGNvbmd1ZSBsaWJlcm8gc2l0IGFtZXQgZGlnbmlzc2lt
+LiBQcm9pbiBxdWlzIGFyY3UgbGliZXJvLgoKVmVzdGlidWx1bSBhdCBhdWd1ZSBt
+YXVyaXMuIEFsaXF1YW0gc2FnaXR0aXMgcG9ydGEgYW50ZSBpbiB2YXJpdXMuIFZl
+c3RpYnVsdW0gbHVjdHVzIGlhY3VsaXMgYXJjdSBhIGludGVyZHVtLiBVdCB2YXJp
+dXMgaGVuZHJlcml0IGxhY3VzIG5lYyBzYWdpdHRpcy4gU2VkIHV0IHJpc3VzIGFj
+IGxlY3R1cyB1bHRyaWNpZXMgbW9sbGlzLiBOdW5jIGZldWdpYXQgc3VzY2lwaXQg
+bnVuYyBxdWlzIGVsZW1lbnR1bS4gU3VzcGVuZGlzc2UgcG90ZW50aS4gRnVzY2Ug
+bGFvcmVldCBlbGl0IGV1IG9kaW8gZnJpbmdpbGxhIHBlbGxlbnRlc3F1ZS4gRXRp
+YW0gdml0YWUgYXJjdSBxdWlzIHF1YW0gc29kYWxlcyBmYWNpbGlzaXMgY29uc2Vx
+dWF0IHV0IG9yY2kuIFBoYXNlbGx1cyB2aXRhZSBxdWFtIHF1aXMgbGVvIGNvbmd1
+ZSBpbnRlcmR1bSBzZWQgc3VzY2lwaXQgZXN0LiBNYWVjZW5hcyBjb25kaW1lbnR1
+bSwgbWFzc2EgZWdldCB0ZW1wb3IgcGhhcmV0cmEsIGVyYXQgbGVvIGxhY2luaWEg
+b2Rpbywgc2l0IGFtZXQgZmV1Z2lhdCBtYXVyaXMgcmlzdXMgc2VkIHNhcGllbi4g
+TW9yYmkgYXJjdSBsb3JlbSwgZGFwaWJ1cyBlZ2V0IHZlbmVuYXRpcyBzZWQsIHNl
+bXBlciBlZ2V0IGVyb3MuIENyYXMgc2VtcGVyIHVsdHJpY2llcyBlcm9zIHZvbHV0
+cGF0IHZ1bHB1dGF0ZS4gTW9yYmkgYXQgbnVuYyBlZ2V0IG5pYmggZmV1Z2lhdCB0
+ZW1wdXMuCgpJbiBlZ2V0IGVsaXQgYSBkaWFtIHBsYWNlcmF0IHZvbHV0cGF0IHNl
+ZCB0ZW1wdXMgZGlhbS4gTWFlY2VuYXMgdGVtcG9yIHNlbSBpZCBzZW0gdml2ZXJy
+YSB2ZWwgZmVybWVudHVtIHJpc3VzIHBvcnR0aXRvci4gUHJvaW4gYSBtZXR1cyBt
+ZXR1cy4gQWVuZWFuIHF1aXMgdGluY2lkdW50IG1hZ25hLiBEb25lYyBzaXQgYW1l
+dCBwb3N1ZXJlIHJpc3VzLiBEb25lYyBlc3QganVzdG8sIGRhcGlidXMgaW4gc29s
+bGljaXR1ZGluIGV1LCB2ZW5lbmF0aXMgc2l0IGFtZXQgZWxpdC4gQ2xhc3MgYXB0
+ZW50IHRhY2l0aSBzb2Npb3NxdSBhZCBsaXRvcmEgdG9ycXVlbnQgcGVyIGNvbnVi
+aWEgbm9zdHJhLCBwZXIgaW5jZXB0b3MgaGltZW5hZW9zLiBDcmFzIGluIHR1cnBp
+cyBuZWMgbnVuYyBmcmluZ2lsbGEgaWFjdWxpcy4gRXRpYW0gc3VzY2lwaXQgbmli
+aCB2aXRhZSBsaWJlcm8gcGVsbGVudGVzcXVlIHZpdmVycmEuIENyYXMgaWQgbGVj
+dHVzIHF1aXMgZW5pbSBvcm5hcmUgbW9sZXN0aWUgdml0YWUgdmVsIHRlbGx1cy4g
+SW4gdmVzdGlidWx1bSB2dWxwdXRhdGUgdHVycGlzIGlkIHBvc3VlcmUuCgpOYW0g
+ZXN0IGVyYXQsIHJob25jdXMgbm9uIGltcGVyZGlldCBpbiwgc2FnaXR0aXMgdml0
+YWUgaXBzdW0uIE51bGxhIHJ1dHJ1bSB0aW5jaWR1bnQgbGVjdHVzIGV0IGJsYW5k
+aXQuIFV0IHNlZCBsaWd1bGEgbmlzbCwgbm9uIGRpY3R1bSBlcmF0LiBBZW5lYW4g
+bG9yZW0gZW5pbSwgbW9sbGlzIHV0IHRpbmNpZHVudCBpZCwgY29tbW9kbyBzaXQg
+YW1ldCBuaXNsLiBNYWVjZW5hcyBibGFuZGl0IHJob25jdXMgc2VtcGVyLiBGdXNj
+ZSBhIG1hc3NhIG9yY2ksIGV0IHZlbmVuYXRpcyBhcmN1LiBNYXVyaXMgbW9sbGlz
+IGR1aSBxdWlzIGZlbGlzIGJpYmVuZHVtIHBoYXJldHJhLiBDcmFzIHNlZCBpcHN1
+bSBtYXNzYSwgcG9ydHRpdG9yIHB1bHZpbmFyIG5pc2kuIExvcmVtIGlwc3VtIGRv
+bG9yIHNpdCBhbWV0LCBjb25zZWN0ZXR1ciBhZGlwaXNjaW5nIGVsaXQuIFZpdmFt
+dXMgY3Vyc3VzIGVsaXQgc2FnaXR0aXMgbGliZXJvIGhlbmRyZXJpdCB2ZXN0aWJ1
+bHVtLiBTZWQgcG9ydHRpdG9yLCB0b3J0b3IgdGluY2lkdW50IHBvcnR0aXRvciBz
+ZW1wZXIsIGRpYW0gbWFnbmEgZWxlaWZlbmQgbnVuYywgc2VkIGNvbmRpbWVudHVt
+IG5pYmggZXJhdCBxdWlzIG9kaW8uIERvbmVjIHBvc3VlcmUgdmVoaWN1bGEgcHVy
+dXMsIGluIHB1bHZpbmFyIG9kaW8gaW50ZXJkdW0gZXUuIFZlc3RpYnVsdW0gZmFj
+aWxpc2lzIHRpbmNpZHVudCBkYXBpYnVzLiBGdXNjZSBsdWN0dXMgbG9yZW0gZWdl
+dCBxdWFtIGFjY3Vtc2FuIGluIG1hdHRpcyBuaWJoIHZvbHV0cGF0LiBOdWxsYW0g
+ZXQgbGVvIGEgdXJuYSBwb3J0YSB2YXJpdXMgbm9uIHZpdGFlIGR1aS4gU2VkIGlu
+dGVyZHVtLCBtZXR1cyBldSBydXRydW0gcGhhcmV0cmEsIG5pc2wgc2VtIHRlbXB1
+cyBqdXN0bywgdmFyaXVzIGNvbnZhbGxpcyBpcHN1bSBkaWFtIHV0IGxlY3R1cy4K
+CkluIGhhYyBoYWJpdGFzc2UgcGxhdGVhIGRpY3R1bXN0LiBWZXN0aWJ1bHVtIGNv
+bmd1ZSBzb2RhbGVzIG5pc2kgcXVpcyBvcm5hcmUuIEZ1c2NlIGN1cnN1cyBuaXNp
+IGF0IHR1cnBpcyBjb25ndWUgaGVuZHJlcml0LiBWZXN0aWJ1bHVtIG5vbiBsYWN1
+cyB2ZWwgc2FwaWVuIHB1bHZpbmFyIHZlaGljdWxhIGF0IGluIGFudGUuIE51bGxh
+IGZhY2lsaXNpLiBVdCB0cmlzdGlxdWUgdGluY2lkdW50IGVyYXQgaWQgbHVjdHVz
+LiBDdXJhYml0dXIgcG9zdWVyZSBzb2RhbGVzIG5lcXVlIHF1aXMgdmFyaXVzLiBD
+dXJhYml0dXIgY3Vyc3VzIGFjY3Vtc2FuIGlwc3VtLCB2ZWwgbHVjdHVzIGxpZ3Vs
+YSBkYXBpYnVzIG5vbi4gQ3JhcyB2ZWhpY3VsYSBtYWduYSBpbiBsYWN1cyBvcm5h
+cmUgZGFwaWJ1cy4gRG9uZWMgYWxpcXVldCBzb2xsaWNpdHVkaW4gbGFjdXMsIGV1
+IGlhY3VsaXMgZXJhdCBiaWJlbmR1bSBjb21tb2RvLiBEb25lYyBibGFuZGl0IGJp
+YmVuZHVtIGZldWdpYXQuIFByYWVzZW50IGV1IGVzdCBqdXN0by4gUGVsbGVudGVz
+cXVlIGF0IGVuaW0gc2VkIHNlbSB2aXZlcnJhIGNvbnZhbGxpcy4gTWFlY2VuYXMg
+dmVuZW5hdGlzIG1ldHVzIHNhcGllbi4gU2VkIHBsYWNlcmF0IGZhY2lsaXNpcyBl
+bGl0IG5lYyBtYWxlc3VhZGEuIEZ1c2NlIHNhcGllbiBlc3QsIGNvbnNlcXVhdCBh
+IGNvbmd1ZSBlZ2V0LCBhY2N1bXNhbiBlZ2V0IGxvcmVtLiBTdXNwZW5kaXNzZSB0
+aW5jaWR1bnQgcHJldGl1bSBtYWduYSBlZ2V0IGRhcGlidXMuIEZ1c2NlIHZlbCBl
+cm9zIGV0IGxvcmVtIGNvbnNlcXVhdCB0cmlzdGlxdWUgbmVjIGEgaXBzdW0uCgpQ
+cm9pbiBxdWlzIGN1cnN1cyBhcmN1LiBNYWVjZW5hcyBlbGVpZmVuZCBsb3JlbSBp
+ZCBuaXNsIHNjZWxlcmlzcXVlIHBsYWNlcmF0LiBGdXNjZSBpbXBlcmRpZXQgbG9y
+ZW0gZXUgdXJuYSBkaWduaXNzaW0gZmVybWVudHVtLiBQZWxsZW50ZXNxdWUgbnVu
+YyBuaXNsLCBpbXBlcmRpZXQgdXQgYWNjdW1zYW4gaWQsIGZlcm1lbnR1bSBub24g
+bWF1cmlzLiBBZW5lYW4gZnJpbmdpbGxhIGxlY3R1cyB2aXRhZSB0dXJwaXMgZmVy
+bWVudHVtIHZpdGFlIGZhY2lsaXNpcyBvZGlvIG1vbGxpcy4gQWVuZWFuIG5vbiBz
+ZW0gZXQgZXJvcyBjb25ndWUgcG9ydGEgaWQgc2l0IGFtZXQgZGlhbS4gRG9uZWMg
+ZnJpbmdpbGxhIGVyb3MgYXQgcXVhbSBpbXBlcmRpZXQgYXQgZ3JhdmlkYSB0b3J0
+b3IgdWxsYW1jb3JwZXIuIEZ1c2NlIGRvbG9yIHJpc3VzLCB2aXZlcnJhIGlkIGFs
+aXF1ZXQgc2VkLCBkaWduaXNzaW0gcXVpcyBtYXVyaXMuIFF1aXNxdWUgYWMgbWV0
+dXMgaWQgcXVhbSBsb2JvcnRpcyB0cmlzdGlxdWUgYXQgdmVsIGVuaW0uIFBoYXNl
+bGx1cyBpbiB0b3J0b3IgbWF1cmlzLiBTZWQgdGluY2lkdW50IGR1aSBub24gZXJv
+cyBzb2xsaWNpdHVkaW4gdm9sdXRwYXQuIEN1cmFiaXR1ciB2aXZlcnJhIGVsZW1l
+bnR1bSBhcmN1IGFjIHVsdHJpY2VzLiBOdWxsYSBmZWxpcyBsaWd1bGEsIGF1Y3Rv
+ciBhdCBsYWNpbmlhIHNlZCwgdGluY2lkdW50IGF0IG1pLiBJbiB2ZWwgZWxpdCBv
+cmNpLiBWZXN0aWJ1bHVtIGVyYXQgbmlzaSwgbW9sZXN0aWUgdmVsIGF1Y3RvciB2
+ZWwsIHNhZ2l0dGlzIGFjIGxlY3R1cy4gUGVsbGVudGVzcXVlIHVsdHJpY2llcyBj
+b25kaW1lbnR1bSBudWxsYSBuZWMgZXVpc21vZC4KCkRvbmVjIGNvbnNlY3RldHVy
+IHZlbmVuYXRpcyBzZW1wZXIuIFN1c3BlbmRpc3NlIHZlbCBkaWN0dW0gYXVndWUu
+IFBlbGxlbnRlc3F1ZSBub24gbWF1cmlzIGp1c3RvLiBEb25lYyBhY2N1bXNhbiwg
+bWV0dXMgdXQgcHJldGl1bSBtb2xlc3RpZSwgbGlndWxhIGp1c3RvIGx1Y3R1cyBv
+cmNpLCBub24gdmFyaXVzIG1pIG5pYmggZXUganVzdG8uIFZlc3RpYnVsdW0gc2Vt
+IHNlbSwgdGluY2lkdW50IGVnZXQgcG9ydGEgYSwgZmVybWVudHVtIGV0IHNhcGll
+bi4gTnVsbGEgZmFjaWxpc2kuIFBlbGxlbnRlc3F1ZSBpbiB2ZXN0aWJ1bHVtIGFu
+dGUuIE51bmMgaWFjdWxpcyBsaWd1bGEgbmVjIG9kaW8gc2FnaXR0aXMgbmVjIHBv
+cnR0aXRvciBuaWJoIHNlbXBlci4gVXQgZWdldCBtZXR1cyBvcmNpLiBQcm9pbiBn
+cmF2aWRhIG9yY2kgZGlnbmlzc2ltIGRpYW0gaWFjdWxpcyBhY2N1bXNhbi4gQWVu
+ZWFuIGF1Z3VlIG9yY2ksIHBsYWNlcmF0IGV0IGNvbnZhbGxpcyBlZ2V0LCBzb2Rh
+bGVzIHF1aXMgZGlhbS4gU2VkIHN1c2NpcGl0IG5pc2kgcXVpcyBsaWJlcm8gc29s
+bGljaXR1ZGluIGV1IG1vbGxpcyBuZXF1ZSBtb2xlc3RpZS4gTWFlY2VuYXMgcHVy
+dXMgbmlzbCwgY29uc2VjdGV0dXIgbm9uIHZlaGljdWxhIHNpdCBhbWV0LCB1bGxh
+bWNvcnBlciBxdWlzIG5pYmguIFByYWVzZW50IHF1YW0gaXBzdW0sIG1vbGVzdGll
+IGV1IHB1bHZpbmFyIGF0LCBpYWN1bGlzIGV1IHR1cnBpcy4gQ3JhcyBuZWMgZWxp
+dCB1dCBsaWJlcm8gc3VzY2lwaXQgYWxpcXVldCBldCBuZWMgbGVjdHVzLiBWZXN0
+aWJ1bHVtIHB1cnVzIGF1Z3VlLCB0cmlzdGlxdWUgdml0YWUgY29udmFsbGlzIGF0
+LCB2ZWhpY3VsYSBub24gbWV0dXMuIEZ1c2NlIGx1Y3R1cyBjb25ndWUgbWksIHZl
+bCBzYWdpdHRpcyBkb2xvciBtb2xsaXMgdmVsLiBQcmFlc2VudCBpbiBudW5jIGFj
+Y3Vtc2FuIGxvcmVtIGxvYm9ydGlzIGlhY3VsaXMgdXQgdml0YWUgaXBzdW0uIFN1
+c3BlbmRpc3NlIHB1bHZpbmFyLCBudW5jIGFjIGFsaXF1ZXQgc2VtcGVyLCBsYWN1
+cyBsb3JlbSBldWlzbW9kIHB1cnVzLCB2ZWwgbW9sbGlzIG1ldHVzIHJpc3VzIG5l
+YyBzYXBpZW4uCgpJbiB2ZW5lbmF0aXMgcG9zdWVyZSBzYXBpZW4sIHNpdCBhbWV0
+IGV1aXNtb2QgZG9sb3IgcGVsbGVudGVzcXVlIGV1LiBQcmFlc2VudCBsYW9yZWV0
+IGZlbGlzIHV0IG1ldHVzIHZlc3RpYnVsdW0gY29uZGltZW50dW0uIFV0IHNjZWxl
+cmlzcXVlIGxlbyBhdWd1ZS4gU3VzcGVuZGlzc2Ugdml0YWUgZG9sb3IgcHVydXMs
+IGlkIHJ1dHJ1bSBhbnRlLiBGdXNjZSBpbiB2ZWxpdCBhbnRlLCBhIHBlbGxlbnRl
+c3F1ZSBtaS4gTWFlY2VuYXMgdmVsIHJpc3VzIGVnZXQgb3JjaSBmZXJtZW50dW0g
+cHJldGl1bSBuZWMgdmVsIHNhcGllbi4gUGhhc2VsbHVzIGlwc3VtIG1hZ25hLCBi
+aWJlbmR1bSBxdWlzIGZhdWNpYnVzIHZlbCwgcGxhY2VyYXQgaWQgbWFnbmEuIFZp
+dmFtdXMgcXVhbSBkdWksIGNvbnNlY3RldHVyIHNlZCBwdWx2aW5hciBldSwgaW50
+ZXJkdW0gaWQgaXBzdW0uIENyYXMgbG9ib3J0aXMgZmFjaWxpc2lzIHJ1dHJ1bS4g
+Q3VtIHNvY2lpcyBuYXRvcXVlIHBlbmF0aWJ1cyBldCBtYWduaXMgZGlzIHBhcnR1
+cmllbnQgbW9udGVzLCBuYXNjZXR1ciByaWRpY3VsdXMgbXVzLiBOYW0gdmVzdGli
+dWx1bSBudW5jIHNlZCBqdXN0byBkaWduaXNzaW0gYWMgdGluY2lkdW50IHNhcGll
+biBjb25ndWUuCgpQaGFzZWxsdXMgbm9uIGRpY3R1bSB0dXJwaXMuIFByb2luIGVn
+ZXQgbWFzc2EgbGFjaW5pYSBsaWJlcm8gcnV0cnVtIHZlc3RpYnVsdW0uIE51bGxh
+IGFsaXF1ZXQgbGliZXJvIGlkIHNhcGllbiBhbGlxdWFtIGZlcm1lbnR1bS4gVml2
+YW11cyBsZWN0dXMgaXBzdW0sIHBoYXJldHJhIHV0IGRhcGlidXMgdXQsIGFsaXF1
+YW0gYWMgbmVxdWUuIFZpdmFtdXMgZmF1Y2lidXMgbWkgcXVpcyBtYXVyaXMgcnV0
+cnVtIGFjIHBsYWNlcmF0IG5pc2kgc2NlbGVyaXNxdWUuIE1hdXJpcyBlbGl0IG9y
+Y2ksIGFkaXBpc2NpbmcgZXUgY29uc2VxdWF0IGlkLCB2ZW5lbmF0aXMgaW4gbnVu
+Yy4gQWVuZWFuIG5vbiBibGFuZGl0IGxpYmVyby4gU3VzcGVuZGlzc2UgaWQgYXVn
+dWUgZHVpLiBRdWlzcXVlIG5lYyBvcmNpIHZlbCBvZGlvIG1hdHRpcyBncmF2aWRh
+LiBWZXN0aWJ1bHVtIGFudGUgaXBzdW0gcHJpbWlzIGluIGZhdWNpYnVzIG9yY2kg
+bHVjdHVzIGV0IHVsdHJpY2VzIHBvc3VlcmUgY3ViaWxpYSBDdXJhZTsgTWF1cmlz
+IHZvbHV0cGF0IGR1aSB1dCBsYWN1cyBhZGlwaXNjaW5nIGJpYmVuZHVtLiBMb3Jl
+bSBpcHN1bSBkb2xvciBzaXQgYW1ldCwgY29uc2VjdGV0dXIgYWRpcGlzY2luZyBl
+bGl0LiBWaXZhbXVzIHZlbmVuYXRpcyBqdXN0byBldSBzYXBpZW4gZmVybWVudHVt
+IGNvbmd1ZSBxdWlzIGluIG51bmMuIE51bGxhbSBsYWNpbmlhIGVyb3MgbG9yZW0s
+IHV0IGFsaXF1YW0gb3JjaS4gUGhhc2VsbHVzIHN1c2NpcGl0LCBsYWN1cyBldCB0
+ZW1wb3Igc2VtcGVyLCBlc3QgbWF1cmlzIGNvbmd1ZSBtYXNzYSwgc2VkIHVsdHJp
+Y2VzIG9yY2kgZGlhbSB2aXRhZSBpcHN1bS4KCk51bGxhIGZhY2lsaXNpLiBTZWQg
+cG9zdWVyZSBmcmluZ2lsbGEgZmVsaXMsIGFjIHZlbmVuYXRpcyBkdWkgdnVscHV0
+YXRlIHV0LiBQcm9pbiBlbGVpZmVuZCB0ZW1wb3IgbW9sZXN0aWUuIE51bGxhIHRp
+bmNpZHVudCBsZWN0dXMgdml0YWUgbmVxdWUgYmliZW5kdW0gcHJldGl1bS4gSW4g
+bGliZXJvIG5pc2wsIHRyaXN0aXF1ZSBuZWMgYmliZW5kdW0gc2l0IGFtZXQsIHVs
+bGFtY29ycGVyIG5lYyBlcmF0LiBTdXNwZW5kaXNzZSBpbnRlcmR1bSBwb3J0YSBv
+cmNpLCBxdWlzIHZpdmVycmEgZXJhdCBhdWN0b3IgYXQuIER1aXMgYWMgZGlhbSBl
+dCBsaWd1bGEgYmxhbmRpdCB0ZW1wb3IgbmVjIGV1IGxhY3VzLiBDdW0gc29jaWlz
+IG5hdG9xdWUgcGVuYXRpYnVzIGV0IG1hZ25pcyBkaXMgcGFydHVyaWVudCBtb250
+ZXMsIG5hc2NldHVyIHJpZGljdWx1cyBtdXMuIFByYWVzZW50IHBlbGxlbnRlc3F1
+ZSB2YXJpdXMgbnVsbGEgdmVsIGFsaXF1YW0uIEFsaXF1YW0gdXQgbGVjdHVzIG1h
+dXJpcywgaWQgYWxpcXVldCBsYWN1cy4gSW50ZWdlciBzY2VsZXJpc3F1ZSBlbGVt
+ZW50dW0gZHVpLCBldSBsYW9yZWV0IGF1Z3VlIGVsZW1lbnR1bSBzaXQgYW1ldC4g
+VXQgdWxsYW1jb3JwZXIgdGVsbHVzIGNvbnZhbGxpcyBzYXBpZW4gdmVzdGlidWx1
+bSBub24gbGFvcmVldCBwdXJ1cyBhZGlwaXNjaW5nLiBOdW5jIG5lYyBxdWFtIG51
+bmMuIFZpdmFtdXMgdWx0cmljZXMgZmVybWVudHVtIG1hc3NhLCBzaXQgYW1ldCBz
+Y2VsZXJpc3F1ZSBudW5jIGltcGVyZGlldCB1dC4KClZlc3RpYnVsdW0gYW50ZSBp
+cHN1bSBwcmltaXMgaW4gZmF1Y2lidXMgb3JjaSBsdWN0dXMgZXQgdWx0cmljZXMg
+cG9zdWVyZSBjdWJpbGlhIEN1cmFlOyBJbiBoYWMgaGFiaXRhc3NlIHBsYXRlYSBk
+aWN0dW1zdC4gTnVsbGFtIHRpbmNpZHVudCBtb2xlc3RpZSBpcHN1bSB2ZWwgcmhv
+bmN1cy4gSW50ZWdlciBlZ2V0IG51bmMgZXUgdGVsbHVzIHRpbmNpZHVudCBsYWNp
+bmlhLiBJbnRlZ2VyIG5lYyBuaXNpIGVnZXQgYXVndWUgc2VtcGVyIHZhcml1cyBp
+ZCBhYyBxdWFtLiBOYW0gdGluY2lkdW50LCB0ZWxsdXMgYWMgY29uZGltZW50dW0g
+YWNjdW1zYW4sIGRvbG9yIGVyb3Mgdml2ZXJyYSBsZW8sIHBoYXJldHJhIHB1bHZp
+bmFyIGxlY3R1cyBlcm9zIGluIG1pLiBEb25lYyBjb25zZXF1YXQsIHR1cnBpcyBp
+ZCBjb252YWxsaXMgdm9sdXRwYXQsIGFudGUgc2VtIGVsZW1lbnR1bSBtYWduYSwg
+cXVpcyB0ZW1wb3IgcmlzdXMgZGlhbSB2ZWwgdHVycGlzLiBNb3JiaSBhIG9yY2kg
+b3JjaSwgZWdlc3RhcyBmZXVnaWF0IGxlY3R1cy4gTnVsbGEgbmVjIG5pYmggaWQg
+YXVndWUgaW50ZXJkdW0gbW9sbGlzLiBTdXNwZW5kaXNzZSBwbGFjZXJhdCB0ZW1w
+dXMgbnVuYyBhYyB2ZXN0aWJ1bHVtLiBEb25lYyBldCBtZXR1cyBkaWN0dW0gbGVv
+IGJpYmVuZHVtIHVsdHJpY2VzIGluIG5lYyBsZWN0dXMuIFV0IHNlZCB2ZWxpdCBu
+aWJoLCBzb2RhbGVzIHBvcnRhIG51bmMuIEluIGhhYyBoYWJpdGFzc2UgcGxhdGVh
+IGRpY3R1bXN0LiBTZWQgZWxpdCB0b3J0b3IsIGFsaXF1ZXQgdmVsIHZvbHV0cGF0
+IGEsIHRpbmNpZHVudCBzZWQgc2FwaWVuLiBTdXNwZW5kaXNzZSBlZ2V0IGxpYmVy
+byBsYWN1cy4gVml2YW11cyBhdWN0b3IgYW50ZSBub24gbmVxdWUgcG9ydHRpdG9y
+IHV0IHByZXRpdW0gbmlzbCB0ZW1wdXMuIE51bGxhIHNvZGFsZXMgcmlzdXMgZXQg
+ZXJhdCB2YXJpdXMgbGFvcmVldC4gTWFlY2VuYXMgbHVjdHVzIGxvYm9ydGlzIGxp
+Z3VsYSBlZ2V0IGZlcm1lbnR1bS4KClZpdmFtdXMgY29udmFsbGlzIG5pYmggdml0
+YWUgdHVycGlzIGZldWdpYXQgdWx0cmljZXMuIFF1aXNxdWUgdml0YWUgYmxhbmRp
+dCBtYXNzYS4gTWF1cmlzIGV1aXNtb2QgdXJuYSB1dCBuZXF1ZSBmZXJtZW50dW0g
+dml0YWUgaW1wZXJkaWV0IG1hdXJpcyBldWlzbW9kLiBJbiBhIGR1aSB0ZWxsdXMs
+IG5lYyBwb3N1ZXJlIGRvbG9yLiBBZW5lYW4gdWxsYW1jb3JwZXIgYXVndWUgaWQg
+ZXJhdCBsYWNpbmlhIHB1bHZpbmFyLiBQZWxsZW50ZXNxdWUgYXQgbnVsbGEgdGVs
+bHVzLiBOYW0gZWxlbWVudHVtIGlhY3VsaXMgcHVsdmluYXIuIFZpdmFtdXMgdG9y
+dG9yIGxlY3R1cywgZ3JhdmlkYSB1dCBjb21tb2RvIGEsIHZpdmVycmEgdXQgb2Rp
+by4gUGhhc2VsbHVzIGVsZW1lbnR1bSBibGFuZGl0IG9kaW8sIG5lYyBkYXBpYnVz
+IGFudGUgbWFsZXN1YWRhIGEuIE1hZWNlbmFzIGltcGVyZGlldCwgZmVsaXMgYSBz
+ZW1wZXIgZmFjaWxpc2lzLCBtYXNzYSBudWxsYSBhbGlxdWV0IHRvcnRvciwgZXQg
+bWFsZXN1YWRhIG1hZ25hIGxlY3R1cyBhYyBwdXJ1cy4gQWVuZWFuIGF1Y3RvciB0
+ZWxsdXMgaWQganVzdG8gY29uZGltZW50dW0gdHJpc3RpcXVlLiBDcmFzIHZpdGFl
+IHJ1dHJ1bSBhcmN1LiBNYXVyaXMgdGVtcHVzLCBtYWduYSBlZ2V0IHZhcml1cyBp
+bnRlcmR1bSwgbmlzbCBqdXN0byBwb3J0YSBhdWd1ZSwgc2VkIHBvcnRhIG5pc2wg
+cXVhbSBhIG5pYmguIE1hZWNlbmFzIHZpdGFlIHB1cnVzIGRpYW0uIFByYWVzZW50
+IGJpYmVuZHVtIG5pYmggZHVpLCBpbiB0aW5jaWR1bnQgbnVuYy4gRHVpcyB2aXRh
+ZSBzZW0gYW50ZS4KCk1hdXJpcyBwb3N1ZXJlIGZlbGlzIGV0IHR1cnBpcyBzb2Rh
+bGVzIGhlbmRyZXJpdCB1dCBpZCBudW5jLiBEb25lYyBsYW9yZWV0IG1hbGVzdWFk
+YSBlcm9zLiBOYW0gcXVpcyBkaWFtIGFyY3UsIGV1IHRyaXN0aXF1ZSB0ZWxsdXMu
+IFBlbGxlbnRlc3F1ZSBxdWlzIGVsaXQgbnVuYy4gQ3JhcyBsZW8gbG9yZW0sIG9y
+bmFyZSBjb21tb2RvIG1vbGVzdGllIHNpdCBhbWV0LCBjb25zZXF1YXQgdmVsIGVz
+dC4gSW4gaGFjIGhhYml0YXNzZSBwbGF0ZWEgZGljdHVtc3QuIENyYXMgcmlzdXMg
+cXVhbSwgc3VzY2lwaXQgc2VtcGVyIGltcGVyZGlldCB1bHRyaWNlcywgdHJpc3Rp
+cXVlIG5lYyBzYXBpZW4uIFBlbGxlbnRlc3F1ZSBjb25kaW1lbnR1bSwgdHVycGlz
+IG5lYyBzb2RhbGVzIGNvbnNlY3RldHVyLCBkaWFtIHNlbSBiaWJlbmR1bSBkaWFt
+LCB2aXRhZSBhbGlxdWV0IG1pIGFyY3UgYSBhcmN1LiBQaGFzZWxsdXMgaGVuZHJl
+cml0LCBtYWduYSBxdWlzIGdyYXZpZGEgZmVybWVudHVtLCBtYWduYSBsZWN0dXMg
+c2VtcGVyIG1hc3NhLCBzZWQgY29uZ3VlIHVybmEgbmliaCBhdCBudWxsYS4gQ3Jh
+cyBzZWQgbmliaCBtaS4gTnVsbGEgdGVtcG9yIHByZXRpdW0gcG9ydGEuCgpVdCBp
+ZCBqdXN0byB2aXRhZSB0dXJwaXMgY29udmFsbGlzIGNvbmd1ZS4gQ3VyYWJpdHVy
+IG1hbGVzdWFkYSBwdXJ1cyBlZ2V0IGRpYW0gYXVjdG9yIGV0IHVsbGFtY29ycGVy
+IHZlbGl0IG1hbGVzdWFkYS4gUGhhc2VsbHVzIHNjZWxlcmlzcXVlIGZlcm1lbnR1
+bSBsaWJlcm8uIE1vcmJpIGR1aSB0b3J0b3IsIGJsYW5kaXQgbWFsZXN1YWRhIGxv
+Ym9ydGlzIHVsdHJpY2llcywgYmxhbmRpdCBldCBuaXNpLiBOdWxsYSBtYXR0aXMg
+ZmFjaWxpc2lzIGxhY3VzLiBBbGlxdWFtIHNvZGFsZXMgZWxpdCBzaXQgYW1ldCBt
+ZXR1cyB2ZW5lbmF0aXMgYSBjb21tb2RvIHF1YW0gYmliZW5kdW0uIFV0IG5vbiB0
+ZWxsdXMgdG9ydG9yLiBTZWQgc2VtcGVyLCBuaXNpIGluIHRlbXBvciB2ZXN0aWJ1
+bHVtLCBzZW0gbnVsbGEgZXVpc21vZCBhcmN1LCB1dCBzb2RhbGVzIGVzdCBudW5j
+IGF0IHRlbGx1cy4gRG9uZWMgbm9uIG1ldHVzIG5vbiBkb2xvciBzY2VsZXJpc3F1
+ZSB2aXZlcnJhLiBQaGFzZWxsdXMgbmVjIG51bGxhIGp1c3RvLCB1dCBwb3J0dGl0
+b3IgbnVsbGEuIEZ1c2NlIGZldWdpYXQgZ3JhdmlkYSBzb2xsaWNpdHVkaW4uIFNl
+ZCBpZCBoZW5kcmVyaXQgbWF1cmlzLiBEb25lYyBsZWN0dXMgdG9ydG9yLCBwb3J0
+YSBzaXQgYW1ldCBjb25kaW1lbnR1bSBzZWQsIHZhcml1cyBhIHZlbGl0LiBJbiBk
+aWN0dW0gZG9sb3Igc2VkIGVzdCBkaWN0dW0gaW4gcnV0cnVtIG5lcXVlIHN1c2Np
+cGl0LgoKTWFlY2VuYXMgaW1wZXJkaWV0IGNvbnZhbGxpcyB1bHRyaWNpZXMuIEN1
+bSBzb2NpaXMgbmF0b3F1ZSBwZW5hdGlidXMgZXQgbWFnbmlzIGRpcyBwYXJ0dXJp
+ZW50IG1vbnRlcywgbmFzY2V0dXIgcmlkaWN1bHVzIG11cy4gUGVsbGVudGVzcXVl
+IG51bmMgdHVycGlzLCBpYWN1bGlzIHF1aXMgZWxlaWZlbmQgZXUsIHRpbmNpZHVu
+dCB1dCBsYWN1cy4gQ3VyYWJpdHVyIHZpdGFlIHRlbGx1cyBuaWJoLiBQZWxsZW50
+ZXNxdWUgZWdldCBjb21tb2RvIG5pYmguIE51bGxhIGxhb3JlZXQsIGVyb3MgaWQg
+aW1wZXJkaWV0IG1vbGxpcywgbmlzaSBlc3QgZWdlc3RhcyBmZWxpcywgZWdldCBs
+dWN0dXMgZW5pbSBsYWN1cyB2aXRhZSBhcmN1LiBOdWxsYW0gaXBzdW0gZGlhbSwg
+ZmF1Y2lidXMgZmV1Z2lhdCBjb21tb2RvIGV0LCB0ZW1wb3IgYWMgbGFjdXMuIERv
+bmVjIHZlbCBlcmF0IG1hc3NhLCBhdCBwcmV0aXVtIGVzdC4gUGVsbGVudGVzcXVl
+IGx1Y3R1cyBuaXNpIG51bGxhLCBhYyBhbGlxdWV0IGF1Z3VlLiBNYWVjZW5hcyBp
+ZCBwaGFyZXRyYSBkb2xvci4gUHJvaW4gZGFwaWJ1cyBtYXR0aXMgY3Vyc3VzLiBN
+b3JiaSBpbnRlcmR1bSwgZW5pbSBxdWlzIGZlcm1lbnR1bSBwbGFjZXJhdCwgbmlz
+aSBtaSBjb25ndWUgc2VtLCBhIHRlbXBvciBuaXNsIG1hdXJpcyBpbiBzZW0uIElu
+IGNvbmRpbWVudHVtLCBpcHN1bSBuZWMgdmVuZW5hdGlzIHZlbmVuYXRpcywgbnVs
+bGEgZW5pbSBsYW9yZWV0IGFudGUsIG5lYyBoZW5kcmVyaXQgaXBzdW0gbGVjdHVz
+IGVnZXQgcmlzdXMuIFBlbGxlbnRlc3F1ZSBlbmltIGxpYmVybywgdGluY2lkdW50
+IHZpdGFlIG1vbGVzdGllIHNpdCBhbWV0LCBncmF2aWRhIG5lYyBsYWN1cy4gRHVp
+cyBhYyBzYXBpZW4gbGliZXJvLCBpbiBhbGlxdWV0IHF1YW0uIE1vcmJpIHRlbXBv
+ciBsaWJlcm8gcXVpcyBlc3QgZ3JhdmlkYSBzZWQgZWdlc3RhcyBudWxsYSB2dWxw
+dXRhdGUuCgpEb25lYyBsYWNpbmlhIG1pIGF0IHRlbGx1cyB2aXZlcnJhIGxvYm9y
+dGlzLiBOdWxsYSBpbnRlcmR1bSwgdXJuYSB1dCBmYXVjaWJ1cyBzZW1wZXIsIGR1
+aSBsZWN0dXMgZnJpbmdpbGxhIGVyYXQsIHV0IGFsaXF1YW0gbmlzbCBpcHN1bSBh
+dCBlcm9zLiBWaXZhbXVzIGNvbnZhbGxpcyBoZW5kcmVyaXQgYXJjdSBxdWlzIGNv
+bmRpbWVudHVtLiBQcmFlc2VudCBhdCBmZXVnaWF0IHNhcGllbi4gUXVpc3F1ZSBu
+b24gb3JjaSBhcmN1LiBQZWxsZW50ZXNxdWUgZWdldCBtaSBhcmN1LCBzaXQgYW1l
+dCBsdWN0dXMgbnVuYy4gQ3VyYWJpdHVyIGxlY3R1cyBsZW8sIGNvbnNlcXVhdCBz
+ZW1wZXIgaW1wZXJkaWV0IGV0LCBlbGVtZW50dW0gdml0YWUgZGlhbS4gUHJvaW4g
+cHVydXMgbnVsbGEsIHB1bHZpbmFyIGlkIGltcGVyZGlldCBzZWQsIGZldWdpYXQg
+YSBudWxsYS4gUHJvaW4gc3VzY2lwaXQgZWxpdCB2ZWwgYXJjdSB2ZW5lbmF0aXMg
+c29kYWxlcy4gQ3JhcyBhY2N1bXNhbiBtYXNzYSBhYyBudWxsYSBwdWx2aW5hciBm
+ZXVnaWF0IGV1IGF0IHRlbGx1cy4gUXVpc3F1ZSB2aXRhZSBlcmF0IG9yY2ksIG5v
+biB0ZW1wb3IgZW5pbS4gRG9uZWMgb3JuYXJlIGxvYm9ydGlzIG1pIHZpdGFlIGNv
+bnNlcXVhdC4gSW50ZWdlciB2aXZlcnJhLCB2ZWxpdCB2ZWwgcGVsbGVudGVzcXVl
+IGFjY3Vtc2FuLCBhdWd1ZSBsaWd1bGEgYmxhbmRpdCBuaXNsLCBlZ2V0IGNvbmRp
+bWVudHVtIG5lcXVlIGFyY3UgaW4gZXJhdC4gTmFtIHF1aXMgbG9yZW0gbG9yZW0s
+IHZlbCBjdXJzdXMgcmlzdXMuIEluIG5lYyBudW5jIGRvbG9yLCBxdWlzIHBvcnR0
+aXRvciBuZXF1ZS4gTWFlY2VuYXMgdHVycGlzIG9kaW8sIGRpY3R1bSB2aXRhZSBj
+b21tb2RvIHRpbmNpZHVudCwgYWxpcXVhbSB1dCBhdWd1ZS4gUGhhc2VsbHVzIGF0
+IGp1c3RvIGxhY3VzLiBQaGFzZWxsdXMgc2l0IGFtZXQgdXJuYSBhdCBhbnRlIHZh
+cml1cyBwZWxsZW50ZXNxdWUuIFBlbGxlbnRlc3F1ZSBpbiBsaWJlcm8gYWMgdXJu
+YSBmcmluZ2lsbGEgdGluY2lkdW50IHZpdGFlIHNlZCB2ZWxpdC4KCkRvbmVjIGFj
+IHJpc3VzIHNhcGllbi4gTnVsbGEgZmFjaWxpc2kuIERvbmVjIGF0IHZlbGl0IG5v
+biBudW5jIHRlbXB1cyBmZXJtZW50dW0uIEN1bSBzb2NpaXMgbmF0b3F1ZSBwZW5h
+dGlidXMgZXQgbWFnbmlzIGRpcyBwYXJ0dXJpZW50IG1vbnRlcywgbmFzY2V0dXIg
+cmlkaWN1bHVzIG11cy4gRnVzY2UgaW50ZXJkdW0gYWxpcXVhbSBsb3JlbSwgaW4g
+c2NlbGVyaXNxdWUgZW5pbSB0aW5jaWR1bnQgaWQuIFByYWVzZW50IHNvbGxpY2l0
+dWRpbiBkdWkgbmVjIGxhY3VzIGxhY2luaWEgcGxhY2VyYXQuIFV0IGVnZXQgbWF0
+dGlzIG1ldHVzLiBJbiB2ZWwgc2VtIHVybmEsIGV1IGNvbnZhbGxpcyB0dXJwaXMu
+IER1aXMgaGVuZHJlcml0IGlwc3VtIHVybmEsIG5vbiBwZWxsZW50ZXNxdWUgb3Jj
+aS4gVXQgZXN0IG1ldHVzLCBlbGVtZW50dW0gaW4gYmliZW5kdW0gaWQsIHZpdmVy
+cmEgZGlnbmlzc2ltIHRlbGx1cy4gRHVpcyBpZCBlcmF0IGxpYmVyby4gVmVzdGli
+dWx1bSBpbiBsaWJlcm8gbm9uIHNlbSB0aW5jaWR1bnQgZWxlbWVudHVtIHNlZCBl
+dCBuaXNpLiBQaGFzZWxsdXMgbGVjdHVzIGVyYXQsIGVsZWlmZW5kIGlkIHNhZ2l0
+dGlzIHV0LCBmcmluZ2lsbGEgc2VkIHR1cnBpcy4gQWxpcXVhbSB2ZWwgZXJvcyBp
+ZCBudW5jIHZlbmVuYXRpcyB1bGxhbWNvcnBlci4gQWxpcXVhbSB0cmlzdGlxdWUg
+bWFzc2EgYSBtYXVyaXMgc2NlbGVyaXNxdWUgbm9uIGZhdWNpYnVzIG5lcXVlIHVs
+dHJpY2llcy4KCkFsaXF1YW0gY29uc2VxdWF0IGx1Y3R1cyBlbGl0LCBpZCBtYWxl
+c3VhZGEgZXJvcyBsb2JvcnRpcyB1dC4gTnVsbGFtIGEgaGVuZHJlcml0IGxpYmVy
+by4gTWFlY2VuYXMgZXQgc2VtIGF0IGVyYXQgbWF0dGlzIGVsZWlmZW5kIHNlZCBz
+aXQgYW1ldCBzZW0uIE51bGxhIGxvYm9ydGlzIG5pYmggYSBvcmNpIGVsZWlmZW5k
+IHRlbXBvci4gUHJvaW4gbnVsbGEgZmVsaXMsIHZlbmVuYXRpcyBxdWlzIHVsdHJp
+Y2llcyB2ZWwsIGFsaXF1ZXQgaW4gZG9sb3IuIFBoYXNlbGx1cyB0aW5jaWR1bnQg
+ZG9sb3IgZmVybWVudHVtIG1hc3NhIGlhY3VsaXMgZGlnbmlzc2ltIHZlbCB1dCBk
+dWkuIFByb2luIHRpbmNpZHVudCBzYWdpdHRpcyBzb2RhbGVzLiBQcm9pbiBtYXR0
+aXMgdmFyaXVzIGVuaW0sIGF0IGx1Y3R1cyBzZW0gaGVuZHJlcml0IGV1LiBVdCB2
+aXRhZSBncmF2aWRhIG9kaW8uIEFsaXF1YW0gZXJhdCB2b2x1dHBhdC4gTnVsbGEg
+ZnJpbmdpbGxhIHBsYWNlcmF0IHZlbGl0LCBzZWQgYWxpcXVldCBudWxsYSBpbXBl
+cmRpZXQgYS4gRG9uZWMgZWxlaWZlbmQgcHVsdmluYXIgb3JjaSwgaW4gcG9ydGEg
+ZGlhbSBwb3N1ZXJlIGJpYmVuZHVtLiBQcm9pbiBlZ2VzdGFzIHBvcnR0aXRvciBh
+bGlxdWFtLiBRdWlzcXVlIHNhcGllbiBmZWxpcywgaGVuZHJlcml0IGlkIGNvbmd1
+ZSBldSwgdGluY2lkdW50IHNlZCBlc3QuIFZpdmFtdXMgY3Vyc3VzIHByZXRpdW0g
+ZXJhdCB1dCBmYXVjaWJ1cy4gSW50ZWdlciBsaWJlcm8gZWxpdCwgdmVuZW5hdGlz
+IHZlbCBhbGlxdWV0IG5lYywgaW50ZXJkdW0gaW4gZW5pbS4gTmFtIGEgdmVsaXQg
+anVzdG8sIHZpdGFlIGlhY3VsaXMgdHVycGlzLgoKVml2YW11cyBuaWJoIGxpZ3Vs
+YSwgaW50ZXJkdW0gdmVzdGlidWx1bSB2ZW5lbmF0aXMgdml0YWUsIGZlcm1lbnR1
+bSBpbiBtYWduYS4gU3VzcGVuZGlzc2UgZHVpIGFyY3UsIGdyYXZpZGEgYWMgZWdl
+c3RhcyBub24sIGNvbmd1ZSBub24gZGlhbS4gUGVsbGVudGVzcXVlIGhhYml0YW50
+IG1vcmJpIHRyaXN0aXF1ZSBzZW5lY3R1cyBldCBuZXR1cyBldCBtYWxlc3VhZGEg
+ZmFtZXMgYWMgdHVycGlzIGVnZXN0YXMuIFBlbGxlbnRlc3F1ZSBwdWx2aW5hciBw
+aGFyZXRyYSBsb3JlbSwgZXQgcG9zdWVyZSBzZW0gY29uZ3VlIHV0LiBTZWQgZWxl
+bWVudHVtIGNvbnZhbGxpcyBkb2xvciBldSB2dWxwdXRhdGUuIEludGVnZXIgbmli
+aCBqdXN0bywgcGVsbGVudGVzcXVlIGVnZXQgdWx0cmljaWVzIGF1Y3RvciwgZmVy
+bWVudHVtIG5vbiBtaS4gUGVsbGVudGVzcXVlIGF0IG5lcXVlIGVzdC4gQ3VyYWJp
+dHVyIHBlbGxlbnRlc3F1ZSBhcmN1IHNlZCBsYWN1cyBwbGFjZXJhdCBxdWlzIGRp
+Z25pc3NpbSBvcmNpIHBsYWNlcmF0LiBOdWxsYW0gcGVsbGVudGVzcXVlIGxpYmVy
+byBpZCBhbnRlIGRhcGlidXMgc2VkIGJpYmVuZHVtIG1ldHVzIHRyaXN0aXF1ZS4g
+Vml2YW11cyBpZCBkdWkgcXVpcyBhcmN1IHVsdHJpY2VzIHZpdmVycmEuIFBlbGxl
+bnRlc3F1ZSBhdWN0b3IgbmlzaSBzZWQgZXN0IGxhb3JlZXQgdml2ZXJyYS4gU3Vz
+cGVuZGlzc2UgbGFjaW5pYSBsZWN0dXMgbWFzc2EuIEFsaXF1YW0gZXJhdCB2b2x1
+dHBhdC4KClF1aXNxdWUgdWxsYW1jb3JwZXIgYXVndWUgaW4ganVzdG8gdWx0cmlj
+aWVzIHBvcnRhLiBTZWQgcXVpcyBhcmN1IGFjIGxvcmVtIGFjY3Vtc2FuIHBvc3Vl
+cmUuIE1hdXJpcyBjb25zZXF1YXQsIGxpYmVybyBlZ2V0IGZldWdpYXQgbG9ib3J0
+aXMsIGlwc3VtIGZlbGlzIHZlc3RpYnVsdW0gdGVsbHVzLCB2ZWwgdWx0cmljZXMg
+aXBzdW0gYXJjdSBldSBuaXNsLiBDdW0gc29jaWlzIG5hdG9xdWUgcGVuYXRpYnVz
+IGV0IG1hZ25pcyBkaXMgcGFydHVyaWVudCBtb250ZXMsIG5hc2NldHVyIHJpZGlj
+dWx1cyBtdXMuIEluIGhhYyBoYWJpdGFzc2UgcGxhdGVhIGRpY3R1bXN0LiBEdWlz
+IHZpdmVycmEgdHVycGlzIHZlbCBlbGl0IGVsZWlmZW5kIGF0IHBvcnR0aXRvciB2
+ZWxpdCByaG9uY3VzLiBTZWQgYXQgZG9sb3IgcXVpcyBuaXNpIGNvbW1vZG8gcG9y
+dHRpdG9yLiBNb3JiaSBsb3JlbSBvcmNpLCBjb21tb2RvIGEgbGFvcmVldCBuZWMs
+IHZhcml1cyBhdCBsYWN1cy4gTWF1cmlzIHNlZCB2YXJpdXMgZW5pbS4gQWxpcXVh
+bSBncmF2aWRhIGFkaXBpc2Npbmcgc2VtIG5vbiBzZW1wZXIuIFN1c3BlbmRpc3Nl
+IGVnZXQgZ3JhdmlkYSBudW5jLgoKQ3JhcyB2ZXN0aWJ1bHVtIHRvcnRvciBuZWMg
+bGlndWxhIG9ybmFyZSB0ZW1wb3IuIFV0IGlhY3VsaXMgbGlndWxhIGV0IGxlY3R1
+cyB0aW5jaWR1bnQgaWFjdWxpcy4gTWFlY2VuYXMgcHVsdmluYXIgdm9sdXRwYXQg
+bGFjaW5pYS4gQ3VyYWJpdHVyIGhlbmRyZXJpdCBtYWxlc3VhZGEgbGVjdHVzLCBz
+ZWQgbWFsZXN1YWRhIGVyb3MgZWdlc3RhcyBlZ2V0LiBBbGlxdWFtIGJpYmVuZHVt
+IHZhcml1cyBvZGlvIHZhcml1cyBtYXR0aXMuIFByb2luIGFjIHJob25jdXMgYXJj
+dS4gTnVsbGEgc3VzY2lwaXQgdG9ydG9yIGEgZXN0IHZpdmVycmEgdWxsYW1jb3Jw
+ZXIuIEN1cmFiaXR1ciBldCBkdWkgZGlhbS4gU2VkIGF0IG5lcXVlIG5pc2wuIEN1
+cmFiaXR1ciBzYWdpdHRpcyBvcmNpIG5pc2wuIEN1bSBzb2NpaXMgbmF0b3F1ZSBw
+ZW5hdGlidXMgZXQgbWFnbmlzIGRpcyBwYXJ0dXJpZW50IG1vbnRlcywgbmFzY2V0
+dXIgcmlkaWN1bHVzIG11cy4KCkNyYXMgZmVsaXMgbWV0dXMsIHZhcml1cyBzaXQg
+YW1ldCBjb25zZXF1YXQgZWdldCwgc2VtcGVyIHZpdGFlIGxlby4gTWF1cmlzIHV0
+IG5pc2kgbGFjdXMsIGEgcHJldGl1bSBsYWN1cy4gRHVpcyBlZ2V0IGVzdCBuZWMg
+ZG9sb3Igc29sbGljaXR1ZGluIGZlcm1lbnR1bS4gTWFlY2VuYXMgb3JuYXJlIGFk
+aXBpc2NpbmcgZHVpLCB2aXRhZSBwZWxsZW50ZXNxdWUgbmlzbCBhbGlxdWFtIGEu
+IFZpdmFtdXMgYXVjdG9yIGZyaW5naWxsYSBsaWd1bGEsIGlkIHRlbXBvciBqdXN0
+byBjb25ndWUgYS4gUHJhZXNlbnQgcXVpcyBsYW9yZWV0IGF1Z3VlLiBEb25lYyBp
+ZCBvcmNpIHV0IG5pc2kgdml2ZXJyYSBjb21tb2RvLiBQZWxsZW50ZXNxdWUgZGlj
+dHVtIHZhcml1cyBvcmNpIHZlbCBwaGFyZXRyYS4gTnVuYyBsaWJlcm8gbmlzbCBt
+YXNzYSBudW5jLg==</sl:Base64Content>
+ </sl:DataObject>
+ <sl:TransformsInfo>
+ <sl:FinalDataMetaInfo>
+ <sl:MimeType>text/plain</sl:MimeType>
+ </sl:FinalDataMetaInfo>
+ </sl:TransformsInfo>
+ </sl:DataObjectInfo>
+</sl:CreateXMLSignatureRequest>
+ \ No newline at end of file