Files
ssh/public/index.html
2025-09-11 14:19:19 -07:00

68 lines
3.6 KiB
HTML

<!DOCTYPE html>
<html>
<head>
<title>Browser SSH</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
body, html { margin: 0; padding: 0; height: 100%; width: 100%; overflow: hidden; font-family: sans-serif; background: #1e1e1e; color: #ccc; }
#terminal-container { width: 100%; height: 100%; }
#connect-form { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); padding: 2em; background: #2a2a2a; border-radius: 8px; box-shadow: 0 0 20px rgba(0,0,0,0.5); z-index: 10; display: flex; flex-direction: column; gap: 1em; min-width: 300px; }
input, button, textarea { font-size: 1em; padding: 0.5em; border-radius: 4px; border: 1px solid #555; background: #333; color: #eee; }
button { cursor: pointer; background: #007acc; border-color: #007acc; font-weight: bold; }
.form-row { display: grid; grid-template-columns: 80px 1fr; gap: 1em; align-items: center; }
</style>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/xterm@5.3.0/css/xterm.min.css" />
<script src="https://cdn.jsdelivr.net/npm/xterm@5.3.0/lib/xterm.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/xterm-addon-fit@0.8.0/lib/xterm-addon-fit.min.js"></script>
</head>
<body>
<div id="connect-form">
<h2>Connect via Worker</h2>
<div class="form-row"><label for="host">Host:</label><input id="host" type="text" placeholder="ssh.example.com" required></div>
<div class="form-row"><label for="port">Port:</label><input id="port" type="number" value="22" required></div>
<div class="form-row"><label for="username">User:</label><input id="username" type="text" placeholder="root" required></div>
<div class="form-row"><label for="password">Password:</label><input id="password" type="password"></div>
<div class="form-row"><label for="privateKey">Pvt. Key:</label><textarea id="privateKey" rows="3" placeholder="... or paste RSA/ED25519 key"></textarea></div>
<button id="connect-btn">Connect</button>
</div>
<div id="terminal-container"></div>
<script>
const term = new Terminal({ convertEol: true, cursorBlink: true, theme: { background: '#1e1e1e' } });
const fitAddon = new FitAddon.FitAddon();
term.loadAddon(fitAddon);
const connectForm = document.getElementById('connect-form');
const terminalContainer = document.getElementById('terminal-container');
function startSession(params) {
connectForm.style.display = 'none';
term.open(terminalContainer);
fitAddon.fit();
const ws = new WebSocket(new URL('/ws', window.location.href).toString().replace(/^http/, 'ws'));
term.onResize((d) => ws.readyState === 1 && ws.send(JSON.stringify({ resize: d })));
term.onData((d) => ws.readyState === 1 && ws.send(d));
ws.onmessage = (e) => term.write(e.data instanceof Blob ? e.data.arrayBuffer().then(b=>new Uint8Array(b)) : e.data);
ws.onopen = () => ws.send(JSON.stringify(params));
ws.onclose = (e) => term.writeln(`\r\n\x1b[31m[Connection Closed: ${e.reason || 'Normal'}]\x1b[0m`);
ws.onerror = () => term.writeln("\r\n\x1b[31m[Connection Error]\x1b[0m");
window.addEventListener('resize', () => fitAddon.fit());
}
document.getElementById('connect-btn').addEventListener('click', () => {
const params = Object.fromEntries(new FormData(connectForm).entries());
Object.keys(params).forEach(k => !params[k] && delete params[k]);
startSession({
host: document.getElementById('host').value, port: document.getElementById('port').value,
username: document.getElementById('username').value, password: document.getElementById('password').value,
privateKey: document.getElementById('privateKey').value,
});
});
</script>
</body>
</html>