/** * settings.js - Einstellungen und gemeinsam genutzte Hilfsmittel. * * Die Einstellungen liegen in browser.storage.local, also im Profil von * Thunderbird. Der Token steht dort im Klartext - das entspricht dem, was * Erweiterungen üblicherweise tun, ist aber kein Geheimnisspeicher. * Einzelheiten in SICHERHEIT.md. */ const VORGABEN = { baseUrl: "", token: "", // Adresse, unter der das Archiv von aussen erreichbar ist. // // Wird nur für Freigabelinks verwendet. Paperless liefert in der // Antwort lediglich den Slug; die vollständige Adresse setzt die // Erweiterung zusammen. Führt der interne Zugang über einen // abweichenden Port oder einen anderen Namen, wäre ein daraus gebauter // Link für den Empfänger wertlos. // // Leer = baseUrl verwenden. shareBaseUrl: "", versionLabel: "Thunderbird {datum}", // Wie eine ganze Nachricht abgelegt wird. // // "pdf" lesbar aufbereitet, Original und Anhänge im PDF eingebettet // "eml" Rohformat, verlustfrei und wieder in ein Mailprogramm // einlesbar, aber im Archiv unhandlich mailFormat: "pdf", // Anhänge zusätzlich IN das PDF einbetten. Ohne das enthält das PDF // nur die Originalnachricht - die Anhänge stecken dann zwar in der // .eml, sind aber nicht einzeln greifbar. pdfAnhaengeEinbetten: true, // Grundschriftgröße des erzeugten PDF in Punkten. 11 ist gut lesbar // und entspricht etwa dem, was Textverarbeitungen als Vorgabe nutzen. // Die Überschrift wächst schwächer mit, damit sie nicht über zwei // Zeilen läuft. pdfSchriftgroesse: 11, // Papierformat und Ränder. Die Ränder in Millimetern. // // Links mehr als rechts, damit beim Abheften nichts im Ordner // verschwindet - bei einem Archivdokument der wahrscheinlichere Fall // als eine symmetrische Gestaltung. pdfFormat: "a4", pdfRandLinks: 20, pdfRandRechts: 10, pdfRandOben: 10, pdfRandUnten: 10, shareDays: 7, shareTag: "Sharelink", // Beschriftung der eingefügten Linkblöcke. Leer lassen für keine // Nummerierung ist nicht vorgesehen - eine Nummer hilft beim Bezugnehmen // im Fließtext ("siehe Datei 2"). linkBezeichner: "", // Anhänge, die üblicherweise keine Dokumente sind. Sie werden im // Auswahldialog vorab abgewählt, lassen sich aber anhaken. ignorierteTypen: ["image/gif", "image/png", "image/jpeg", "text/vcard", "text/calendar", "application/pkcs7-signature", "application/pgp-signature"], ignorierteKleiner: 8192 // Bytes; darunter meist Signaturbilder }; export async function ladeEinstellungen() { const gespeichert = await browser.storage.local.get(Object.keys(VORGABEN)); return { ...VORGABEN, ...gespeichert }; } export async function speichereEinstellungen(werte) { await browser.storage.local.set(werte); } export function vollstaendig(s) { return Boolean(s?.baseUrl) && Boolean(s?.token); } /** * Zugriffsmuster für browser.permissions aus einer Basisadresse. * * WICHTIG: Muster dürfen KEINEN Port enthalten. "https://rechner:8443/*" * ist ungültig, und permissions.request wirft dann eine Ausnahme mit * einer Meldung, die nichts über die Ursache verrät. * * Ein Zugriffsrecht gilt ohnehin für alle Ports desselben Rechners - die * Einschränkung kostet also nichts. */ export function zugriffsmuster(baseUrl) { const u = new URL(String(baseUrl).trim()); return `${u.protocol}//${u.hostname}/*`; } /** * Beliebige Zeichenkette in einen unbedenklichen Dateinamen überführen. * * Der Name eines E-Mail-Anhangs stammt vom Absender und ist damit nicht * vertrauenswürdig. Er wird zwar nur an Paperless weitergereicht und nicht * ins Dateisystem geschrieben, aber ein Wert wie "../../x" hat in einem * Dateinamen nichts zu suchen. */ export function sichererName(name, vorgabe = "Dokument", maxlen = 120) { let n = String(name || ""); n = n.replace(/\\/g, "/").split("/").pop(); n = n.replace(/[<>:"|?*\u0000-\u001f]/g, "").trim(); n = n.replace(/\s+/g, " ").replace(/^[. ]+|[. ]+$/g, ""); if (!n) return vorgabe; const reserviert = /^(CON|PRN|AUX|NUL|COM[1-9]|LPT[1-9])(\.|$)/i; if (reserviert.test(n)) n = "_" + n; if (n.length > maxlen) { const punkt = n.lastIndexOf("."); const endung = punkt > 0 && n.length - punkt <= 9 ? n.slice(punkt) : ""; n = n.slice(0, maxlen - endung.length) + endung; } return n || vorgabe; } export function versionslabel(vorlage) { const heute = new Date().toISOString().slice(0, 10); return String(vorlage || "Thunderbird {datum}").replace("{datum}", heute); } /** Kürzt einen Text für die Anzeige. */ export function kurz(text, laenge = 70) { const t = String(text || ""); return t.length > laenge ? t.slice(0, laenge - 1) + "…" : t; } /** Menschenlesbare Größenangabe. */ export function groesse(bytes) { const b = Number(bytes) || 0; if (b < 1024) return `${b} B`; if (b < 1024 * 1024) return `${(b / 1024).toFixed(0)} KB`; return `${(b / 1024 / 1024).toFixed(1)} MB`; } /** * Betreff einer Nachricht in einen Dokumenttitel überführen. * * Präfixe wie "AW:" oder "Fwd:" tragen im Archiv nichts bei und stören * beim Sortieren. */ export function titelAusBetreff(betreff) { let t = String(betreff || "").trim(); const praefixe = /^((AW|RE|WG|FWD|FW|TR|RÉF|REF)\s*(\[\d+\])?\s*:\s*)+/i; t = t.replace(praefixe, "").trim(); return t || "E-Mail ohne Betreff"; } /** Übersetzung über die eingebaute Verwaltung von Thunderbird. */ export function t(schluessel, ersetzungen) { const s = browser.i18n.getMessage(schluessel, ersetzungen); return s || schluessel; }