Compare commits

...

5 Commits

Author SHA1 Message Date
Markus Busche
5478d943e5 Teilen-Button, Klartext-Hinweis und README aktualisiert (WLAN-Passwort im Link sichtbar) 2025-07-08 11:59:35 +02:00
Markus Busche
9c5d022604 Update Caddyfile 2025-07-03 12:04:56 +02:00
Markus Busche
83f49d14bc Add main.js to Dockerfile 2025-07-03 11:51:16 +02:00
Markus Busche
bfddca6495 Reference to alster.space 2025-07-03 11:37:28 +02:00
Markus Busche
1ebc4c4ec2 Change title 2025-07-03 11:30:53 +02:00
5 changed files with 87 additions and 21 deletions

View File

@@ -2,8 +2,10 @@
root * /usr/share/caddy root * /usr/share/caddy
file_server file_server
# Behandle die HTML-Datei als Index @notStatic {
try_files {path} /Just%20a%20QR%20Code.html not path_regexp static \.\(js|css|png|jpg|jpeg|gif|svg|ico|json|webmanifest|map|txt|woff2?\)$
}
try_files {path} /index.html @notStatic
# CORS-Header für Cross-Origin-Requests # CORS-Header für Cross-Origin-Requests
header { header {

View File

@@ -2,6 +2,7 @@ FROM caddy:2-alpine
# Kopiere die HTML-Datei # Kopiere die HTML-Datei
COPY index.html /usr/share/caddy/ COPY index.html /usr/share/caddy/
COPY main.js /usr/share/caddy/
# Kopiere den Ordner mit den JavaScript-Dateien # Kopiere den Ordner mit den JavaScript-Dateien
COPY assets /usr/share/caddy/assets/ COPY assets /usr/share/caddy/assets/

View File

@@ -2,18 +2,22 @@
Ein einfacher QR-Code-Generator, der vollständig im Browser läuft. Keine Daten werden an externe Server gesendet. Ein einfacher QR-Code-Generator, der vollständig im Browser läuft. Keine Daten werden an externe Server gesendet.
Dieses Projekt basiert auf dem Code von https://qr.alster.space/. Er wurde um verschiedene praktische Funktionen erweitert.
## Features ## Features
- Vollständig clientseitig (keine Server-Kommunikation) - Vollständig clientseitig (keine Server-Kommunikation)
- URL-Parameter für alle Einstellungen - URL-Parameter für alle Einstellungen
- Anpassbare Größen und Farben - Anpassbare Größen und Farben
- Verschiedene Fehlerkorrektur-Level - Verschiedene Fehlerkorrektur-Level
- Download-Funktion - Download-Funktion
- ✅ Responsive Design - Teilen-Funktion (Link mit aktuellen Einstellungen kopieren)
- **WiFi QR-Code Unterstützung mit eigener UI** - Hinweis bei WiFi: Passwort im Link im Klartext
- **Dynamische Klartext-Anzeige** - Responsive Design
- **Automatische QR-Code-Generierung** - WiFi QR-Code Unterstützung mit eigener UI
- **Sicher gegen XSS (Content Security Policy, validierte Eingaben, kein Inline-JS)** - Dynamische Klartext-Anzeige
- Automatische QR-Code-Generierung
- Sicher gegen XSS (Content Security Policy, validierte Eingaben, kein Inline-JS)
## Docker Setup ## Docker Setup
@@ -27,7 +31,7 @@ docker-compose up -d
docker-compose down docker-compose down
``` ```
### Mit Docker direkt ### Docker build/run
```bash ```bash
# Image bauen # Image bauen
@@ -88,6 +92,8 @@ http://localhost:8080/?ssid=MeinWLAN&password=MeinPasswort123
http://localhost:8080/?ssid=OffenesWLAN http://localhost:8080/?ssid=OffenesWLAN
``` ```
**Achtung:** Das WLAN-Passwort ist im Link im Klartext sichtbar!
## WiFi QR-Code Format ## WiFi QR-Code Format
Die App generiert automatisch QR-Codes im Standard-WiFi-Format: Die App generiert automatisch QR-Codes im Standard-WiFi-Format:
@@ -125,6 +131,12 @@ Das Smartphone erkennt automatisch, dass es sich um WiFi-Daten handelt und biete
- WiFi-Passwort ohne SSID wird als Fehler angezeigt - WiFi-Passwort ohne SSID wird als Fehler angezeigt
- Leere Eingaben werden entsprechend behandelt - Leere Eingaben werden entsprechend behandelt
### Teilen-Funktion
Mit dem Button "Teilen" kann ein Link mit allen aktuellen Einstellungen (inkl. WiFi-Daten) in die Zwischenablage kopiert werden. Dieser Link kann weitergegeben werden und öffnet die App direkt mit den gewählten Einstellungen.
**Achtung:** Wenn ein WLAN-Passwort eingegeben ist, wird dieses im Link im Klartext übertragen!
## Sicherheit & Content Security Policy (CSP) ## Sicherheit & Content Security Policy (CSP)
Die Anwendung ist gegen XSS-Angriffe abgesichert: Die Anwendung ist gegen XSS-Angriffe abgesichert:

File diff suppressed because one or more lines are too long

47
main.js
View File

@@ -16,6 +16,8 @@ document.addEventListener('DOMContentLoaded', function() {
const infoPanel = document.getElementById('info-panel'); const infoPanel = document.getElementById('info-panel');
const infoClose = document.getElementById('info-close'); const infoClose = document.getElementById('info-close');
const titleElement = document.getElementById('title'); const titleElement = document.getElementById('title');
const shareBtn = document.getElementById('share');
const shareHint = document.getElementById('share-hint');
// Title Easter egg // Title Easter egg
let titleClickCount = 0; let titleClickCount = 0;
@@ -292,4 +294,49 @@ document.addEventListener('DOMContentLoaded', function() {
// Update clear button visibility // Update clear button visibility
toggleClearButton(); toggleClearButton();
} }
function updateShareHint() {
const wifiPassword = wifiPasswordInput.value.trim();
if (wifiPassword) {
shareHint.style.display = 'block';
} else {
shareHint.style.display = 'none';
}
}
wifiPasswordInput.addEventListener('input', updateShareHint);
wifiSsidInput.addEventListener('input', updateShareHint);
textInput.addEventListener('input', updateShareHint);
// Initial anzeigen, falls Passwort schon gesetzt
updateShareHint();
shareBtn.addEventListener('click', function() {
const params = new URLSearchParams();
const text = textInput.value.trim();
const wifiSsid = wifiSsidInput.value.trim();
const wifiPassword = wifiPasswordInput.value.trim();
const size = sizeSelect.value;
const errorCorrection = errorCorrectionSelect.value;
const fgColor = foregroundColor.value;
const bgColor = backgroundColor.value;
// Entscheide, was kodiert werden soll
if (wifiSsid) params.set('ssid', wifiSsid);
if (wifiPassword) params.set('password', wifiPassword);
if (!wifiSsid && !wifiPassword && text) params.set('text', text);
if (size !== '256') params.set('size', size);
if (errorCorrection !== 'M') params.set('errorCorrection', errorCorrection);
if (fgColor !== '#000000') params.set('foreground', fgColor);
if (bgColor !== '#ffffff') params.set('background', bgColor);
const url = window.location.origin + window.location.pathname + '?' + params.toString();
// In Zwischenablage kopieren
navigator.clipboard.writeText(url).then(() => {
const original = shareBtn.textContent;
shareBtn.textContent = 'Link kopiert!';
setTimeout(() => { shareBtn.textContent = original; }, 2000);
}, () => {
alert('Konnte Link nicht kopieren.');
});
});
}); });