umbau 1.1
This commit is contained in:
63
_to_delete/csp_test.html
Normal file
63
_to_delete/csp_test.html
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<link rel="stylesheet" href="/static/js/vendor/xterm.css">
|
||||||
|
<style>body{background:#111;color:#eee;font-family:monospace;white-space:pre-wrap;}</style>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div id="out">running...</div>
|
||||||
|
<div id="term" style="width:600px;height:300px;"></div>
|
||||||
|
<script src="/static/js/vendor/xterm.js"></script>
|
||||||
|
<script>
|
||||||
|
(async () => {
|
||||||
|
const results = {};
|
||||||
|
try {
|
||||||
|
const term = new Terminal({
|
||||||
|
cursorBlink: false,
|
||||||
|
fontFamily: "monospace",
|
||||||
|
fontSize: 14,
|
||||||
|
theme: { background: "#000000", foreground: "#e6e8eb", cursor: "#e6e8eb" },
|
||||||
|
copyOnSelect: true,
|
||||||
|
});
|
||||||
|
term.open(document.getElementById('term'));
|
||||||
|
term.write("Hello World Selection Test\r\n");
|
||||||
|
await new Promise(r => setTimeout(r, 100));
|
||||||
|
|
||||||
|
// Try to programmatically select a range: xterm.js exposes term.select(col, row, length)
|
||||||
|
term.select(0, 0, 11); // select "Hello World"
|
||||||
|
|
||||||
|
await new Promise(r => setTimeout(r, 100));
|
||||||
|
|
||||||
|
// Inspect style elements injected by xterm
|
||||||
|
const styleEls = [...document.querySelectorAll('style')];
|
||||||
|
results.styleElementCount = styleEls.length;
|
||||||
|
results.styleElementInfo = styleEls.map(s => ({
|
||||||
|
len: s.textContent.length,
|
||||||
|
sheetRulesAccessible: (() => { try { return s.sheet ? s.sheet.cssRules.length : null; } catch(e) { return 'ERR:'+e.message; } })(),
|
||||||
|
containsSelectionRule: s.textContent.includes('selectionBackgroundOpaque') || s.textContent.includes('xterm-selection')
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Find the selection layer div(s)
|
||||||
|
const selLayer = document.querySelector('.xterm-selection-layer, [class*=selection]');
|
||||||
|
results.selLayerFound = !!selLayer;
|
||||||
|
results.selLayerClass = selLayer ? selLayer.className : null;
|
||||||
|
const selDivs = document.querySelectorAll('.xterm-selection-layer div, [class*=selection] div');
|
||||||
|
results.selDivCount = selDivs.length;
|
||||||
|
results.selDivComputedBg = [...selDivs].slice(0,5).map(d => getComputedStyle(d).backgroundColor);
|
||||||
|
results.selDivInlineStyle = [...selDivs].slice(0,5).map(d => d.getAttribute('style'));
|
||||||
|
|
||||||
|
results.hasCssomSelectionRule = styleEls.some(s => {
|
||||||
|
try {
|
||||||
|
return s.sheet && [...s.sheet.cssRules].some(r => r.cssText && r.cssText.includes('selection'));
|
||||||
|
} catch(e) { return 'ERR:'+e.message; }
|
||||||
|
});
|
||||||
|
|
||||||
|
document.getElementById('out').textContent = 'DONE:' + JSON.stringify(results, null, 2);
|
||||||
|
} catch (e) {
|
||||||
|
document.getElementById('out').textContent = 'EXCEPTION: ' + e.message + '\n' + e.stack;
|
||||||
|
}
|
||||||
|
})();
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@ -21,12 +21,14 @@ npm init -y >/dev/null
|
|||||||
npm install --no-audit --no-fund \
|
npm install --no-audit --no-fund \
|
||||||
xterm@5 \
|
xterm@5 \
|
||||||
xterm-addon-fit@0.8 \
|
xterm-addon-fit@0.8 \
|
||||||
|
xterm-addon-canvas@0.5 \
|
||||||
guacamole-common-js@1.5
|
guacamole-common-js@1.5
|
||||||
|
|
||||||
echo "==> Kopiere Dist-Dateien nach $VENDOR_DIR"
|
echo "==> Kopiere Dist-Dateien nach $VENDOR_DIR"
|
||||||
cp node_modules/xterm/lib/xterm.js "$VENDOR_DIR/xterm.js"
|
cp node_modules/xterm/lib/xterm.js "$VENDOR_DIR/xterm.js"
|
||||||
cp node_modules/xterm/css/xterm.css "$VENDOR_DIR/xterm.css"
|
cp node_modules/xterm/css/xterm.css "$VENDOR_DIR/xterm.css"
|
||||||
cp node_modules/xterm-addon-fit/lib/xterm-addon-fit.js "$VENDOR_DIR/xterm-addon-fit.js"
|
cp node_modules/xterm-addon-fit/lib/xterm-addon-fit.js "$VENDOR_DIR/xterm-addon-fit.js"
|
||||||
|
cp node_modules/xterm-addon-canvas/lib/xterm-addon-canvas.js "$VENDOR_DIR/xterm-addon-canvas.js"
|
||||||
|
|
||||||
# guacamole-common-js liefert nur ESM/CJS-Builds aus, keinen fertigen
|
# guacamole-common-js liefert nur ESM/CJS-Builds aus, keinen fertigen
|
||||||
# Browser-Global-Build. Fuer die Einbindung per klassischem <script>-Tag
|
# Browser-Global-Build. Fuer die Einbindung per klassischem <script>-Tag
|
||||||
|
|||||||
@ -1325,6 +1325,15 @@
|
|||||||
});
|
});
|
||||||
const fitAddon = new FitAddon.FitAddon();
|
const fitAddon = new FitAddon.FitAddon();
|
||||||
term.loadAddon(fitAddon);
|
term.loadAddon(fitAddon);
|
||||||
|
// Bug-Fix (Live-Test, F.6/Aufgabe#11, siehe terminal.js _setupTerminal()
|
||||||
|
// fuer die ausfuehrliche Begruendung): DOM-Renderer-Faerbung wird durch
|
||||||
|
// die strikte CSP (style-src 'self') stillschweigend verworfen. Canvas-
|
||||||
|
// Renderer zeichnet stattdessen direkt auf <canvas> und ist CSP-unabhaengig.
|
||||||
|
try {
|
||||||
|
term.loadAddon(new CanvasAddon.CanvasAddon());
|
||||||
|
} catch (err) {
|
||||||
|
console.warn("CanvasAddon konnte nicht geladen werden, Fallback auf DOM-Renderer:", err);
|
||||||
|
}
|
||||||
term.open(container);
|
term.open(container);
|
||||||
fitAddon.fit();
|
fitAddon.fit();
|
||||||
|
|
||||||
@ -1427,6 +1436,15 @@
|
|||||||
});
|
});
|
||||||
const fitAddon = new FitAddon.FitAddon();
|
const fitAddon = new FitAddon.FitAddon();
|
||||||
term.loadAddon(fitAddon);
|
term.loadAddon(fitAddon);
|
||||||
|
// Bug-Fix (Live-Test, F.6/Aufgabe#11, siehe terminal.js _setupTerminal()
|
||||||
|
// fuer die ausfuehrliche Begruendung): DOM-Renderer-Faerbung wird durch
|
||||||
|
// die strikte CSP (style-src 'self') stillschweigend verworfen. Canvas-
|
||||||
|
// Renderer zeichnet stattdessen direkt auf <canvas> und ist CSP-unabhaengig.
|
||||||
|
try {
|
||||||
|
term.loadAddon(new CanvasAddon.CanvasAddon());
|
||||||
|
} catch (err) {
|
||||||
|
console.warn("CanvasAddon konnte nicht geladen werden, Fallback auf DOM-Renderer:", err);
|
||||||
|
}
|
||||||
term.open(container);
|
term.open(container);
|
||||||
fitAddon.fit();
|
fitAddon.fit();
|
||||||
|
|
||||||
|
|||||||
@ -299,6 +299,26 @@
|
|||||||
});
|
});
|
||||||
this.fitAddon = new FitAddon.FitAddon();
|
this.fitAddon = new FitAddon.FitAddon();
|
||||||
this.term.loadAddon(this.fitAddon);
|
this.term.loadAddon(this.fitAddon);
|
||||||
|
// Bug-Fix (Live-Test, F.6/Aufgabe#11): xterm.js' Standard-DOM-Renderer
|
||||||
|
// faerbt Zellen (inkl. Markierungs-Hintergrund) teils per dynamisch
|
||||||
|
// erzeugtem <style>-Element, teils per element.setAttribute("style", ...).
|
||||||
|
// Beides sind "inline styles" im Sinne der CSP (style-src 'self', kein
|
||||||
|
// 'unsafe-inline'/Nonce/Hash) -- der Browser verwirft diese Regeln
|
||||||
|
// stillschweigend (element.sheet bleibt null), wodurch u.a. die
|
||||||
|
// Text-Markierung unsichtbar bleibt, obwohl die Auswahl-Logik selbst
|
||||||
|
// funktioniert. Der Canvas-Renderer zeichnet Zeichen/Farben stattdessen
|
||||||
|
// direkt auf ein <canvas> (Pixel statt CSS) und ist von style-src nicht
|
||||||
|
// betroffen -- CSP bleibt dadurch unveraendert strikt.
|
||||||
|
try {
|
||||||
|
this.canvasAddon = new CanvasAddon.CanvasAddon();
|
||||||
|
this.term.loadAddon(this.canvasAddon);
|
||||||
|
} catch (err) {
|
||||||
|
// Faellt der Canvas-Renderer aus irgendeinem Grund aus (z.B. sehr
|
||||||
|
// altes/eingeschraenktes Canvas-2D-Umfeld), bleibt der DOM-Renderer
|
||||||
|
// als Fallback aktiv -- Faerbung/Markierung waeren dann wieder vom
|
||||||
|
// CSP-Fix abhaengig, aber die Sitzung funktioniert weiterhin.
|
||||||
|
console.warn("CanvasAddon konnte nicht geladen werden, Fallback auf DOM-Renderer:", err);
|
||||||
|
}
|
||||||
this.term.open(this.terminalContainer);
|
this.term.open(this.terminalContainer);
|
||||||
if (this.themeSelect) this.themeSelect.value = this._themeName;
|
if (this.themeSelect) this.themeSelect.value = this._themeName;
|
||||||
|
|
||||||
|
|||||||
@ -701,6 +701,7 @@
|
|||||||
|
|
||||||
<script src="/static/js/vendor/xterm.js"></script>
|
<script src="/static/js/vendor/xterm.js"></script>
|
||||||
<script src="/static/js/vendor/xterm-addon-fit.js"></script>
|
<script src="/static/js/vendor/xterm-addon-fit.js"></script>
|
||||||
|
<script src="/static/js/vendor/xterm-addon-canvas.js"></script>
|
||||||
<script src="/static/js/vendor/guacamole-common.js"></script>
|
<script src="/static/js/vendor/guacamole-common.js"></script>
|
||||||
<script src="/static/js/admin.js"></script>
|
<script src="/static/js/admin.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
@ -21,6 +21,7 @@
|
|||||||
|
|
||||||
<script src="/static/js/vendor/xterm.js"></script>
|
<script src="/static/js/vendor/xterm.js"></script>
|
||||||
<script src="/static/js/vendor/xterm-addon-fit.js"></script>
|
<script src="/static/js/vendor/xterm-addon-fit.js"></script>
|
||||||
|
<script src="/static/js/vendor/xterm-addon-canvas.js"></script>
|
||||||
<script src="/static/js/session-keepalive.js"></script>
|
<script src="/static/js/session-keepalive.js"></script>
|
||||||
<script src="/static/js/terminal.js"></script>
|
<script src="/static/js/terminal.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
@ -54,6 +54,7 @@
|
|||||||
|
|
||||||
<script src="/static/js/vendor/xterm.js"></script>
|
<script src="/static/js/vendor/xterm.js"></script>
|
||||||
<script src="/static/js/vendor/xterm-addon-fit.js"></script>
|
<script src="/static/js/vendor/xterm-addon-fit.js"></script>
|
||||||
|
<script src="/static/js/vendor/xterm-addon-canvas.js"></script>
|
||||||
<script src="/static/js/vendor/guacamole-common.js"></script>
|
<script src="/static/js/vendor/guacamole-common.js"></script>
|
||||||
<script src="/static/js/session-keepalive.js"></script>
|
<script src="/static/js/session-keepalive.js"></script>
|
||||||
<script src="/static/js/terminal.js"></script>
|
<script src="/static/js/terminal.js"></script>
|
||||||
|
|||||||
Reference in New Issue
Block a user