export function agentBackendUrl(value, origin) { if (/[\r\n\t]/.test(String(value || ''))) throw new Error('Die Serveradresse darf keine Steuerzeichen enthalten.') const url = new URL(String(value || '/').trim(), origin) if (!['http:', 'https:'].includes(url.protocol) || url.username || url.password || url.search || url.hash) { throw new Error('Bitte eine HTTP(S)-Adresse ohne Zugangsdaten, Suchparameter oder Fragment eingeben.') } return url.toString().replace(/\/+$/, '') } function base64(value) { const bytes = new TextEncoder().encode(value) let binary = '' for (const byte of bytes) binary += String.fromCharCode(byte) return btoa(binary) } export function renderAgentInstaller(bundle, options) { if (!/^[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}$/i.test(options.agentId)) { throw new Error('Ungültige Agent-ID') } if (!/^fedeo_agent_[a-f0-9]{64}$/.test(options.token)) throw new Error('Bitte den vollständigen Agent-Token eingeben.') const url = agentBackendUrl(options.backendUrl) if (/\s|["'`\\]/.test(url)) throw new Error('Die Serveradresse enthält ungültige Zeichen.') const configuration = [ `FEDEO_URL=${url}`, `FEDEO_AGENT_TOKEN=${options.token}`, 'FEDEO_POLL_SECONDS=5', 'FEDEO_SCAN_FORMAT=pdf', 'FEDEO_SCAN_RESOLUTION=300', 'FEDEO_SCAN_MODE=Color', 'FEDEO_SCAN_TIMEOUT_SECONDS=900', 'FEDEO_SCAN_POSTPROCESS=false', 'FEDEO_SCAN_POSTPROCESS_PROFILE=document', '', ].join('\n') const replacements = { AGENT_ID: options.agentId, AUTOSTART: String(Boolean(options.autostart)), PAYLOAD_BASE64: base64(JSON.stringify(bundle.files)), CONFIG_BASE64: base64(configuration), } return bundle.installerTemplate.replace(/@@([A-Z0-9_]+)@@/g, (_, key) => { if (!(key in replacements)) throw new Error('Unbekannter Platzhalter im Installationspaket') return replacements[key] }) } export const ix1600ScanDefaults = { format: 'pdf', resolution: 300, mode: 'Color', source: 'ADF Duplex', paperSize: 'A4', postprocess: false, postprocessProfile: 'document', } export function agentSetupReady(agent, since = 0, now = Date.now()) { const lastSeen = Date.parse(agent?.lastSeenAt || '') return Boolean(agent?.active && Number.isFinite(lastSeen) && lastSeen >= since && now - lastSeen < 120000) }