diff --git a/README.md b/README.md index f1837c0..6013dce 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,24 @@ -# docmanagement +# docman -DMS-Anbindung \ No newline at end of file +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: + + DocMan + de.superx.docmanagement.DocMan + + + DocMan + /servlet/DocMan + + +* 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. \ No newline at end of file diff --git a/build.xml b/build.xml new file mode 100644 index 0000000..4d1c15c --- /dev/null +++ b/build.xml @@ -0,0 +1,103 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/docman_scripte/authentifizierungstest.x b/docman_scripte/authentifizierungstest.x new file mode 100755 index 0000000..04ae6c7 --- /dev/null +++ b/docman_scripte/authentifizierungstest.x @@ -0,0 +1 @@ +java -cp superx-docmanagement1.3.jar de.superx.docmanagement.HISConnektorTest $1 $2 diff --git a/docman_scripte/docman_encryptor.x b/docman_scripte/docman_encryptor.x new file mode 100755 index 0000000..6023d11 --- /dev/null +++ b/docman_scripte/docman_encryptor.x @@ -0,0 +1 @@ +java -cp superx-docmanagement1.3.jar de.superx.docmanagement.Encryptor $1 diff --git a/docman_scripte/docman_propcreator.x b/docman_scripte/docman_propcreator.x new file mode 100755 index 0000000..8dd8ab7 --- /dev/null +++ b/docman_scripte/docman_propcreator.x @@ -0,0 +1 @@ +java -cp superx-docmanagement1.3.jar de.superx.docmanagement.ArchivePropHandler $1 $2 $3 diff --git a/docman_scripte/dvelop-metadata-update.x b/docman_scripte/dvelop-metadata-update.x new file mode 100755 index 0000000..83034fc --- /dev/null +++ b/docman_scripte/dvelop-metadata-update.x @@ -0,0 +1 @@ +java -cp superx-docmanagement1.3.jar:$JDBC_CLASSPATH de.superx.docmanagement.DvelopMetadatenLoader "$@" diff --git a/docman_scripte/dvelopdownloadtest1.x b/docman_scripte/dvelopdownloadtest1.x new file mode 100755 index 0000000..537e87e --- /dev/null +++ b/docman_scripte/dvelopdownloadtest1.x @@ -0,0 +1 @@ +java -cp superx-docmanagement1.3.jar:$JDBC_CLASSPATH de.superx.docmanagement.DvelopDownloadTester $1 $2 diff --git a/docman_scripte/dvelopdownloadtest2.x b/docman_scripte/dvelopdownloadtest2.x new file mode 100755 index 0000000..f3bb186 --- /dev/null +++ b/docman_scripte/dvelopdownloadtest2.x @@ -0,0 +1 @@ +java -cp superx-docmanagement1.3.jar:$JDBC_CLASSPATH de.superx.docmanagement.DvelopDownloadTester2 $1 $2 diff --git a/docman_scripte/superx-docmanagement1.3.jar b/docman_scripte/superx-docmanagement1.3.jar new file mode 100644 index 0000000..8f8d9e4 Binary files /dev/null and b/docman_scripte/superx-docmanagement1.3.jar differ diff --git a/lizenz.txt b/lizenz.txt new file mode 100644 index 0000000..87cbe97 --- /dev/null +++ b/lizenz.txt @@ -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 + + + diff --git a/src/de/superx/docmanagement/AbstractDocPresenter.java b/src/de/superx/docmanagement/AbstractDocPresenter.java new file mode 100644 index 0000000..fc5a5fa --- /dev/null +++ b/src/de/superx/docmanagement/AbstractDocPresenter.java @@ -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 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 readParams(HttpServletRequest request) { + logger.info("DocPresenter ("+sys+"): Lese Parameter aus Request"); + Map params = new HashMap(); + + 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 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 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 params) { + String result; + String id = getId(params); + logger.info("DocPresenter ("+sys+"): Ermittle DokumentenListe für id " + id); + List> doclist = readDocumentList(getId(params)); + try { + for (Map 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ü fü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 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> readDocumentList(String id) { + return readAttribMapsFromDB(readDocumentListSql, id); + } + + String getReadDocIdRightSql() { + return readDocIdRightSql; + } + + void setReadDocIdRightSql(String readDocIdRightSql) { + this.readDocIdRightSql = readDocIdRightSql; + } + + protected String getId(Map params) { + return params.get("id"); + } + + boolean hasDocId(Map 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 readStringsFromDB(String sql, String param1) { + List result = new LinkedList(); + 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> readAttribMapsFromDB(String sql, String param1) { + List> result = new LinkedList>(); + 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 readMapFromDB(String sql, String param1) { + Map result = new HashMap(); + 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 getHashMap(ResultSet rs) throws SQLException { + HashMap einEintrag = new HashMap(); + 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; + + + +} diff --git a/src/de/superx/docmanagement/ArchivePropHandler.java b/src/de/superx/docmanagement/ArchivePropHandler.java new file mode 100644 index 0000000..926fb13 --- /dev/null +++ b/src/de/superx/docmanagement/ArchivePropHandler.java @@ -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; + } + +} diff --git a/src/de/superx/docmanagement/BasicAuthTokenRequester.java b/src/de/superx/docmanagement/BasicAuthTokenRequester.java new file mode 100644 index 0000000..d73809d --- /dev/null +++ b/src/de/superx/docmanagement/BasicAuthTokenRequester.java @@ -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("", ""); + result = result.replaceAll("", ""); + result = result.replaceAll("\n", ""); + result = result.replaceAll("\r", ""); + } + + return result; + + } +} diff --git a/src/de/superx/docmanagement/ConnectionTest.java b/src/de/superx/docmanagement/ConnectionTest.java new file mode 100644 index 0000000..a2fa168 --- /dev/null +++ b/src/de/superx/docmanagement/ConnectionTest.java @@ -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(); + } + +} diff --git a/src/de/superx/docmanagement/DocMan.java b/src/de/superx/docmanagement/DocMan.java new file mode 100644 index 0000000..0daa2c1 --- /dev/null +++ b/src/de/superx/docmanagement/DocMan.java @@ -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 docPresenters = new HashMap(); + + 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 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 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ü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(); + } +} diff --git a/src/de/superx/docmanagement/DocPresentationResult.java b/src/de/superx/docmanagement/DocPresentationResult.java new file mode 100644 index 0000000..b491097 --- /dev/null +++ b/src/de/superx/docmanagement/DocPresentationResult.java @@ -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; + } + +} diff --git a/src/de/superx/docmanagement/DocumentMetadata.java b/src/de/superx/docmanagement/DocumentMetadata.java new file mode 100644 index 0000000..0a1cb91 --- /dev/null +++ b/src/de/superx/docmanagement/DocumentMetadata.java @@ -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); + +} + +} diff --git a/src/de/superx/docmanagement/DvelopArchiv1.java b/src/de/superx/docmanagement/DvelopArchiv1.java new file mode 100644 index 0000000..554e210 --- /dev/null +++ b/src/de/superx/docmanagement/DvelopArchiv1.java @@ -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 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()"); + 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(); + 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("<>", 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); + } +} + diff --git a/src/de/superx/docmanagement/DvelopDocumentMetadata.java b/src/de/superx/docmanagement/DvelopDocumentMetadata.java new file mode 100644 index 0000000..68716e7 --- /dev/null +++ b/src/de/superx/docmanagement/DvelopDocumentMetadata.java @@ -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); + + } + + +} diff --git a/src/de/superx/docmanagement/DvelopDownloadTester.java b/src/de/superx/docmanagement/DvelopDownloadTester.java new file mode 100644 index 0000000..cd4e0e2 --- /dev/null +++ b/src/de/superx/docmanagement/DvelopDownloadTester.java @@ -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"); + } + + } +} diff --git a/src/de/superx/docmanagement/DvelopDownloadTester2.java b/src/de/superx/docmanagement/DvelopDownloadTester2.java new file mode 100644 index 0000000..f0b735e --- /dev/null +++ b/src/de/superx/docmanagement/DvelopDownloadTester2.java @@ -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"); + } + + } +} diff --git a/src/de/superx/docmanagement/DvelopMetadatenLoader.java b/src/de/superx/docmanagement/DvelopMetadatenLoader.java new file mode 100644 index 0000000..efa9d86 --- /dev/null +++ b/src/de/superx/docmanagement/DvelopMetadatenLoader.java @@ -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 + ""); //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"); + } + + +} \ No newline at end of file diff --git a/src/de/superx/docmanagement/Encryptor.java b/src/de/superx/docmanagement/Encryptor.java new file mode 100644 index 0000000..14d1317 --- /dev/null +++ b/src/de/superx/docmanagement/Encryptor.java @@ -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"); + } + + } + +} diff --git a/src/de/superx/docmanagement/FSVDocumentRetriever.java b/src/de/superx/docmanagement/FSVDocumentRetriever.java new file mode 100644 index 0000000..b7edaee --- /dev/null +++ b/src/de/superx/docmanagement/FSVDocumentRetriever.java @@ -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"); + } + + } +} diff --git a/src/de/superx/docmanagement/FSVTokenRequester.java b/src/de/superx/docmanagement/FSVTokenRequester.java new file mode 100644 index 0000000..0fd5a7a --- /dev/null +++ b/src/de/superx/docmanagement/FSVTokenRequester.java @@ -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("", ""); + result = result.replaceAll("", ""); + } + + return result; + + } +} diff --git a/src/de/superx/docmanagement/HISConnektorTest.java b/src/de/superx/docmanagement/HISConnektorTest.java new file mode 100644 index 0000000..aa44aca --- /dev/null +++ b/src/de/superx/docmanagement/HISConnektorTest.java @@ -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(); + } + +} + +} diff --git a/src/de/superx/docmanagement/MBSArchiv1.java b/src/de/superx/docmanagement/MBSArchiv1.java new file mode 100644 index 0000000..68cb314 --- /dev/null +++ b/src/de/superx/docmanagement/MBSArchiv1.java @@ -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 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 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(); + 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); + } +} + diff --git a/src/de/superx/docmanagement/MBSArchiv1TokenRequester.java b/src/de/superx/docmanagement/MBSArchiv1TokenRequester.java new file mode 100644 index 0000000..b6cdfd5 --- /dev/null +++ b/src/de/superx/docmanagement/MBSArchiv1TokenRequester.java @@ -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("", ""); + result = result.replaceAll("", ""); + result = result.replaceAll("\n", ""); + result = result.replaceAll("\r", ""); + } + return result; + } + +} diff --git a/src/de/superx/docmanagement/MBSBusinessTransactionArchiv.java b/src/de/superx/docmanagement/MBSBusinessTransactionArchiv.java new file mode 100644 index 0000000..2ad53e7 --- /dev/null +++ b/src/de/superx/docmanagement/MBSBusinessTransactionArchiv.java @@ -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 -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); + } +} diff --git a/src/de/superx/docmanagement/PCKSSigner.java.bak b/src/de/superx/docmanagement/PCKSSigner.java.bak new file mode 100644 index 0000000..24c37af --- /dev/null +++ b/src/de/superx/docmanagement/PCKSSigner.java.bak @@ -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 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)); + } +} + + diff --git a/src/de/superx/docmanagement/SAPArchiv1.java b/src/de/superx/docmanagement/SAPArchiv1.java new file mode 100644 index 0000000..b052d90 --- /dev/null +++ b/src/de/superx/docmanagement/SAPArchiv1.java @@ -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 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 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(); + 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())", + doc_id, doc_id); + + if ("ja".contentEquals(loeschdatumUberschritten)) { + result.setMessage("Es kann kein Dokument geladen werden, da das Löschdatum für die DocID " + doc_id + + " ü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) { + + } +} diff --git a/src/de/superx/docmanagement/SignerTest.java.bak b/src/de/superx/docmanagement/SignerTest.java.bak new file mode 100644 index 0000000..88d7e7e --- /dev/null +++ b/src/de/superx/docmanagement/SignerTest.java.bak @@ -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(); + } + +} diff --git a/src/de/superx/docmanagement/UniFrSecKeyGenerator.java b/src/de/superx/docmanagement/UniFrSecKeyGenerator.java new file mode 100644 index 0000000..7e1ab1c --- /dev/null +++ b/src/de/superx/docmanagement/UniFrSecKeyGenerator.java @@ -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; + + } +} diff --git a/src/de/superx/docmanagement/UniFrSecKeyGeneratorTest.java b/src/de/superx/docmanagement/UniFrSecKeyGeneratorTest.java new file mode 100644 index 0000000..78802f5 --- /dev/null +++ b/src/de/superx/docmanagement/UniFrSecKeyGeneratorTest.java @@ -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>|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 + } +} diff --git a/superx/WEB-INF/lib/superx-docmanagement1.4.jar b/superx/WEB-INF/lib/superx-docmanagement1.4.jar new file mode 100644 index 0000000..4312bcc Binary files /dev/null and b/superx/WEB-INF/lib/superx-docmanagement1.4.jar differ diff --git a/superx/WEB-INF/lib_ext/bc-jar-README.txt b/superx/WEB-INF/lib_ext/bc-jar-README.txt new file mode 100644 index 0000000..28ea349 --- /dev/null +++ b/superx/WEB-INF/lib_ext/bc-jar-README.txt @@ -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. diff --git a/superx/WEB-INF/lib_ext/bcpkix-jdk15on-169.jar b/superx/WEB-INF/lib_ext/bcpkix-jdk15on-169.jar new file mode 100644 index 0000000..9838192 Binary files /dev/null and b/superx/WEB-INF/lib_ext/bcpkix-jdk15on-169.jar differ diff --git a/superx/WEB-INF/lib_ext/bcprov-jdk15on-169.jar b/superx/WEB-INF/lib_ext/bcprov-jdk15on-169.jar new file mode 100644 index 0000000..8647635 Binary files /dev/null and b/superx/WEB-INF/lib_ext/bcprov-jdk15on-169.jar differ diff --git a/superx/WEB-INF/lib_ext/bcutil-jdk15on-169.jar b/superx/WEB-INF/lib_ext/bcutil-jdk15on-169.jar new file mode 100644 index 0000000..a4fcfa4 Binary files /dev/null and b/superx/WEB-INF/lib_ext/bcutil-jdk15on-169.jar differ diff --git a/superx/WEB-INF/lib_ext/groovy-LICENSE.txt b/superx/WEB-INF/lib_ext/groovy-LICENSE.txt new file mode 100644 index 0000000..e0908d4 --- /dev/null +++ b/superx/WEB-INF/lib_ext/groovy-LICENSE.txt @@ -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. + * + */ + \ No newline at end of file diff --git a/superx/WEB-INF/lib_ext/groovy-NOTICE.txt b/superx/WEB-INF/lib_ext/groovy-NOTICE.txt new file mode 100644 index 0000000..33cb7ab --- /dev/null +++ b/superx/WEB-INF/lib_ext/groovy-NOTICE.txt @@ -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/). \ No newline at end of file diff --git a/superx/WEB-INF/lib_ext/groovy-all-2.3.6.jar b/superx/WEB-INF/lib_ext/groovy-all-2.3.6.jar new file mode 100644 index 0000000..495be3e Binary files /dev/null and b/superx/WEB-INF/lib_ext/groovy-all-2.3.6.jar differ diff --git a/superx/WEB-INF/lib_ext/servlet-api.jar b/superx/WEB-INF/lib_ext/servlet-api.jar new file mode 100644 index 0000000..a9e8d24 Binary files /dev/null and b/superx/WEB-INF/lib_ext/servlet-api.jar differ diff --git a/superx/WEB-INF/lib_ext/superx5.3.jar b/superx/WEB-INF/lib_ext/superx5.3.jar new file mode 100644 index 0000000..a9d9877 Binary files /dev/null and b/superx/WEB-INF/lib_ext/superx5.3.jar differ