From 83d345075b3ec36e050446b2e0b4926955eaeafb Mon Sep 17 00:00:00 2001 From: OfficeServer dgsoft Date: Sun, 5 Oct 2025 20:58:02 +0200 Subject: [PATCH] =?UTF-8?q?=F0=9F=97=91=EF=B8=8F=20WebDAV=20komplett=20ent?= =?UTF-8?q?fernt?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ✨ Bereinigungen: - Alle WebDAV-bezogenen Code-Teile entfernt - Dokumentation auf HTTP-Zugriff umgestellt - Veraltete WebDAV-Backup-Dateien gelöscht - URLs von /webdav/* auf direkte Pfade geändert 📁 Gelöschte Dateien: - WEBDAV-INTEGRATION.md - SCHREIBSCHUTZ-BEHOBEN.md - server_old.js - server_webdav_backup.js 🔄 Aktualisierte URLs: - /webdav/templates/ → /templates/ - /webdav/documents/ → /documents/ 📝 Bereinigte Dokumentation: - README.md - WebDAV-Referenzen entfernt - STATUS.md - URLs aktualisiert - SSL-*.md - WebDAV-Links ersetzt - Start-Scripts - Pfade korrigiert 🎯 Fokus jetzt auf: - HTTP-basierte Dateifreigabe - Management-GUI System - Custom Tags REST-APIs - Template-Verarbeitung ohne WebDAV-Komplexität --- .gitignore | 1 - README.md | 49 +- SCHREIBSCHUTZ-BEHOBEN.md | 127 ---- SSL-SETUP.md | 8 +- SSL-SUCCESS.md | 12 +- STATUS.md | 16 +- TABELLE-SUCCESS.md | 8 +- WEBDAV-INTEGRATION.md | 106 --- documents/final-test-custom-tags.docx | Bin 0 -> 1102 bytes documents/test-all-custom-tags.docx | Bin 0 -> 1105 bytes documents/test-with-custom-tags.docx | Bin 0 -> 1100 bytes server_old.js | 939 -------------------------- server_webdav_backup.js | 939 -------------------------- start-ssl.sh | 8 +- start.sh | 4 +- 15 files changed, 45 insertions(+), 2172 deletions(-) delete mode 100644 SCHREIBSCHUTZ-BEHOBEN.md delete mode 100644 WEBDAV-INTEGRATION.md create mode 100644 documents/final-test-custom-tags.docx create mode 100644 documents/test-all-custom-tags.docx create mode 100644 documents/test-with-custom-tags.docx delete mode 100644 server_old.js delete mode 100644 server_webdav_backup.js diff --git a/.gitignore b/.gitignore index acc2262..1a57d56 100644 --- a/.gitignore +++ b/.gitignore @@ -4,7 +4,6 @@ uploads/ .env .DS_Store Thumbs.db -webdav-tree.json 203_cert.pem 203_key.pem private-key.pem diff --git a/README.md b/README.md index 680cffa..b3ca509 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # DOCX Template Server -Ein Node.js-Server für die automatische Verarbeitung von DOCX-Templates mit WebDAV-ähnlicher Dateifreigabe. +Ein Node.js-Server für die automatische Verarbeitung von DOCX-Templates mit Management-GUI. ## ✨ Features @@ -25,9 +25,11 @@ npm start ## 🌐 Zugriff -- **Web-Interface:** http://localhost:80 -- **Templates:** http://localhost:80/webdav/templates/ -- **Dokumente:** http://localhost:80/webdav/documents/ +### 🌐 **Web-Zugriff:** +- **Server:** http://localhost:80/ +- **Management:** http://localhost:3000/ +- **Templates:** http://localhost:80/templates/ +- **Dokumente:** http://localhost:80/documents/ ## 📋 Verwendung @@ -41,7 +43,8 @@ Erstellen Sie ein DOCX-Dokument mit Tags wie: ### 2. Template hochladen - Über Web-Interface: Datei auswählen und hochladen - Über API: `POST /upload-template` -- Über Dateifreigabe: Datei in `/webdav/templates/` kopieren +- Über Web-Upload: http://localhost:80/ → "Template hochladen" +- Direkt in Ordner: Datei in `/templates/` kopieren ### 3. Automatische Verarbeitung Der Server erkennt automatisch alle Tags und füllt sie mit passenden Demo-Daten: @@ -125,25 +128,12 @@ Body: { } ``` -## 💾 Dateifreigabe Setup +## 🌐 HTTP-Zugriff -### Windows Explorer -1. Windows Explorer öffnen -2. Adressleiste: `\\localhost\webdav$` -3. Oder: "Netzlaufwerk verbinden" → `http://localhost:80/webdav/templates/` - -### Linux/macOS -```bash -# Verzeichnis erstellen -sudo mkdir -p /mnt/docx-templates -sudo mkdir -p /mnt/docx-documents - -# Mounten (davfs2 erforderlich) -sudo mount -t davfs http://localhost:80/webdav/templates/ /mnt/docx-templates -sudo mount -t davfs http://localhost:80/webdav/documents/ /mnt/docx-documents - -# Oder über GUI: Dateimanager → "Mit Server verbinden" → http://localhost:80/webdav/templates/ -``` +### Direkte HTTP-URLs: +Templates und generierte Dokumente sind über HTTP zugänglich: +- **Templates:** http://localhost:80/templates/ +- **Dokumente:** http://localhost:80/documents/ ## 🔒 SSL/HTTPS Einrichtung @@ -297,15 +287,10 @@ ls -la private-key.pem certificate.pem - Tags richtig geschrieben (`{tag}` nicht `{{tag}}`)? - Datei-Berechtigungen prüfen -### Dateifreigabe funktioniert nicht -```bash -# WebDAV-Client installieren -# Ubuntu/Debian: -sudo apt install davfs2 - -# macOS: -brew install davfs2 -``` +### Templates nicht sichtbar +Prüfen Sie: +- Server läuft: `http://localhost:80/` +- Templates-Ordner: `http://localhost:80/templates/` ### SSL-Probleme ```bash diff --git a/SCHREIBSCHUTZ-BEHOBEN.md b/SCHREIBSCHUTZ-BEHOBEN.md deleted file mode 100644 index 6d878d0..0000000 --- a/SCHREIBSCHUTZ-BEHOBEN.md +++ /dev/null @@ -1,127 +0,0 @@ -# 🔓 SCHREIBSCHUTZ-PROBLEM BEHOBEN! - -## ✅ **Erweiterte WebDAV-Implementierung** - -Ich habe die WebDAV-Implementierung erweitert, um das Schreibschutz-Problem zu lösen: - -### 🔧 **Was wurde verbessert:** - -#### **1. Erweiterte WebDAV-Properties:** -- `F` - Explizit NICHT schreibgeschützt -- `F` - Microsoft Office spezifisch -- `F` - Nicht ausführbar -- `F` - Nicht versteckt - -#### **2. Office-kompatible HTTP-Header:** -- `Server: Microsoft-IIS/10.0` - Word erkennt als IIS-Server -- `DAV: 1, 2, ordered-collections, versioning` - Vollständige WebDAV-Unterstützung -- `Cache-Control: no-cache` - Keine Zwischenspeicherung -- `ETag` und `Last-Modified` für Versionskontrolle - -#### **3. Automatische Dateiberechtigungen:** -- Dateien werden mit `chmod 666` (rw-rw-rw-) gespeichert -- Explizite Schreibrechte für alle Benutzer - -#### **4. Bessere Lock-Unterstützung:** -- Sowohl exklusive als auch geteilte Locks -- Office-kompatible Lock-Token - -### 📝 **Neue Word-Integration:** - -#### **Schritt 1: WebDAV-Netzlaufwerk einrichten** -``` -1. Windows Explorer öffnen -2. "Dieser PC" → Rechtsklick → "Netzlaufwerk verbinden" -3. Ordner: \\localhost\webdav\templates (oder \documents) -4. Port: 80 -5. NICHT "Mit anderen Anmeldeinformationen" ankreuzen -``` - -#### **Schritt 2: In Word öffnen** -``` -1. Word öffnen -2. Datei → Öffnen -3. Das neue Netzlaufwerk auswählen -4. Template öffnen -``` - -#### **Schritt 3: Test der Schreibrechte** -``` -1. Text bearbeiten -2. Strg+S drücken -3. Sollte jetzt DIREKT auf dem Server speichern! -``` - -### 🚨 **Troubleshooting:** - -#### **Falls immer noch schreibgeschützt:** - -**Option 1: Dateiberechtigungen prüfen** -```bash -cd /home/OfficeServerJS/templates -ls -la *.docx -# Sollte zeigen: -rw-rw-rw- -``` - -**Option 2: Alternative WebDAV-URL** -``` -Statt: http://localhost:80/webdav/templates/ -Verwenden: http://localhost/webdav/templates/ -Oder: http://127.0.0.1:80/webdav/templates/ -``` - -**Option 3: Windows WebDAV-Client konfigurieren** -```cmd -# Als Administrator ausführen: -net stop webclient -net start webclient - -# WebDAV Registry-Einstellungen: -reg add HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\WebClient\Parameters /v BasicAuthLevel /t REG_DWORD /d 2 /f -``` - -**Option 4: Office Trust Center** -``` -1. Word → Datei → Optionen -2. Trust Center → Trust Center-Einstellungen -3. Geschützte Ansicht → Alle Häkchen entfernen -4. Datenschutz-Optionen → "Dateien aus dem Internet..." deaktivieren -``` - -### 🔍 **Live-Monitoring:** - -Der Server zeigt jetzt Live-Logs: -``` -📖 Word öffnet Template: rechnung_template.docx -📝 Word speichert Template: rechnung_template.docx -✅ Template gespeichert: rechnung_template.docx -``` - -### 🎯 **Test-Verfahren:** - -1. **Server-Logs beobachten** beim Öffnen/Speichern -2. **Datei-Timestamps prüfen** nach dem Speichern -3. **Browser-Zugriff testen**: http://localhost:80/webdav/templates/ - -### ⚡ **Sofort-Test:** - -```bash -# 1. Datei über WebDAV hochladen -curl -X PUT --data-binary @test.docx http://localhost:80/webdav/templates/test.docx - -# 2. Berechtigung prüfen -ls -la /home/OfficeServerJS/templates/test.docx - -# 3. WebDAV-Properties abfragen -curl -X PROPFIND -H "Depth: 1" http://localhost:80/webdav/templates/test.docx -``` - -## 🎉 **Ergebnis:** - -✅ **Erweiterte WebDAV-Properties** für Office-Kompatibilität -✅ **Explizite Schreibrechte** in XML-Response -✅ **Automatische Dateiberechtigungen** beim Speichern -✅ **Office-optimierte HTTP-Header** -✅ **Live-Monitoring** für Debugging - -**Word sollte jetzt die Dateien als beschreibbar erkennen und direkt auf dem Server speichern! 🔓✍️** \ No newline at end of file diff --git a/SSL-SETUP.md b/SSL-SETUP.md index b1ce845..dd83b0c 100644 --- a/SSL-SETUP.md +++ b/SSL-SETUP.md @@ -41,13 +41,13 @@ cd /home/OfficeServerJS ### HTTP (immer verfügbar): - **Web-Interface:** http://localhost:80 -- **Templates:** http://localhost:80/webdav/templates/ -- **Dokumente:** http://localhost:80/webdav/documents/ +- **Templates:** http://localhost:80/templates/ +- **Dokumente:** http://localhost:80/documents/ ### HTTPS (nach SSL-Aktivierung): - **Web-Interface:** https://localhost:443 -- **Templates:** https://localhost:443/webdav/templates/ -- **Dokumente:** https://localhost:443/webdav/documents/ +- **Templates:** https://localhost:443/templates/ +- **Dokumente:** https://localhost:443/documents/ ## 🔧 Zertifikat-Validierung diff --git a/SSL-SUCCESS.md b/SSL-SUCCESS.md index 3f5df15..b4bd9eb 100644 --- a/SSL-SUCCESS.md +++ b/SSL-SUCCESS.md @@ -15,14 +15,14 @@ Ihr DOCX Template Server läuft jetzt mit **vollständiger SSL-Verschlüsselung* #### HTTP (Port 80): - **Web-Interface:** http://localhost:80 -- **Templates:** http://localhost:80/webdav/templates/ -- **Dokumente:** http://localhost:80/webdav/documents/ +- **Templates:** http://localhost:80/templates/ +- **Dokumente:** http://localhost:80/documents/ - **API:** http://localhost:80/api/ #### HTTPS (Port 443) - **NEU AKTIV**: - **Web-Interface:** https://localhost:443 -- **Templates:** https://localhost:443/webdav/templates/ -- **Dokumente:** https://localhost:443/webdav/documents/ +- **Templates:** https://localhost:443/templates/ +- **Dokumente:** https://localhost:443/documents/ - **API:** https://localhost:443/api/ ### 🚀 **Server-Features:** @@ -31,7 +31,7 @@ Ihr DOCX Template Server läuft jetzt mit **vollständiger SSL-Verschlüsselung* - ✅ **DOCX-Template-Verarbeitung** mit automatischer Tag-Erkennung - ✅ **Demo-Daten-Generierung** für alle Tag-Typen - ✅ **Tabellen-Unterstützung** für Listen und Wiederholungen -- ✅ **WebDAV-ähnliche Dateifreigabe** ohne Authentifizierung +- ✅ **HTTP-Dateifreigabe** ohne Authentifizierung - ✅ **Vollständige API** für programmatischen Zugriff ### 📋 **Einsatz in der Produktion:** @@ -103,7 +103,7 @@ curl -I -k https://localhost:443 ✅ **docxtemplater-Integration** mit intelligenter Tag-Erkennung ✅ **Automatische Demo-Daten-Generierung** ✅ **Tabellen- und Listen-Unterstützung** -✅ **WebDAV-ähnliche Dateifreigabe** ohne Authentifizierung +✅ **HTTP-Dateifreigabe** ohne Authentifizierung ✅ **Produktionsbereit** mit vollständiger Dokumentation **Ihr DOCX Template Server ist vollständig einsatzbereit und SSL-gesichert! 🔒✨** \ No newline at end of file diff --git a/STATUS.md b/STATUS.md index 91c1e8a..e9918a5 100644 --- a/STATUS.md +++ b/STATUS.md @@ -8,14 +8,14 @@ - ✅ **Intelligente Tag-Erkennung** - erkennt automatisch alle `{tags}` im Template - ✅ **Demo-Daten-Generierung** - füllt Tags mit realistischen Testdaten - ✅ **Tabellen-Unterstützung** - `{#items}...{/items}` für Listen/Tabellen -- ✅ **WebDAV-ähnliche Dateifreigabe** - Templates und Dokumente ohne Auth zugänglich +- ✅ **HTTP-Dateifreigabe** - Templates und Dokumente über HTTP zugänglich - ✅ **Web-Interface** - Benutzerfreundliche Oberfläche - ✅ **SSL-Vorbereitung** - Ready für HTTPS mit Zertifikaten ### 📁 Verfügbare Endpoints - ✅ `http://localhost:80` - Web-Interface -- ✅ `http://localhost:80/webdav/templates/` - Template-Verzeichnis -- ✅ `http://localhost:80/webdav/documents/` - Dokument-Verzeichnis +- ✅ `http://localhost:80/templates/` - Template-Verzeichnis +- ✅ `http://localhost:80/documents/` - Dokument-Verzeichnis - ✅ `http://localhost:80/api/templates` - Template-API - ✅ `http://localhost:80/api/documents` - Dokument-API @@ -48,8 +48,8 @@ Der Server erkennt automatisch und befüllt: Der Server ist aktiv und einsatzbereit: - 🌐 Web-Interface: http://localhost:80 -- 📁 Templates: http://localhost:80/webdav/templates/ -- 📁 Dokumente: http://localhost:80/webdav/documents/ +- 📁 Templates: http://localhost:80/templates/ +- 📁 Dokumente: http://localhost:80/documents/ ## 🎯 Nächste Schritte: @@ -78,10 +78,10 @@ Der Server ist aktiv und einsatzbereit: 4. Fertiges Dokument herunterladen ### Upload via Dateifreigabe: -1. Template in `http://localhost:80/webdav/templates/` kopieren +1. Template in `http://localhost:80/templates/` hochladen 2. Server erkennt Template automatisch 3. Über API verarbeiten lassen -4. Ergebnis aus `http://localhost:80/webdav/documents/` abholen +4. Ergebnis aus `http://localhost:80/documents/` abholen ### API-Verwendung: ```bash @@ -101,7 +101,7 @@ curl -X POST -H "Content-Type: application/json" \ ✅ **Automatische Tag-Erkennung** ✅ **Demo-Daten-Generierung** ✅ **Tabellen-Unterstützung** -✅ **WebDAV-ähnliche Dateifreigabe** ohne Auth +✅ **HTTP-Dateifreigabe** ohne Auth ✅ **SSL-Vorbereitung** ✅ **Vollständige Dokumentation** diff --git a/TABELLE-SUCCESS.md b/TABELLE-SUCCESS.md index 219924b..79653c4 100644 --- a/TABELLE-SUCCESS.md +++ b/TABELLE-SUCCESS.md @@ -38,12 +38,12 @@ ### 🌐 **Zugriff auf Templates und Dokumente:** **HTTP:** -- Templates: http://localhost:80/webdav/templates/ -- Dokumente: http://localhost:80/webdav/documents/ +- Templates: http://localhost:80/templates/ +- Dokumente: http://localhost:80/documents/ **HTTPS:** -- Templates: https://localhost:443/webdav/templates/ -- Dokumente: https://localhost:443/webdav/documents/ +- Templates: https://localhost:443/templates/ +- Dokumente: https://localhost:443/documents/ ### 🧪 **Demo-Daten werden automatisch generiert:** - **Position:** 1, 2, 3, 4, 5... (fortlaufend) diff --git a/WEBDAV-INTEGRATION.md b/WEBDAV-INTEGRATION.md deleted file mode 100644 index 404bb7d..0000000 --- a/WEBDAV-INTEGRATION.md +++ /dev/null @@ -1,106 +0,0 @@ -# 🔗 WORD-WEBDAV-INTEGRATION EINGERICHTET! - -## ✅ **Server mit echter WebDAV-Unterstützung** - -Ihr Server unterstützt jetzt **echte WebDAV-Funktionen** für direktes Speichern in Word/Office: - -### 🌐 **WebDAV-Endpunkte:** -- **Templates:** http://localhost:80/webdav/templates/ -- **Dokumente:** http://localhost:80/webdav/documents/ -- **HTTPS Templates:** https://localhost:443/webdav/templates/ -- **HTTPS Dokumente:** https://localhost:443/webdav/documents/ - -## 📝 **Word-Integration Setup:** - -### **Methode 1: Word → Datei → Öffnen → Netzwerk hinzufügen** -1. Öffnen Sie Microsoft Word -2. Gehen Sie zu **Datei** → **Öffnen** -3. Klicken Sie auf **Netzwerk hinzufügen** -4. Wählen Sie **WebDAV** -5. Geben Sie ein: `http://localhost:80/webdav/templates/` -6. **Kein Benutzername/Passwort erforderlich** (einfach OK klicken) - -### **Methode 2: Windows Explorer → Netzlaufwerk** -1. Öffnen Sie Windows Explorer -2. Rechtsklick auf **Dieser PC** -3. **Netzlaufwerk verbinden** -4. Als Ordner eingeben: `http://localhost:80/webdav/templates/` -5. **"Anmeldung mit anderen Anmeldeinformationen"** NICHT ankreuzen - -### **Methode 3: Direkte URL in Word** -- Templates: `\\localhost@80\webdav\templates\` -- Dokumente: `\\localhost@80\webdav\documents\` - -## 🔧 **Was jetzt funktioniert:** - -### ✅ **WebDAV-Funktionen implementiert:** -- **PROPFIND** - Dateilisten für Office -- **GET/PUT** - Dateien öffnen und speichern -- **LOCK/UNLOCK** - Office-Sperrmechanismus -- **DAV-Header** - Word erkennt WebDAV-Server - -### ✅ **Word-Integration:** -- **Direktes Öffnen** von Templates über WebDAV -- **Automatisches Speichern** auf dem Server (nicht lokal!) -- **Versionskontrolle** durch Server-basierte Speicherung -- **Gleichzeitiges Arbeiten** mit Locks - -### ✅ **API erweitert:** -```json -{ - "templates": [ - { - "name": "rechnung_template.docx", - "fileUrl": "http://localhost:80/webdav/templates/rechnung_template.docx", - "wordWebdavUrl": "ms-word:ofe|u|http://localhost:80/webdav/templates/rechnung_template.docx", - "wordDirectUrl": "word:ofe|u|http://localhost:80/webdav/templates/rechnung_template.docx", - "downloadUrl": "http://localhost:80/webdav/templates/rechnung_template.docx", - "webdavDirect": "\\\\localhost@80\\webdav\\templates\\rechnung_template.docx" - } - ] -} -``` - -## 🎯 **So funktioniert das Speichern:** - -### **Vorher (Problem):** -- Word öffnet Datei → Bearbeiten → **Speichern geht nur lokal** - -### **Jetzt (Lösung):** -- Word öffnet über WebDAV → Bearbeiten → **Speichern geht direkt auf Server!** - -## 🔍 **Test der WebDAV-Funktionen:** - -### Server-Status prüfen: -```bash -curl -X PROPFIND -H "Depth: 1" http://localhost:80/webdav/templates/ -``` - -### Datei hochladen via WebDAV: -```bash -curl -X PUT --data-binary @meine_datei.docx http://localhost:80/webdav/templates/meine_datei.docx -``` - -### API-Test: -```bash -curl http://localhost:80/api/templates -``` - -## 📋 **Anleitung für Benutzer:** - -1. **Word öffnen** -2. **Datei → Öffnen → Netzwerk hinzufügen → WebDAV** -3. **URL eingeben:** `http://localhost:80/webdav/templates/` -4. **Template auswählen und öffnen** -5. **Bearbeiten** -6. **Strg+S drücken** → **Speichert automatisch auf dem Server!** - -## 🚀 **Ergebnis:** - -✅ **Echte WebDAV-Integration** für Office -✅ **Direktes Speichern** auf dem Server -✅ **Keine lokalen Kopien** mehr nötig -✅ **Professioneller Workflow** für Teams -✅ **Zentrale Datenverwaltung** auf dem Server - -**Word speichert jetzt automatisch auf dem Server, wenn über WebDAV geöffnet! 🎉** \ No newline at end of file diff --git a/documents/final-test-custom-tags.docx b/documents/final-test-custom-tags.docx new file mode 100644 index 0000000000000000000000000000000000000000..74a8d516eae99333bc3a5315d8ed74e6f5f85313 GIT binary patch literal 1102 zcmWIWW@h1HU|`^2P+sO5?IE@P*$2V}788XN_WTuEc6Z0uPp`M@)^EyLzums9 zh1=7h&;013kfYmXu3f*Y`0Y(0caKuOU%NEhB=)Xbb%8I%aLPI1<+o0D9-ZOza`o!T z=en~sSq|@&T^+SDH1%S^#WM^-UvHOg&w1aNKgna-4H-=ri%DOV-J-%Rr-r_JCBOB_ z!IBR*E-m}u)cC~7^>f-K3#og&<$DDV%Y3`RC)^;P;d$6^!c9XNna2$_jo+>87f71! z>3Q~g@}*fGVdu?d=4eN!t2ca?I3IR+Q_PA@VPA`wvfKkVT>r2n?4{xr=ODBC>u28m zkDe7D01qpf^)As0(rvFc0mDd-k%565NXHkY<`nDefymzTyZM?7MA#n8U7m4HkCi={ zr}gNJ4N^4?%WS8(Re471@7XIWbHu`8-tF>F=65fjdD5qtl`eTDm6c^}K~VJ32S#(u zsuc_iwST_RF^Vv7x-NEBGJW1B-#J_QRg}$)W(0j=_gXyT!iNZ}elveJaUTDjJY7|K z>tYn|hF$Gz^Jl)*G(pt6>ZHP#O>9Owa{nLRwa998SI=Y1{q^x_w(@Bk4IdskJrAw> zZ;duP6npLJy19=5<~0UzG64Dp4p@OKa58`?fuxk{l`XG60;P5UeJ>28qn-2fN`Q$Z zKBTfBwKx`(R%$1l^*d}J(DJ^P>-2T4!c&ZjQ!WXNPrvLm zQQ&FD*&5^5nb+ChACWV@DPgs9m9(b8i;Nrz>!157*S%Y^fazdEH=}i>%cR$J7xVf! zJq=`5Ob*t38K-$kxN3ow8qXRY!)lE`XBK-c*lw_BSLUqfrO6r+UZKx;ZtAyW$QL%u z)qeEyz^R|pdis`BSX4jX<>%yeE=yz0>RN;SU8~klnsst=yV~rGlWZ&3O+EAIYoGj= zsp_Y$EvRUYi94`4u=YsKl+LQ>lI#Ba|9X7Of+y^8>-@_>eNvqj)$d<*KRVdQwaT bMA)ST)Pf~)1H4(;K#Ev^@C}gmVFvL4>sFv3 literal 0 HcmV?d00001 diff --git a/documents/test-all-custom-tags.docx b/documents/test-all-custom-tags.docx new file mode 100644 index 0000000000000000000000000000000000000000..f6abbb87a527cbc16fa856c8fe2321cd07159753 GIT binary patch literal 1105 zcmWIWW@h1HU|`^25MAaPea&~FG6N$6Lm(3agCJ0}JijPKKP5l8G&eP`M6V(@XX&Kf zd4~;nT))?_KD6DGbU;@@#ZUT+p~%}QdUr);Zft$U>g6|U|N1G5qRsThr>j&rOo+*^ zU(+ZYbmd;|D$&PRw?(fxzvz3`rWZm_c6C46v+~%KrWLPOxNR{qlE3iu*2T$FHQPuF##@O>mK;0sEg%0;TQOsQ zvDo+jdUy2$;K3!c-X&T=y6x2_U@++cgNz$U#}}pM6zl7O$lmk2`I-zw*dEMXo^ei( zl|7lK_2`TZQZ)_BY^S(Yc}DB+*()n^#KL0U?eb6NcQ2oL(x;e}E_o%Dm1S)~Q1sCU zMsv)n6$}ftf4%8@@X3lA09b9 z53T!ejW#0Qv?FSb;2XN`NVWB$n%yEw4TTrFH;)FASuko%8cb zfaxSYq_QBjI2M##YA2laJ8U4(^1hbq^mVPmQ;dpJmay0L9av~{;M6^pu)pf-qi=0b zzw9(o;AzI$8spcQ*V*46ku$z2VYPFWw5Gv}j2sE;pZhA;y<4(?>0m=Qqjjarq}O#9 z^ZGbF4P;hK4%U1br+G=ZYJrs+&l(=XYK=c<7JDt&Zm?)q=B((Y$r=(~q0e}3>bGRb z7dFh*e)RIdsh`t&`j%8!R6pP4=j3%ROJmLIT7&&vtJY7Nb#ijM+U$&zY%AAIJ@e>m zpZu4p>Zh(PsA!IfJFq#h_DIf@&Z_5<>;C)ydVI@*C+uu-i%Bl47f8CJWRn1jO>N19a{oJXx9e@I#O~&Xv7|U5RC#riVK*vp^=H| eRP^XX*rf~9f+cbTyjj^midcZ~4UqO{2Jrx$ahJyc literal 0 HcmV?d00001 diff --git a/documents/test-with-custom-tags.docx b/documents/test-with-custom-tags.docx new file mode 100644 index 0000000000000000000000000000000000000000..32e3ac46001d51b285358d33b3370e831b9b6f74 GIT binary patch literal 1100 zcmWIWW@h1HU|`^2U|Z%IZFP5|$8R9di;00j5J;Ej7p3T@E`eM3Qo@ln;R^OGZhY$xIjmOuxwq-do?7wAk3M)j z{LK4t$ppE!9dc8>cdI>|%(3}d!HIGm{m9CQ#w^1L5*Byff459FcRcy$Z*tN9@=Jf1 z0^lJfv)(0ILAveLCSVBZF)}c41L^pp)SO~{JrLP@em7r}fe71!xyv)o>9MjW^RynF zu|cY)VVUg|w<^zQ{XKhSWsX=_%)4Fw$^7o+Gf(;yv(hE6q_VQCEeMJ}`oL(8S+#;; zq4v)=Iz|x&PS?fGN~X{I|Tp!T=)=S)o%~n2bqv69Nr{|${|Ew zI9p@B9; zipjy6FXJ>X30Ez!QsY^}V_2>6=geZS1=|f4?aG`Ly);=v!YlL{&rSW74Ee%_x!R9j z9ys-LT2J4S3XAIJyZoHI&Shz=SzT+eziZX{NwZE)ZdaR~aguH2x~XR#eeIL~GFAQ5 zwFMQ;F>wbr2i6|RnbKMHTyoui|6h-9S@48CZk>NQs86c1qWb--?nejP-p6lwWm5B> zGr*gXNrVA+UV?`yn1PYAkhNn=U { - if (!fs.existsSync(dir)) { - fs.mkdirSync(dir, { recursive: true }); - } -}); - -// WebDAV-Implementierung für Word/Office-Integration mit SharePoint-Kompatibilität -const webdavMethods = ['PROPFIND', 'PROPPATCH', 'MKCOL', 'COPY', 'MOVE', 'LOCK', 'UNLOCK']; - -// SharePoint-spezifische Namespaces und Header -const sharePointNamespaces = { - 'xmlns:D': 'DAV:', - 'xmlns:S': 'http://schemas.microsoft.com/sharepoint/soap/', - 'xmlns:Z': 'urn:schemas-microsoft-com:', - 'xmlns:O': 'urn:schemas-microsoft-com:office:office', - 'xmlns:T': 'http://schemas.microsoft.com/repl/' -}; - -// WebDAV PROPFIND Handler mit SharePoint-Modus -app.use('/webdav', (req, res, next) => { - // Erweiterte CORS und WebDAV-Header für Office/SharePoint - res.set({ - 'DAV': '1, 2, ordered-collections, versioning, extended-mkcol', - 'MS-Author-Via': 'DAV', - 'Server': 'Microsoft-IIS/10.0 Microsoft-HTTPAPI/2.0', - 'MicrosoftSharePointTeamServices': '15.0.0.4569', - 'SPRequestGuid': `{${crypto.randomUUID()}}`, - 'SPIisLatency': '0', - 'Allow': 'GET, HEAD, POST, PUT, DELETE, OPTIONS, PROPFIND, PROPPATCH, MKCOL, COPY, MOVE, LOCK, UNLOCK', - 'Access-Control-Allow-Origin': '*', - 'Access-Control-Allow-Methods': 'GET, HEAD, POST, PUT, DELETE, OPTIONS, PROPFIND, PROPPATCH, MKCOL, COPY, MOVE, LOCK, UNLOCK', - 'Access-Control-Allow-Headers': 'Content-Type, Depth, Authorization, Destination, If, Lock-Token, Overwrite, Timeout, X-Requested-With, SOAPAction', - 'Cache-Control': 'no-cache, no-store, must-revalidate', - 'Pragma': 'no-cache', - 'Expires': '0', - 'X-SharePointHealthScore': '0', - 'X-AspNet-Version': '4.0.30319', - 'X-Powered-By': 'ASP.NET' - }); - - if (req.method === 'OPTIONS') { - return res.status(200).end(); - } - - if (req.method === 'PROPFIND') { - const depth = req.headers.depth || 'infinity'; - const requestPath = req.path.replace('/webdav', ''); - - let targetDir; - if (requestPath.startsWith('/templates')) { - targetDir = path.join(templateDir, requestPath.replace('/templates', '')); - } else if (requestPath.startsWith('/documents')) { - targetDir = path.join(outputDir, requestPath.replace('/documents', '')); - } else { - targetDir = __dirname; - } - - try { - let items = []; - - if (fs.existsSync(targetDir)) { - const stats = fs.statSync(targetDir); - - if (stats.isDirectory()) { - const files = fs.readdirSync(targetDir); - - // Verzeichnis selbst - items.push({ - href: req.path + (req.path.endsWith('/') ? '' : '/'), - isDirectory: true, - lastModified: stats.mtime.toUTCString(), - size: 0 - }); - - // Dateien im Verzeichnis - files.forEach(file => { - const filePath = path.join(targetDir, file); - const fileStats = fs.statSync(filePath); - - items.push({ - href: req.path + (req.path.endsWith('/') ? '' : '/') + file, - isDirectory: fileStats.isDirectory(), - lastModified: fileStats.mtime.toUTCString(), - size: fileStats.size || 0, - contentType: fileStats.isDirectory() ? 'httpd/unix-directory' : 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' - }); - }); - } else { - // Einzelne Datei - items.push({ - href: req.path, - isDirectory: false, - lastModified: stats.mtime.toUTCString(), - size: stats.size, - contentType: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' - }); - } - } - - // WebDAV XML Response mit SharePoint-spezifischen Eigenschaften - const xmlResponse = ` - -${items.map(item => ` - - ${item.href} - - - ${path.basename(item.href)} - ${item.lastModified} - ${item.size} - ${item.contentType} - ${item.isDirectory ? '' : ''} - - - - - - - - - - - "${Date.now()}-${item.size}" - ${new Date(item.lastModified).toISOString()} - ${item.isDirectory ? 'true' : 'false'} - F - F - F - F - ${new Date(item.lastModified).toISOString()} - ${new Date().toISOString()} - ${new Date(item.lastModified).toISOString()} - 00000020 - System Account - - 0 - - 1 - 0x0101 - 0 - - HTTP/1.1 200 OK - - `).join('')} -`; - - res.set('Content-Type', 'application/xml; charset=utf-8'); - res.status(207).send(xmlResponse); - } catch (error) { - res.status(404).send('Not Found'); - } - return; - } - - next(); -}); - -// WebDAV PUT Handler für Dateien speichern -// PUT - File Upload (für Word Speichern) -app.put('/dav/*', (req, res) => { - const filePath = path.join(__dirname, 'uploads', req.params[0]); - const dirPath = path.dirname(filePath); - - console.log(`� PUT Request: ${req.params[0]}`); - console.log(`📂 Speichere nach: ${filePath}`); - - // Stelle sicher dass der Ordner existiert - fs.mkdirSync(dirPath, { recursive: true }); - - const writeStream = fs.createWriteStream(filePath); - - req.pipe(writeStream); - - writeStream.on('finish', () => { - console.log(`✅ Datei gespeichert: ${filePath}`); - res.set({ - 'DAV': '1, 2, ordered-collections, versioning, extended-mkcol', - 'MS-Author-Via': 'DAV', - 'Server': 'Microsoft-IIS/10.0 Microsoft-HTTPAPI/2.0', - 'MicrosoftSharePointTeamServices': '15.0.0.4569', - 'SPRequestGuid': `{${crypto.randomUUID()}}`, - 'Cache-Control': 'no-cache', - 'ETag': `"${Date.now()}-${req.headers['content-length'] || 0}"`, - 'Last-Modified': new Date().toUTCString(), - 'X-SharePoint-HealthScore': '0' - }); - res.status(201).send('Created'); - }); - - writeStream.on('error', (err) => { - console.error(`❌ Fehler beim Speichern: ${err.message}`); - res.status(500).send('Internal Server Error'); - }); -}); - -app.put('/webdav/documents/:filename', (req, res) => { - const filename = req.params.filename; - const filePath = path.join(outputDir, filename); - - console.log(`📝 Word speichert Dokument: ${filename}`); - - const writeStream = fs.createWriteStream(filePath); - req.pipe(writeStream); - - writeStream.on('finish', () => { - // Dateirechte explizit setzen - try { - fs.chmodSync(filePath, 0o666); // Lese-/Schreibrechte für alle - } catch (error) { - console.warn('Warnung: Konnte Dateiberechtigungen nicht setzen:', error.message); - } - - res.set({ - 'DAV': '1, 2, ordered-collections, versioning', - 'MS-Author-Via': 'DAV', - 'Server': 'Microsoft-IIS/10.0', - 'Cache-Control': 'no-cache', - 'ETag': `"${Date.now()}-${req.headers['content-length'] || 0}"`, - 'Last-Modified': new Date().toUTCString() - }); - res.status(201).send('Created'); - console.log(`✅ Dokument gespeichert: ${filename}`); - }); - - writeStream.on('error', (error) => { - console.error('❌ Fehler beim Speichern:', error); - res.status(500).send('Internal Server Error'); - }); -}); - -// WebDAV GET Handler für Dateien lesen -app.get('/webdav/templates/:filename', (req, res) => { - const filename = req.params.filename; - const filePath = path.join(templateDir, filename); - - if (fs.existsSync(filePath)) { - const stats = fs.statSync(filePath); - res.set({ - 'DAV': '1, 2, ordered-collections, versioning', - 'MS-Author-Via': 'DAV', - 'Server': 'Microsoft-IIS/10.0', - 'Content-Type': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', - 'Content-Length': stats.size, - 'Last-Modified': stats.mtime.toUTCString(), - 'ETag': `"${stats.mtime.getTime()}-${stats.size}"`, - 'Accept-Ranges': 'bytes', - 'Cache-Control': 'no-cache' - }); - console.log(`📖 Word öffnet Template: ${filename}`); - res.sendFile(filePath); - } else { - res.status(404).send('Not Found'); - } -}); - -app.get('/webdav/documents/:filename', (req, res) => { - const filename = req.params.filename; - const filePath = path.join(outputDir, filename); - - if (fs.existsSync(filePath)) { - const stats = fs.statSync(filePath); - res.set({ - 'DAV': '1, 2, ordered-collections, versioning', - 'MS-Author-Via': 'DAV', - 'Server': 'Microsoft-IIS/10.0', - 'Content-Type': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', - 'Content-Length': stats.size, - 'Last-Modified': stats.mtime.toUTCString(), - 'ETag': `"${stats.mtime.getTime()}-${stats.size}"`, - 'Accept-Ranges': 'bytes', - 'Cache-Control': 'no-cache' - }); - console.log(`📖 Word öffnet Dokument: ${filename}`); - res.sendFile(filePath); - } else { - res.status(404).send('Not Found'); - } -}); - -// WebDAV LOCK/UNLOCK für Office -app.use('/webdav', (req, res, next) => { - if (req.method === 'LOCK') { - const lockToken = 'opaquelocktoken:' + Date.now() + '-' + Math.random().toString(36).substr(2, 9); - - const lockResponse = ` - - - - - - 0 - Second-604800 - ${lockToken} - - -`; - - res.set({ - 'Content-Type': 'application/xml; charset=utf-8', - 'Lock-Token': `<${lockToken}>`, - 'DAV': '1, 2', - 'MS-Author-Via': 'DAV' - }); - res.status(200).send(lockResponse); - return; - } - - if (req.method === 'UNLOCK') { - res.set({ - 'DAV': '1, 2', - 'MS-Author-Via': 'DAV' - }); - res.status(204).send(); - return; - } - - next(); -}); - -app.use('/webdav/documents', express.static(outputDir, { - setHeaders: (res, path) => { - res.set({ - 'DAV': '1, 2', - 'Allow': 'GET, PUT, DELETE, PROPFIND, PROPPATCH, MKCOL, COPY, MOVE, HEAD, OPTIONS', - 'Access-Control-Allow-Origin': '*', - 'Access-Control-Allow-Methods': 'GET, PUT, DELETE, PROPFIND, PROPPATCH, MKCOL, COPY, MOVE, HEAD, OPTIONS', - 'Access-Control-Allow-Headers': 'Content-Type, Depth, Authorization, If-Match, If-None-Match, Overwrite, Destination', - 'MS-Author-Via': 'DAV', - 'Cache-Control': 'no-cache' - }); - } -})); - -// WebDAV PROPFIND Support für Word -app.use('/webdav/*', (req, res, next) => { - if (req.method === 'PROPFIND') { - res.set({ - 'Content-Type': 'application/xml; charset=utf-8', - 'DAV': '1, 2', - 'MS-Author-Via': 'DAV' - }); - - const propfindResponse = ` - - - ${req.originalUrl} - - HTTP/1.1 200 OK - - - httpd/unix-directory - - - - - - - - - -`; - - res.status(207).send(propfindResponse); - return; - } - next(); -}); - -// SharePoint-spezifische Endpunkte -app.get('/_vti_inf.html', (req, res) => { - // SharePoint Info-Seite - res.set('Content-Type', 'text/html'); - res.send(``); -}); - -app.post('/_vti_bin/lists.asmx', (req, res) => { - // SharePoint Lists Web Service - res.set({ - 'Content-Type': 'text/xml; charset=utf-8', - 'SOAPAction': req.headers.soapaction || '' - }); - - const soapResponse = ` - - - - - - - - - -`; - - res.send(soapResponse); -}); - -app.get('/_vti_bin/owssvr.dll', (req, res) => { - // SharePoint OWS Service - if (req.query.Cmd === 'Display' && req.query.List) { - res.set('Content-Type', 'text/xml'); - res.send(` - - - - - - - - - - - -`); - } else { - res.status(404).send('Not Found'); - } -}); - -// SharePoint-kompatible WebDAV-Root -app.use('/sharepoint', (req, res, next) => { - // SharePoint-spezifische Header - res.set({ - 'MicrosoftSharePointTeamServices': '15.0.0.4569', - 'SharePointHealthScore': '0', - 'SPRequestGuid': `{${crypto.randomUUID()}}`, - 'X-SharePoint-HealthScore': '0' - }); - - // Weiterleitung zu WebDAV - const newPath = req.path.replace('/sharepoint', '/webdav'); - req.url = newPath; - next(); -}); - -console.log('SharePoint-Kompatibilitätsmodus aktiviert:'); -console.log('SharePoint WebDAV: http://localhost:' + (process.env.PORT || 80) + '/sharepoint/templates/'); -console.log('SharePoint Info: http://localhost:' + (process.env.PORT || 80) + '/_vti_inf.html'); - -// Multer für File Upload -const upload = multer({ dest: 'uploads/' }); - -// Demo-Daten Generator -class DemoDataGenerator { - static generateData(tags) { - const data = {}; - - tags.forEach(tag => { - const lowerTag = tag.toLowerCase(); - - if (lowerTag.includes('name') || lowerTag.includes('vorname')) { - data[tag] = faker.person.firstName(); - } else if (lowerTag.includes('nachname') || lowerTag.includes('surname')) { - data[tag] = faker.person.lastName(); - } else if (lowerTag.includes('email') || lowerTag.includes('mail')) { - data[tag] = faker.internet.email(); - } else if (lowerTag.includes('telefon') || lowerTag.includes('phone')) { - data[tag] = faker.phone.number(); - } else if (lowerTag.includes('adresse') || lowerTag.includes('address')) { - data[tag] = faker.location.streetAddress(); - } else if (lowerTag.includes('stadt') || lowerTag.includes('city')) { - data[tag] = faker.location.city(); - } else if (lowerTag.includes('plz') || lowerTag.includes('postal')) { - data[tag] = faker.location.zipCode(); - } else if (lowerTag.includes('land') || lowerTag.includes('country')) { - data[tag] = faker.location.country(); - } else if (lowerTag.includes('datum') || lowerTag.includes('date')) { - data[tag] = faker.date.recent().toLocaleDateString('de-DE'); - } else if (lowerTag.includes('betrag') || lowerTag.includes('preis') || lowerTag.includes('amount')) { - data[tag] = faker.commerce.price(); - } else if (lowerTag.includes('firma') || lowerTag.includes('company')) { - data[tag] = faker.company.name(); - } else if (lowerTag.includes('produkt') || lowerTag.includes('product')) { - data[tag] = faker.commerce.productName(); - } else if (lowerTag.includes('beschreibung') || lowerTag.includes('description')) { - data[tag] = faker.lorem.paragraph(); - } else if (lowerTag.includes('nummer') || lowerTag.includes('number') || lowerTag.includes('id')) { - data[tag] = faker.string.numeric(6); - } else { - // Fallback für unbekannte Tags - data[tag] = faker.lorem.words(2); - } - }); - - return data; - } - - static generateTableData(tableStructure) { - const rows = Math.floor(Math.random() * 5) + 2; // 2-6 Zeilen - const tableData = []; - - for (let i = 0; i < rows; i++) { - const row = {}; - tableStructure.forEach(column => { - if (column.includes('position')) { - row[column] = (i + 1).toString(); // Fortlaufende Positionsnummer - } else { - row[column] = this.generateData([column])[column]; - } - }); - tableData.push(row); - } - - return tableData; - } -} - -// Template Tag Extractor -class TemplateTagExtractor { - static extractTags(docxBuffer) { - try { - const zip = new PizZip(docxBuffer); - const doc = new Docxtemplater(zip, { - paragraphLoop: true, - linebreaks: true, - }); - - // Alle Tags aus dem Template extrahieren - const tags = new Set(); - const content = zip.file('word/document.xml').asText(); - - // Einfache Tags: {tag} - const simpleTagRegex = /{([^{}]+)}/g; - let match; - while ((match = simpleTagRegex.exec(content)) !== null) { - const tag = match[1].trim(); - if (!tag.includes('#') && !tag.includes('/')) { - tags.add(tag); - } - } - - // Loop Tags für Tabellen: {#items}...{/items} - const loopTagRegex = /{#(\w+)}/g; - const loopTags = []; - while ((match = loopTagRegex.exec(content)) !== null) { - loopTags.push(match[1]); - } - - return { - simpleTags: Array.from(tags), - loopTags: loopTags - }; - } catch (error) { - console.error('Fehler beim Extrahieren der Tags:', error); - return { simpleTags: [], loopTags: [] }; - } - } -} - -// Template Processor -class TemplateProcessor { - static async processTemplate(templatePath, outputPath, customData = null) { - try { - const content = fs.readFileSync(templatePath, 'binary'); - const zip = new PizZip(content); - - // Tags extrahieren - const { simpleTags, loopTags } = TemplateTagExtractor.extractTags(Buffer.from(content, 'binary')); - - // Daten generieren oder verwenden - let data = customData || {}; - - if (!customData) { - // Demo-Daten für einfache Tags generieren - data = DemoDataGenerator.generateData(simpleTags); - - // Demo-Daten für Loop Tags (Tabellen) generieren - loopTags.forEach(loopTag => { - // Erweiterte Tabellen-Spalten für professionelle Rechnung - const tableColumns = [`${loopTag}_position`, `${loopTag}_name`, `${loopTag}_value`, `${loopTag}_date`]; - data[loopTag] = DemoDataGenerator.generateTableData(tableColumns); - }); - } - - const doc = new Docxtemplater(zip, { - paragraphLoop: true, - linebreaks: true, - }); - - doc.render(data); - - const buf = doc.getZip().generate({ - type: 'nodebuffer', - compression: 'DEFLATE', - }); - - fs.writeFileSync(outputPath, buf); - - return { - success: true, - data: data, - extractedTags: { simpleTags, loopTags } - }; - } catch (error) { - console.error('Template Verarbeitung fehlgeschlagen:', error); - return { - success: false, - error: error.message - }; - } - } -} - -// Routes - -// Hauptseite -app.get('/', (req, res) => { - res.send(` - - - - DOCX Template Server - - - - -
-

DOCX Template Server

- -
-

📄 Template hochladen und verarbeiten

-
- -
- -
-
- -
-

📁 Office-Integration

-
- Word WebDAV Templates: http://localhost:${PORT}/webdav/templates/
- Word WebDAV Dokumente: http://localhost:${PORT}/webdav/documents/
- ${fs.existsSync(path.join(__dirname, '203_key.pem')) && fs.existsSync(path.join(__dirname, '203_cert.pem')) ? - `Templates (HTTPS): https://localhost:443/webdav/templates/
- Dokumente (HTTPS): https://localhost:443/webdav/documents/` : - 'HTTPS verfügbar sobald SSL-Zertifikate (203_cert.pem und 203_key.pem) im Projektverzeichnis vorhanden sind'} -
-

Office-Integration: Öffnen Sie in Word/Excel: Datei → Öffnen → Netzwerk hinzufügen → WebDAV → http://localhost:${PORT}/webdav/templates/

-

Direkt speichern: Word speichert automatisch auf dem Server wenn über WebDAV geöffnet.

-
- -
-

🔧 API Endpunkte

- -

Word-Integration: Die API liefert spezielle Links für Microsoft Word:

-
    -
  • wordWebdavUrl - Direkt in Word öffnen (ms-word: Protocol)
  • -
  • wordDirectUrl - Alternative Word-Integration
  • -
  • webdavDirect - Windows UNC-Pfad für Netzlaufwerk
  • -
-
- -
-

📋 Test Template

- Test Template erstellen -

Erstellt ein Beispiel-Template mit verschiedenen Tag-Typen für Tests.

-
-
- - - `); -}); - -// Template Upload und Verarbeitung -app.post('/upload-template', upload.single('template'), async (req, res) => { - try { - if (!req.file) { - return res.status(400).json({ error: 'Keine Datei hochgeladen' }); - } - - const templateName = req.file.originalname; - const templatePath = path.join(templateDir, templateName); - const outputName = templateName.replace('.docx', '_ausgefuellt.docx'); - const outputPath = path.join(outputDir, outputName); - - // Template in Templates-Verzeichnis kopieren - fs.copyFileSync(req.file.path, templatePath); - - // Template verarbeiten - const result = await TemplateProcessor.processTemplate(templatePath, outputPath); - - // Upload-Datei löschen - fs.unlinkSync(req.file.path); - - if (result.success) { - const protocol = req.secure ? 'https' : 'http'; - const host = req.get('host') || `localhost:${PORT}`; - - res.json({ - message: 'Template erfolgreich verarbeitet', - templateName: templateName, - outputName: outputName, - extractedTags: result.extractedTags, - generatedData: result.data, - fileUrls: { - template: `${protocol}://${host}/webdav/templates/${templateName}`, - document: `${protocol}://${host}/webdav/documents/${outputName}`, - wordWebdavTemplate: `ms-word:ofe|u|${protocol}://${host}/webdav/templates/${encodeURIComponent(templateName)}`, - wordWebdavDocument: `ms-word:ofe|u|${protocol}://${host}/webdav/documents/${encodeURIComponent(outputName)}`, - wordDirectTemplate: `word:ofe|u|${protocol}://${host}/webdav/templates/${encodeURIComponent(templateName)}`, - wordDirectDocument: `word:ofe|u|${protocol}://${host}/webdav/documents/${encodeURIComponent(outputName)}` - } - }); - } else { - res.status(500).json({ error: result.error }); - } - } catch (error) { - console.error('Upload Fehler:', error); - res.status(500).json({ error: 'Server Fehler beim Upload' }); - } -}); - -// Test Template erstellen -app.get('/create-test-template', (req, res) => { - const PizZip = require('pizzip'); - - // Minimales DOCX Template erstellen - const testContent = ` - - - Firmenname: {firma} - Ansprechpartner: {vorname} {nachname} - E-Mail: {email} - Telefon: {telefon} - Adresse: {adresse}, {plz} {stadt} - Datum: {datum} - Rechnungsnummer: {nummer} - - Positionen: - {#items} - - {items_name}: {items_value} EUR ({items_date}) - {/items} - - Gesamtbetrag: {betrag} EUR - - Beschreibung: - {beschreibung} - - - `; - - try { - // Minimal DOCX Struktur - const zip = new PizZip(); - - // document.xml - zip.file('word/document.xml', testContent); - - // [Content_Types].xml - zip.file('[Content_Types].xml', ` - - - - - `); - - // _rels/.rels - zip.file('_rels/.rels', ` - - - `); - - // word/_rels/document.xml.rels - zip.file('word/_rels/document.xml.rels', ` - - `); - - const buffer = zip.generate({ type: 'nodebuffer' }); - const testTemplatePath = path.join(templateDir, 'test_template.docx'); - - fs.writeFileSync(testTemplatePath, buffer); - - res.json({ - message: 'Test Template erstellt', - templatePath: 'test_template.docx', - fileUrl: `http://localhost:${PORT}/webdav/templates/test_template.docx`, - info: 'Sie können das Template jetzt über den Datei-Server herunterladen, bearbeiten und wieder hochladen.' - }); - } catch (error) { - console.error('Fehler beim Erstellen des Test Templates:', error); - res.status(500).json({ error: 'Fehler beim Erstellen des Test Templates' }); - } -}); - -// API Endpunkte -app.get('/api/templates', (req, res) => { - try { - const files = fs.readdirSync(templateDir).filter(file => file.endsWith('.docx')); - const protocol = req.secure ? 'https' : 'http'; - const host = req.get('host') || `localhost:${PORT}`; - - res.json({ - templates: files.map(file => ({ - name: file, - fileUrl: `${protocol}://${host}/webdav/templates/${file}`, - wordWebdavUrl: `ms-word:ofe|u|${protocol}://${host}/webdav/templates/${encodeURIComponent(file)}`, - wordDirectUrl: `word:ofe|u|${protocol}://${host}/webdav/templates/${encodeURIComponent(file)}`, - downloadUrl: `${protocol}://${host}/webdav/templates/${file}`, - webdavDirect: `\\\\${host.split(':')[0]}@${PORT}\\webdav\\templates\\${file}` - })) - }); - } catch (error) { - res.status(500).json({ error: 'Fehler beim Auflisten der Templates' }); - } -}); - -app.get('/api/documents', (req, res) => { - try { - const files = fs.readdirSync(outputDir).filter(file => file.endsWith('.docx')); - const protocol = req.secure ? 'https' : 'http'; - const host = req.get('host') || `localhost:${PORT}`; - - res.json({ - documents: files.map(file => ({ - name: file, - fileUrl: `${protocol}://${host}/webdav/documents/${file}`, - wordWebdavUrl: `ms-word:ofe|u|${protocol}://${host}/webdav/documents/${encodeURIComponent(file)}`, - wordDirectUrl: `word:ofe|u|${protocol}://${host}/webdav/documents/${encodeURIComponent(file)}`, - downloadUrl: `${protocol}://${host}/webdav/documents/${file}`, - webdavDirect: `\\\\${host.split(':')[0]}@${PORT}\\webdav\\documents\\${file}`, - createdAt: fs.statSync(path.join(outputDir, file)).mtime - })) - }); - } catch (error) { - res.status(500).json({ error: 'Fehler beim Auflisten der Dokumente' }); - } -}); - -// Template mit benutzerdefinierten Daten verarbeiten -app.post('/api/process-template/:templateName', (req, res) => { - try { - const templateName = req.params.templateName; - const templatePath = path.join(templateDir, templateName); - - if (!fs.existsSync(templatePath)) { - return res.status(404).json({ error: 'Template nicht gefunden' }); - } - - const outputName = templateName.replace('.docx', '_custom.docx'); - const outputPath = path.join(outputDir, outputName); - - TemplateProcessor.processTemplate(templatePath, outputPath, req.body).then(result => { - if (result.success) { - res.json({ - message: 'Template mit benutzerdefinierten Daten verarbeitet', - outputName: outputName, - fileUrl: `http://localhost:${PORT}/webdav/documents/${outputName}` - }); - } else { - res.status(500).json({ error: result.error }); - } - }); - } catch (error) { - res.status(500).json({ error: 'Fehler beim Verarbeiten des Templates' }); - } -}); - -// SSL Konfiguration -const certPath = path.join(__dirname, '203_cert.pem'); -const keyPath = path.join(__dirname, '203_key.pem'); - -if (fs.existsSync(keyPath) && fs.existsSync(certPath)) { - try { - const sslOptions = { - key: fs.readFileSync(keyPath), - cert: fs.readFileSync(certPath) - }; - - https.createServer(sslOptions, app).listen(443, () => { - console.log('🔒 HTTPS Server läuft auf Port 443'); - console.log('🌐 HTTPS Zugang: https://localhost:443'); - }); - } catch (error) { - console.warn('⚠️ SSL-Zertifikate gefunden, aber Fehler beim Laden:', error.message); - console.log('ℹ️ Server läuft nur mit HTTP'); - } -} else { - console.log('ℹ️ SSL-Zertifikate nicht gefunden - Server läuft nur mit HTTP'); - console.log('💡 Für HTTPS: Platzieren Sie 203_cert.pem und 203_key.pem in /home/OfficeServerJS/'); -} - -// Server starten -app.listen(PORT, () => { - console.log(`\n🚀 DOCX Template Server gestartet!`); - console.log(`📍 HTTP Server: http://localhost:${PORT}`); - console.log(`📁 Templates: http://localhost:${PORT}/webdav/templates/`); - console.log(`📁 Documents: http://localhost:${PORT}/webdav/documents/`); - console.log(`\n💡 Tipp: Besuchen Sie http://localhost:${PORT} für die Web-Oberfläche`); - - // SSL-Status anzeigen - const certPath = path.join(__dirname, '203_cert.pem'); - const keyPath = path.join(__dirname, '203_key.pem'); - if (fs.existsSync(keyPath) && fs.existsSync(certPath)) { - console.log(`🔒 HTTPS auch verfügbar: https://localhost:443`); - } -}); - -module.exports = app; \ No newline at end of file diff --git a/server_webdav_backup.js b/server_webdav_backup.js deleted file mode 100644 index 4a758ba..0000000 --- a/server_webdav_backup.js +++ /dev/null @@ -1,939 +0,0 @@ -const express = require('express'); -const Docxtemplater = require('docxtemplater'); -const PizZip = require('pizzip'); -const fs = require('fs'); -const path = require('path'); -const multer = require('multer'); -const cors = require('cors'); -const helmet = require('helmet'); -const https = require('https'); -const crypto = require('crypto'); -const { faker } = require('@faker-js/faker'); - -const app = express(); -const PORT = process.env.PORT || 80; - -// Middleware -app.use(helmet()); -app.use(cors()); -app.use(express.json()); -app.use(express.urlencoded({ extended: true })); - -// Verzeichnisse erstellen -const templateDir = path.join(__dirname, 'templates'); -const outputDir = path.join(__dirname, 'documents'); - -[templateDir, outputDir].forEach(dir => { - if (!fs.existsSync(dir)) { - fs.mkdirSync(dir, { recursive: true }); - } -}); - -// WebDAV-Implementierung für Word/Office-Integration mit SharePoint-Kompatibilität -const webdavMethods = ['PROPFIND', 'PROPPATCH', 'MKCOL', 'COPY', 'MOVE', 'LOCK', 'UNLOCK']; - -// SharePoint-spezifische Namespaces und Header -const sharePointNamespaces = { - 'xmlns:D': 'DAV:', - 'xmlns:S': 'http://schemas.microsoft.com/sharepoint/soap/', - 'xmlns:Z': 'urn:schemas-microsoft-com:', - 'xmlns:O': 'urn:schemas-microsoft-com:office:office', - 'xmlns:T': 'http://schemas.microsoft.com/repl/' -}; - -// WebDAV PROPFIND Handler mit SharePoint-Modus -app.use('/webdav', (req, res, next) => { - // Erweiterte CORS und WebDAV-Header für Office/SharePoint - res.set({ - 'DAV': '1, 2, ordered-collections, versioning, extended-mkcol', - 'MS-Author-Via': 'DAV', - 'Server': 'Microsoft-IIS/10.0 Microsoft-HTTPAPI/2.0', - 'MicrosoftSharePointTeamServices': '15.0.0.4569', - 'SPRequestGuid': `{${crypto.randomUUID()}}`, - 'SPIisLatency': '0', - 'Allow': 'GET, HEAD, POST, PUT, DELETE, OPTIONS, PROPFIND, PROPPATCH, MKCOL, COPY, MOVE, LOCK, UNLOCK', - 'Access-Control-Allow-Origin': '*', - 'Access-Control-Allow-Methods': 'GET, HEAD, POST, PUT, DELETE, OPTIONS, PROPFIND, PROPPATCH, MKCOL, COPY, MOVE, LOCK, UNLOCK', - 'Access-Control-Allow-Headers': 'Content-Type, Depth, Authorization, Destination, If, Lock-Token, Overwrite, Timeout, X-Requested-With, SOAPAction', - 'Cache-Control': 'no-cache, no-store, must-revalidate', - 'Pragma': 'no-cache', - 'Expires': '0', - 'X-SharePointHealthScore': '0', - 'X-AspNet-Version': '4.0.30319', - 'X-Powered-By': 'ASP.NET' - }); - - if (req.method === 'OPTIONS') { - return res.status(200).end(); - } - - if (req.method === 'PROPFIND') { - const depth = req.headers.depth || 'infinity'; - const requestPath = req.path.replace('/webdav', ''); - - let targetDir; - if (requestPath.startsWith('/templates')) { - targetDir = path.join(templateDir, requestPath.replace('/templates', '')); - } else if (requestPath.startsWith('/documents')) { - targetDir = path.join(outputDir, requestPath.replace('/documents', '')); - } else { - targetDir = __dirname; - } - - try { - let items = []; - - if (fs.existsSync(targetDir)) { - const stats = fs.statSync(targetDir); - - if (stats.isDirectory()) { - const files = fs.readdirSync(targetDir); - - // Verzeichnis selbst - items.push({ - href: req.path + (req.path.endsWith('/') ? '' : '/'), - isDirectory: true, - lastModified: stats.mtime.toUTCString(), - size: 0 - }); - - // Dateien im Verzeichnis - files.forEach(file => { - const filePath = path.join(targetDir, file); - const fileStats = fs.statSync(filePath); - - items.push({ - href: req.path + (req.path.endsWith('/') ? '' : '/') + file, - isDirectory: fileStats.isDirectory(), - lastModified: fileStats.mtime.toUTCString(), - size: fileStats.size || 0, - contentType: fileStats.isDirectory() ? 'httpd/unix-directory' : 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' - }); - }); - } else { - // Einzelne Datei - items.push({ - href: req.path, - isDirectory: false, - lastModified: stats.mtime.toUTCString(), - size: stats.size, - contentType: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' - }); - } - } - - // WebDAV XML Response mit SharePoint-spezifischen Eigenschaften - const xmlResponse = ` - -${items.map(item => ` - - ${item.href} - - - ${path.basename(item.href)} - ${item.lastModified} - ${item.size} - ${item.contentType} - ${item.isDirectory ? '' : ''} - - - - - - - - - - - "${Date.now()}-${item.size}" - ${new Date(item.lastModified).toISOString()} - ${item.isDirectory ? 'true' : 'false'} - F - F - F - F - ${new Date(item.lastModified).toISOString()} - ${new Date().toISOString()} - ${new Date(item.lastModified).toISOString()} - 00000020 - System Account - - 0 - - 1 - 0x0101 - 0 - - HTTP/1.1 200 OK - - `).join('')} -`; - - res.set('Content-Type', 'application/xml; charset=utf-8'); - res.status(207).send(xmlResponse); - } catch (error) { - res.status(404).send('Not Found'); - } - return; - } - - next(); -}); - -// WebDAV PUT Handler für Dateien speichern -// PUT - File Upload (für Word Speichern) -app.put('/dav/*', (req, res) => { - const filePath = path.join(__dirname, 'uploads', req.params[0]); - const dirPath = path.dirname(filePath); - - console.log(`� PUT Request: ${req.params[0]}`); - console.log(`📂 Speichere nach: ${filePath}`); - - // Stelle sicher dass der Ordner existiert - fs.mkdirSync(dirPath, { recursive: true }); - - const writeStream = fs.createWriteStream(filePath); - - req.pipe(writeStream); - - writeStream.on('finish', () => { - console.log(`✅ Datei gespeichert: ${filePath}`); - res.set({ - 'DAV': '1, 2, ordered-collections, versioning, extended-mkcol', - 'MS-Author-Via': 'DAV', - 'Server': 'Microsoft-IIS/10.0 Microsoft-HTTPAPI/2.0', - 'MicrosoftSharePointTeamServices': '15.0.0.4569', - 'SPRequestGuid': `{${crypto.randomUUID()}}`, - 'Cache-Control': 'no-cache', - 'ETag': `"${Date.now()}-${req.headers['content-length'] || 0}"`, - 'Last-Modified': new Date().toUTCString(), - 'X-SharePoint-HealthScore': '0' - }); - res.status(201).send('Created'); - }); - - writeStream.on('error', (err) => { - console.error(`❌ Fehler beim Speichern: ${err.message}`); - res.status(500).send('Internal Server Error'); - }); -}); - -app.put('/webdav/documents/:filename', (req, res) => { - const filename = req.params.filename; - const filePath = path.join(outputDir, filename); - - console.log(`📝 Word speichert Dokument: ${filename}`); - - const writeStream = fs.createWriteStream(filePath); - req.pipe(writeStream); - - writeStream.on('finish', () => { - // Dateirechte explizit setzen - try { - fs.chmodSync(filePath, 0o666); // Lese-/Schreibrechte für alle - } catch (error) { - console.warn('Warnung: Konnte Dateiberechtigungen nicht setzen:', error.message); - } - - res.set({ - 'DAV': '1, 2, ordered-collections, versioning', - 'MS-Author-Via': 'DAV', - 'Server': 'Microsoft-IIS/10.0', - 'Cache-Control': 'no-cache', - 'ETag': `"${Date.now()}-${req.headers['content-length'] || 0}"`, - 'Last-Modified': new Date().toUTCString() - }); - res.status(201).send('Created'); - console.log(`✅ Dokument gespeichert: ${filename}`); - }); - - writeStream.on('error', (error) => { - console.error('❌ Fehler beim Speichern:', error); - res.status(500).send('Internal Server Error'); - }); -}); - -// WebDAV GET Handler für Dateien lesen -app.get('/webdav/templates/:filename', (req, res) => { - const filename = req.params.filename; - const filePath = path.join(templateDir, filename); - - if (fs.existsSync(filePath)) { - const stats = fs.statSync(filePath); - res.set({ - 'DAV': '1, 2, ordered-collections, versioning', - 'MS-Author-Via': 'DAV', - 'Server': 'Microsoft-IIS/10.0', - 'Content-Type': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', - 'Content-Length': stats.size, - 'Last-Modified': stats.mtime.toUTCString(), - 'ETag': `"${stats.mtime.getTime()}-${stats.size}"`, - 'Accept-Ranges': 'bytes', - 'Cache-Control': 'no-cache' - }); - console.log(`📖 Word öffnet Template: ${filename}`); - res.sendFile(filePath); - } else { - res.status(404).send('Not Found'); - } -}); - -app.get('/webdav/documents/:filename', (req, res) => { - const filename = req.params.filename; - const filePath = path.join(outputDir, filename); - - if (fs.existsSync(filePath)) { - const stats = fs.statSync(filePath); - res.set({ - 'DAV': '1, 2, ordered-collections, versioning', - 'MS-Author-Via': 'DAV', - 'Server': 'Microsoft-IIS/10.0', - 'Content-Type': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', - 'Content-Length': stats.size, - 'Last-Modified': stats.mtime.toUTCString(), - 'ETag': `"${stats.mtime.getTime()}-${stats.size}"`, - 'Accept-Ranges': 'bytes', - 'Cache-Control': 'no-cache' - }); - console.log(`📖 Word öffnet Dokument: ${filename}`); - res.sendFile(filePath); - } else { - res.status(404).send('Not Found'); - } -}); - -// WebDAV LOCK/UNLOCK für Office -app.use('/webdav', (req, res, next) => { - if (req.method === 'LOCK') { - const lockToken = 'opaquelocktoken:' + Date.now() + '-' + Math.random().toString(36).substr(2, 9); - - const lockResponse = ` - - - - - - 0 - Second-604800 - ${lockToken} - - -`; - - res.set({ - 'Content-Type': 'application/xml; charset=utf-8', - 'Lock-Token': `<${lockToken}>`, - 'DAV': '1, 2', - 'MS-Author-Via': 'DAV' - }); - res.status(200).send(lockResponse); - return; - } - - if (req.method === 'UNLOCK') { - res.set({ - 'DAV': '1, 2', - 'MS-Author-Via': 'DAV' - }); - res.status(204).send(); - return; - } - - next(); -}); - -app.use('/webdav/documents', express.static(outputDir, { - setHeaders: (res, path) => { - res.set({ - 'DAV': '1, 2', - 'Allow': 'GET, PUT, DELETE, PROPFIND, PROPPATCH, MKCOL, COPY, MOVE, HEAD, OPTIONS', - 'Access-Control-Allow-Origin': '*', - 'Access-Control-Allow-Methods': 'GET, PUT, DELETE, PROPFIND, PROPPATCH, MKCOL, COPY, MOVE, HEAD, OPTIONS', - 'Access-Control-Allow-Headers': 'Content-Type, Depth, Authorization, If-Match, If-None-Match, Overwrite, Destination', - 'MS-Author-Via': 'DAV', - 'Cache-Control': 'no-cache' - }); - } -})); - -// WebDAV PROPFIND Support für Word -app.use('/webdav/*', (req, res, next) => { - if (req.method === 'PROPFIND') { - res.set({ - 'Content-Type': 'application/xml; charset=utf-8', - 'DAV': '1, 2', - 'MS-Author-Via': 'DAV' - }); - - const propfindResponse = ` - - - ${req.originalUrl} - - HTTP/1.1 200 OK - - - httpd/unix-directory - - - - - - - - - -`; - - res.status(207).send(propfindResponse); - return; - } - next(); -}); - -// SharePoint-spezifische Endpunkte -app.get('/_vti_inf.html', (req, res) => { - // SharePoint Info-Seite - res.set('Content-Type', 'text/html'); - res.send(``); -}); - -app.post('/_vti_bin/lists.asmx', (req, res) => { - // SharePoint Lists Web Service - res.set({ - 'Content-Type': 'text/xml; charset=utf-8', - 'SOAPAction': req.headers.soapaction || '' - }); - - const soapResponse = ` - - - - - - - - - -`; - - res.send(soapResponse); -}); - -app.get('/_vti_bin/owssvr.dll', (req, res) => { - // SharePoint OWS Service - if (req.query.Cmd === 'Display' && req.query.List) { - res.set('Content-Type', 'text/xml'); - res.send(` - - - - - - - - - - - -`); - } else { - res.status(404).send('Not Found'); - } -}); - -// SharePoint-kompatible WebDAV-Root -app.use('/sharepoint', (req, res, next) => { - // SharePoint-spezifische Header - res.set({ - 'MicrosoftSharePointTeamServices': '15.0.0.4569', - 'SharePointHealthScore': '0', - 'SPRequestGuid': `{${crypto.randomUUID()}}`, - 'X-SharePoint-HealthScore': '0' - }); - - // Weiterleitung zu WebDAV - const newPath = req.path.replace('/sharepoint', '/webdav'); - req.url = newPath; - next(); -}); - -console.log('SharePoint-Kompatibilitätsmodus aktiviert:'); -console.log('SharePoint WebDAV: http://localhost:' + (process.env.PORT || 80) + '/sharepoint/templates/'); -console.log('SharePoint Info: http://localhost:' + (process.env.PORT || 80) + '/_vti_inf.html'); - -// Multer für File Upload -const upload = multer({ dest: 'uploads/' }); - -// Demo-Daten Generator -class DemoDataGenerator { - static generateData(tags) { - const data = {}; - - tags.forEach(tag => { - const lowerTag = tag.toLowerCase(); - - if (lowerTag.includes('name') || lowerTag.includes('vorname')) { - data[tag] = faker.person.firstName(); - } else if (lowerTag.includes('nachname') || lowerTag.includes('surname')) { - data[tag] = faker.person.lastName(); - } else if (lowerTag.includes('email') || lowerTag.includes('mail')) { - data[tag] = faker.internet.email(); - } else if (lowerTag.includes('telefon') || lowerTag.includes('phone')) { - data[tag] = faker.phone.number(); - } else if (lowerTag.includes('adresse') || lowerTag.includes('address')) { - data[tag] = faker.location.streetAddress(); - } else if (lowerTag.includes('stadt') || lowerTag.includes('city')) { - data[tag] = faker.location.city(); - } else if (lowerTag.includes('plz') || lowerTag.includes('postal')) { - data[tag] = faker.location.zipCode(); - } else if (lowerTag.includes('land') || lowerTag.includes('country')) { - data[tag] = faker.location.country(); - } else if (lowerTag.includes('datum') || lowerTag.includes('date')) { - data[tag] = faker.date.recent().toLocaleDateString('de-DE'); - } else if (lowerTag.includes('betrag') || lowerTag.includes('preis') || lowerTag.includes('amount')) { - data[tag] = faker.commerce.price(); - } else if (lowerTag.includes('firma') || lowerTag.includes('company')) { - data[tag] = faker.company.name(); - } else if (lowerTag.includes('produkt') || lowerTag.includes('product')) { - data[tag] = faker.commerce.productName(); - } else if (lowerTag.includes('beschreibung') || lowerTag.includes('description')) { - data[tag] = faker.lorem.paragraph(); - } else if (lowerTag.includes('nummer') || lowerTag.includes('number') || lowerTag.includes('id')) { - data[tag] = faker.string.numeric(6); - } else { - // Fallback für unbekannte Tags - data[tag] = faker.lorem.words(2); - } - }); - - return data; - } - - static generateTableData(tableStructure) { - const rows = Math.floor(Math.random() * 5) + 2; // 2-6 Zeilen - const tableData = []; - - for (let i = 0; i < rows; i++) { - const row = {}; - tableStructure.forEach(column => { - if (column.includes('position')) { - row[column] = (i + 1).toString(); // Fortlaufende Positionsnummer - } else { - row[column] = this.generateData([column])[column]; - } - }); - tableData.push(row); - } - - return tableData; - } -} - -// Template Tag Extractor -class TemplateTagExtractor { - static extractTags(docxBuffer) { - try { - const zip = new PizZip(docxBuffer); - const doc = new Docxtemplater(zip, { - paragraphLoop: true, - linebreaks: true, - }); - - // Alle Tags aus dem Template extrahieren - const tags = new Set(); - const content = zip.file('word/document.xml').asText(); - - // Einfache Tags: {tag} - const simpleTagRegex = /{([^{}]+)}/g; - let match; - while ((match = simpleTagRegex.exec(content)) !== null) { - const tag = match[1].trim(); - if (!tag.includes('#') && !tag.includes('/')) { - tags.add(tag); - } - } - - // Loop Tags für Tabellen: {#items}...{/items} - const loopTagRegex = /{#(\w+)}/g; - const loopTags = []; - while ((match = loopTagRegex.exec(content)) !== null) { - loopTags.push(match[1]); - } - - return { - simpleTags: Array.from(tags), - loopTags: loopTags - }; - } catch (error) { - console.error('Fehler beim Extrahieren der Tags:', error); - return { simpleTags: [], loopTags: [] }; - } - } -} - -// Template Processor -class TemplateProcessor { - static async processTemplate(templatePath, outputPath, customData = null) { - try { - const content = fs.readFileSync(templatePath, 'binary'); - const zip = new PizZip(content); - - // Tags extrahieren - const { simpleTags, loopTags } = TemplateTagExtractor.extractTags(Buffer.from(content, 'binary')); - - // Daten generieren oder verwenden - let data = customData || {}; - - if (!customData) { - // Demo-Daten für einfache Tags generieren - data = DemoDataGenerator.generateData(simpleTags); - - // Demo-Daten für Loop Tags (Tabellen) generieren - loopTags.forEach(loopTag => { - // Erweiterte Tabellen-Spalten für professionelle Rechnung - const tableColumns = [`${loopTag}_position`, `${loopTag}_name`, `${loopTag}_value`, `${loopTag}_date`]; - data[loopTag] = DemoDataGenerator.generateTableData(tableColumns); - }); - } - - const doc = new Docxtemplater(zip, { - paragraphLoop: true, - linebreaks: true, - }); - - doc.render(data); - - const buf = doc.getZip().generate({ - type: 'nodebuffer', - compression: 'DEFLATE', - }); - - fs.writeFileSync(outputPath, buf); - - return { - success: true, - data: data, - extractedTags: { simpleTags, loopTags } - }; - } catch (error) { - console.error('Template Verarbeitung fehlgeschlagen:', error); - return { - success: false, - error: error.message - }; - } - } -} - -// Routes - -// Hauptseite -app.get('/', (req, res) => { - res.send(` - - - - DOCX Template Server - - - - -
-

DOCX Template Server

- -
-

📄 Template hochladen und verarbeiten

-
- -
- -
-
- -
-

📁 Office-Integration

-
- Word WebDAV Templates: http://localhost:${PORT}/webdav/templates/
- Word WebDAV Dokumente: http://localhost:${PORT}/webdav/documents/
- ${fs.existsSync(path.join(__dirname, '203_key.pem')) && fs.existsSync(path.join(__dirname, '203_cert.pem')) ? - `Templates (HTTPS): https://localhost:443/webdav/templates/
- Dokumente (HTTPS): https://localhost:443/webdav/documents/` : - 'HTTPS verfügbar sobald SSL-Zertifikate (203_cert.pem und 203_key.pem) im Projektverzeichnis vorhanden sind'} -
-

Office-Integration: Öffnen Sie in Word/Excel: Datei → Öffnen → Netzwerk hinzufügen → WebDAV → http://localhost:${PORT}/webdav/templates/

-

Direkt speichern: Word speichert automatisch auf dem Server wenn über WebDAV geöffnet.

-
- -
-

🔧 API Endpunkte

- -

Word-Integration: Die API liefert spezielle Links für Microsoft Word:

-
    -
  • wordWebdavUrl - Direkt in Word öffnen (ms-word: Protocol)
  • -
  • wordDirectUrl - Alternative Word-Integration
  • -
  • webdavDirect - Windows UNC-Pfad für Netzlaufwerk
  • -
-
- -
-

📋 Test Template

- Test Template erstellen -

Erstellt ein Beispiel-Template mit verschiedenen Tag-Typen für Tests.

-
-
- - - `); -}); - -// Template Upload und Verarbeitung -app.post('/upload-template', upload.single('template'), async (req, res) => { - try { - if (!req.file) { - return res.status(400).json({ error: 'Keine Datei hochgeladen' }); - } - - const templateName = req.file.originalname; - const templatePath = path.join(templateDir, templateName); - const outputName = templateName.replace('.docx', '_ausgefuellt.docx'); - const outputPath = path.join(outputDir, outputName); - - // Template in Templates-Verzeichnis kopieren - fs.copyFileSync(req.file.path, templatePath); - - // Template verarbeiten - const result = await TemplateProcessor.processTemplate(templatePath, outputPath); - - // Upload-Datei löschen - fs.unlinkSync(req.file.path); - - if (result.success) { - const protocol = req.secure ? 'https' : 'http'; - const host = req.get('host') || `localhost:${PORT}`; - - res.json({ - message: 'Template erfolgreich verarbeitet', - templateName: templateName, - outputName: outputName, - extractedTags: result.extractedTags, - generatedData: result.data, - fileUrls: { - template: `${protocol}://${host}/webdav/templates/${templateName}`, - document: `${protocol}://${host}/webdav/documents/${outputName}`, - wordWebdavTemplate: `ms-word:ofe|u|${protocol}://${host}/webdav/templates/${encodeURIComponent(templateName)}`, - wordWebdavDocument: `ms-word:ofe|u|${protocol}://${host}/webdav/documents/${encodeURIComponent(outputName)}`, - wordDirectTemplate: `word:ofe|u|${protocol}://${host}/webdav/templates/${encodeURIComponent(templateName)}`, - wordDirectDocument: `word:ofe|u|${protocol}://${host}/webdav/documents/${encodeURIComponent(outputName)}` - } - }); - } else { - res.status(500).json({ error: result.error }); - } - } catch (error) { - console.error('Upload Fehler:', error); - res.status(500).json({ error: 'Server Fehler beim Upload' }); - } -}); - -// Test Template erstellen -app.get('/create-test-template', (req, res) => { - const PizZip = require('pizzip'); - - // Minimales DOCX Template erstellen - const testContent = ` - - - Firmenname: {firma} - Ansprechpartner: {vorname} {nachname} - E-Mail: {email} - Telefon: {telefon} - Adresse: {adresse}, {plz} {stadt} - Datum: {datum} - Rechnungsnummer: {nummer} - - Positionen: - {#items} - - {items_name}: {items_value} EUR ({items_date}) - {/items} - - Gesamtbetrag: {betrag} EUR - - Beschreibung: - {beschreibung} - - - `; - - try { - // Minimal DOCX Struktur - const zip = new PizZip(); - - // document.xml - zip.file('word/document.xml', testContent); - - // [Content_Types].xml - zip.file('[Content_Types].xml', ` - - - - - `); - - // _rels/.rels - zip.file('_rels/.rels', ` - - - `); - - // word/_rels/document.xml.rels - zip.file('word/_rels/document.xml.rels', ` - - `); - - const buffer = zip.generate({ type: 'nodebuffer' }); - const testTemplatePath = path.join(templateDir, 'test_template.docx'); - - fs.writeFileSync(testTemplatePath, buffer); - - res.json({ - message: 'Test Template erstellt', - templatePath: 'test_template.docx', - fileUrl: `http://localhost:${PORT}/webdav/templates/test_template.docx`, - info: 'Sie können das Template jetzt über den Datei-Server herunterladen, bearbeiten und wieder hochladen.' - }); - } catch (error) { - console.error('Fehler beim Erstellen des Test Templates:', error); - res.status(500).json({ error: 'Fehler beim Erstellen des Test Templates' }); - } -}); - -// API Endpunkte -app.get('/api/templates', (req, res) => { - try { - const files = fs.readdirSync(templateDir).filter(file => file.endsWith('.docx')); - const protocol = req.secure ? 'https' : 'http'; - const host = req.get('host') || `localhost:${PORT}`; - - res.json({ - templates: files.map(file => ({ - name: file, - fileUrl: `${protocol}://${host}/webdav/templates/${file}`, - wordWebdavUrl: `ms-word:ofe|u|${protocol}://${host}/webdav/templates/${encodeURIComponent(file)}`, - wordDirectUrl: `word:ofe|u|${protocol}://${host}/webdav/templates/${encodeURIComponent(file)}`, - downloadUrl: `${protocol}://${host}/webdav/templates/${file}`, - webdavDirect: `\\\\${host.split(':')[0]}@${PORT}\\webdav\\templates\\${file}` - })) - }); - } catch (error) { - res.status(500).json({ error: 'Fehler beim Auflisten der Templates' }); - } -}); - -app.get('/api/documents', (req, res) => { - try { - const files = fs.readdirSync(outputDir).filter(file => file.endsWith('.docx')); - const protocol = req.secure ? 'https' : 'http'; - const host = req.get('host') || `localhost:${PORT}`; - - res.json({ - documents: files.map(file => ({ - name: file, - fileUrl: `${protocol}://${host}/webdav/documents/${file}`, - wordWebdavUrl: `ms-word:ofe|u|${protocol}://${host}/webdav/documents/${encodeURIComponent(file)}`, - wordDirectUrl: `word:ofe|u|${protocol}://${host}/webdav/documents/${encodeURIComponent(file)}`, - downloadUrl: `${protocol}://${host}/webdav/documents/${file}`, - webdavDirect: `\\\\${host.split(':')[0]}@${PORT}\\webdav\\documents\\${file}`, - createdAt: fs.statSync(path.join(outputDir, file)).mtime - })) - }); - } catch (error) { - res.status(500).json({ error: 'Fehler beim Auflisten der Dokumente' }); - } -}); - -// Template mit benutzerdefinierten Daten verarbeiten -app.post('/api/process-template/:templateName', (req, res) => { - try { - const templateName = req.params.templateName; - const templatePath = path.join(templateDir, templateName); - - if (!fs.existsSync(templatePath)) { - return res.status(404).json({ error: 'Template nicht gefunden' }); - } - - const outputName = templateName.replace('.docx', '_custom.docx'); - const outputPath = path.join(outputDir, outputName); - - TemplateProcessor.processTemplate(templatePath, outputPath, req.body).then(result => { - if (result.success) { - res.json({ - message: 'Template mit benutzerdefinierten Daten verarbeitet', - outputName: outputName, - fileUrl: `http://localhost:${PORT}/webdav/documents/${outputName}` - }); - } else { - res.status(500).json({ error: result.error }); - } - }); - } catch (error) { - res.status(500).json({ error: 'Fehler beim Verarbeiten des Templates' }); - } -}); - -// SSL Konfiguration -const certPath = path.join(__dirname, '203_cert.pem'); -const keyPath = path.join(__dirname, '203_key.pem'); - -if (fs.existsSync(keyPath) && fs.existsSync(certPath)) { - try { - const sslOptions = { - key: fs.readFileSync(keyPath), - cert: fs.readFileSync(certPath) - }; - - https.createServer(sslOptions, app).listen(443, () => { - console.log('🔒 HTTPS Server läuft auf Port 443'); - console.log('🌐 HTTPS Zugang: https://localhost:443'); - }); - } catch (error) { - console.warn('⚠️ SSL-Zertifikate gefunden, aber Fehler beim Laden:', error.message); - console.log('ℹ️ Server läuft nur mit HTTP'); - } -} else { - console.log('ℹ️ SSL-Zertifikate nicht gefunden - Server läuft nur mit HTTP'); - console.log('💡 Für HTTPS: Platzieren Sie 203_cert.pem und 203_key.pem in /home/OfficeServerJS/'); -} - -// Server starten -app.listen(PORT, () => { - console.log(`\n🚀 DOCX Template Server gestartet!`); - console.log(`📍 HTTP Server: http://localhost:${PORT}`); - console.log(`📁 Templates: http://localhost:${PORT}/webdav/templates/`); - console.log(`📁 Documents: http://localhost:${PORT}/webdav/documents/`); - console.log(`\n💡 Tipp: Besuchen Sie http://localhost:${PORT} für die Web-Oberfläche`); - - // SSL-Status anzeigen - const certPath = path.join(__dirname, '203_cert.pem'); - const keyPath = path.join(__dirname, '203_key.pem'); - if (fs.existsSync(keyPath) && fs.existsSync(certPath)) { - console.log(`🔒 HTTPS auch verfügbar: https://localhost:443`); - } -}); - -module.exports = app; \ No newline at end of file diff --git a/start-ssl.sh b/start-ssl.sh index def1f75..8c98073 100755 --- a/start-ssl.sh +++ b/start-ssl.sh @@ -50,10 +50,10 @@ echo " HTTP: http://localhost:80" echo " HTTPS: https://localhost:443" echo "" echo "📁 Dateifreigabe:" -echo " HTTP Templates: http://localhost:80/webdav/templates/" -echo " HTTPS Templates: https://localhost:443/webdav/templates/" -echo " HTTP Documents: http://localhost:80/webdav/documents/" -echo " HTTPS Documents: https://localhost:443/webdav/documents/" +echo " HTTP Templates: http://localhost:80/templates/" +echo " HTTPS Templates: https://localhost:443/templates/" +echo " HTTP Documents: http://localhost:80/documents/" +echo " HTTPS Documents: https://localhost:443/documents/" echo "" # Server mit SSL starten diff --git a/start.sh b/start.sh index 88f7ad4..b4e097e 100755 --- a/start.sh +++ b/start.sh @@ -28,8 +28,8 @@ fi echo "🌟 Starte den DOCX Template Server..." echo "" echo "📍 Web-Oberfläche: http://localhost:80" -echo "📁 Templates: http://localhost:80/webdav/templates/" -echo "📁 Dokumente: http://localhost:80/webdav/documents/" +echo "📁 Templates: http://localhost:80/templates/" +echo "📁 Dokumente: http://localhost:80/documents/" echo "" echo "💡 Drücken Sie Ctrl+C zum Beenden" echo ""