Browse Source

Build für TC 10 #1

master
Daniel Quathamer 10 months ago
parent
commit
fd910cdd37
  1. 25
      README.md
  2. 103
      build.xml
  3. 1
      docman_scripte/authentifizierungstest.x
  4. 1
      docman_scripte/docman_encryptor.x
  5. 1
      docman_scripte/docman_propcreator.x
  6. 1
      docman_scripte/dvelop-metadata-update.x
  7. 1
      docman_scripte/dvelopdownloadtest1.x
  8. 1
      docman_scripte/dvelopdownloadtest2.x
  9. BIN
      docman_scripte/superx-docmanagement1.3.jar
  10. 248
      lizenz.txt
  11. 603
      src/de/superx/docmanagement/AbstractDocPresenter.java
  12. 155
      src/de/superx/docmanagement/ArchivePropHandler.java
  13. 174
      src/de/superx/docmanagement/BasicAuthTokenRequester.java
  14. 138
      src/de/superx/docmanagement/ConnectionTest.java
  15. 526
      src/de/superx/docmanagement/DocMan.java
  16. 56
      src/de/superx/docmanagement/DocPresentationResult.java
  17. 48
      src/de/superx/docmanagement/DocumentMetadata.java
  18. 177
      src/de/superx/docmanagement/DvelopArchiv1.java
  19. 36
      src/de/superx/docmanagement/DvelopDocumentMetadata.java
  20. 66
      src/de/superx/docmanagement/DvelopDownloadTester.java
  21. 85
      src/de/superx/docmanagement/DvelopDownloadTester2.java
  22. 432
      src/de/superx/docmanagement/DvelopMetadatenLoader.java
  23. 23
      src/de/superx/docmanagement/Encryptor.java
  24. 70
      src/de/superx/docmanagement/FSVDocumentRetriever.java
  25. 106
      src/de/superx/docmanagement/FSVTokenRequester.java
  26. 59
      src/de/superx/docmanagement/HISConnektorTest.java
  27. 180
      src/de/superx/docmanagement/MBSArchiv1.java
  28. 89
      src/de/superx/docmanagement/MBSArchiv1TokenRequester.java
  29. 67
      src/de/superx/docmanagement/MBSBusinessTransactionArchiv.java
  30. 84
      src/de/superx/docmanagement/PCKSSigner.java.bak
  31. 141
      src/de/superx/docmanagement/SAPArchiv1.java
  32. 87
      src/de/superx/docmanagement/SignerTest.java.bak
  33. 226
      src/de/superx/docmanagement/UniFrSecKeyGenerator.java
  34. 224
      src/de/superx/docmanagement/UniFrSecKeyGeneratorTest.java
  35. BIN
      superx/WEB-INF/lib/superx-docmanagement1.4.jar
  36. 1
      superx/WEB-INF/lib_ext/bc-jar-README.txt
  37. BIN
      superx/WEB-INF/lib_ext/bcpkix-jdk15on-169.jar
  38. BIN
      superx/WEB-INF/lib_ext/bcprov-jdk15on-169.jar
  39. BIN
      superx/WEB-INF/lib_ext/bcutil-jdk15on-169.jar
  40. 15
      superx/WEB-INF/lib_ext/groovy-LICENSE.txt
  41. 5
      superx/WEB-INF/lib_ext/groovy-NOTICE.txt
  42. BIN
      superx/WEB-INF/lib_ext/groovy-all-2.3.6.jar
  43. BIN
      superx/WEB-INF/lib_ext/servlet-api.jar
  44. BIN
      superx/WEB-INF/lib_ext/superx5.3.jar

25
README.md

@ -1,3 +1,24 @@ @@ -1,3 +1,24 @@
# docmanagement
# docman
DMS-Anbindung
DMS-Anbindung für SuperX
Zur Installation
* Kopieren Sie die superx-docmanagement${version}.jar nach webapps/superx/WEB-INF/lib, und binden Sie das Servlet in der web.xml ein:
<servlet>
<servlet-name>DocMan</servlet-name>
<servlet-class>de.superx.docmanagement.DocMan</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>DocMan</servlet-name>
<url-pattern>/servlet/DocMan</url-pattern>
</servlet-mapping>
* Starten Sie Tomcat neu
Zum Build der Java Quellen installieren Sie
* Installieren Sie ANT, wenn noch nicht geschehen
* SuperX mit Java 17, und führen Sie aus:
ant -DWEBAPP=./superx ant distDocman
Damit wird die superx-docmanagement*.jar erzeugt und in den Ordner WEB-INF/lib kopiert.

103
build.xml

@ -0,0 +1,103 @@ @@ -0,0 +1,103 @@
<?xml version="1.0" encoding="UTF-8"?>
<project name="ModuleCreation" default="all" basedir=".">
<!--
docman-JAR erzeugen:
. SQL_ENV_JAVA17
ant -DWEBAPP=./superx distDocman
ant -DWEBAPP=./superx cleanBuildPath
-->
<dirname file="${ant.file.superx}" property="superxBuildBaseDir" />
<property name="distDir" location="${superxBuildBaseDir}/superx/WEB-INF/lib" />
<property environment="env" />
<!-- set global properties for this build -->
<property name="BASE_DIR" value="." />
<property name="SUPERX_DIR" value="${WEBAPP}"/>
<property name="BUILD_PATH" value="${WEBAPP}/WEB-INF/classes"/>
<property name="SRC_DIR" value="${BASE_DIR}/src" />
<property name="SRC_DIR_TEST" value="${BASE_DIR}/test-src"/>
<property name="LIB_SUPERX_DIR" value="${WEBAPP}/WEB-INF/lib"/>
<property name="LIB_WEBAPP_DIR" value="${WEBAPP}"/>
<property name="LIB_EXT_SUPERX_DIR" value="${WEBAPP}/WEB-INF/lib_ext"/>
<property name="superx-classes" value="${WEBAPP}/WEB-INF/classes" />
<property name="build_cobertura" value="${superxBuildBaseDir}/cobertura_build_classes" />
<property name="test-target" value="${superxBuildBaseDir}/cobertura_build_tests"/>
<property name="superx-lib" value="${WEBAPP}/WEB-INF/lib" />
<property name="build-results" value="${superxBuildBaseDir}/results" />
<property name="build_cobertura_report" value="${superxBuildBaseDir}/coveragereport" />
<property name="src-java" value="${SRC_DIR}"/>
<property name="test-resource" location="resource"/>
<property name="version" value="1.4" />
<dirname file="${ant.file}" property="moduleCreateBaseDir" />
<property name="BASE_DIR" value="${moduleCreateBaseDir}/../.." />
<property name="WEBAPP" value="" />
<path id="classpath">
<!--WEB-INF/lib-->
<fileset dir="${WEBAPP}/WEB-INF">
<include name="lib/**/*.jar" />
<include name="classes" />
</fileset>
<fileset dir="${LIB_EXT_SUPERX_DIR}">
<include name="**/*.jar" />
</fileset>
<fileset dir="/home/superx/git/superx/superx/WEB-INF/lib">
<include name="*.jar" />
<exclude name="jarheaven_backup/**/*.jar" />
</fileset>
</path>
<taskdef name="groovy"
classname="org.codehaus.groovy.ant.Groovy"
classpathref="classpath"/>
<target name="initTimestamp">
<tstamp>
<format property="SX_TIMESTAMP" pattern="dd.MM.yyyy HH:mm" />
</tstamp>
</target>
<target name="distDocman" depends="compileSuperx" description="Erzeugt die superx-docman.jar. ">
<delete>
<fileset dir="${distDir}" includes="superx-etl*.jar" />
</delete>
<jar destfile="${distDir}/superx-docmanagement${version}.jar" basedir="${BUILD_PATH}" includes="de/superx/docmanagement/**" excludes="**/*.java">
<manifest>
<!-- Who is building this jar? -->
<attribute name="Built-By" value="superx"/>
<!-- Information about the program itself -->
<attribute name="Implementation-Date" value="${SX_TIMESTAMP}"/>
<attribute name="Implementation-Title" value="SuperX"/>
<attribute name="Implementation-Version" value="${version}"/>
</manifest>
</jar>
</target>
<target name="compileSuperx" depends="cleanBuildPath" description="Compile all classes for superx.">
<filter token="sxtimestamp" value="${SX_TIMESTAMP}" />
<filter token="version" value="${etl_version}" />
<copy todir="${BUILD_PATH}" filtering="true">
<fileset dir="${SRC_DIR}">
<include name="**/*.java" />
</fileset>
</copy>
<!--source="1.8" target="1.8"-->
<javac source="17" target="17"
srcdir="${BUILD_PATH}" excludes="**/*Test*.java,test/**/*"
destdir="${BUILD_PATH}"
listfiles="false" encoding="UTF-8" debug="yes">
<classpath refid="classpath" />
</javac>
</target>
<target name="cleanBuildPath" depends="initTimestamp" description="Löscht alle *.class-Dateien in WEB-INF/classes">
<delete failonerror="false" includeemptydirs="true">
<fileset dir="${BUILD_PATH}" includes="**/*.class,**/*.java" excludes="*.properties" />
</delete>
</target>
</project>

1
docman_scripte/authentifizierungstest.x

@ -0,0 +1 @@ @@ -0,0 +1 @@
java -cp superx-docmanagement1.3.jar de.superx.docmanagement.HISConnektorTest $1 $2

1
docman_scripte/docman_encryptor.x

@ -0,0 +1 @@ @@ -0,0 +1 @@
java -cp superx-docmanagement1.3.jar de.superx.docmanagement.Encryptor $1

1
docman_scripte/docman_propcreator.x

@ -0,0 +1 @@ @@ -0,0 +1 @@
java -cp superx-docmanagement1.3.jar de.superx.docmanagement.ArchivePropHandler $1 $2 $3

1
docman_scripte/dvelop-metadata-update.x

@ -0,0 +1 @@ @@ -0,0 +1 @@
java -cp superx-docmanagement1.3.jar:$JDBC_CLASSPATH de.superx.docmanagement.DvelopMetadatenLoader "$@"

1
docman_scripte/dvelopdownloadtest1.x

@ -0,0 +1 @@ @@ -0,0 +1 @@
java -cp superx-docmanagement1.3.jar:$JDBC_CLASSPATH de.superx.docmanagement.DvelopDownloadTester $1 $2

1
docman_scripte/dvelopdownloadtest2.x

@ -0,0 +1 @@ @@ -0,0 +1 @@
java -cp superx-docmanagement1.3.jar:$JDBC_CLASSPATH de.superx.docmanagement.DvelopDownloadTester2 $1 $2

BIN
docman_scripte/superx-docmanagement1.3.jar

Binary file not shown.

248
lizenz.txt

@ -0,0 +1,248 @@ @@ -0,0 +1,248 @@
CampusSource · AGB und Lizenz
Allgemeine Geschäftsbedingungen (AGB) und Lizenz
Mit CampusSource wird die Nutzung universitärer Entwicklungen durch Dritte zu
den Bedingungen der General GNU Public Licence (GPL) ermöglicht, die eine der
bekanntesten Opensource-Lizenzen ist.
Die GPL ist eine Lizenz, die dem amerikanischen Recht, nicht jedoch dem
deutschen Recht genügt. So sind einige Passagen der GPL nach dem deutschen Recht
nicht wirksam. CampusSource hat aus diesem Grunde Allgemeine
Geschäftsbedingungen formuliert, die die Interpretation der GPL unter deutschem
Recht vornimmt und ergänzt.
Allgemeine Geschäftsbedingungen für die
Nutzung der Software der Initiative CampusSource
1. Vorbemerkung
Diese Allgemeinen Geschäftsbedingungen regeln die Rechtsbeziehungen zwischen dem
Land Nordrhein-Westfalen, vertreten durch die FernUniversität Hagen, diese
wiederum vertreten durch die Geschäftsstelle der Initiative CampusSource bei der
FernUniversität Hagen, Universitätsstraße 11, D-58097 Hagen (im Folgenden
»Lizenzgeber« genannt) und dem Nutzer (im Folgenden »Lizenznehmer« genannt) der
CampusSource-Software. Sie sind ebenso wie die GNU General Public License (siehe
dazu Abschnitt 4 »Lizenz«) Bestandteil des zwischen dem Lizenzgeber und dem
Lizenznehmer geschlossenen Vertrages.
Die GNU General Public License (im Folgenden GPL genannt) finden Sie im Internet
unter www.gnu.org/copyleft/gpl.html, eine deutsche Übersetzung unter
www.gnu.de/gpl-ger.html.
2. Vertragsgegenstand
Gegenstand des Vertragsangebotes des Lizenzgebers ist die auf diesem Server
befindliche Software des CampusSource-Projektes (im Folgenden »Software«
genannt) und dazugehöriges Begleitmaterial.
Der Lizenzgeber bietet dem Lizenznehmer nach erfolgter Registrierung die
folgenden Leistungen an:
Der Lizenzgeber verschafft dem Lizenznehmer die Möglichkeit, auf
elektronischem Weg Zugang zur Software, deren Dokumentation und zu
Erfahrungsberichten zu erhalten und sich einen Überblick über das
Softwareangebot zu verschaffen.
Der Lizenzgeber gestattet dem Lizenznehmer, die Software physikalisch
downzuloaden.
Der Lizenzgeber überträgt die in Abschnitt 4 »Lizenz« näher bezeichneten
Nutzungsrechte auf den Lizenznehmer.
Lizenzgeber und Lizenznehmer sind sich einig darüber, dass die Inanspruchnahme
der unter 1.) bis 3.) angebotenen Leistungen unentgeltlich, schenkungsweise
erfolgen soll. Dies bedeutet jedoch nicht, dass der Lizenzgeber irgendwelche
durch die Nutzung des Angebots entstandenen Kosten übernimmt.
Sofern der Lizenznehmer die Software bearbeitet und diese Bearbeitung Dritten
zugänglich macht, ist er verpflichtet, dem Lizenzgeber auch eine Kopie der
Bearbeitung kostenlos zukommen zu lassen, oder, sofern die Bearbeitung
öffentlich und kostenlos zugänglich ist, dem Lizenzgeber die Quelle mitzuteilen.
Die in diesen Allgemeinen Geschäftsbedingungen festgelegten Nebenpflichten
stellen keine Gegenleistung im Sinne des Bürgerlichen Rechts dar und sind für
den Lizenznehmer verbindlich. Nicht Gegenstand des Vertrages sind irgendeine
Form von Softwareinstallation, Softwarepflege oder Beratung im Zusammenhang mit
der Software. Insbesondere wird durch die mit der Software beigefügte oder für
die Software bereitgestellte Information oder Dokumentation kein
Beratungsvertrag angeboten. Wenn Sie solche Dienstleistungen wünschen, wenden
Sie sich an die Geschäftsstelle der Initiative CampusSource.
Der Lizenzgeber behält sich vor, das Leistungsangebot jederzeit einzustellen.
Bezüglich bereits empfangener Leistungen bleiben die Verpflichtungen beider
Parteien hiervon unberührt, insbesondere entfallen dadurch nicht die in diesen
Allgemeinen Geschäftsbedingungen festgelegten Nebenpflichten des Lizenznehmers.
Diese Allgemeinen Geschäftsbedingungen gelten auch dann, wenn der Lizenznehmer
das oben genannte Leistungspaket nur teilweise in Anspruch nimmt.
3. Sorgfaltspflichten des Lizenznehmers
Der Lizenznehmer ist verpflichtet, sein Passwort sorgfältig aufzubewahren und
Dritten nicht zugänglich zu machen. Der Lizenznehmer haftet für alle Schäden,
die aus der Verletzung dieser Sorgfaltspflicht entstehen.
4. Lizenz
Die Nutzungsrechte, welche der Lizenznehmer erhält, ergeben sich aus der GNU
General Public License. Diese Nutzungsrechte sind dinglich - im Sinne des
Urheberrechts - mit der Software verknüpft und gelten auch dann, wenn der
Lizenznehmer keine Kenntnis davon nimmt. Die GNU General Public License (im
Folgenden GPL genannt) finden Sie im Internet unter
www.gnu.org/copyleft/gpl.html, eine deutsche Übersetzung unter
www.gnu.de/gpl-ger.html.
Die GPL ist zu dem Zweck entworfen worden, dass Sie die unter diese Lizenz
gestellte Software weitergeben und verändern dürfen. Wenn Sie die Software
verändern und weitergeben, müssen Sie den Quellcode der bearbeiteten Software
wieder unter die GPL stellen und den Quellcode zugänglich machen, so dass auch
andere von Ihrem Werk profitieren, wie auch Sie von der erhaltenen Software
profitiert haben. Auf diese Art und Weise soll ein System von jedermann frei
zugänglicher Software geschaffen werden.
Der Lizenzgeber weist den Lizenznehmer darauf hin, dass die GPL in den USA
entworfen wurde und daher einige Bestimmungen nach deutschem Recht nicht wirksam
sind oder in Deutschland rechtlich anders beurteilt werden als in den USA:
Die Formulierung »You may charge a fee for the physical act of transferring a
copy« in Abschnitt 1 der GPL ist nach deutschem Recht so zu verstehen, dass
nur eine angemessene, marktübliche Gegenleistung für die Anfertigung einer
Kopie verlangt werden darf. Sofern eine das marktübliche überschreitende
Gegenleistung für das Anfertigen von Kopien verlangt werden würde, hätte dies
neben einer möglichen Lizenzverletzung zur Folge, dass die durch die
kostenlose Weitergabe bestehende Haftungsprivilegierung wegfallen könnte und
der Lizenznehmer wie ein Verkäufer oder Unternehmer (Werkvertrag) bei Mängeln
auf Schadensersatz haftet.
Abschnitt 11 und 12 der GPL (Haftungsausschluss) verstoßen gegen das »Gesetz
zur Regelung des Rechts der Allgemeinen Geschäftsbedingungen« (AGBG) und sind
nach deutschem Recht unwirksam. An ihre Stelle treten die entsprechenden
Bestimmungen des Bürgerlichen Rechts §§ 521ff. (Haftung des Schenkers).
Es folgt eine kurze unvollständige Zusammenfassung der GPL. Der Lizenznehmer ist
verpflichtet, die weiterführenden und präziseren Bestimmungen der GPL zu
beachten. Der Lizenznehmer wird darauf hingewiesen, dass die GPL einige
(auflösende) Bedingungen enthält, bei deren Verletzung die dem Lizenznehmer
übertragenen Nutzungsrechte automatisch ohne jeden Widerruf erlöschen und eine
weitere Nutzung des Programms zu einer (strafbaren) Urheberrechtsverletzung
wird.
Die Lizenz erlaubt dem Lizenznehmer das Ausführen der Programme zu jedem
Zweck. Gesetzliche Einschränkungen werden hiervon nicht berührt.
Der Lizenznehmer darf unveränderte Kopien des Quellcodes anfertigen und
weiterverbreiten, unter der Bedingung, dass mit der Kopie ein entsprechender
Urheberrechtsvermerk sowie ein Haftungsausschluß veröffentlicht wird und dass
alle die GPL betreffenden Hinweise unverändert weitergegeben werden. Ein
Entgelt darf nur für die Anfertigung von Kopien oder für das Anbieten einer
Garantie genommen werden. Näheres enthält § 1 GPL.
Der Lizenznehmer darf das Programm verändern und die so entstandene
Bearbeitung unter der Bedingung vervielfältigen und verbreiten, dass er einen
auffälligen Vermerk über die vorgenommenen Modifizierungen anbringt, die
Kopien der Bearbeitung ohne Lizenzgebühren unter den Bedingungen der GPL
verbreitet und dafür sorgt, dass das Programm bei interaktiver Nutzung einen
Urheberrechtsvermerk ausgibt. Näheres regelt § 2 GPL.
Der Lizenznehmer darf das Programm oder eine Bearbeitung als Objectcode oder
in ausführbarer Form unter Berücksichtigung der letzten beiden Abschnitte
unter der Bedingung vervielfältigen und verbreiten, dass er den Quelltext
beifügt oder eine der in § 3 GPL genannten Alternativen erfüllt. Näheres
regelt § 3 GPL.
Sollte dem Lizenznehmer infolge eines Gerichtsurteils oder durch einen
gerichtlichen Vergleich Bedingungen auferlegt werden, die der GPL
widersprechen, so entbindet dies den Lizenznehmer nicht von der Einhaltung der
GPL. Näheres regelt § 7 GPL.
Wenn die Verbreitung oder die Benutzung des Programms in bestimmten Staaten
durch Patent- oder Urheberrecht eingeschränkt ist, kann der Lizenznehmer bei
der Verbreitung des Programms durch einen entsprechenden Vermerk bestimmen,
dass die Verbreitung des Programms in bestimmten Staaten ausgeschlossen ist.
Näheres regelt § 8 GPL.
5. Schutzrechte Dritter
Der Lizenzgeber geht davon aus, dass der Besitz und der vertragsgemäße Gebrauch
der Software keine Schutzrechte Dritter für den Bereich der BRD beeinträchtigt.
Im Zusammenhang mit einer möglichen Beeinträchtigung der Schutzrechte Dritter
werden die folgenden Nebenpflichten vereinbart:
Der Lizenznehmer verpflichtet sich, dass er weder für sich noch im Auftrag
eines Dritten die Software zu dem Zweck verwendet, diese nach
Schutzrechtsverletzungen zu untersuchen oder untersuchen zu lassen.
Der Lizenznehmer verpflichtet sich, den Lizenzgeber unverzüglich zu
benachrichtigen, wenn Dritte Schutzrechtsverletzungen geltend machen.
Hat der Lizenznehmer den Eindruck, dass die Software Patente oder andere
Schutzrechte Dritter verletzt, so ist er verpflichtet, den Lizenzgeber
unverzüglich schriftlich unter Beifügung einer genauen Beschreibung der
Verletzungshandlung zu unterrichten. Es ist dem Lizenznehmer untersagt, andere
natürliche oder juristische Personen ohne schriftliches Einverständnis des
Lizenzgebers zu informieren.
Bei Verletzung einer der obigen Nebenpflichten verpflichtet sich der
Lizenznehmer, dem Lizenzgeber Schadensersatz für alle durch die Verletzung
entstandenen Schäden (einschließlich der Prozeßkosten) zu leisten. Ist die
Verletzung einer solchen Nebenpflicht festgestellt, so genügt es, wenn der
Lizenzgeber plausibel darlegt, dass der Schaden durch die Verletzung entstanden
ist. Den Lizenznehmer trifft die volle Beweislast für das Gegenteil. Der
Lizenznehmer verpflichtet sich, dem Lizenzgeber alle Auskünfte im Zusammenhang
mit der Verletzung einer der obigen Nebenpflichten zu erteilen.
Der Lizenzgeber weist darauf hin, dass zur CampusSource-Software nicht die
Software anderer Hersteller gehört, mit der die CampusSource-Software
zusammenarbeiten kann oder die für den Betrieb der CampusSource-Software
notwendigerweise vorhanden sein muss, wie z. B. WWW-Server,
Funktionsbibliotheken, Werkzeugsysteme und Datenbankmanagementsysteme. Die
Lizenzen für diese Software müssen vom jeweiligen Hersteller separat erworben
werden. Die GPL gilt für diese Software in der Regel nicht.
6. Datenschutz
Der Lizenzgeber verpflichtet sich, bezüglich der bei der Registrierung
angegebenen Daten die einschlägigen landes- und bundesrechtlichen
Datenschutzbestimmungen einzuhalten. Alle Verbindungen zu diesem Server im
Download- und Registrierbereich werden in einem LOG-File aufgezeichnet.
7. Schriftform
Alle Nebenabreden, die zwischen dem Lizenzgeber und dem Lizenznehmer
abgeschlossen werden, bedürfen der Schriftform. Eine Abänderung oder Aufhebung
dieser Klausel bedarf ebenfalls der Schriftform.
8. Gerichtsstand
Gerichtsstand für alle Streitigkeiten aus diesem Vertrag ist Hagen, sofern der
Lizenznehmer Kaufmann, eine juristische Person des öffentlichen Rechts oder ein
öffentlich-rechtliches Sondervermögen ist.
Die Parteien vereinbaren die Anwendung deutschen Rechts. Sollte nach
Internationalem Verfahrensrecht die Zuständigkeit eines deutschen Gerichts
möglich sein, so vereinbaren die Parteien die Zuständigkeit der deutschen
Gerichtsbarkeit und innerhalb Deutschlands die Zuständigkeit des Amtsgerichtes
bzw. Landgerichtes Hagen. Bezüglich der in Abschnitt 5 »Schutzrechte Dritter«
festgelegten Nebenpflichten des Lizenznehmers kann der Lizenzgeber abweichend
von Satz 3 ein beliebiges international zuständiges Gericht anrufen.
© 2000 CampusSource Alle Rechte vorbehalten

603
src/de/superx/docmanagement/AbstractDocPresenter.java

@ -0,0 +1,603 @@ @@ -0,0 +1,603 @@
package de.superx.docmanagement;
import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.HttpURLConnection;
import java.net.Proxy;
import java.net.URL;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.Date;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import de.memtext.util.DateUtils;
import de.superx.common.SxUser;
import de.superx.servlet.SxPools;
public abstract class AbstractDocPresenter {
private static final long serialVersionUID = 1;
static final String MANDANTENID = "default";
final java.util.logging.Logger logger = java.util.logging.Logger.getLogger("docman");
private Proxy proxy = null;
private String sys;
// Vorlage für einzelne URLS zum DokuServer in der z.B: DocID ersetzt werden
// muss
private String urlVorlage;
// HTML+Freemarker Vorlage für ein HTML-Menü, falls es mehrere Subdokumente
// gibt.
private String menuVorlage;
// SQL zum Lesen der Anzahl von Dokumenten pro ID
private String readDocumentCountSql;
// Lesen von Dokumenten mit optional auch mehreren Attributen
private String readDocumentListSql;
// optional: SQL zum Löschen abgelaufener Berechtigungen
private String deleteOldRightsSql;
// SQL zum Lesen der Berechtigungen auf eine ID für einen User
private String readIdRightSql;
// SQL zum Lesen der Berechtigungen auf eine docId für einen User (für
// Untermenü)
private String readDocIdRightSql;
// ID to DocID
private String readDocIdSql;
// HauptDokumentID für eine ID suchen
private String readMainDocIdSql;
private boolean isDirectLinkToDocMWanted = true;
private boolean isDocMenuAlwaysWanted=false;
private boolean isRenewAuthentificationOnErrorWanted=false;
protected AbstractDocPresenter(String sys, String params) throws ServletException {
setSys(sys);
initSystem();
checkConfiguration();
}
protected boolean isRenewAuthentificationOnErrorWanted()
{
return isRenewAuthentificationOnErrorWanted;
}
protected void setRenewAuthentificationOnErrorWanted(boolean b)
{
this.isRenewAuthentificationOnErrorWanted=b;
}
protected void renewAuthentification() throws IOException
{
throw new IllegalStateException("nicht unterstützt");
}
protected void setDocMenuAlwaysWanted(boolean isDocMenuAlwaysWanted)
{
this.isDocMenuAlwaysWanted=isDocMenuAlwaysWanted;
}
protected void setProxy(Proxy proxy) {
this.proxy = proxy;
}
protected void checkConfiguration() {
if (urlVorlage == null)
throw new IllegalStateException("urlVorlage ist null");
if (readDocumentCountSql == null)
throw new IllegalStateException("readDocumentCountSql ist null");
if (readDocumentListSql == null)
throw new IllegalStateException("readDocumentListSql ist null");
if (readIdRightSql == null)
throw new IllegalStateException("readIdRightSql ist null");
if (readDocIdSql == null)
throw new IllegalStateException("readDocIdSql ist null");
if (readMainDocIdSql == null)
throw new IllegalStateException("readMainDocIdSql ist null");
// menuVorlage und readDocumentListSql dürfen null sein, wenn für konkreten Fall
// nicht genutzt
}
abstract void initSystem() throws ServletException;
protected boolean isDirectLinkToDocMWanted() {
return isDirectLinkToDocMWanted;
}
protected void setDirectLinkToDocMWanted(boolean isDirectLinkToDocMWanted) {
this.isDirectLinkToDocMWanted = isDirectLinkToDocMWanted;
}
protected DocPresentationResult getReply(HttpServletRequest request, SxUser user) {
DocPresentationResult dpresult = new DocPresentationResult();
Map<String, String> params = readParams(request);
if (isAccessAllowed(user, params)) {
try {
updateDocResult(params, dpresult);
} catch (Exception e) {
String id = getId(params);
String doc_id = params.get("doc_id");
logger.severe("sys:"+sys+" Berechtigung vorhanden, aber Fehler bei der Ermittlung von Dokument "
+ (id != null ? " ID=" + id : "") + (doc_id != null ? " docID:" + doc_id : "") + " "
+ getExceptionStackTrace(e));
}
} else {
dpresult.setMessage("Berechtigungsfehler in sys:"+sys);
}
if (!dpresult.isOK()) {
dpresult.setMessage("Es konnte keine DocManagement URL ermittelt werden in sys:"+sys);
}
return dpresult;
}
/**
* TODO ggfs. in utils auslagern
*
* @param e
* @return
*/
String getExceptionStackTrace(Exception e) {
String result = "";
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
result = sw.toString();
pw.close();
return result;
}
protected Map<String, String> readParams(HttpServletRequest request) {
logger.info("DocPresenter ("+sys+"): Lese Parameter aus Request");
Map<String, String> params = new HashMap<String, String>();
String id = DocMan.getParameter(request, "id");
String doc_id = DocMan.getParameter(request, "doc_id");
if ((id == null || id.length() == 0) && (doc_id == null || doc_id.length() == 0))
throw new IllegalArgumentException("Param id oder doc_id muss angegeben werden");
params.put("id", id);
if (doc_id != null)
params.put("doc_id", doc_id);
String main_doc_only = DocMan.getParameter(request, "main_doc_only");
if (main_doc_only != null && main_doc_only.equalsIgnoreCase("false")) {
params.put("main_doc_only", "false");
} else {
params.put("main_doc_only", "true");
}
return params;
}
/**
* Wenn in den params eine id vorhanden ist, wird die Berechtigung dafür
* geprüft, ist es eine doc_id auch dafür
*
* @param user
* @param params
* @return
*/
protected boolean isAccessAllowed(SxUser user, Map<String, String> params) {
boolean isAccessAllowed = false;
if (deleteOldRightsSql != null) {
logger.fine("DocPresenter ("+sys+"): Lösche etwaige abgelaufene Berechtigungen");
executeUpdate(deleteOldRightsSql);
}
String id = getId(params);
if (id != null) {
isAccessAllowed = isIdAllowed(user, id);
}
String doc_id = params.get("doc_id");
if (doc_id != null) {
isAccessAllowed = isDocIdAllowed(user, doc_id);
}
return isAccessAllowed;
}
boolean isDocIdAllowed(SxUser user, String doc_id) {
boolean isAccessAllowed = false;
int count = readIntFromDB("Berechtigung für DocId suchen sys:"+sys, readDocIdRightSql, (Integer) user.getId(), doc_id);
if (count > 0)
isAccessAllowed = true;
logger.info("DocPresenter: Für User " + user.getName() + " (userinfo.tid=" + user.getId() + ") aktuell " + count
+ " Rechte für DocId " + doc_id + " gefunden (sys:"+sys+")");
return isAccessAllowed;
}
private boolean isIdAllowed(SxUser user, String id) {
boolean isAccessAllowed = false;
int count = readIntFromDB("Berechtigung für ID suchen sys:"+sys, readIdRightSql, (Integer) user.getId(), id);
if (count > 0)
isAccessAllowed = true;
logger.fine("DocPresenter: Für User " + user.getName() + " (userinfo.tid=" + user.getId() + ") aktuell " + count
+ " Rechte für "+id+" gefunden (sys:"+sys+")");
return isAccessAllowed;
}
String getSys() {
return sys;
}
private void setSys(String sys) {
this.sys = sys;
}
protected void updateDocResult(Map<String, String> params, DocPresentationResult result) throws Exception {
if (hasDocId(params)) {
String doc_id = params.get("doc_id");
logger.info("DocPresenter ("+sys+"): Für doc_id " + doc_id + " direkt ausgeliefert");
updateDocLink(result, doc_id);
}
else {
if (params.get("main_doc_only").contentEquals("true")) {
logger.info("DocPresenter ("+sys+"): Liefere nur Hauptdokument");
updateDocLink(result, getMainDocId(getId(params)));
} else {
int docCount = readDocumentCount(getId(params));
if (docCount==1&&isDocMenuAlwaysWanted) docCount=99;
switch (docCount) {
case 0:
logger.info("DocPresenter ("+sys+"): Für id " + getId(params) + " keine relevanten Angaben in Datenbank gefunden");
result.setMessage("Keine relevanten Angaben in der Datenbank gefunden");
break;
case 1:
// wenn es für eine ID nur eine einzige DocId gibt, diese direkt liefern
logger.info("DocPresenter ("+sys+"): Für id " + getId(params)
+ " für ein Dokument gefunden, wird direkt ausgeliefert");
updateDocLink(result, readDocIdFromDatabase(params));
break;
// mehr als ein Dokument oder Menü auf jeden Fall gewünscht
default:
logger.info("DocPresenter ("+sys+"): Für id " + getId(params)
+ " wird Auswahlmenü mit Einzeldokumenten dargestellt");
result.setMessage(getDocumentMenu(params));
}
}
}
}
private String getDocumentMenu(Map<String, String> params) {
String result;
String id = getId(params);
logger.info("DocPresenter ("+sys+"): Ermittle DokumentenListe für id " + id);
List<Map<String, String>> doclist = readDocumentList(getId(params));
try {
for (Map<String, String> einEintrag : doclist) {
if (!einEintrag.containsKey("doc_id")) throw new IllegalStateException("Liste für Einzeldokumente sys="+sys+" enhält keine doc_id,ReadDocumentListSql anpassen!");
String urlString = ""; // Freemarker arbeitet mit LeerString nicht null
DocPresentationResult dpResult = new DocPresentationResult();
String doc_id=einEintrag.get("doc_id");
if (doc_id==null||doc_id.length()==0) throw new IllegalStateException("Keine doc_id zu id "+id+ " gefunden! sys="+sys);
updateDocLink(dpResult,doc_id );
// interner/externer Link
if (dpResult.getDocManagementUrl() != null) {
if (isDirectLinkToDocMWanted) {
urlString = dpResult.getDocManagementUrl().toString();
} else {
// verweis auf eine konkrete DocID,da für eine id (UFR vim) mehrere Dokumente
// geben kann
urlString = "/superx/servlet/DocMan?sys=" + getSys() + "&doc_id=" + einEintrag.get("doc_id");
}
}
einEintrag.put("doc_link", urlString);
}
HashMap map = new HashMap();
map.put("doclist", doclist);
logger.info("DocPresenter ("+sys+"): Erstellte HTML für DokumentenListe für id " + id + " mittels Freemarker");
result = SxPools.get(MANDANTENID).getTemplateProcessor().process(map, null, "DocManagementMenu",
menuVorlage, null, SxPools.get(MANDANTENID).getRepository(),
SxPools.get(MANDANTENID).getSqlDialect());
} catch (Exception e) {
result = "Fehler bei der Erzeugung von Men&uuml; f&uuml;r Einzeldokumente";
e.printStackTrace();
}
return result;
}
abstract protected void updateDocLink(DocPresentationResult result, String id) throws Exception;
/**
* HauptDokument für eine id Berechtigungskontrolle is vorher schon gelaufen
*
* @param id
* @return
*/
private String getMainDocId(String id) {
return readStringFromDB(readMainDocIdSql, id);
}
protected String adaptUrl(String marker, String value) {
if (urlVorlage == null || urlVorlage.trim().length() == 0)
throw new IllegalStateException("Keine URL-Vorlage für Dokumentenmanagesystem gefunden (sys:"+sys+")");
return urlVorlage.replaceAll(marker, value);
}
/**
* Liefert zu einer als Parameter übergebenen ID, die zugehörige DocID des
* DokumentenManagement-Servers
*
* @param params
* @return
*/
protected String readDocIdFromDatabase(Map<String, String> params) {
return readStringFromDB(readDocIdSql, getId(params));
}
/**
* Liefert, wieviele Einzeldokument für eine als Parameter übergebene ID gibt
*
* @param id
* @return
*/
protected int readDocumentCount(String id) {
return readIntFromDB("Ermittlung Anzahl der Dokument für ID " + id+ "(sys:"+sys+")", readDocumentCountSql, null, id);
}
/**
* Liest Liste von Infos zu einzelnen Doc zu einer VIM-Nummer
*/
protected List<Map<String, String>> readDocumentList(String id) {
return readAttribMapsFromDB(readDocumentListSql, id);
}
String getReadDocIdRightSql() {
return readDocIdRightSql;
}
void setReadDocIdRightSql(String readDocIdRightSql) {
this.readDocIdRightSql = readDocIdRightSql;
}
protected String getId(Map<String, String> params) {
return params.get("id");
}
boolean hasDocId(Map<String, String> params) {
return params.containsKey("doc_id");
}
protected void setMenuVorlage(String vorlage) {
menuVorlage = vorlage;
logger.info("DocPresenter ("+sys+"): MenuVorlage gesetzt");
}
protected void setUrlVorlage(String vorlage) {
urlVorlage = vorlage;
if (urlVorlage == null || urlVorlage.trim().length() == 0)
throw new IllegalStateException("Keine URL-Vorlage für Dokumentenmanagesystem gefunden für sys="+sys);
logger.info("DocPresenter ("+sys+"): UrlVorlage gesetzt");
}
String getUrlVorlage() {
return urlVorlage;
}
protected void setReadMainDocIdSql(String readMainDocIdSql) {
this.readMainDocIdSql = readMainDocIdSql;
}
protected void setReadDocIdSql(String readDocIdSql) {
this.readDocIdSql = readDocIdSql;
}
protected void setReadIdRightSql(String readIdRightSql) {
this.readIdRightSql = readIdRightSql;
}
protected void setDeleteOldRightsSql(String deleteOldRightsSql) {
this.deleteOldRightsSql = deleteOldRightsSql;
}
protected void setReadDocumentListSql(String readDocumentListSql) {
this.readDocumentListSql = readDocumentListSql;
}
protected void setReadDocumentCountSql(String readDocumentCountSql) {
this.readDocumentCountSql = readDocumentCountSql;
}
protected String readStringFromDB(String sql, String param1) {
return readStringFromDB(sql, param1, null);
}
/**
*
* @param sql
* @param param1 - kann null sein, wird dann nicht gesetzt
* @return
*/
protected String readStringFromDB(String sql, String param1, String param2) {
String result = "NICHTS_GEFUNDEN";
try (Connection con = SxPools.get(MANDANTENID).getConnection();) {
PreparedStatement pst = con.prepareStatement(sql);
if (param1 != null)
pst.setString(1, param1);
if (param2 != null)
pst.setString(2, param2);
ResultSet rs = pst.executeQuery();
while (rs.next()) {
result = rs.getString(1);
}
rs.close();
pst.close();
} catch (SQLException e) {
e.printStackTrace();
throw new IllegalStateException("Fehler bei DocManagement (sys:"+sys+")");
}
if (result.equals("NICHTS_GEFUNDEN"))
throw new IllegalArgumentException("DocManagement ("+sys+"): Keine Angaben in der Datenbank gefunden ("+sql+" "+param1+" "+param2==null?"":param2);
return result;
}
protected void executeUpdate(String sql) {
try (Connection con = SxPools.get(MANDANTENID).getConnection();) {
Statement stm = con.createStatement();
stm.executeUpdate(sql);
stm.close();
} catch (SQLException e) {
e.printStackTrace();
throw new IllegalStateException("Fehler bei DocManagement ("+sys+")");
}
}
protected List<String> readStringsFromDB(String sql, String param1) {
List<String> result = new LinkedList<String>();
try (Connection con = SxPools.get(MANDANTENID).getConnection();) {
PreparedStatement pst = con.prepareStatement(sql);
if (param1 != null)
pst.setString(1, param1);
ResultSet rs = pst.executeQuery();
while (rs.next()) {
result.add(rs.getString(1));
}
rs.close();
pst.close();
} catch (SQLException e) {
e.printStackTrace();
throw new IllegalStateException("Fehler bei DocManagement ("+sys+") ");
}
return result;
}
protected List<Map<String, String>> readAttribMapsFromDB(String sql, String param1) {
List<Map<String, String>> result = new LinkedList<Map<String, String>>();
try (Connection con = SxPools.get(MANDANTENID).getConnection();) {
PreparedStatement pst = con.prepareStatement(sql);
if (param1 != null)
pst.setString(1, param1);
ResultSet rs = pst.executeQuery();
while (rs.next()) {
result.add(getHashMap(rs));
}
rs.close();
pst.close();
} catch (SQLException e) {
e.printStackTrace();
throw new IllegalStateException("Fehler bei DocManagement ("+sys+") " + e);
}
return result;
}
Map<String, String> readMapFromDB(String sql, String param1) {
Map<String, String> result = new HashMap<String, String>();
try (Connection con = SxPools.get(MANDANTENID).getConnection();) {
PreparedStatement pst = con.prepareStatement(sql);
if (param1 != null)
pst.setString(1, param1);
ResultSet rs = pst.executeQuery();
while (rs.next()) {
result.put(rs.getString(1), rs.getString(2));
}
rs.close();
pst.close();
} catch (SQLException e) {
e.printStackTrace();
throw new IllegalStateException("Fehler bei DocManagement ("+sys+") " + e);
}
return result;
}
private HashMap<String, String> getHashMap(ResultSet rs) throws SQLException {
HashMap<String, String> einEintrag = new HashMap<String, String>();
ResultSetMetaData rsmd = rs.getMetaData();
for (int i = 1; i <= rsmd.getColumnCount(); i++) {
String label = rsmd.getColumnLabel(i);
Object value = rs.getObject(i);
// Null-Werte führen in Freemarker absicht zu Fehler "has evaluated to null"
// daher Leerstring
String valueString = "";
if (value != null)
if (value instanceof Date) {
valueString = DateUtils.formatGerman((Date) value);
} else {
valueString = value.toString();
}
einEintrag.put(label, valueString);
}
return einEintrag;
}
protected String readVorlageFromRepository(String vorlagenName) {
return readStringFromDB(
"select content from sx_repository where aktiv=1 and today() between gueltig_seit and gueltig_bis and id=?",
vorlagenName);
}
/**
* Lesen aus der Datenbank per PreparedStatement
*
* @param task
* @param query
* @param Integer param1 - falls null wird param2 als erster Param für das
* PreparedStatement genutzt
* @param param2
* @return int result
*/
protected int readIntFromDB(String task, String query, Integer param1, String param2) {
int result = -1;
try (Connection con = SxPools.get(MANDANTENID).getConnection();) {
PreparedStatement pst = con.prepareStatement(query);
if (param1 != null) {
pst.setInt(1, param1.intValue());
if (param2 != null)
pst.setString(2, param2);
} else {
pst.setString(1, param2);
}
ResultSet rs = pst.executeQuery();
while (rs.next()) {
result = rs.getInt(1);
}
rs.close();
pst.close();
} catch (SQLException e) {
e.printStackTrace();
throw new IllegalStateException(task);
}
return result;
}
/**
* Öffnet URLConnection mit/ohne Proxy und Timeout von 15 Sekunden
*
* @param url
* @return URLConnection
*/
public HttpURLConnection openConnection(URL url) {
HttpURLConnection con = null;
try {
if (proxy == null)
con = (HttpURLConnection) url.openConnection();
else {
con = (HttpURLConnection) url.openConnection(proxy);
}
con.setConnectTimeout(15 * 1000);
} catch (IOException e) {
logger.severe("sys: "+sys+" Fehler bei Verbindungsaufbau mit " + url + " " + proxy != null ? "(Proxy gesetzt)" : "");
logger.severe(getExceptionStackTrace(e));
}
return con;
}
protected abstract void setHeaderAuthorisation(HttpURLConnection urlConnection) throws IOException;
}

155
src/de/superx/docmanagement/ArchivePropHandler.java

@ -0,0 +1,155 @@ @@ -0,0 +1,155 @@
package de.superx.docmanagement;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Properties;
import java.util.StringTokenizer;
import javax.crypto.Cipher;
import javax.crypto.spec.SecretKeySpec;
public class ArchivePropHandler {
//from memtext.util.CryptUtils;
private static Cipher desCipher;
//geaendert im Vergleich zu Vorlage
// private static final byte[] KEY_DATA = { -118, -55, -53, -71, -92, 28, -112, 107 };
private static final byte[] KEY_DATA = { -108, -50, -5, -75, -98, 28, -116, 107 };
private static final SecretKeySpec KEY = new SecretKeySpec(KEY_DATA, "DES");
public ArchivePropHandler() {
try {
if (desCipher == null) desCipher = Cipher.getInstance("DES");
} catch (Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
if (args.length != 3) {
System.out.println("Usage: URL username password");
System.exit(-1);
} else {
ArchivePropHandler ph = new ArchivePropHandler();
ph.createPropFile(args);
}
}
/**
*
* @param propfile
* @return Passwort bleibt verschluesselt, wird von aufrufender Methode entschluesselt
* @throws IOException
*/
public String getUrlVorlage(String propfile) throws IOException {
if (!new File(propfile).exists()) {
throw new IOException("Properties Datei " + propfile + " nicht gefunden");
}
String urlVorlage = "";
Properties props = new Properties();
FileInputStream is = new FileInputStream(propfile);
props.load(is);
is.close();
urlVorlage = props.getProperty("URL") + "|" + props.getProperty("username") + "|";
String passwd = props.getProperty("password");
if (passwd == null || !passwd.startsWith("sx_des")) {
throw new IOException("Passwort nicht gefunden oder nicht verschluesselt");
}
urlVorlage += passwd;
return urlVorlage;
}
private void createPropFile(String args[]) {
try {
Properties props = new Properties();
props.put("URL", args[0]);
props.put("username", args[1]);
String verschl = encryptStringDES(args[2]);
props.put("password", "sx_des" + verschl);
OutputStream os = new FileOutputStream("docman_mbsarchive.properties");
props.store(os, "DocMan MBSArchive");
os.close();
System.out.println("Verschluesseltes Passwort: sx_des"+verschl);
System.out.println("Datei docman_mbsarchive.properties erzeugt");
} catch (Exception e) {
System.out.println("Fehler bei der Verschluesselung");
e.printStackTrace();
}
}
public String decryptStringDES(String aValue) throws Exception {
if (aValue == null) return null;
desCipher.init(Cipher.DECRYPT_MODE, KEY);
byte[] encrypted = makeArrayDES(aValue);
byte[] decrypted = desCipher.doFinal(encrypted);
String result = new String(decrypted);
return result;
}
public String encryptStringDES(String aValue) throws Exception {
if (aValue == null) return null;
desCipher.init(Cipher.ENCRYPT_MODE, KEY);
byte[] values = aValue.getBytes();
byte[] encrypted = desCipher.doFinal(values);
return makeStringDES(encrypted);
}
/**
* Creates a String from the given array which can be used to store the
* array in a text file
*
* @see #makeArrayDES(String)
*/
private String makeStringDES(byte[] values) {
StringBuffer buff = new StringBuffer(values.length * 3);
for (int i = 0; i < values.length; i++) {
buff.append('#');
buff.append(values[i]);
}
return buff.toString();
}
/**
* Internal method which converts an "Array String" into a byte array which
* can be used for decoding
*
* @see #makeString(byte[])
*/
private byte[] makeArrayDES(String values) {
StringTokenizer tok = new StringTokenizer(values, "#");
byte[] result = new byte[tok.countTokens()];
byte b;
String c;
int i = 0;
while (tok.hasMoreTokens()) {
c = tok.nextToken();
try {
b = Byte.parseByte(c);
result[i] = b;
i++;
} catch (NumberFormatException e) {
return new byte[1];
}
}
return result;
}
}

174
src/de/superx/docmanagement/BasicAuthTokenRequester.java

@ -0,0 +1,174 @@ @@ -0,0 +1,174 @@
package de.superx.docmanagement;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.time.Duration;
import java.time.Instant;
import java.util.StringTokenizer;
import jakarta.servlet.ServletException;
public class BasicAuthTokenRequester {
private static final long serialVersionUID = 1L;
private String url, basicAuthString;
private static boolean isTestModus = false;
private static boolean isDebug = false;
private String token = null;
private Instant tokenCreationTime ;
private final java.util.logging.Logger logger = java.util.logging.Logger.getLogger("docman");
public static void main(String[] args) {
System.out.println("Tokentester Version 2023-08-22");
if (args.length != 2) {
System.out.println("Parameter URL BasicAuthString");
} else {
isTestModus = true;
BasicAuthTokenRequester batr = new BasicAuthTokenRequester(args[0], args[1]);
String token;
try {
batr.authenticateAndInitToken();
token = batr.getToken();
System.out.println("");
System.out.println("Token:");
System.out.println(token);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
BasicAuthTokenRequester(String vorlage) throws IOException {
StringTokenizer st = new StringTokenizer(vorlage, "|");
String tokenURL = null, basicAuthString = null;
int i = 1;
while (st.hasMoreTokens()) {
String val = st.nextToken();
if (i == 1) tokenURL = val;
if (i == 2) basicAuthString = val;
i++;
}
if (tokenURL == null || basicAuthString == null) {
throw new IOException("Fehler beim Initialisieren der Tokenvorlage, URL|BasicAuthString benötigt");
}
if (basicAuthString.startsWith("sx_des")) {
try {
if (isDebug) {
System.out.println("Verschluesselter String " + basicAuthString);
}
basicAuthString = new ArchivePropHandler().decryptStringDES(basicAuthString.substring(6));
if (isDebug) {
System.out.println("Entschluesselt: " + basicAuthString);
}
} catch (Exception e) {
throw new IOException("Fehler beim Initialisieren der Tokenvorlage, basicAuthString nicht verarbeitet " + e);
}
} else {
throw new IllegalStateException("basicAuthString nicht verschluesselt");
}
if (isDebug) {
System.out.println("Ziel URL " + tokenURL);
}
this.url = tokenURL;
this.basicAuthString = basicAuthString;
}
BasicAuthTokenRequester(String url, String basicAuthString) {
this.url = url;
this.basicAuthString = basicAuthString;
}
public void authenticateAndInitToken() throws IOException {
HttpURLConnection con = null;
try {
URL myurl = new URL(url);
con = (HttpURLConnection) myurl.openConnection();
con.setDoOutput(true);
con.setRequestMethod("POST");
con.setRequestProperty("User-Agent", "Java client");
con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
con.setRequestProperty("charset", "utf-8");
con.setRequestProperty("Content-Length", "0");
con.setUseCaches(false);
con.setRequestProperty("Authorization", "Basic " + basicAuthString);
DataOutputStream wr = new DataOutputStream(con.getOutputStream());
byte[] postData = new byte[0];
wr.write(postData);
wr.write(postData);
StringBuilder content;
BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream()));
String line;
content = new StringBuilder();
while ((line = br.readLine()) != null) {
content.append(line);
content.append(System.lineSeparator());
}
if (isTestModus) {
System.out.println("Serverantwort:");
System.out.println(content.toString());
}
token = extractToken(content.toString());
tokenCreationTime= Instant.now();
logger.info("Neues Token erzeugt");
if (isDebug) {
System.out.println("Token: " + token);
}
} catch (Exception e) {
// System.out.println("Fehler: " + e.toString());
// e.printStackTrace();
throw new IOException("Token konnte nicht ermittelt werden " + e);
} finally {
if (con != null) con.disconnect();
}
}
public String getToken() throws IOException {
if (token == null) {
authenticateAndInitToken();
}
long hoursElapsed = Duration.between(tokenCreationTime, Instant.now()).toHours();
if (hoursElapsed>20)
{
logger.info("Token älter als 20 Stunden, erzeuge neues");
authenticateAndInitToken();
}
return token;
}
private String extractToken(String input) {
String result = "";
if (input != null) {
result = input.replaceAll("<ticket>", "");
result = result.replaceAll("</ticket>", "");
result = result.replaceAll("\n", "");
result = result.replaceAll("\r", "");
}
return result;
}
}

138
src/de/superx/docmanagement/ConnectionTest.java

@ -0,0 +1,138 @@ @@ -0,0 +1,138 @@
package de.superx.docmanagement;
import java.io.BufferedInputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.NetworkInterface;
import java.net.Proxy;
import java.net.Proxy.Type;
import java.net.SocketException;
import java.net.URL;
import java.net.URLConnection;
import java.nio.charset.Charset;
import java.util.Enumeration;
public class ConnectionTest {
// Für Testzwecke Standard HTTP-Type für Proxy auf Socks umstellbar, default
// false
private static boolean isSocksDebug = false;
private static Proxy proxy;
private static Type proxyType = Proxy.Type.HTTP;
public static void main(String[] args) {
if (isSocksDebug)
proxyType = Proxy.Type.SOCKS;
if (args.length < 2) {
System.out.println(
"Usage URL outfile z.B. https://saphost.de:8090/ out.html optional 3. Parameter ProxyHost 4. Parameter ProxyPort"
+
"\n+ Beispiel 1 https://saphost.de:8090/ out.html"
+ "\n+ Beispiel 2 https://saphost.de:8090/ out.html proxy.uni-freiburg.de 8080"
+ "\n Wenn eine TestURL sehr lang, ist kann man als 1.Parameter eine Quelldatei angeben, in der die URL steht (wird erkannt, wenn Parameter nicht mit http startet),z.B."
+ "\n Beispiel 2 testurl.txt out.html proxy.uni-freiburg.de 8080\"+");
System.exit(-1);
}
try {
System.out.println("Version " + DocMan.VERSION);
printIPs();
initProxyIfFound(args);
System.out.print("Starte Abruf..");
String urlparam = args[0];
if (!urlparam.startsWith("http")) {
urlparam = readFile(new File(urlparam));
}
System.out.println(" ZielURL:"+urlparam);
URL url = new URL(urlparam);
FileOutputStream fout = new FileOutputStream(args[1]);
URLConnection con = null;
if (proxy == null)
con = url.openConnection();
else {
con = url.openConnection(proxy);
}
con.setConnectTimeout(15 * 1000);
// BufferedInputStream bis = new BufferedInputStream(url.openStream());
BufferedInputStream bis = new BufferedInputStream(con.getInputStream());
byte[] res = new byte[1024 * 8];
int got;
while ((got = bis.read(res)) != -1) {
fout.write(res, 0, got);
}
fout.flush();
fout.close();
bis.close();
System.out.println("..Erledigt");
} catch (Exception e) {
System.out.println("Fehler " + e);
}
}
private static void initProxyIfFound(String[] args) {
if (args.length > 2 && args[2] != null) {
String host = args[2];
int port = 8080;
if (args.length > 3 && args[3] != null) {
port = Integer.parseInt(args[3]);
}
System.out.println(" versuche mit Proxy " + host + " port " + port);
proxy = new Proxy(proxyType, new InetSocketAddress(host, port));
}
}
private static void printIPs() throws SocketException {
System.out.println("IP Adressen dieser Maschine:");
Enumeration e = NetworkInterface.getNetworkInterfaces();
while (e.hasMoreElements()) {
NetworkInterface n = (NetworkInterface) e.nextElement();
Enumeration ee = n.getInetAddresses();
while (ee.hasMoreElements()) {
InetAddress i = (InetAddress) ee.nextElement();
System.out.println(i.getHostAddress());
}
}
}
/**
* from de.memtext.util.StringUtils /** Reads the contents of a file and returns
* them as a string
*
* @param filename
* @return String with content of files
* @throws IOException
*/
private static String readFile(File file) throws IOException {
Charset charset = Charset.defaultCharset();
return readFile(file, charset);
}
private static String readFile(File file, Charset charset) throws IOException {
FileInputStream fileinputstream = new FileInputStream(file);
InputStreamReader inputstreamreader = new InputStreamReader(fileinputstream, charset);
BufferedReader bufferedreader = new BufferedReader(inputstreamreader);
String line;
StringBuffer result = new StringBuffer();
while ((line = bufferedreader.readLine()) != null) {
result.append(line + "\n");
}
bufferedreader.close();
inputstreamreader.close();
fileinputstream.close();
return result.toString();
}
}

526
src/de/superx/docmanagement/DocMan.java

@ -0,0 +1,526 @@ @@ -0,0 +1,526 @@
package de.superx.docmanagement;
import java.io.File;
import java.io.IOException;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Locale;
import java.util.logging.FileHandler;
import java.util.logging.Handler;
import java.util.logging.Level;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;
import java.util.zip.GZIPOutputStream;
import java.util.zip.ZipOutputStream;
import jakarta.servlet.ServletConfig;
import jakarta.servlet.ServletException;
import jakarta.servlet.ServletOutputStream;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.apache.commons.io.IOUtils;
import de.memtext.util.DateUtils;
import de.memtext.util.FileUtils;
import de.memtext.util.TimeUtils;
import de.superx.common.SxUser;
import de.superx.servlet.AbstractSuperXServlet;
import de.superx.servlet.ServletUtils;
import de.superx.servlet.SuperXManager;
import de.superx.servlet.SxPools;
import de.superx.util.SqlStringUtils;
public class DocMan extends AbstractSuperXServlet {
private static final long serialVersionUID = 2;
private static final String LOGFILE = "docman.log";
private static final String MANDANTENID = "default";
private HashMap<String, AbstractDocPresenter> docPresenters = new HashMap<String, AbstractDocPresenter>();
private boolean isInitOk = false;
private String initExceptionText = "";
private final java.util.logging.Logger logger = java.util.logging.Logger.getLogger("docman");
final static String VERSION = "1.3 (2025-03-07)";
public void init(ServletConfig config) {
logger.info("start initSubsystem");
try {
super.init(config);
System.out.println("Starte DocManagement-Servlet Version " + VERSION);
// Bei Bedarf Zugriff auf ServletCOnfig möglich via
// this.getServletConfig()
initLogging();
initDocPresenters();
isInitOk = true;
} catch (ServletException e) {
initExceptionText = "Fehler bei Initialisierung der DokumentenManagementServlet " + e;
logger.severe(initExceptionText + "\n" + getExceptionStackTrace(e));
}
}
private void initDocPresenters() throws ServletException {
try (Connection con = SxPools.get(MANDANTENID).getConnection();) {
String hs_nr="";
Statement stm=con.createStatement();
ResultSet rs_hsinfo=stm.executeQuery("select hs_nr from hochschulinfo");
while (rs_hsinfo.next())
{
hs_nr=rs_hsinfo.getString(1);
}
rs_hsinfo.close();
stm.close();
PreparedStatement pst = con.prepareStatement("select count(*) from sx_repository where aktiv=1 and id=?");
pst.setString(1, "SAP_ARCHIV1_URLVORLAGE");
ResultSet rs = pst.executeQuery();
int count = 0;
while (rs.next()) {
count = rs.getInt(1);
}
rs.close();
if (count > 0) {
// Uni FR/Mannheim
AbstractDocPresenter p = new SAPArchiv1("gxstage");
docPresenters.put("gxstage", p);
logger.info(" SAPArchiv1 initialisiert");
}
pst.setString(1, "MBS_ARCHIV1_URLVORLAGE");
rs = pst.executeQuery();
count = 0;
while (rs.next()) {
count = rs.getInt(1);
}
rs.close();
if (count > 0) {
AbstractDocPresenter p = new MBSArchiv1("mbs");
docPresenters.put("mbs", p);
logger.info(" MBSArchiv1 initialisiert");
//Für Regensburg zusätzlicher Presenter mit barcodes
if (hs_nr.equals("1341"))
{
p = new MBSBusinessTransactionArchiv("mbs_business_transaction");
docPresenters.put("mbs_business_transaction", p);
logger.info(" MBSBusinessTransactionArchiv initialisiert");
}
}
pst.setString(1, "DVELOP_ARCHIV1_URLVORLAGE");
rs = pst.executeQuery();
count = 0;
while (rs.next()) {
count = rs.getInt(1);
}
rs.close();
if (count > 0) {
AbstractDocPresenter p = new DvelopArchiv1("gxstage");
docPresenters.put("gxstage", p);
logger.info(" DVELOP_ARCHIV1 initialisiert");
}
pst.close();
} catch (SQLException e) {
e.printStackTrace();
throw new IllegalStateException("Fehler bei DocManagement " + e);
}
}
private void initLogging() {
try {
String logfile = getLogDir() + "/docman.log";
File f = new File(logfile + ".lck");
if (f.exists()) f.delete();
f = new File(logfile);
if (f.exists()) f.delete();
initRawFileDateTime("docman", logfile, 20000, 1, true, true);
} catch (IOException e) {
throw new IllegalStateException("Konnte docman Logging nicht aufbauen", e);
}
logger.setLevel(java.util.logging.Level.FINEST);
logger.info("Starte DocManagement-Servlet Version " + VERSION);
}
private String getLogDir() {
String targetDir = SuperXManager.getWEB_INFPfad() + File.separator + "logs";
File f = new File(targetDir);
if (!f.exists()) f.mkdir();
if (System.getProperty("SX_LOG_TO_TMP") != null && System.getProperty("SX_LOG_TO_TMP").equalsIgnoreCase("true")) targetDir = System.getProperty("java.io.tmpdir");
return targetDir;
}
public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
if (!isInitOk) {
sendBack(request, response, initExceptionText, "text/html");
} else {
String mand = getMandantenID(request);
if (!"default".contentEquals(mand)) throw new IllegalArgumentException("Funktion derzeit nur für Mandant default implementiert");
setEncoding(request);
SxUser user = (SxUser) request.getSession().getAttribute("user");
if ("true".equals(getParameter(request, "refresh"))) {
String result = doPresenterRefresh(user);
sendHtmlMessage(request, response, result);
} else {
try {
docPresentation(request, response, user);
} catch (IOException e) {
response.reset();
sendErrorMessage(request, response, "Es ist ein Fehler beim Dokumentenabruf aufgetreten: " + e + " Logdatei " + LOGFILE + " pruefen", e);
}
}
}
}
/**
* TODO ggfs. in utils auslagern
*
* @param e
* @return
*/
String getExceptionStackTrace(Exception e) {
String result = "";
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
result = sw.toString();
pw.close();
return result;
}
private void docPresentation(HttpServletRequest request, HttpServletResponse response, SxUser user) throws IOException {
logger.info("Verarbeite DocAbruf");
String sys = getParameter(request, "sys");
if (sys == null || sys.length() == 0) throw new IllegalArgumentException("Param sys fehlt");
if (!docPresenters.containsKey(sys)) {
StringBuffer msg = new StringBuffer("Kein DocPresenter für " + sys + " definiert. Aktiv: ");
Iterator<String> it = docPresenters.keySet().iterator();
while (it.hasNext()) {
msg.append(it.next() + "");
}
throw new IllegalArgumentException(msg.toString());
} else {
AbstractDocPresenter presenter = docPresenters.get(sys);
DocPresentationResult dpresult = presenter.getReply(request, user);
if (dpresult.hasMessage()) {
sendHtmlMessage(request, response, dpresult.getMessage());
} else {
if (presenter.isDirectLinkToDocMWanted()) {
response.sendRedirect(dpresult.getDocManagementUrl().toString());
} else {
try {
loadAndDeliverContent(true, presenter, request, response, dpresult);
} catch (IOException e) {
if (presenter.isRenewAuthentificationOnErrorWanted()) {
presenter.renewAuthentification();
}
//2. Versuch
loadAndDeliverContent(false, presenter, request, response, dpresult);
}
}
}
}
}
private void loadAndDeliverContent(boolean tryAgainOnError, AbstractDocPresenter presenter, HttpServletRequest request, HttpServletResponse response,
DocPresentationResult dpresult)
throws IOException {
URL url = dpresult.getDocManagementUrl();
//Abgelaufene Test-URL
// url = new URL(
// "https://saphost-pot.bwhsrw.de:8090/archive?get&pVersion=0046&contRep=PF&docId=aaabk3kvy63gcleb33aaaiiew6tii&accessMode=r&authId=bi-superx-freiburg&expiration=20211013094020&secKey=MIAGCSqGSIb3DQEHAqCAMIACAQExCzAJBgUrDgMCGgUAMIAGCSqGSIb3DQEHAQAAMYIB2zCCAdcCAQEwKTAdMRswGQYDVQQDDBJiaS1zdXBlcngtZnJlaWJ1cmcCCGD%2Bp%2BaHNNcPMAkGBSsOAwIaBQCggYgwGAYJKoZIhvcNAQkDMQsGCSqGSIb3DQEHATAcBgkqhkiG9w0BCQUxDxcNMjExMDEzMDkyMjAyWjAjBgkqhkiG9w0BCQQxFgQUCAxB%2FtRhmBRnNvrBZ8wrjQfn3mswKQYJKoZIhvcNAQk0MRwwGjAJBgUrDgMCGgUAoQ0GCSqGSIb3DQEBAQUAMA0GCSqGSIb3DQEBAQUABIIBAJZVtVIUF3SihW2NZG%2F48aJPjXEeEVcuuBIlRdVfhC7lssmQFMrLqJoKOXcvLXv6Bi4OUTqH60LaSkS8ramG%2Fxh7up%2FURR%2B93oJ2lmTvMp7HA5FmKiW5pBajgRq4MClM%2Fd9PpeMNHMfhZMQUNue3lk%2Fo9hucfS%2B%2Fd9V67TlBXRNQaBouyNR88ZfJdvuN4zR16Jjs4UoX0v0wPVgDGCdhmRF9r4zflssxEhxiIjmrY%2FaVjFA%2BU8mL4isGmVdyzBp%2FjPXjyKgIpwbKPuk5GyFqd6Dpv3ZA0Vgp87Pf6IDOs2Zh1QlPqTENe6Dg%2BbPGelb5l3YUXoQnnx33d7nLcAl0EvoAAAAAAAA%3D");
logger.info("interner Download und Auslieferung von " + url);
String targetMimeType = dpresult.getMimetype();
logger.info(" Ziel Mimetype " + targetMimeType);
HttpURLConnection urlConnection = presenter.openConnection(url);
presenter.setHeaderAuthorisation(urlConnection);
response.reset();
byte[] bytes = new byte[0];
try {
// Wirft IO Exception auch bei Fehler in der URL also 401 o.ä.
bytes = IOUtils.toByteArray(urlConnection.getInputStream());
logger.fine(" " + bytes.length + " Bytes an Daten erhalten");
logger.info("HTTP-StatusCode: " + urlConnection.getResponseCode());
if (urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {
if (targetMimeType != null) {
response.setContentType(targetMimeType);
}
String desiredFilename = FileUtils.removeProblemChars(dpresult.getDesiredFilename());
logger.fine(" Sende aus: " + desiredFilename);
response.setHeader("Content-disposition", "attachment; filename=" + desiredFilename);
response.setHeader("Cache-Control", "expires=0");
// response.setContentLength(outStream.size()); //evtl. bytes.size()
ServletOutputStream sos = response.getOutputStream();
sos.write(bytes);
sos.flush();
sos.close();
} else {
if (tryAgainOnError) {
String msg = "Fehler beim Lesen der Daten vom DocServer " + new IOException("Http Status " + urlConnection.getResponseCode() + "versuche erneut");
logger.warning(msg);
throw new IOException(msg);
} else {
sendErrorMessage(request, response, "Fehler beim Lesen der Daten vom DocServer ", new IOException("Http Status " + urlConnection.getResponseCode()));
}
/*
* ursprüngliche Idee bei 401 genauen Text ausliefern, für Hackerversuche nicht
* so gut IO-Utils oder urlConnection.inputStream oben wirft IO Exception wenn
* nicht http-Status-OK else {
* logger.severe("Es ist ein Fehler beim DocServer aufgetreten " +
* urlConnection.getResponseMessage()); String responsedata = new String(bytes,
* StandardCharsets.UTF_8); logger.severe(" Details:\n" + responsedata);
* sendBack(request, response, responsedata, "text/html"); }
*/
}
} catch (IOException e) {
if (tryAgainOnError) {
String msg = "Fehler beim Lesen der Daten vom DocServer Http Status " + urlConnection.getResponseCode() + " "+e+" versuche erneut";
logger.warning(msg);
throw new IOException(msg);
} else {
sendErrorMessage(request, response, "Fehler beim Lesen der Daten vom DocServer ", e);
}
}
}
private void sendErrorMessage(HttpServletRequest request, HttpServletResponse response, String message, Exception e) throws IOException {
String logme = message;
if (e != null) {
logme += "\n" + getExceptionStackTrace(e);
}
logger.severe(logme);
message = message + " " + e;
//Falls in Datenbank ein Errortext hinterlegt ist, diesen anzeigen
try (Connection con = SxPools.get(MANDANTENID).getConnection();) {
Statement st = con.createStatement();
ResultSet rs = st.executeQuery("select content from sx_repository where id='DMS_ERRORTEXT' and aktiv=1 and today() between gueltig_seit and gueltig_bis");
while (rs.next()) {
message = rs.getString(1);
}
rs.close();
st.close();
} catch (SQLException ex) {
ex.printStackTrace();
logger.severe("Fehler bei DocManagement : Lesen von möglichem DMS_ERRORTEXT " + ex);
}
sendBack(request, response, message, "text/html; charset=utf-8");
}
private void sendHtmlMessage(HttpServletRequest request, HttpServletResponse response, String message) throws IOException {
logger.fine("HTML Darstellung Lokalisierung und Ausliererung von HTML");
Locale desiredLocale = getDesiredLocale(request);
String txt = SxPools.get(getMandantenID(request)).localize(message, desiredLocale);
// TODO Optimal mit csrfToken, Methode aber in älteren Kernmodul nicht vorhanden
// da aktuell nicht benötigt, auskommentiert
// sendBack(request, response, insertCsrfToken(request, result), "text/html");
sendBack(request, response, txt, "text/html");
}
private String doPresenterRefresh(SxUser user) throws ServletException {
String result;
if (user.isAdmin()) {
logger.info("Refresh wird gestartet");
Iterator<String> it = docPresenters.keySet().iterator();
while (it.hasNext()) {
AbstractDocPresenter p = docPresenters.get(it.next());
p.initSystem();
}
result = "Refresh erfolgreich (" + new java.util.Date() + ")";
} else {
result = "Diese Funktion steht nur Administratoren zur Verf&uuml;gung";
}
return result;
}
public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
}
public void destroy() {
java.util.logging.Handler[] h = logger.getHandlers();
for (int i = 0; i < h.length; i++) {
h[i].close();
}
}
public String getMandantenID(HttpServletRequest request) {
return ServletUtils.getMandantenID(request);
}
/**
* TODO Methoden in de.superx.servlet.ServletBasics auf public setzen, damit
* wiederverwendet werden kann
*
* @return
*/
protected void sendBack(HttpServletRequest request, HttpServletResponse response, String txt, String contenttype) throws IOException {
OutputStream out = null;
TimeUtils t = new TimeUtils();
t.start();
// Check the Accepting-Encoding header from the HTTP request.
// If the header includes gzip, choose GZIP.
// If the header includes compress, choose ZIP.
// Otherwise choose no compression.
byte[] stuff = txt.getBytes(SqlStringUtils.getEncoding());
String encoding = request.getHeader("Accept-Encoding");
if (!SuperXManager.isResponseCompressionWanted) encoding = "none";
if (encoding != null && encoding.indexOf("gzip") != -1) {
response.setHeader("Content-Encoding", "gzip");
out = new GZIPOutputStream(response.getOutputStream());
} else if (encoding != null && encoding.indexOf("compress") != -1) {
response.setHeader("Content-Encoding", "compress");
out = new ZipOutputStream(response.getOutputStream());
} else {
response.setContentLength(stuff.length);
out = response.getOutputStream();
}
if (contenttype != null) {
response.setContentType(contenttype);
}
out.write(stuff);
out.close();
}
public Locale getDesiredLocale(HttpServletRequest request) {
// locale of browser
Locale desiredLocale = request.getLocale();
// if a locale is defined in session, it has priority
if (request.getSession() != null && request.getSession().getAttribute("locale") != null) {
desiredLocale = new Locale((String) request.getSession().getAttribute("locale"));
}
// if a locale parameter is in the current request
String locale_param = (String) request.getParameter("locale");
if (locale_param != null) desiredLocale = new Locale(locale_param);
return desiredLocale;
}
//aus de.superx.servlet.ServletBasics
public static String getParameter(HttpServletRequest request, String name) {
String p = request.getParameter(name);
//Parameter auf unterlaubte Tags kontrollieren
//ausser bei SuperX-Standalone Formularfeldern passwort,passwort2, altes_passwort
//dort können Sonderzeichen genutzt werden
// vergl. servlet.SuperXmlPwChanger
if (name.indexOf("passwort") == -1) {
if (p != null && containsTags(p)) {
throw new IllegalArgumentException("Parameter " + name + " enthält unerlaubte Tags");
}
}
return p;
}
/**
* aus de.memtext.util.StringUtils
* Prüft ob Tags <***> enthalten sind, \n wird auch moniert Text javascript
* wird auch moniert
*
* @param source
* @return
*/
private static boolean containsTags(String source) {
// return source.replaceAll("<[^>]+>", "");
boolean result = false;
if (source != null) {
int startpos = 0;
while (source.indexOf("<", startpos) > -1) {
startpos = source.indexOf("<", startpos);
int tagend = source.indexOf(">", startpos);
if (tagend > -1 && tagend > startpos + 1 && source.substring(startpos, tagend).indexOf(" ") == -1) {
result = true;
break;
} else if (tagend > -1)
startpos = tagend + 1;
else
startpos++;
}
if (source.indexOf("javascript") > -1) result = true;
// gab Probleme mit csv upload
// if (source.indexOf("\n")>-1) result=true;
if (source.indexOf("\u0000") > -1) result = true;
/*
* StringTokenizer st = new StringTokenizer(source, " <", true);
* while (st.hasMoreTokens()) { String tok = st.nextToken(); int pos =
* tok.indexOf(">"); //größer 0 damit nicht ">1996" als tag zählt if
* (pos > 0 && tok.substring(0, pos).indexOf(" ") == -1) { result =
* true; break; } }
*/
}
return result;
}
// aus de.memtext.util.LogUtils
private void initRawFileDateTime(String loggername, String filename, int maxKB, int count, boolean append, boolean tryLckDeletion) throws SecurityException, IOException {
if (tryLckDeletion) {
if (count > 1) throw new IllegalArgumentException("tryLckDeletion doesn't work for >1 file");
File f = new File(filename + ".lck");
if (f.exists()) f.delete();
}
if (count > 1) filename = FileUtils.addToEndOfFileName(filename, "%g");
Handler fh = new FileHandler(filename, maxKB * 1024, count, append);
fh.setFormatter(new SimpleFormatter() {
public String format(LogRecord l) {
String result = DateUtils.getTodayString() + " " + DateUtils.getNowString() + ":" + l.getMessage() + "\n";
return result;
}
public String formatMessage(LogRecord l) {
return format(l);
}
});
Logger.getLogger(loggername).addHandler(fh);
Logger.getLogger(loggername).setLevel(Level.FINEST);
}
public static String exceptionToString(Exception e) {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw);
e.printStackTrace(pw);
return sw.toString();
}
}

56
src/de/superx/docmanagement/DocPresentationResult.java

@ -0,0 +1,56 @@ @@ -0,0 +1,56 @@
package de.superx.docmanagement;
import java.net.URL;
public class DocPresentationResult {
private static final long serialVersionUID = 1;
private String message, mimetype, desiredFilename;
private URL docManagementUrl;
String getDesiredFilename() {
return desiredFilename;
}
void setDesiredFilename(String desiredFilename) {
this.desiredFilename = desiredFilename;
}
String getMessage() {
return message;
}
void setMessage(String message) {
this.message = message;
}
String getMimetype() {
return mimetype;
}
void setMimetype(String mimetype) {
this.mimetype = mimetype;
}
URL getDocManagementUrl() {
return docManagementUrl;
}
void setDocManagementUrl(URL docManagementUrl) {
this.docManagementUrl = docManagementUrl;
}
/**
* Prüft ob eine vernünftige Antwort geliefert werden kann dann muss entweder
* eine Message oder eine URL bereit liegen
*
* @return
*/
boolean isOK() {
return getMessage() != null || getDocManagementUrl() != null;
}
public boolean hasMessage() {
return getMessage() != null;
}
}

48
src/de/superx/docmanagement/DocumentMetadata.java

@ -0,0 +1,48 @@ @@ -0,0 +1,48 @@
package de.superx.docmanagement;
public class DocumentMetadata {
private String filename, mimetyp, docid,art;
String getArt() {
return art;
}
void setArt(String art) {
this.art = art;
}
String getFilename() {
return filename;
}
void setFilename(String filename) {
this.filename = filename;
}
String getMimetyp() {
return mimetyp;
}
void setMimetyp(String mimetyp) {
this.mimetyp = mimetyp;
}
String getDocid() {
return docid;
}
void setDocid(String docid) {
this.docid = docid;
}
public boolean isValid() {
return getFilename()!=null&&getMimetyp()!=null&&getDocid()!=null&&getArt()!=null;
}
public void clear() {
setFilename(null);
setMimetyp(null);
setDocid(null);
}
}

177
src/de/superx/docmanagement/DvelopArchiv1.java

@ -0,0 +1,177 @@ @@ -0,0 +1,177 @@
package de.superx.docmanagement;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.Proxy.Type;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;
import jakarta.servlet.ServletException;
public class DvelopArchiv1 extends AbstractDocPresenter {
// Für Testzwecke Standard HTTP-Type für Proxy auf Socks umstellbar, default
// false
private static boolean isSocksDebug = false;
private static Type proxyType = Proxy.Type.HTTP;
private static final long serialVersionUID = 3L;
private final boolean isDebug = false; // true schaltet Authentication Header ab!
private Map<String, String> doctyp_Mimetype;
private BasicAuthTokenRequester tokenrequester;
void initSystem() throws ServletException {
if (isSocksDebug) proxyType = Proxy.Type.SOCKS;
//URL zum Abruf der Dokumente
setUrlVorlage(readVorlageFromRepository("DVELOP_ARCHIV1_URLVORLAGE"));
//Token URL username und passwort
initTokenRequester();
setDirectLinkToDocMWanted(false);
setMenuVorlage(readVorlageFromRepository("DVELOP_ARCHIV1_MENU_VORLAGE"));
setReadDocumentCountSql("select count(*) from gxstage_dms_metadata where id_jahr_belegnr=? and anzeige_relevant=1");
//Hier wichtig, die ID im DokumentenManageManageSystem muss doc_id sein, für MenüVorlage daher "as doc_id"
// keine Unterstriche, da übersichtlicher in Freemarker
setReadDocumentListSql("select docid as doc_id,filename,art from gxstage_dms_metadata where id_jahr_belegnr=? and anzeige_relevant=1 order by filename");
setDeleteOldRightsSql("delete from gxstage_dms_rights where gueltig_bis<today()");
setReadIdRightSql("select count(*) from gxstage_dms_rights where userinfo_id=?::integer and id_jahr_belegnr=? and gueltig_bis>=today()");
setReadDocIdRightSql("select count(*) from gxstage_dms_rights R,gxstage_dms_metadata M where userinfo_id=?::integer and R.id_jahr_belegnr=M.id_jahr_belegnr and M.anzeige_relevant=1 and gueltig_bis>=today() "
+ "and M.docid=?");
setReadDocIdSql("select docid from gxstage_dms_metadata where id_jahr_belegnr=? and anzeige_relevant=1");
setReadMainDocIdSql("select distinct docid from gxstage_dms_metadata where id_jahr_belegnr=? and maindoc=1 and anzeige_relevant=1");
// default=false setDocMenuAlwaysWanted(true);
setRenewAuthentificationOnErrorWanted(true);
initMimeTypes();
initProxy();
}
private void initTokenRequester() throws ServletException {
String tokenvorlage = readVorlageFromRepository("DVELOP_ARCHIV1_TOKENURL");
//TODO ggfs aus Datei
/*if (tokenvorlage.equals("docman_mbsarchive.properties")) {
try {
logger.info("Lese Tokeninformationen aus Datei "+SuperXManager.getWEB_INFPfad() + File.separator + "docman_mbsarchive.properties");
tokenvorlage = ph.getUrlVorlage(SuperXManager.getWEB_INFPfad() + File.separator + "docman_mbsarchive.properties");
} catch (IOException e) {
e.printStackTrace();
throw new ServletException("Fehler bei Lesen von Properties-Datei " + e);
}
}*/
StringTokenizer st = new StringTokenizer(tokenvorlage, "|");
String tokenURL = null, basicAuthString = null;
int i = 1;
while (st.hasMoreTokens()) {
String val = st.nextToken();
if (i == 1) tokenURL = val;
if (i == 2) basicAuthString = val;
i++;
}
if (tokenURL == null || basicAuthString == null) {
throw new ServletException("Fehler beim Initialisieren der Tokenvorlage, URL|basicAuthString bzw. Properties-Datei benötigt");
}
if (basicAuthString.startsWith("sx_des")) {
try {
if (isDebug) {
logger.info("Verschluesseltes Passwort " + basicAuthString);
}
basicAuthString = new ArchivePropHandler().decryptStringDES(basicAuthString.substring(6));
if (isDebug) {
logger.info("Entschluesseltes Passwort " + basicAuthString);
}
} catch (Exception e) {
throw new ServletException("Fehler beim Initialisieren der Tokenvorlage, Password nicht verarbeitet " + e);
}
} else {
throw new IllegalStateException("Passwort nicht verschluesselt");
}
tokenrequester = new BasicAuthTokenRequester(tokenURL, basicAuthString);
}
protected void renewAuthentification() throws IOException {
if (!isDebug) {
logger.info("Erneuere Token mittels Authentification-String");
tokenrequester.authenticateAndInitToken();
}
}
private void initProxy() {
String[] params = getUrlVorlage().split("\\|");
if (params.length > 5) {
logger.info("Intialisierung mit Proxy für das DocManagement");
int port = 8080;
String host = params[5];
if (params.length > 6 && params[6] != null) {
try {
port = Integer.parseInt(params[6]);
} catch (NumberFormatException e) {
String msg = "Konnte Portnummer für Proxy nicht in Integer umwandeln: " + params[6];
logger.severe(msg);
throw new IllegalStateException(msg);
}
}
logger.info(" ProxyHost: " + host + " Port: " + port);
setProxy(new Proxy(proxyType, new InetSocketAddress(host, port)));
}
}
private void initMimeTypes() {
// Hier erst initialisieren wegen komplexem Ablauf von Kontruktoren und
// initSystem
if (doctyp_Mimetype == null) doctyp_Mimetype = new HashMap<String, String>();
doctyp_Mimetype.clear();
// doctyp_Mimetype.putAll(readMapFromDB("SELECT lower(endung),mimetype FROM fin_dms_mimetypes", null));
// logger.fine(" Mimetype Zuordnungen gefunden:" + doctyp_Mimetype);
}
public DvelopArchiv1(String sys) throws ServletException {
super(sys, null);
}
/**
*
*
* @param doc_id - Hier eine docId!
* @return
* @throws Exception
*/
public void updateDocLink(DocPresentationResult result, String doc_id) throws Exception {
result.setDocManagementUrl(new URL(getUrlVorlage().replaceFirst("<<DOCID>>", doc_id)));
String filename = readStringFromDB("select filename from gxstage_dms_metadata where docid=?", doc_id);
result.setDesiredFilename(filename);
String mt = readStringFromDB("select mimetype from gxstage_dms_metadata where docid=?", doc_id);
logger.fine(" Ermittelte minetype: " + mt + "");
if (!mt.contentEquals("")) result.setMimetype(mt);
}
protected void setHeaderAuthorisation(HttpURLConnection urlConnection) throws IOException {
String token = "";
if (!isDebug) {
//macht auch authentifizierung falls token noch null
token = tokenrequester.getToken();
}
logger.info(" set Header Authorization Bearer " + token);
urlConnection.setRequestProperty("Authorization", "Bearer " + token);
}
}

36
src/de/superx/docmanagement/DvelopDocumentMetadata.java

@ -0,0 +1,36 @@ @@ -0,0 +1,36 @@
package de.superx.docmanagement;
public class DvelopDocumentMetadata extends DocumentMetadata {
private int gejahr = 0;
int getGejahr() {
return gejahr;
}
void setGejahr(int gejahr) {
this.gejahr = gejahr;
}
String getBelegnummer() {
return belegnummer;
}
void setBelegnummer(String belegnummer) {
this.belegnummer = belegnummer;
}
private String belegnummer;
public boolean isValid() {
return super.isValid() && getGejahr() != 0 && getBelegnummer() != null;
}
public void clear() {
super.clear();
setGejahr(0);
setBelegnummer(null);
}
}

66
src/de/superx/docmanagement/DvelopDownloadTester.java

@ -0,0 +1,66 @@ @@ -0,0 +1,66 @@
package de.superx.docmanagement;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import org.apache.commons.io.IOUtils;
public class DvelopDownloadTester {
private static final long serialVersionUID = 1L;
private String token;
public static void main(String[] args) {
System.out.println("Version 1.0 11.9.2023");
if (args.length !=2) {
System.out.println("Parameter DownloadURL token");
} else {
try {
DvelopDownloadTester fdr = new DvelopDownloadTester();
fdr.setToken(args[1]);
fdr.test(args[0]);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public void setToken(String token)
{
this.token=token;
}
public void test(String currentURL) throws IOException {
System.out.println("Rufe ab "+currentURL);
URL url=new URL(currentURL);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
System.out.println(" set Header Authorization Bearer "+token);
urlConnection.setRequestProperty ("Authorization", "Bearer "+token);
byte[] bytes = new byte[0];
// Wirft IO Exception auch bei Fehler in der URL also 401 o.ä.
bytes = IOUtils.toByteArray(urlConnection.getInputStream());
// logger.fine(" " + bytes.length + " Bytes an Daten erhalten");
// logger.info("HTTP-StatusCode: " + urlConnection.getResponseCode());
System.out.println(" " + bytes.length + " Bytes an Daten erhalten");
System.out.println("HTTP-StatusCode: " + urlConnection.getResponseCode());
if (urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {
File outputFile = new File("test.pdf");
if (outputFile.exists()) {
outputFile.delete();
}
FileOutputStream outputStream = new FileOutputStream(outputFile);
outputStream.write(bytes);
outputStream.close();
System.out.println("als test.pdf gespeichert");
} else {
System.out.println("Fehler StatusCode nicht OK");
}
}
}

85
src/de/superx/docmanagement/DvelopDownloadTester2.java

@ -0,0 +1,85 @@ @@ -0,0 +1,85 @@
package de.superx.docmanagement;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.URL;
import java.sql.Connection;
import java.sql.ResultSet;
import org.apache.commons.io.IOUtils;
import de.superx.bin.SxConnection;
public class DvelopDownloadTester2 {
private static final long serialVersionUID = 1L;
private String token;
public static void main(String[] args) {
System.out.println("Version 1.0 11.9.2023");
if (args.length !=2) {
System.out.println("Parameter DownloadURL /pfad/zur/db.properties");
} else {
try {
DvelopDownloadTester2 fdr = new DvelopDownloadTester2();
SxConnection myConnection = new SxConnection();
myConnection.setPropfile(args[1]);
Connection con = myConnection.getConnection();
java.sql.Statement st = con.createStatement();
ResultSet rs=st.executeQuery("select content from sx_repository where id='DVELOP_ARCHIV1_TOKENURL' and aktiv=1 and today() between gueltig_seit and gueltig_bis");
String input=null;
while (rs.next()) {
input = rs.getString("content");
}
if (input == null || input.trim().length() == 0) {
throw new IllegalStateException("Keine aktive DVELOP_ARCHIV1_TOKENURL im Repository gefunden");
}
BasicAuthTokenRequester tokenrequester=new BasicAuthTokenRequester(input);
st.close();
con.close();
fdr.setToken(tokenrequester.getToken());
fdr.test(args[0]);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public void setToken(String token)
{
this.token=token;
}
public void test(String currentURL) throws IOException {
System.out.println("Rufe ab "+currentURL);
URL url=new URL(currentURL);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
System.out.println(" set Header Authorization Bearer "+token);
urlConnection.setRequestProperty ("Authorization", "Bearer "+token);
byte[] bytes = new byte[0];
// Wirft IO Exception auch bei Fehler in der URL also 401 o.ä.
bytes = IOUtils.toByteArray(urlConnection.getInputStream());
// logger.fine(" " + bytes.length + " Bytes an Daten erhalten");
// logger.info("HTTP-StatusCode: " + urlConnection.getResponseCode());
System.out.println(" " + bytes.length + " Bytes an Daten erhalten");
System.out.println("HTTP-StatusCode: " + urlConnection.getResponseCode());
if (urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {
File outputFile = new File("test.pdf");
if (outputFile.exists()) {
outputFile.delete();
}
FileOutputStream outputStream = new FileOutputStream(outputFile);
outputStream.write(bytes);
outputStream.close();
System.out.println("als test.pdf gespeichert");
} else {
System.out.println("Fehler StatusCode nicht OK");
}
}
}

432
src/de/superx/docmanagement/DvelopMetadatenLoader.java

@ -0,0 +1,432 @@ @@ -0,0 +1,432 @@
package de.superx.docmanagement;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.time.Year;
import java.util.logging.FileHandler;
import java.util.logging.Handler;
import java.util.logging.LogRecord;
import java.util.logging.Logger;
import java.util.logging.SimpleFormatter;
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import de.memtext.util.DateUtils;
import de.memtext.util.FileUtils;
import de.superx.bin.SxConnection;
/**
*
* "http://www.mbisping.de/tmp/page1.out";
// ohne nextPage
"http://www.mbisping.de/tmp/page2.out";
*
*/
public class DvelopMetadatenLoader {
private final static String VERSION="Version 2023-09-11";
private BasicAuthTokenRequester tokenrequester;
private Connection con;
private Statement stmt;
private PreparedStatement pst;
private int counter = 0;
private String urlBase;
private String firstRelativeUrl;
private final java.util.logging.Logger logger = java.util.logging.Logger.getLogger("docman_metadata");
//Zum Testen kann deaktiviert werden
private boolean isTokenNeeded = true;
public static void main(String[] args) {
if (args.length < 4 || args.length > 5) {
System.err.println("Parameter /pfad/zur/db.properties URLBase RelativeURL loglevel (info,fine,finest) Startjahr(optional)");
System.err.println("Parameter /home/superx/tomcat/webapps/superx/WEB-INF/db.properties \"https://dms-test.verw.uni-xy.de\" \"/dms/metadata\" info 2021 ");
System.exit(1);
}
System.out.println(VERSION);
System.out.println("Logfile: docman_metadata.log");
try {
int startjahr = Year.now().getValue() - 1;
if (args.length == 5) {
startjahr = Integer.parseInt(args[4]);
}
String loglevel = args[3];
DvelopMetadatenLoader dml = new DvelopMetadatenLoader(args[1], args[2], loglevel);
if (loglevel.equalsIgnoreCase("finest")) {
dml.deleteTmpJsonFiles();
}
dml.prepareDbAndPreparedStatement(args[0]);
for (int einjahr = startjahr; einjahr <= Year.now().getValue(); einjahr++) {
dml.update(einjahr);
}
dml.finishWorkinDb();
} catch (Exception e) {
System.out.println("Fehler bei der Metadatenverarbeitung");
e.printStackTrace();
System.exit(1);
}
}
private void deleteTmpJsonFiles() {
File directory = new File(".");
for (File f : directory.listFiles()) {
if (f.getName().startsWith("tmpMetadata")) {
f.delete();
}
}
}
public DvelopMetadatenLoader(String urlbase, String relativeUrl, String loglevel) {
this.urlBase = urlbase;
this.firstRelativeUrl = relativeUrl;
initLogging(loglevel);
}
private void initLogging(String loglevel) {
if (loglevel.equalsIgnoreCase("info")) {
logger.setLevel(java.util.logging.Level.INFO);
} else if (loglevel.equalsIgnoreCase("fine")) {
logger.setLevel(java.util.logging.Level.FINE);
} else if (loglevel.equalsIgnoreCase("finest")) {
logger.setLevel(java.util.logging.Level.FINEST);
} else {
System.out.println("als Loglevel info,fine oder finest angeben");
System.exit(-1);
}
try {
String logfile = "docman_metadata.log";
File f = new File(logfile + ".lck");
if (f.exists()) f.delete();
f = new File(logfile);
if (f.exists()) f.delete();
initRawFileDateTime("docman_metadata", logfile, 20000, 1, false, false);
} catch (IOException e) {
throw new IllegalStateException("Konnte docman Logging nicht aufbauen", e);
}
//deaktivierung von Console handler
logger.setUseParentHandlers(false);
logger.info(VERSION);
}
// aus de.memtext.util.LogUtils
private void initRawFileDateTime(String loggername, String filename, int maxKB, int count, boolean append, boolean tryLckDeletion) throws SecurityException, IOException {
if (tryLckDeletion) {
if (count > 1) throw new IllegalArgumentException("tryLckDeletion doesn't work for >1 file");
File f = new File(filename + ".lck");
if (f.exists()) f.delete();
}
if (count > 1) filename = FileUtils.addToEndOfFileName(filename, "%g");
Handler fh = new FileHandler(filename, maxKB * 1024, count, append);
fh.setFormatter(new SimpleFormatter() {
public String format(LogRecord l) {
String result = DateUtils.getTodayString() + " " + DateUtils.getNowString() + ":" + l.getMessage() + "\n";
return result;
}
public String formatMessage(LogRecord l) {
return format(l);
}
});
Logger.getLogger(loggername).addHandler(fh);
// Logger.getLogger(loggername).setLevel(Level.FINEST);
}
private void update(int gejahr) throws JsonParseException, IOException, SQLException {
System.out.println("Update fuer Geschaeftsjahr " + gejahr);
logger.info("Update fuer Geschaeftsjahr " + gejahr);
String firstOrNextPage = firstRelativeUrl.replaceFirst("<<GEJAHR>>", gejahr + ""); //die erste aufzurufendeSeite
try {
stmt.execute("begin transaction");
stmt.execute("delete from gxstage_dms_metadata where gejahr=" + gejahr);
int pageCount = 1;
while (firstOrNextPage != null) {
System.out.println("Lade page " + pageCount + " via " + urlBase + firstOrNextPage);
logger.info("\nLade page " + pageCount + " via " + urlBase + firstOrNextPage);
String json = getMetadata(gejahr, firstOrNextPage);
if (logger.getLevel() == java.util.logging.Level.FINEST) {
saveJsonToDisk(gejahr, pageCount, json);
}
firstOrNextPage = parse(gejahr, json);
pageCount++;
}
stmt.execute("commit");
} catch (Exception e) {
if (stmt != null) {
stmt.execute("rollback");
stmt.close();
}
e.printStackTrace();
System.exit(-1);
}
}
private void saveJsonToDisk(int gejahr, int pageCount, String json) throws IOException {
String filename = "tmpMetadata-" + gejahr + "-" + pageCount + ".json";
logger.info(" Speichere json in " + filename);
File outfile = new File(filename);
FileWriter writer = new FileWriter(outfile);
writer.append(json);
writer.close();
}
private String getMetadata(int gejahr, String relUrl) throws IOException {
StringBuffer json = new StringBuffer();
URL myurl = new URL(urlBase + relUrl.replaceAll("PARAMGEJAHR", gejahr + ""));
HttpURLConnection urlConnection = (HttpURLConnection) myurl.openConnection();
urlConnection.setDoOutput(true);
urlConnection.setRequestMethod("GET");
urlConnection.setRequestProperty("User-Agent", "Java client");
urlConnection.setRequestProperty("charset", "utf-8");
urlConnection.setRequestProperty("Accept", "application/json");
// httpcon.setRequestProperty("Content-Length", "0");
urlConnection.setUseCaches(false);
if (isTokenNeeded) {
urlConnection.setRequestProperty("Authorization", "Bearer " + getToken());
}
if (urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {
BufferedReader br = new BufferedReader(new InputStreamReader(urlConnection.getInputStream()));
String line;
while ((line = br.readLine()) != null) {
json.append(line);
}
} else {
throw new IOException("Fehler beim Lesen von Metadaten " + urlConnection.getResponseMessage() + "Status Code " + urlConnection.getResponseCode());
}
return json.toString();
}
protected String getToken() {
String token = null;
try {
token = tokenrequester.getToken();
//logger.finest("Token: "+token);
} catch (IOException e) {
System.out.println("Fehler bei der Tokenermittlung");
e.printStackTrace();
System.exit(1);
}
return token;
}
private void prepareDbAndPreparedStatement(String dbpropfile) throws Exception {
logger.info("Vorbereitung der Datenbankverbindung");
SxConnection myConnection = new SxConnection();
myConnection.setPropfile(dbpropfile);
con = myConnection.getConnection();
con.setAutoCommit(false);
stmt = con.createStatement();
initTokenRequester(stmt);
pst = con.prepareStatement("insert into gxstage_dms_metadata (gejahr, belegnummer,id_jahr_belegnr,filename,mimetype,docid,art) values (?,?,?,?,?,?,?)");
}
private void initTokenRequester(Statement st) throws SQLException, IOException {
ResultSet rs = st.executeQuery("select content from sx_repository where id='DVELOP_ARCHIV1_TOKENURL' and aktiv=1 and today() between gueltig_seit and gueltig_bis");
String input = null;
while (rs.next()) {
input = rs.getString("content");
}
if (input == null || input.trim().length() == 0) {
throw new IllegalStateException("Keine aktive DVELOP_ARCHIV1_TOKENURL im Repository gefunden");
}
tokenrequester = new BasicAuthTokenRequester(input);
logger.fine("Tokenermittler vorbereitet ");
}
private void finishWorkinDb() throws SQLException {
stmt.close();
pst.close();
con.close();
}
private String parse(int gejahr, String json) throws JsonParseException, IOException, SQLException {
JsonFactory jfactory = new JsonFactory();
JsonParser jParser = jfactory.createParser(json);
DvelopDocumentMetadata d = new DvelopDocumentMetadata();
d.setGejahr(gejahr);
String nextPage = null;
while (jParser.nextToken() != JsonToken.END_OBJECT) {
String fieldname = jParser.getCurrentName();
logger.finest(" Verarbeite JSON Fieldname " + fieldname);
if ("items".equals(fieldname)) {
JsonToken tok = jParser.nextToken();
while (tok != JsonToken.END_ARRAY) {
if ("sourceProperties".equals(jParser.getCurrentName())) {
//logger.finest(" analysiere sourceProperties");
tok = jParser.nextToken();
String value = "";
String key = "";
while (tok != JsonToken.END_ARRAY) {
if ("key".equals(jParser.currentName())) {
jParser.nextToken();
key = jParser.getText();
jParser.nextToken();
if ("value".equals(jParser.currentName())) {
jParser.nextToken();
value = jParser.getText();
}
}
if ("docid".equals(key) && d.getDocid() == null) {
d.setDocid(value);
logger.fine(" DocID:" + d.getDocid());
}
if ("belnr".equals(key) && d.getBelegnummer() == null) {
d.setBelegnummer(value);
logger.fine(" Belegnr " + d.getBelegnummer());
}
if ("mimetype".equals(key) && d.getMimetyp() == null) {
d.setMimetyp(value);
logger.fine(" MimeType:" + d.getMimetyp());
}
if ("filename".equals(key) && d.getFilename() == null) {
d.setFilename(value);
logger.fine(" Filename " + d.getFilename());
}
if ("docart".equals(key) && d.getArt() == null) {
d.setArt(value);
logger.fine(" Art " + d.getArt());
}
if (d.isValid()) {
counter++;
logger.info(" Speichere Eintrag " + counter);
insertIntoDb(d);
d = new DvelopDocumentMetadata();
d.setGejahr(gejahr);
key = null;
value = null;
//sourceCategories überspringen
}
tok = jParser.nextToken();
}
}
tok = jParser.nextToken();
if ("sourceCategories".equals(jParser.getCurrentName())) {
jParser.skipChildren();
tok = jParser.nextToken();
}
}
}
//nur wenn nextPage noch nicht gesetzt ist
if ("_links".equals(fieldname) && nextPage == null) {
nextPage = parseLinksForNextPage(jParser);
}
}
jParser.close();
return nextPage;
}
protected String parseLinksForNextPage(JsonParser jParser) throws IOException {
String nextPage = null;
JsonToken tok4 = jParser.nextToken();
int i = 0;
while (!("_links".equals(jParser.currentName()) && tok4 == JsonToken.END_OBJECT) && i < 500000) {
if ("next".equals(jParser.currentName())) break;
tok4 = jParser.nextToken();
i++;
}
if (i == 500000) throw new IOException("Endlosschleife entdeckt (pos 6)");
if ("next".equals(jParser.currentName())) {
jParser.nextToken();
jParser.nextToken();
if ("href".equals(jParser.currentName())) {
jParser.nextToken();
nextPage = jParser.getText();
logger.info(" NextPage-Eintrag gefunden " + nextPage);
}
}
//Ans Ende von _links springen
i = 0;
while (!"_links".equals(jParser.currentName()) && i < 500000) {
// System.out.println(jParser.currentName() + " " + tok4);
tok4 = jParser.nextToken();
i++;
}
if (i == 500000) throw new IOException("Endlosschleife entdeckt (pos 7)");
if (tok4 == JsonToken.END_OBJECT) {
jParser.nextToken();
}
;
return nextPage;
}
private void insertIntoDb(DvelopDocumentMetadata d) throws SQLException {
// System.out.println(" einfügen von Datensatz "+counter);
pst.clearParameters();
pst.setInt(1, d.getGejahr());
pst.setString(2, d.getBelegnummer());
pst.setString(3, d.getGejahr() + "-" + d.getBelegnummer());
pst.setString(4, d.getFilename());
pst.setString(5, d.getMimetyp());
pst.setString(6, d.getDocid());
pst.setString(7, d.getArt());
pst.execute();
logger.finest(" Eintrag in Datenbank gespeichert");
}
}

23
src/de/superx/docmanagement/Encryptor.java

@ -0,0 +1,23 @@ @@ -0,0 +1,23 @@
package de.superx.docmanagement;
public class Encryptor {
public static void main(String[] args) {
if (args.length==1)
{
try {
System.out.println("sx_des"+new ArchivePropHandler().encryptStringDES(args[0]));
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
else
{
System.out.println("Usage 1 Parameter: Quellstring");
}
}
}

70
src/de/superx/docmanagement/FSVDocumentRetriever.java

@ -0,0 +1,70 @@ @@ -0,0 +1,70 @@
package de.superx.docmanagement;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import org.apache.commons.io.IOUtils;
public class FSVDocumentRetriever {
private static final long serialVersionUID = 1L;
private String urlbase;
private String token;
public static void main(String[] args) {
System.out.println("Version 1.0 11.9.2023");
if (args.length != 3) {
System.out.println("Parameter URLBase token docID");
} else {
try {
FSVDocumentRetriever fdr = new FSVDocumentRetriever(args[0]);
fdr.setToken(args[1]);
fdr.test(args[2]);
} catch (Exception e) {
e.printStackTrace();
}
}
}
public void setToken(String token)
{
this.token=token;
}
public FSVDocumentRetriever(String urlbase) throws MalformedURLException {
this.urlbase = urlbase;
}
public void test(String id) throws IOException {
String currentURL=urlbase+"?id="+id;
System.out.println("Rufe ab "+currentURL);
URL url=new URL(currentURL);
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
System.out.println(" set Header Authorization Bearer "+token);
urlConnection.setRequestProperty ("Authorization", "Bearer "+token);
byte[] bytes = new byte[0];
// Wirft IO Exception auch bei Fehler in der URL also 401 o.ä.
bytes = IOUtils.toByteArray(urlConnection.getInputStream());
// logger.fine(" " + bytes.length + " Bytes an Daten erhalten");
// logger.info("HTTP-StatusCode: " + urlConnection.getResponseCode());
System.out.println(" " + bytes.length + " Bytes an Daten erhalten");
System.out.println("HTTP-StatusCode: " + urlConnection.getResponseCode());
if (urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {
File outputFile = new File("test.pdf");
if (outputFile.exists()) {
outputFile.delete();
}
FileOutputStream outputStream = new FileOutputStream(outputFile);
outputStream.write(bytes);
outputStream.close();
System.out.println("als test.pdf gespeichert");
} else {
System.out.println("Fehler StatusCode nicht OK");
}
}
}

106
src/de/superx/docmanagement/FSVTokenRequester.java

@ -0,0 +1,106 @@ @@ -0,0 +1,106 @@
package de.superx.docmanagement;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
public class FSVTokenRequester {
private static final long serialVersionUID = 1L;
private String url, username, password;
private static boolean isTestModus = false;
public static void main(String[] args) {
System.out.println("Tokentester Version 2023-09-11");
if (args.length != 3) {
System.out.println("Parameter URL username Passwort");
} else {
isTestModus = true;
FSVTokenRequester FSVtr = new FSVTokenRequester(args[0], args[1], args[2]);
String token;
try {
token = FSVtr.authenticateAndGetToken();
System.out.println("");
System.out.println("Token:");
System.out.println(token);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
FSVTokenRequester(String url, String username, String password) {
this.url = url;
this.username = username;
this.password = password;
}
public String authenticateAndGetToken() throws IOException {
String token = null;
String urlParameters = "u=" + username + "&pw=" + password;
byte[] postData = urlParameters.getBytes(StandardCharsets.UTF_8);
int postDataLength = postData.length;
HttpURLConnection con = null;
try {
URL myurl = new URL(url);
con = (HttpURLConnection) myurl.openConnection();
con.setDoOutput(true);
con.setRequestMethod("POST");
con.setRequestProperty("User-Agent", "Java client");
con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
con.setRequestProperty("charset", "utf-8");
con.setRequestProperty("Content-Length", Integer.toString(postDataLength));
con.setUseCaches(false);
DataOutputStream wr = new DataOutputStream(con.getOutputStream());
wr.write(postData);
StringBuilder content;
BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream()));
String line;
content = new StringBuilder();
while ((line = br.readLine()) != null) {
content.append(line);
content.append(System.lineSeparator());
}
if (isTestModus) {
System.out.println("Serverantwort:");
System.out.println(content.toString());
}
token = extractToken(content.toString());
} catch (Exception e) {
System.out.println("Fehler: " + e.toString());
e.printStackTrace();
throw new IOException("Token konnte nicht ermittelt werden " + e);
} finally {
if (con != null) con.disconnect();
}
return token;
}
private String extractToken(String input) {
String result = "";
if (input != null) {
result = input.replaceAll("<ticket>", "");
result = result.replaceAll("</ticket>", "");
}
return result;
}
}

59
src/de/superx/docmanagement/HISConnektorTest.java

@ -0,0 +1,59 @@ @@ -0,0 +1,59 @@
package de.superx.docmanagement;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
public class HISConnektorTest {
public static void main(String[] args) {
System.out.println("Version 2023-09-11");
if (args.length != 2) {
System.out.println("Parameter URL basic_authentification_string");
} else {
testtoken(args[0],args[1]);
}
}
private static void testtoken(String url,String basicAuthentificationString)
{
HttpURLConnection con = null;
try {
URL myurl = new URL(url);
con = (HttpURLConnection) myurl.openConnection();
con.setDoOutput(true);
con.setRequestMethod("POST");
con.setRequestProperty("User-Agent", "Java client");
con.setRequestProperty("Accept", "application/json");
con.setRequestProperty("charset", "utf-8");
con.setRequestProperty("Content-Length", "0");
con.setUseCaches(false);
con.setRequestProperty("Authorization", "Basic " + basicAuthentificationString);
DataOutputStream wr = new DataOutputStream(con.getOutputStream());
byte[] postData=new byte[0];
wr.write(postData);
BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream()));
String line;
while ((line = br.readLine()) != null) {
System.out.println(line);
}
} catch (Exception e) {
System.out.println("Fehler: " + e.toString());
e.printStackTrace();
} finally {
if (con != null) con.disconnect();
}
}
}

180
src/de/superx/docmanagement/MBSArchiv1.java

@ -0,0 +1,180 @@ @@ -0,0 +1,180 @@
package de.superx.docmanagement;
import java.io.File;
import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.Proxy.Type;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;
import jakarta.servlet.ServletException;
import de.superx.servlet.SuperXManager;
public class MBSArchiv1 extends AbstractDocPresenter {
// Für Testzwecke Standard HTTP-Type für Proxy auf Socks umstellbar, default
// false
static boolean isSocksDebug = false;
static Type proxyType = Proxy.Type.HTTP;
private static final long serialVersionUID = 2L;
private final boolean isDebug = false;
Map<String, String> doctyp_Mimetype;
private MBSArchiv1TokenRequester tokenrequester;
void initSystem() throws ServletException {
if (isSocksDebug) proxyType = Proxy.Type.SOCKS;
//URL zum Abruf der Dokumente
setUrlVorlage(readVorlageFromRepository("MBS_ARCHIV1_URLVORLAGE"));
//Token URL username und passwort
initTokenRequester();
setDirectLinkToDocMWanted(false);
setMenuVorlage(readVorlageFromRepository("MBS_ARCHIV1_MENU_VORLAGE"));
setReadDocumentCountSql("select count(*) from fin_r_dokumente rd , fin_dokumente d where rd.dokumente_join_id = d.dokumente_serial "
+ " and rd.rechnungseingangsbuch_join_id::varchar(200)=?");
//Hier wichtig, die ID im DokumentenManageManageSystem muss doc_id sein, für MenüVorlage daher "as doc_id"
// keine Unterstriche, da übersichtlicher in Freemarker
setReadDocumentListSql("select dokumente_dms_join_id::varchar(200) as doc_id,dokumente_filename as filename , dokumente_zeitstempel as zeitstempel from fin_r_dokumente rd , fin_dokumente d where rd.dokumente_join_id = d.dokumente_serial "
+ " and rd.rechnungseingangsbuch_join_id::varchar(200)=? order by dokumente_serial");
setDeleteOldRightsSql("delete from fin_user_rdrights where gueltig_bis<today()");
setReadIdRightSql("select count(*) from fin_user_rdrights where userinfo_id=?::integer and rechnungseingangsbuch_id::varchar(200)=?");
setReadDocIdRightSql("select count(*) from fin_dokumente D,fin_r_dokumente RD, fin_user_rdrights R where userinfo_id=?::integer "
+ "and D.dokumente_serial=RD.dokumente_join_id and RD.rechnungseingangsbuch_join_id=R.rechnungseingangsbuch_id "
+ "and D.dokumente_dms_join_id::varchar(200)=?");
setReadDocIdSql("select dokumente_dms_join_id::varchar(200) from fin_r_dokumente rd , fin_dokumente d where rd.dokumente_join_id = d.dokumente_serial "
+ " and rd.rechnungseingangsbuch_join_id::varchar(200)=?");
setReadMainDocIdSql("'not implemented' --select distinct doc_id from gxstage_ufr_docmanagement where maindoc=1 and vim=? and anzeige_relevant=1");
// default=false setDocMenuAlwaysWanted(true);
initMimeTypes();
initProxy();
}
void initTokenRequester() throws ServletException {
ArchivePropHandler ph = new ArchivePropHandler();
String tokenvorlage = readVorlageFromRepository("MBS_ARCHIV1_TOKENURL");
if (tokenvorlage.equals("docman_mbsarchive.properties")) {
try {
logger.info("Lese Tokeninformationen aus Datei "+SuperXManager.getWEB_INFPfad() + File.separator + "docman_mbsarchive.properties");
tokenvorlage = ph.getUrlVorlage(SuperXManager.getWEB_INFPfad() + File.separator + "docman_mbsarchive.properties");
} catch (IOException e) {
e.printStackTrace();
throw new ServletException("Fehler bei Lesen von Properties-Datei " + e);
}
}
StringTokenizer st = new StringTokenizer(tokenvorlage, "|");
String tokenURL = null, tokenUsername = null, tokenPassword = null;
int i = 1;
while (st.hasMoreTokens()) {
String val = st.nextToken();
if (i == 1) tokenURL = val;
if (i == 2) tokenUsername = val;
if (i == 3) tokenPassword = val;
i++;
}
if (tokenURL == null || tokenUsername == null || tokenPassword == null) {
throw new ServletException("Fehler beim Initialisieren der Tokenvorlage, URL|Username|Password bzw. Properties-Datei benötigt");
}
if (tokenPassword.startsWith("sx_des")) {
try {
if (isDebug)
{
logger.info("Verschluesseltes Passwort "+tokenPassword);
}
tokenPassword = ph.decryptStringDES(tokenPassword.substring(6));
if (isDebug)
{
logger.info("Entchluesseltes Passwort "+tokenPassword);
}
} catch (Exception e) {
throw new ServletException("Fehler beim Initialisieren der Tokenvorlage, Password nicht verarbeitet " + e);
}
} else {
throw new IllegalStateException("Passwort nicht verschluesselt");
}
tokenrequester = new MBSArchiv1TokenRequester(tokenURL, tokenUsername, tokenPassword);
}
void initProxy() {
String[] params = getUrlVorlage().split("\\|");
if (params.length > 5) {
logger.info("Intialisierung mit Proxy für das DocManagement");
int port = 8080;
String host = params[5];
if (params.length > 6 && params[6] != null) {
try {
port = Integer.parseInt(params[6]);
} catch (NumberFormatException e) {
String msg = "Konnte Portnummer für Proxy nicht in Integer umwandeln: " + params[6];
logger.severe(msg);
throw new IllegalStateException(msg);
}
}
logger.info(" ProxyHost: " + host + " Port: " + port);
setProxy(new Proxy(proxyType, new InetSocketAddress(host, port)));
}
}
void initMimeTypes() {
// Hier erst initialisieren wegen komplexem Ablauf von Kontruktoren und
// initSystem
if (doctyp_Mimetype == null) doctyp_Mimetype = new HashMap<String, String>();
doctyp_Mimetype.clear();
doctyp_Mimetype.putAll(readMapFromDB("SELECT lower(endung),mimetype FROM fin_dms_mimetypes", null));
logger.fine(" Mimetype Zuordnungen gefunden:" + doctyp_Mimetype);
}
public MBSArchiv1(String sys) throws ServletException {
super(sys, null);
}
/**
*
*
* @param doc_id - Hier eine docId!
* @return
* @throws Exception
*/
public void updateDocLink(DocPresentationResult result, String doc_id) throws Exception {
result.setDocManagementUrl(new URL(getUrlVorlage() + "?id=" + doc_id));
String filename = readStringFromDB("select dokumente_filename from fin_dokumente where dokumente_dms_join_id::varchar(200)=?", doc_id);
result.setDesiredFilename(filename);
String mt = "";
if (filename.indexOf(".") > -1) {
String endung = filename.substring(filename.lastIndexOf(".") + 1, filename.length()).toLowerCase();
if (doctyp_Mimetype.containsKey(endung)) {
mt = doctyp_Mimetype.get(endung);
}
}
logger.fine(" Ermittelte minetype: " + mt + "");
if (!mt.contentEquals("")) result.setMimetype(mt);
}
protected void setHeaderAuthorisation(HttpURLConnection urlConnection) throws IOException {
String token = tokenrequester.getToken();
logger.info(" set Header Authorization Bearer " + token);
urlConnection.setRequestProperty("Authorization", "Bearer " + token);
}
}

89
src/de/superx/docmanagement/MBSArchiv1TokenRequester.java

@ -0,0 +1,89 @@ @@ -0,0 +1,89 @@
package de.superx.docmanagement;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
public class MBSArchiv1TokenRequester {
private String tokenURL,tokenUsername,tokenPassword;
private final java.util.logging.Logger logger = java.util.logging.Logger.getLogger("docman");
private final boolean isDebug=false;
public MBSArchiv1TokenRequester(String tokenURL,String tokenUsername,String tokenPassword)
{
this.tokenURL=tokenURL;
this.tokenUsername=tokenUsername;
this.tokenPassword=tokenPassword;
}
public String getToken() throws IOException {
String token = null;
String urlParameters = "u=" + tokenUsername + "&pw=" + tokenPassword;
if (isDebug)
{
logger.info("Tokenermittlung parameter "+urlParameters);
}
byte[] postData = urlParameters.getBytes(StandardCharsets.UTF_8);
int postDataLength = postData.length;
HttpURLConnection con = null;
try {
URL myurl = new URL(tokenURL);
con = (HttpURLConnection) myurl.openConnection();
con.setDoOutput(true);
con.setRequestMethod("POST");
con.setRequestProperty("User-Agent", "Java client");
con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
con.setRequestProperty("charset", "utf-8");
con.setRequestProperty("Content-Length", Integer.toString(postDataLength));
con.setUseCaches(false);
DataOutputStream wr = new DataOutputStream(con.getOutputStream());
wr.write(postData);
StringBuilder content;
BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream()));
String line;
content = new StringBuilder();
while ((line = br.readLine()) != null) {
content.append(line);
content.append(System.lineSeparator());
}
if (isDebug)
{
logger.info("Server lieferte als Token-Response: "+content);
}
token = extractToken(content.toString());
if (isDebug)
{
logger.info("extrahiertes Token: "+token);
}
} catch (Exception e) {
System.out.println("Fehler: " + e.toString());
e.printStackTrace();
throw new IOException("Token konnte nicht ermittelt werden " + e);
} finally {
if (con != null) con.disconnect();
}
return token;
}
private String extractToken(String input) {
String result = "";
if (input != null) {
result = input.replaceAll("<ticket>", "");
result = result.replaceAll("</ticket>", "");
result = result.replaceAll("\n", "");
result = result.replaceAll("\r", "");
}
return result;
}
}

67
src/de/superx/docmanagement/MBSBusinessTransactionArchiv.java

@ -0,0 +1,67 @@ @@ -0,0 +1,67 @@
package de.superx.docmanagement;
import java.net.Proxy;
import java.net.URL;
import jakarta.servlet.ServletException;
public class MBSBusinessTransactionArchiv extends MBSArchiv1 {
public MBSBusinessTransactionArchiv(String sys) throws ServletException {
super(sys);
}
void initSystem() throws ServletException {
if (isSocksDebug) proxyType = Proxy.Type.SOCKS;
//URL zum Abruf der Dokumente
setUrlVorlage(readVorlageFromRepository("MBS_ARCHIV1_URLVORLAGE"));
//Token URL username und passwort
initTokenRequester();
setDirectLinkToDocMWanted(false);
setMenuVorlage(readVorlageFromRepository("MBS_ARCHIV1_MENU_VORLAGE"));
setReadDocumentCountSql("select count(*) from fin_dms_ext where ref_business_transaction::varchar(200)=?");
//Hier wichtig, die ID im DokumentenManageManageSystem muss doc_id sein, für MenüVorlage daher "as doc_id"
// keine Unterstriche, da übersichtlicher in Freemarker
setReadDocumentListSql("select doc_id,filename from fin_dms_ext "
+ " where ref_business_transaction::varchar(200)=? order by 1");
setDeleteOldRightsSql("delete from fin_user_rdrights where gueltig_bis<today()");
setReadIdRightSql("select count(*) from fin_user_rdrights where userinfo_id=?::integer and ref_business_transaction::varchar(200)=?");
setReadDocIdRightSql("select count(*) from fin_dms_ext D, fin_user_rdrights R where userinfo_id=?::integer "
+ "D.ref_business_transaction=R.ref_business_transaction "
+ "and D.ref_business_transaction::varchar(200)=?");
setReadDocIdSql("select doc_id::varchar(200) from fin_dms_ext where ref_business_transaction::varchar(200)=?");
setReadMainDocIdSql("'not implemented' --select distinct doc_id from gxstage_ufr_docmanagement where maindoc=1 and vim=? and anzeige_relevant=1");
// default=false setDocMenuAlwaysWanted(true);
initMimeTypes();
initProxy();
}
/**
*
*
* @param doc_id - Hier eine docId!
* @return
* @throws Exception
*/
public void updateDocLink(DocPresentationResult result, String doc_id) throws Exception {
result.setDocManagementUrl(new URL(getUrlVorlage() + "?id=" + doc_id));
String filename = readStringFromDB("select filename from fin_dms_ext where doc_id::varchar(200)=?", doc_id);
result.setDesiredFilename(filename);
String mt = "";
if (filename.indexOf(".") > -1) {
String endung = filename.substring(filename.lastIndexOf(".") + 1, filename.length()).toLowerCase();
if (doctyp_Mimetype.containsKey(endung)) {
mt = doctyp_Mimetype.get(endung);
}
}
logger.fine(" Ermittelte minetype: " + mt + "");
if (!mt.contentEquals("")) result.setMimetype(mt);
}
}

84
src/de/superx/docmanagement/PCKSSigner.java.bak

@ -0,0 +1,84 @@ @@ -0,0 +1,84 @@
package de.superx.docmanagement;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.math.BigInteger;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.Signature;
import java.security.cert.X509Certificate;
import java.util.Enumeration;
import sun.security.pkcs.ContentInfo;
import sun.security.pkcs.PKCS7;
import sun.security.pkcs.SignerInfo;
import sun.security.util.DerOutputStream;
import sun.security.util.DerValue;
import sun.security.x509.AlgorithmId;
import sun.security.x509.X500Name;
public class PCKSSigner {
static final String STORENAME = "/home/superx/git/Memtext-Interna/Projekte/freiburg_uni/muster/SAP/documentenManagementAnbindung/tls/sapdokserver.jks";
static final String STOREPASS = "$Anfang202020";
public static void main(String[] args) throws Exception{
//First load the keystore object by providing the p12 file path
KeyStore clientStore = KeyStore.getInstance("PKCS12");
//replace testPass with the p12 password/pin
clientStore.load(new FileInputStream(STORENAME), STOREPASS.toCharArray());
String aliaz = "sapdokserver";
//optional find first KeyEntry
// Enumeration<String> aliases = clientStore.aliases();
// String aliaz = "";
// while(aliases.hasMoreElements()){
// aliaz = aliases.nextElement();
// System.out.println(aliaz);
// if(clientStore.isKeyEntry(aliaz)){
// break;
// }
// }
X509Certificate c = (X509Certificate)clientStore.getCertificate(aliaz);
//Data to sign
byte[] dataToSign = "kjasdflkjasdflkjasdflkjasdlkfjasöldkfj".getBytes();
//compute signature:
Signature signature = Signature.getInstance("Sha1WithRSA");
signature.initSign((PrivateKey)clientStore.getKey(aliaz, STOREPASS.toCharArray()));
signature.update(dataToSign);
byte[] signedData = signature.sign();
//load X500Name
X500Name xName = X500Name.asX500Name(c.getSubjectX500Principal());
//load serial number
BigInteger serial = c.getSerialNumber();
//laod digest algorithm
AlgorithmId digestAlgorithmId = new AlgorithmId(AlgorithmId.MD5_oid);
//load signing algorithm
//AlgorithmId signAlgorithmId = new AlgorithmId(AlgorithmId.RSAEncryption_oid);
AlgorithmId signAlgorithmId = new AlgorithmId(AlgorithmId.MD5_oid);
//Create SignerInfo:
SignerInfo sInfo = new SignerInfo(xName, serial, digestAlgorithmId, signAlgorithmId, signedData);
//Create ContentInfo:
ContentInfo cInfo = new ContentInfo(ContentInfo.DIGESTED_DATA_OID, new DerValue(DerValue.tag_OctetString, dataToSign));
// ContentInfo cInfo = new ContentInfo(ContentInfo.DATA_OID, new DerValue(DerValue.tag_OctetString, dataToSign));
//Create PKCS7 Signed data
PKCS7 p7 = new PKCS7(new AlgorithmId[] { digestAlgorithmId }, cInfo,
new java.security.cert.X509Certificate[] { c },
new SignerInfo[] { sInfo });
//Write PKCS7 to bYteArray
ByteArrayOutputStream bOut = new DerOutputStream();
p7.encodeSignedData(bOut);
byte[] encodedPKCS7 = bOut.toByteArray();
System.out.println(new String(encodedPKCS7));
}
}

141
src/de/superx/docmanagement/SAPArchiv1.java

@ -0,0 +1,141 @@ @@ -0,0 +1,141 @@
package de.superx.docmanagement;
import java.io.File;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.Proxy.Type;
import java.util.HashMap;
import java.util.Map;
import jakarta.servlet.ServletException;
import de.superx.servlet.SuperXManager;
public class SAPArchiv1 extends AbstractDocPresenter {
// Für Testzwecke Standard HTTP-Type für Proxy auf Socks umstellbar, default
// false
private static boolean isSocksDebug = false;
private static Type proxyType = Proxy.Type.HTTP;
private static final long serialVersionUID = 1L;
private UniFrSecKeyGenerator secKeyGenerator;
private Map<String, String> doctyp_Mimetype;
void initSystem() throws ServletException {
if (isSocksDebug)
proxyType = Proxy.Type.SOCKS;
setUrlVorlage(readVorlageFromRepository("SAP_ARCHIV1_URLVORLAGE"));
setDirectLinkToDocMWanted(false);
// setUrlVorlage(
// "https://saphost-qot.bwhsrw.de:8090/archive?|pVersion=0046|authId=superx-test|expiration=10m"); + ggfs. Proxy und Port
setMenuVorlage(readVorlageFromRepository("SAP_ARCHIV1_MENU_VORLAGE"));
setReadDocumentCountSql("select count(*) from gxstage_ufr_docmanagement where vim=? and anzeige_relevant=1");
setReadDocumentListSql(
"select doc_id, CASE WHEN a.label IS NOT NULL THEN a.label ELSE d.dokumentenart END as dokumentenart,"
+ "dokumententyp,ablagedatum,loeschdatum,"
+ "CASE WHEN a.sort_nr IS NOT NULL THEN a.sort_nr ELSE 99 END as sort "
+ "from gxstage_ufr_docmanagement d "
+ "left join gxstage_ufr_dokart a on (d.dokumentenart = a.dokumentenart) " + "where vim=? "
+" and anzeige_relevant=1 "
+ " order by sort asc;");
setDeleteOldRightsSql("delete from gxstage_ufr_user_vimrights where gueltig_bis<today()");
setReadIdRightSql("select count(*) from gxstage_ufr_user_vimrights where userinfo_id=?::integer and vim=?");
setReadDocIdRightSql(
"select count(*) from gxstage_ufr_docmanagement D, gxstage_ufr_user_vimrights R where userinfo_id=?::integer and D.vim=R.vim and D.doc_id=? and D.anzeige_relevant=1");
setReadDocIdSql("select doc_id from gxstage_ufr_docmanagement where vim=? and anzeige_relevant=1");
setReadMainDocIdSql("select distinct doc_id from gxstage_ufr_docmanagement where maindoc=1 and vim=? and anzeige_relevant=1");
setDocMenuAlwaysWanted(true);
initMimeTypes();
initSecKeyGenerator();
initProxy();
}
private void initProxy() {
String[] params = getUrlVorlage().split("\\|");
if (params.length > 5) {
logger.info("Intialisierung mit Proxy für das DocManagement");
int port = 8080;
String host = params[5];
if (params.length > 6 && params[6] != null) {
try {
port = Integer.parseInt(params[6]);
} catch (NumberFormatException e) {
String msg = "Konnte Portnummer für Proxy nicht in Integer umwandeln: " + params[6];
logger.severe(msg);
throw new IllegalStateException(msg);
}
}
logger.info(" ProxyHost: " + host + " Port: " + port);
setProxy(new Proxy(proxyType, new InetSocketAddress(host, port)));
}
}
private void initMimeTypes() {
// Hier erst initialisieren wegen komplexem Ablauf von Kontruktoren und
// initSystem
if (doctyp_Mimetype == null)
doctyp_Mimetype = new HashMap<String, String>();
doctyp_Mimetype.clear();
doctyp_Mimetype.putAll(
readMapFromDB("SELECT lower(dokumententyp),mimetype FROM gxstage_ufr_dokumententyp_mimetype", null));
logger.fine(" Mimetype Zuordnungen gefunden:" + doctyp_Mimetype);
}
public SAPArchiv1(String sys) throws ServletException {
super(sys, null);
}
private void initSecKeyGenerator() throws ServletException {
try {
String privateKeyFile = SuperXManager.getWEB_INFPfad() + File.separator + "conf" + File.separator
+ "superx.p12";
logger.info("Initing secKeyGenerator with " + privateKeyFile);
secKeyGenerator = new UniFrSecKeyGenerator(privateKeyFile, getUrlVorlage());
} catch (Exception e) {
logger.severe("Fehler bei Intialisieren von SecKeyGenerator " + getExceptionStackTrace(e));
throw new ServletException("Fehler bei Intialisieren von SecKeyGenerator " + e.toString());
}
}
/**
*
*
* @param doc_id - Hier eine docId!
* @return
* @throws Exception
*/
public void updateDocLink(DocPresentationResult result, String doc_id) throws Exception {
String loeschdatumUberschritten = readStringFromDB(
"select 'ja' from gxstage_ufr_docmanagement where doc_id=? and loeschdatum<today() union select 'nein' from gxstage_ufr_docmanagement where doc_id=? and (loeschdatum is null or loeschdatum>=today())",
doc_id, doc_id);
if ("ja".contentEquals(loeschdatumUberschritten)) {
result.setMessage("Es kann kein Dokument geladen werden, da das L&ouml;schdatum f&uuml;r die DocID " + doc_id
+ " &uuml;berschritten ist");
} else {
String contentRep = readStringFromDB("select contentRep from gxstage_ufr_docmanagement where doc_id=?",
doc_id);
result.setDocManagementUrl(secKeyGenerator.getUrl(doc_id, contentRep));
String doctyp = readStringFromDB("select dokumententyp from gxstage_ufr_docmanagement where doc_id=?",
doc_id);
result.setDesiredFilename(doc_id + "." + doctyp.toLowerCase());
String mt = doctyp_Mimetype.get(doctyp.toLowerCase());
logger.fine(" Ermittelter Dokumententyp " + doctyp + " (minetype: " + mt + ")");
result.setMimetype(mt);
}
}
/**
* Bei SAP-Achriv keine HeaderAuthorisation nötig, wird über secKey gemacht
*/
protected void setHeaderAuthorisation(HttpURLConnection urlConnection) {
}
}

87
src/de/superx/docmanagement/SignerTest.java.bak

@ -0,0 +1,87 @@ @@ -0,0 +1,87 @@
package de.superx.docmanagement;
import java.io.File;
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.security.KeyFactory;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.interfaces.RSAPrivateKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;
public class SignerTest {
public static void main(String[] args) throws Exception {
// KeyPair keyPair = getTestKeyPair();
RSAPrivateKey privateKey=readPrivateKey2("/home/superx/git/Memtext-Interna/Projekte/freiburg_uni/muster/SAP/documentenManagementAnbindung/tls/private.der");
byte[] data = "test".getBytes("UTF8");
Signature sig = Signature.getInstance("SHA1WithRSA");
sig.initSign(privateKey);
sig.update(data);
byte[] signatureBytes = sig.sign();
System.out.println("Signature:" +Base64.getEncoder().encodeToString(signatureBytes));
// sig.initVerify(keyPair.getPublic());
// sig.update(data);
// System.out.println(sig.verify(signatureBytes));
}
public static PrivateKey getPrivateKey(String filename)
throws Exception {
byte[] keyBytes = Files.readAllBytes(Paths.get(filename));
PKCS8EncodedKeySpec spec =
new PKCS8EncodedKeySpec(keyBytes);
KeyFactory kf = KeyFactory.getInstance("RSA");
return kf.generatePrivate(spec);
}
public static RSAPrivateKey readPrivateKey2(String filename) throws Exception {
File file=new File(filename);
String key = new String(Files.readAllBytes(file.toPath()), Charset.defaultCharset());
String privateKeyPEM = key
.replace("-----BEGIN PRIVATE KEY-----", "")
.replaceAll(System.lineSeparator(), "")
.replace("-----END PRIVATE KEY-----", "");
byte[] encoded = Base64.getDecoder().decode(privateKeyPEM);
KeyFactory keyFactory = KeyFactory.getInstance("RSA");
PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(encoded);
return (RSAPrivateKey) keyFactory.generatePrivate(keySpec);
}
public static PublicKey getPublicKey(String filename)
throws Exception {
byte[] keyBytes = Files.readAllBytes(Paths.get(filename));
X509EncodedKeySpec spec =
new X509EncodedKeySpec(keyBytes);
KeyFactory kf = KeyFactory.getInstance("RSA");
return kf.generatePublic(spec);
}
private static KeyPair getTestKeyPair() throws NoSuchAlgorithmException {
KeyPairGenerator kpg = KeyPairGenerator.getInstance("RSA");
kpg.initialize(1024);
return kpg.genKeyPair();
}
}

226
src/de/superx/docmanagement/UniFrSecKeyGenerator.java

@ -0,0 +1,226 @@ @@ -0,0 +1,226 @@
package de.superx.docmanagement;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLEncoder;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.PrivateKey;
import java.security.Security;
import java.security.cert.X509Certificate;
import java.text.SimpleDateFormat;
import java.time.ZoneId;
import java.util.Base64;
import java.util.Date;
import java.util.StringTokenizer;
import java.util.TimeZone;
import org.bouncycastle.cms.CMSException;
import org.bouncycastle.cms.CMSProcessableByteArray;
import org.bouncycastle.cms.CMSSignedData;
import org.bouncycastle.cms.CMSSignedDataGenerator;
import org.bouncycastle.cms.jcajce.JcaSignerInfoGeneratorBuilder;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.OperatorCreationException;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder;
public class UniFrSecKeyGenerator {
private final BouncyCastleProvider BCPROVIDER=new BouncyCastleProvider();
private PrivateKey privateKey;
private X509Certificate certificate;
private String urlstart;
private String pVersion;
private String authId;
private String expiration;
private String compId;
public UniFrSecKeyGenerator(String p12path,String urlVorlage) throws Exception {
initKeystore(p12path);
initGeneralParams(urlVorlage);
}
private void initGeneralParams(String urlVorlage) {
//Erwartet
//"https://saphost-pot.bwhsrw.de/superx/archive|pVersion=0046|authId=superx|expiration=20210801000000");
StringTokenizer st=new StringTokenizer(urlVorlage,"|");
int i=0;
while (st.hasMoreTokens())
{
String param=st.nextToken();
i++;
if (i==1) urlstart=param;
if (i==2) pVersion=param.substring(param.indexOf("=")+1);
if (i==3) authId=param.substring(param.indexOf("=")+1);
if (i==4) compId=param.substring(param.indexOf("=")+1);
if (i==5) expiration=param.substring(param.indexOf("=")+1);
//Param 6 und 7 können noch Proxy und desses Port sein, hier irrelevant
}
if (this.urlstart==null) throw new IllegalStateException("URL Anfang nicht gefunden");
if (this.pVersion==null) throw new IllegalStateException("pVersion nicht gefunden");
if (this.authId==null) throw new IllegalStateException("authId nicht gefunden");
if (this.compId==null) throw new IllegalStateException("compId nicht gefunden - wenn nicht genutzt werden soll compId=false übergeben");
if (this.expiration==null) throw new IllegalStateException("expiration nicht gefunden");
}
private void initKeystore(String p12path) throws Exception
{
final KeyStore ks = KeyStore.getInstance("PKCS12");
try (final InputStream in = new FileInputStream(p12path)) {
final char[] pwd = "sUp3rx!".toCharArray();
ks.load(in, pwd);
final String alias = "1";
privateKey = (PrivateKey) ks.getKey(alias, pwd);
certificate = (X509Certificate) ks.getCertificate(alias);
}
}
public URL getUrl(String docId,String contRep) throws Exception {
// Refactoring möglich, für etwaige Abstimmung mit GISA nah am Beispielcode bleiben
UrlParams params = new UrlParams();
params.command = "get";
params.accessModes = "r";
params.pVersion=pVersion;
params.contRep=contRep;
params.docId=docId;
SecKeyParams secKeyParams = new SecKeyParams();
secKeyParams.authId = authId;
secKeyParams.privateKey = privateKey;
secKeyParams.certificate = certificate;
String query = build(params, secKeyParams);
URL url = new URL(urlstart + query);
return(url);
}
private String build(UrlParams params, SecKeyParams secKeyParams) throws IOException, GeneralSecurityException {
boolean sign = secKeyParams != null;
StringBuilder query = new StringBuilder(1000);
StringBuilder sigData = sign ? new StringBuilder(1000) : null;
query.append(params.command);
addUrlParameter(query, "pVersion", params.pVersion, null);
addUrlParameter(query, "contRep", params.contRep, sigData);
addUrlParameter(query, "docId", params.docId, sigData);
if (compId!=null&&compId.length()>0&&!compId.contentEquals(("false")))
{
// Sonderlocke für create im PUT-Modus: compId mit signieren
boolean needSignCompId = sign && "create".equals(params.command) && "PUT".equals(params.method);
addUrlParameter(query, "compId", compId, needSignCompId ? sigData : null);
}
if (sign) {
addUrlParameter(query, "accessMode", params.accessModes, sigData);
addUrlParameter(query, "authId", secKeyParams.authId, sigData);
addUrlParameter(query, "expiration", getExpiration(secKeyParams), sigData);
byte[] sigBlock = sign(secKeyParams.privateKey, secKeyParams.certificate, sigData.toString().getBytes());
String seckey = Base64.getEncoder().encodeToString(sigBlock);
addUrlParameter(query, "secKey", seckey, null);
}
return query.toString();
}
/**
* Zu Testzwecken festen Zeitpunkt
* @param secKeyParams
* @return
*/
private String getExpiration(SecKeyParams secKeyParams) {
String result;
if (expiration.indexOf("m")>-1) //in Minuten
{
//TODO Datum aktuelle Zeitzone oder UTC?
int minuten=Integer.parseInt(expiration.replaceAll("m", ""));
int expirationSekunden=60*minuten;
Date expires = new Date(System.currentTimeMillis() + expirationSekunden * 1000L);
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
sdf.setTimeZone(TimeZone.getTimeZone(ZoneId.of("Z"))); // UTC
result = sdf.format(expires);
}
else //fester Wert
{
if (expiration.length()!=14) throw new IllegalStateException("Fester Parameter für expiration muss 14stellig sein oder m für Minuten enthalten, ist "+expiration);
result=expiration;
}
return result;
}
private byte[] sign(PrivateKey privateKey, X509Certificate certificate, byte[] dataToSign)
throws GeneralSecurityException, IOException {
try {
String sigAlgName = certificate.getSigAlgName();
CMSSignedDataGenerator generator = new CMSSignedDataGenerator();
//Original Beispielcode
// ContentSigner signer = new JcaContentSignerBuilder(sigAlgName).setProvider("BC").build(privateKey);
//Sicherheitshalber explizit als Objekt setzen,damit nicht Systemweiter Provider BC nötig
ContentSigner signer = new JcaContentSignerBuilder(sigAlgName).setProvider(BCPROVIDER).build(privateKey);
//Original Beispielcode
//JcaDigestCalculatorProviderBuilder cpb = new JcaDigestCalculatorProviderBuilder().setProvider("BC");
//Sicherheitshalber explizit als Objekt setzen,damit nicht Systemweiter Provider BC nötig
JcaDigestCalculatorProviderBuilder cpb = new JcaDigestCalculatorProviderBuilder().setProvider(BCPROVIDER);
JcaSignerInfoGeneratorBuilder sigb = new JcaSignerInfoGeneratorBuilder(cpb.build());
generator.addSignerInfoGenerator(sigb.build(signer, certificate));
CMSProcessableByteArray content = new CMSProcessableByteArray(dataToSign);
CMSSignedData signedData = generator.generate(content, false);
return signedData.getEncoded();
} catch (CMSException | OperatorCreationException | Error ex) {
throw new GeneralSecurityException(ex);
}
}
private void addUrlParameter(StringBuilder query, String key, String value, StringBuilder sigData)
throws UnsupportedEncodingException {
if (value != null && !value.isEmpty()) {
query.append('&').append(key).append('=');
String encoded = URLEncoder.encode(value, "UTF-8");
int i = encoded.indexOf('+');
if (i < 0) {
query.append(encoded);
} else {
int pos = query.length();
query.append(encoded, 0, i).append("%20");
++i;
for (int len = encoded.length(); i < len; ++i) {
char ch = encoded.charAt(i);
if (ch == '+') {
query.append("%20");
} else {
query.append(ch);
}
}
encoded = query.substring(pos);
}
if (sigData != null) {
sigData.append(encoded);
}
}
}
private static class UrlParams {
public String method; // GET, POST, PUT
public String command; // get, docGet, info, create etc.
public String contRep;
public String docId;
public String pVersion;
public String compId = "data";
public String accessModes; // r,c,u,d (any combination of)
}
private static class SecKeyParams {
public String authId;
public PrivateKey privateKey;
public X509Certificate certificate;
}
}

224
src/de/superx/docmanagement/UniFrSecKeyGeneratorTest.java

@ -0,0 +1,224 @@ @@ -0,0 +1,224 @@
package de.superx.docmanagement;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.net.URLEncoder;
import java.security.GeneralSecurityException;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.Security;
import java.security.cert.X509Certificate;
import java.text.SimpleDateFormat;
import java.time.ZoneId;
import java.util.Base64;
import java.util.Date;
import java.util.TimeZone;
import org.bouncycastle.cms.CMSException;
import org.bouncycastle.cms.CMSProcessableByteArray;
import org.bouncycastle.cms.CMSSignedData;
import org.bouncycastle.cms.CMSSignedDataGenerator;
import org.bouncycastle.cms.jcajce.JcaSignerInfoGeneratorBuilder;
import org.bouncycastle.jce.provider.BouncyCastleProvider;
import org.bouncycastle.operator.ContentSigner;
import org.bouncycastle.operator.OperatorCreationException;
import org.bouncycastle.operator.jcajce.JcaContentSignerBuilder;
import org.bouncycastle.operator.jcajce.JcaDigestCalculatorProviderBuilder;
public class UniFrSecKeyGeneratorTest {
private String p12path="bi-superx.p12";
private static String expirationSecs;
private static final String[] IDS= {"005056B5CBB01EEBA1C4963349F29CBF", "005056B5CBB01EEBA1C4983423EC7CD9",
"005056B5CBB01EEBA1C4983423EDDCD9", "005056B5CBB01EEBA1C4983423EF3CD9",
"005056B5CBB01EDBA1C8C4E5C2318381", "005056B5CBB01EEBA1B6526415B14239",
"005056B5CBB01EEBA1B653DA414E823D", "005056B5CBB01EEBA1B653DA414FE23D",
"005056B5CBB01EDBA1B25629173A1AF1", "005056B5CBB01EDBA1B257EB1AFEDAF4",
"005056B5CBB01EDBA1B2580A57DB1AF4", "005056B5CBB01EDBA1B2580A57DB3AF4",
"005056B5CBB01EEBA1E007B8D56C0DBE", "005056B5CBB01EDBA0E7A3151C561357",
"005056B5CBB01EEBA1E7B756E82D5B90"
};
public static void main(String a[]) {
if (a.length!=5)
{
System.out.println(" Argumente: URL-Anfang (https://saphost-qot.bwhsrw.de:8090/archive?) docId contentRep auth-id sekunden bis expiration (3600=1h)");
System.out.println(" Beispiel");
System.out.println(" https://saphost-qot.bwhsrw.de:8090/archive? 005056B5CBB01EEBA1C4963349F29CBF QM superx-test 3600");
System.exit(-1);
}
String urlstart=a[0];
String docId=a[1];
String contentRep=a[2];
String authId=a[3];
expirationSecs=a[4];
try {
UniFrSecKeyGeneratorTest test = new UniFrSecKeyGeneratorTest();
URL url=test.getUrl(urlstart,"0046",docId ,contentRep,authId);
System.out.println(url);
/* for (int i=0;i<IDS.length;i++)
{
System.out.println(test.getUrl("https://saphost-qot.bwhsrw.de:8090/archive?","0046",IDS[i] ,"QM","superx-test"));
}*/
} catch (Exception e) {
e.printStackTrace();
}
}
public UniFrSecKeyGeneratorTest() {
try {
//TODO setPath SuperXManager.getWEB_INFPfad()+File.separator+"conf"+File.separator+"superx.p12"
//TODO prüfen, ob ohne explizites setzen von BouncyCastleProvider geht.
Security.addProvider(new BouncyCastleProvider());
} catch (Throwable ex) {
ex.printStackTrace(System.err);
}
}
//Params in DB 'urlstart=https://saphost-pot.bwhsrw.de/superx/archive|get=null|pVersion=0046|contRep=<<CONTENTREP>>|docId=<<DOCID>>|compId=data|accessMode=r|authId=superx|expiration=20210801000000',
public URL getUrl(String urlstart,String pVersion,String docId,String contRep,String authId) throws FileNotFoundException, IOException, GeneralSecurityException {
UrlParams params = new UrlParams();
params.command = "get";
params.accessModes = "r";
params.pVersion=pVersion;
params.contRep=contRep;
params.docId=docId;
SecKeyParams secKeyParams = new SecKeyParams();
secKeyParams.authId = authId;
final KeyStore ks = KeyStore.getInstance("PKCS12");
try (final InputStream in = new FileInputStream(p12path)) {
final char[] pwd = "sUp3rx!".toCharArray();
ks.load(in, pwd);
final String alias = "1";
secKeyParams.privateKey = (PrivateKey) ks.getKey(alias, pwd);
secKeyParams.certificate = (X509Certificate) ks.getCertificate(alias);
}
catch(Exception e)
{
System.out.println("Konnte bisuperx.p12 nicht einlesen");
System.out.println(e);
System.exit(-1);
}
String query = build(params, secKeyParams);
URL url = new URL(urlstart + query);
// todo SSL/TLS setup etc.
return(url);
}
private String build(UrlParams params, SecKeyParams secKeyParams) throws IOException, GeneralSecurityException {
boolean sign = secKeyParams != null;
StringBuilder query = new StringBuilder(1000);
StringBuilder sigData = sign ? new StringBuilder(1000) : null;
query.append(params.command);
addUrlParameter(query, "pVersion", params.pVersion, null);
addUrlParameter(query, "contRep", params.contRep, sigData);
addUrlParameter(query, "docId", params.docId, sigData);
// Sonderlocke für create im PUT-Modus: compId mit signieren
boolean needSignCompId = sign && "create".equals(params.command) && "PUT".equals(params.method);
addUrlParameter(query, "compId", params.compId, needSignCompId ? sigData : null);
if (sign) {
addUrlParameter(query, "accessMode", params.accessModes, sigData);
addUrlParameter(query, "authId", secKeyParams.authId, sigData);
addUrlParameter(query, "expiration", getExpiration(secKeyParams), sigData);
byte[] sigBlock = sign(secKeyParams.privateKey, secKeyParams.certificate, sigData.toString().getBytes());
String seckey = Base64.getEncoder().encodeToString(sigBlock);
addUrlParameter(query, "secKey", seckey, null);
}
return query.toString();
}
/**
* Zu Testzwecken festen Zeitpunkt
* @param secKeyParams
* @return
*/
private String getExpiration(SecKeyParams secKeyParams) {
//TODO Datum aktuelle Zeitzone oder UTC?
int secs=secKeyParams.expirationSeconds;
secs=Integer.parseInt(expirationSecs);
Date expires = new Date(System.currentTimeMillis() + secs * 1000L);
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss");
sdf.setTimeZone(TimeZone.getTimeZone(ZoneId.of("Z"))); // UTC
String expiration = sdf.format(expires);
return expiration;
}
private byte[] sign(PrivateKey privateKey, X509Certificate certificate, byte[] dataToSign)
throws GeneralSecurityException, IOException {
try {
String sigAlgName = certificate.getSigAlgName();
CMSSignedDataGenerator generator = new CMSSignedDataGenerator();
ContentSigner signer = new JcaContentSignerBuilder(sigAlgName).setProvider("BC").build(privateKey);
JcaDigestCalculatorProviderBuilder cpb = new JcaDigestCalculatorProviderBuilder().setProvider("BC");
JcaSignerInfoGeneratorBuilder sigb = new JcaSignerInfoGeneratorBuilder(cpb.build());
generator.addSignerInfoGenerator(sigb.build(signer, certificate));
CMSProcessableByteArray content = new CMSProcessableByteArray(dataToSign);
CMSSignedData signedData = generator.generate(content, false);
return signedData.getEncoded();
} catch (CMSException | OperatorCreationException | Error ex) {
throw new GeneralSecurityException(ex);
}
}
private void addUrlParameter(StringBuilder query, String key, String value, StringBuilder sigData)
throws UnsupportedEncodingException {
if (value != null && !value.isEmpty()) {
query.append('&').append(key).append('=');
String encoded = URLEncoder.encode(value, "UTF-8");
int i = encoded.indexOf('+');
if (i < 0) {
query.append(encoded);
} else {
int pos = query.length();
query.append(encoded, 0, i).append("%20");
++i;
for (int len = encoded.length(); i < len; ++i) {
char ch = encoded.charAt(i);
if (ch == '+') {
query.append("%20");
} else {
query.append(ch);
}
}
encoded = query.substring(pos);
}
if (sigData != null) {
sigData.append(encoded);
}
}
}
private static class UrlParams {
public String method; // GET, POST, PUT
public String command; // get, docGet, info, create etc.
public String contRep;
public String docId;
public String pVersion;
public String compId = "data";
public String accessModes; // r,c,u,d (any combination of)
}
private static class SecKeyParams {
public String authId;
public PrivateKey privateKey;
public X509Certificate certificate;
public int expirationSeconds = 3600; // 1h
}
}

BIN
superx/WEB-INF/lib/superx-docmanagement1.4.jar

Binary file not shown.

1
superx/WEB-INF/lib_ext/bc-jar-README.txt

@ -0,0 +1 @@ @@ -0,0 +1 @@
Die jars bcpkix-jdk15on-169.jar bcprov-jdk15on-169.jar bcutil-jdk15on-169.jar sind BouncyCastle Klassen für das Documentenmangementanbindung in Freiburg/Mannheim nötig.

BIN
superx/WEB-INF/lib_ext/bcpkix-jdk15on-169.jar

Binary file not shown.

BIN
superx/WEB-INF/lib_ext/bcprov-jdk15on-169.jar

Binary file not shown.

BIN
superx/WEB-INF/lib_ext/bcutil-jdk15on-169.jar

Binary file not shown.

15
superx/WEB-INF/lib_ext/groovy-LICENSE.txt

@ -0,0 +1,15 @@ @@ -0,0 +1,15 @@
/*
* 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.
*
*/

5
superx/WEB-INF/lib_ext/groovy-NOTICE.txt

@ -0,0 +1,5 @@ @@ -0,0 +1,5 @@
Apache Commons CLI
Copyright 2001-2009 The Apache Software Foundation
This product includes software developed by
The Apache Software Foundation (http://www.apache.org/).

BIN
superx/WEB-INF/lib_ext/groovy-all-2.3.6.jar

Binary file not shown.

BIN
superx/WEB-INF/lib_ext/servlet-api.jar

Binary file not shown.

BIN
superx/WEB-INF/lib_ext/superx5.3.jar

Binary file not shown.
Loading…
Cancel
Save