V1.0
This commit is contained in:
361
server.js
Normal file
361
server.js
Normal file
@@ -0,0 +1,361 @@
|
||||
const WebSocket = require('ws');
|
||||
const http = require('http');
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
|
||||
// Create HTTP server
|
||||
const server = http.createServer((req, res) => {
|
||||
// CORS headers
|
||||
res.setHeader('Access-Control-Allow-Origin', '*');
|
||||
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
|
||||
res.setHeader('Access-Control-Allow-Headers', 'Content-Type');
|
||||
|
||||
if (req.method === 'OPTIONS') {
|
||||
res.writeHead(200);
|
||||
res.end();
|
||||
return;
|
||||
}
|
||||
|
||||
// Serve files
|
||||
let urlPath = req.url;
|
||||
|
||||
// Remove query string if present
|
||||
urlPath = urlPath.split('?')[0];
|
||||
|
||||
// Handle root path
|
||||
if (urlPath === '/' || urlPath === '/index.html') {
|
||||
urlPath = '/html/signature.html';
|
||||
}
|
||||
|
||||
// Map URL paths to file system paths based on file type
|
||||
let cleanPath = urlPath.startsWith('/') ? urlPath.substring(1) : urlPath;
|
||||
|
||||
// Route requests to appropriate directories
|
||||
// Only add directory prefix if path doesn't already have it
|
||||
if (cleanPath.endsWith('.html')) {
|
||||
// HTML files from html/ directory
|
||||
const fileName = path.basename(cleanPath);
|
||||
if (!cleanPath.startsWith('html/')) {
|
||||
cleanPath = 'html/' + fileName;
|
||||
}
|
||||
} else if (cleanPath.endsWith('.css')) {
|
||||
// CSS files from css/ directory
|
||||
const fileName = path.basename(cleanPath);
|
||||
if (!cleanPath.startsWith('css/')) {
|
||||
cleanPath = 'css/' + fileName;
|
||||
}
|
||||
} else if (cleanPath.endsWith('.js')) {
|
||||
// JS files from js/ directory
|
||||
const fileName = path.basename(cleanPath);
|
||||
if (!cleanPath.startsWith('js/')) {
|
||||
cleanPath = 'js/' + fileName;
|
||||
}
|
||||
}
|
||||
|
||||
// Security: Prevent directory traversal attacks
|
||||
if (cleanPath.includes('..')) {
|
||||
res.writeHead(403, { 'Content-Type': 'text/html' });
|
||||
res.end('<h1>403 - Zugriff verweigert</h1>', 'utf-8');
|
||||
return;
|
||||
}
|
||||
|
||||
// Convert to filesystem path
|
||||
const filePath = path.join(process.cwd(), cleanPath);
|
||||
|
||||
// Security: Ensure resolved path is within current directory
|
||||
const currentDir = process.cwd();
|
||||
const resolvedPath = path.resolve(filePath);
|
||||
|
||||
if (!resolvedPath.startsWith(currentDir)) {
|
||||
res.writeHead(403, { 'Content-Type': 'text/html' });
|
||||
res.end('<h1>403 - Zugriff verweigert</h1>', 'utf-8');
|
||||
return;
|
||||
}
|
||||
|
||||
const extname = String(path.extname(filePath)).toLowerCase();
|
||||
const mimeTypes = {
|
||||
'.html': 'text/html; charset=utf-8',
|
||||
'.js': 'text/javascript; charset=utf-8',
|
||||
'.css': 'text/css; charset=utf-8',
|
||||
'.json': 'application/json',
|
||||
'.png': 'image/png',
|
||||
'.jpg': 'image/jpeg',
|
||||
'.jpeg': 'image/jpeg',
|
||||
'.gif': 'image/gif',
|
||||
'.svg': 'image/svg+xml',
|
||||
'.pdf': 'application/pdf',
|
||||
'.ico': 'image/x-icon'
|
||||
};
|
||||
|
||||
const contentType = mimeTypes[extname] || 'application/octet-stream';
|
||||
|
||||
// Log file requests for debugging
|
||||
console.log(`📄 Request: ${req.url} -> ${filePath} (${contentType})`);
|
||||
|
||||
fs.readFile(filePath, (error, content) => {
|
||||
if (error) {
|
||||
if (error.code === 'ENOENT') {
|
||||
console.log(`❌ 404: Datei nicht gefunden: ${filePath}`);
|
||||
res.writeHead(404, { 'Content-Type': 'text/html; charset=utf-8' });
|
||||
res.end(`<h1>404 - Datei nicht gefunden</h1><p>Gesuchte Datei: ${filePath}</p>`, 'utf-8');
|
||||
} else {
|
||||
console.error(`❌ Server Fehler bei ${filePath}:`, error);
|
||||
res.writeHead(500, { 'Content-Type': 'text/html; charset=utf-8' });
|
||||
res.end(`<h1>500 - Server Fehler</h1><p>${error.code}</p>`, 'utf-8');
|
||||
}
|
||||
} else {
|
||||
res.writeHead(200, { 'Content-Type': contentType });
|
||||
res.end(content, 'utf-8');
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Create WebSocket server
|
||||
const wss = new WebSocket.Server({ server });
|
||||
|
||||
// Store connections
|
||||
let masterConnection = null;
|
||||
let signatureConnection = null;
|
||||
|
||||
wss.on('connection', (ws) => {
|
||||
console.log('Neue WebSocket Verbindung');
|
||||
|
||||
ws.on('message', (message) => {
|
||||
try {
|
||||
const data = JSON.parse(message);
|
||||
console.log('📨 Nachricht empfangen:', data.type);
|
||||
console.log(' Von:', ws === masterConnection ? 'Master' : ws === signatureConnection ? 'Signatur-Station' : 'Unbekannt');
|
||||
|
||||
switch (data.type) {
|
||||
case 'register_master':
|
||||
handleMasterRegister(ws);
|
||||
break;
|
||||
|
||||
case 'register_signature':
|
||||
handleSignatureRegister(ws);
|
||||
break;
|
||||
|
||||
case 'pdf':
|
||||
handlePdfUpload(data);
|
||||
break;
|
||||
|
||||
case 'signature':
|
||||
handleSignature(data);
|
||||
break;
|
||||
|
||||
case 'page_change':
|
||||
handlePageChange(data);
|
||||
break;
|
||||
|
||||
case 'signature_placed':
|
||||
console.log('🔄 signature_placed Nachricht empfangen, leite weiter...');
|
||||
handleSignaturePlaced();
|
||||
break;
|
||||
|
||||
case 'discard':
|
||||
console.log('🔄 discard Nachricht empfangen, leite weiter...');
|
||||
handleDiscard();
|
||||
break;
|
||||
|
||||
default:
|
||||
console.log('⚠️ Unbekannter Nachrichtentyp:', data.type);
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('❌ Fehler beim Verarbeiten der Nachricht:', error);
|
||||
}
|
||||
});
|
||||
|
||||
ws.on('close', () => {
|
||||
console.log('WebSocket Verbindung geschlossen');
|
||||
if (ws === masterConnection) {
|
||||
masterConnection = null;
|
||||
console.log('Master getrennt');
|
||||
}
|
||||
if (ws === signatureConnection) {
|
||||
signatureConnection = null;
|
||||
console.log('Signatur-Station getrennt');
|
||||
|
||||
// Notify master that signature station disconnected
|
||||
if (masterConnection && masterConnection.readyState === WebSocket.OPEN) {
|
||||
masterConnection.send(JSON.stringify({
|
||||
type: 'signature_station_disconnected'
|
||||
}));
|
||||
console.log('Master über Signatur-Station Trennung informiert');
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
function handleMasterRegister(ws) {
|
||||
masterConnection = ws;
|
||||
console.log('Master registriert');
|
||||
|
||||
// Notify master about current signature station connection status
|
||||
if (signatureConnection && signatureConnection.readyState === WebSocket.OPEN) {
|
||||
ws.send(JSON.stringify({
|
||||
type: 'signature_station_connected'
|
||||
}));
|
||||
console.log('Master über Signatur-Station Verbindung informiert');
|
||||
} else {
|
||||
ws.send(JSON.stringify({
|
||||
type: 'signature_station_disconnected'
|
||||
}));
|
||||
console.log('Master über fehlende Signatur-Station informiert');
|
||||
}
|
||||
}
|
||||
|
||||
function handleSignatureRegister(ws) {
|
||||
signatureConnection = ws;
|
||||
console.log('Signatur-Station registriert');
|
||||
|
||||
// Notify master that signature station is now connected
|
||||
if (masterConnection && masterConnection.readyState === WebSocket.OPEN) {
|
||||
masterConnection.send(JSON.stringify({
|
||||
type: 'signature_station_connected'
|
||||
}));
|
||||
console.log('Master über Signatur-Station Verbindung informiert');
|
||||
}
|
||||
}
|
||||
|
||||
function handlePdfUpload(data) {
|
||||
const { pdf } = data;
|
||||
|
||||
if (!signatureConnection || signatureConnection.readyState !== WebSocket.OPEN) {
|
||||
console.log('Keine Signatur-Station verbunden');
|
||||
return;
|
||||
}
|
||||
|
||||
// Forward PDF to signature station
|
||||
signatureConnection.send(JSON.stringify({
|
||||
type: 'pdf',
|
||||
pdf: pdf
|
||||
}));
|
||||
|
||||
console.log('PDF an Signatur-Station weitergeleitet');
|
||||
}
|
||||
|
||||
function handleSignature(data) {
|
||||
const { signature } = data;
|
||||
|
||||
if (!masterConnection || masterConnection.readyState !== WebSocket.OPEN) {
|
||||
console.log('Keine Master-Verbindung');
|
||||
return;
|
||||
}
|
||||
|
||||
// Send signature to master
|
||||
masterConnection.send(JSON.stringify({
|
||||
type: 'signature',
|
||||
signature: signature
|
||||
}));
|
||||
|
||||
console.log('Unterschrift an Master gesendet');
|
||||
}
|
||||
|
||||
function handlePageChange(data) {
|
||||
const { pageNum, totalPages } = data;
|
||||
|
||||
if (!signatureConnection || signatureConnection.readyState !== WebSocket.OPEN) {
|
||||
console.log('Keine Signatur-Station verbunden');
|
||||
return;
|
||||
}
|
||||
|
||||
// Forward page change to signature station
|
||||
signatureConnection.send(JSON.stringify({
|
||||
type: 'page_change',
|
||||
pageNum: pageNum,
|
||||
totalPages: totalPages
|
||||
}));
|
||||
|
||||
console.log('Seitenwechsel an Signatur-Station weitergeleitet: Seite', pageNum, 'von', totalPages);
|
||||
}
|
||||
|
||||
function handleSignaturePlaced() {
|
||||
console.log('handleSignaturePlaced() aufgerufen');
|
||||
console.log('signatureConnection vorhanden:', signatureConnection ? 'Ja' : 'Nein');
|
||||
console.log('signatureConnection.readyState:', signatureConnection ? signatureConnection.readyState : 'N/A');
|
||||
|
||||
if (!signatureConnection || signatureConnection.readyState !== WebSocket.OPEN) {
|
||||
console.log('⚠️ Keine Signatur-Station verbunden - Bestätigung kann nicht gesendet werden');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// Forward signature placed confirmation to signature station
|
||||
const message = JSON.stringify({
|
||||
type: 'signature_placed'
|
||||
});
|
||||
signatureConnection.send(message);
|
||||
console.log('✅ Unterschrift-Platzierung-Bestätigung an Signatur-Station gesendet');
|
||||
} catch (error) {
|
||||
console.error('❌ Fehler beim Senden der Bestätigung:', error);
|
||||
}
|
||||
}
|
||||
|
||||
function handleDiscard() {
|
||||
console.log('handleDiscard() aufgerufen');
|
||||
console.log('signatureConnection vorhanden:', signatureConnection ? 'Ja' : 'Nein');
|
||||
console.log('signatureConnection.readyState:', signatureConnection ? signatureConnection.readyState : 'N/A');
|
||||
|
||||
if (!signatureConnection || signatureConnection.readyState !== WebSocket.OPEN) {
|
||||
console.log('⚠️ Keine Signatur-Station verbunden - Verwerfen-Nachricht kann nicht gesendet werden');
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
// Forward discard message to signature station
|
||||
const message = JSON.stringify({
|
||||
type: 'discard'
|
||||
});
|
||||
signatureConnection.send(message);
|
||||
console.log('✅ Verwerfen-Nachricht an Signatur-Station gesendet');
|
||||
} catch (error) {
|
||||
console.error('❌ Fehler beim Senden der Verwerfen-Nachricht:', error);
|
||||
}
|
||||
}
|
||||
|
||||
const PORT = 8080;
|
||||
const HOST = '0.0.0.0'; // Listen on all network interfaces
|
||||
|
||||
server.listen(PORT, HOST, () => {
|
||||
const os = require('os');
|
||||
const networkInterfaces = os.networkInterfaces();
|
||||
let ipAddresses = [];
|
||||
|
||||
// Get all IPv4 addresses
|
||||
Object.keys(networkInterfaces).forEach((interfaceName) => {
|
||||
networkInterfaces[interfaceName].forEach((iface) => {
|
||||
if (iface.family === 'IPv4' && !iface.internal) {
|
||||
ipAddresses.push(iface.address);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
console.log(`
|
||||
╔════════════════════════════════════════════════════════════╗
|
||||
║ PDF Unterschrift System gestartet! ║
|
||||
╠════════════════════════════════════════════════════════════╝
|
||||
║
|
||||
║ Lokaler Zugriff:
|
||||
║ Master-Seite: http://localhost:${PORT}/master.html
|
||||
║ Signatur-Seite: http://localhost:${PORT}/signature.html
|
||||
║ `);
|
||||
|
||||
if (ipAddresses.length > 0) {
|
||||
console.log(`║
|
||||
║ Netzwerk-Zugriff (für iPhone/Tablet): `);
|
||||
ipAddresses.forEach(ip => {
|
||||
console.log(`║ Master-Seite: http://${ip}:${PORT}/master.html `);
|
||||
console.log(`║ Signatur-Seite: http://${ip}:${PORT}/signature.html `);
|
||||
});
|
||||
}
|
||||
|
||||
console.log(`║
|
||||
║ WICHTIG: Öffne die Signatur-Seite einmal und lasse
|
||||
║ sie offen. Jede neue PDF wird dort automatisch
|
||||
║ angezeigt!
|
||||
║
|
||||
║ WebSocket Server läuft auf Port ${PORT}
|
||||
║
|
||||
╚═════════════════════════════════════════════════════════════
|
||||
`);
|
||||
});
|
||||
Reference in New Issue
Block a user