| <!DOCTYPE html> |
| <html lang="en"> |
| <head> |
| <meta charset="UTF-8"> |
| <meta name="viewport" content="width=device-width, initial-scale=1.0"> |
| <title>WebSSH Client</title> |
| <script src="https://cdn.tailwindcss.com"></script> |
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css"> |
| <style> |
| .terminal { |
| font-family: 'Courier New', monospace; |
| background-color: #1e1e1e; |
| color: #f0f0f0; |
| height: 400px; |
| overflow-y: auto; |
| padding: 1rem; |
| border-radius: 0.5rem; |
| box-shadow: 0 4px 6px -1px rgba(0, 0, 0, 0.1), 0 2px 4px -1px rgba(0, 0, 0, 0.06); |
| } |
| |
| .prompt { |
| color: #4ade80; |
| } |
| |
| .command { |
| color: #60a5fa; |
| } |
| |
| .output { |
| color: #f0f0f0; |
| white-space: pre-wrap; |
| } |
| |
| .error { |
| color: #f87171; |
| } |
| |
| .cursor { |
| display: inline-block; |
| width: 10px; |
| height: 20px; |
| background-color: #f0f0f0; |
| animation: blink 1s infinite; |
| } |
| |
| @keyframes blink { |
| 0%, 100% { opacity: 1; } |
| 50% { opacity: 0; } |
| } |
| |
| |
| .terminal::-webkit-scrollbar { |
| width: 8px; |
| } |
| |
| .terminal::-webkit-scrollbar-track { |
| background: #2d2d2d; |
| } |
| |
| .terminal::-webkit-scrollbar-thumb { |
| background: #4b5563; |
| border-radius: 4px; |
| } |
| |
| .terminal::-webkit-scrollbar-thumb:hover { |
| background: #6b7280; |
| } |
| </style> |
| </head> |
| <body class="bg-gray-900 min-h-screen text-white"> |
| <div class="container mx-auto px-4 py-8"> |
| <div class="max-w-4xl mx-auto"> |
| <div class="flex items-center justify-between mb-6"> |
| <h1 class="text-3xl font-bold text-green-400"> |
| <i class="fas fa-terminal mr-2"></i> WebSSH Client |
| </h1> |
| <div class="flex items-center space-x-2"> |
| <span id="connection-status" class="px-3 py-1 rounded-full text-xs font-semibold bg-gray-700">Disconnected</span> |
| </div> |
| </div> |
| |
| <div class="bg-gray-800 rounded-lg shadow-lg p-6 mb-6"> |
| <div class="grid grid-cols-1 md:grid-cols-4 gap-4 mb-4"> |
| <div class="md:col-span-1"> |
| <label for="host" class="block text-sm font-medium text-gray-300 mb-1">Host/IP</label> |
| <input type="text" id="host" placeholder="example.com or 192.168.1.1" |
| class="w-full px-3 py-2 bg-gray-700 border border-gray-600 rounded-md text-white focus:outline-none focus:ring-2 focus:ring-green-500"> |
| </div> |
| <div> |
| <label for="port" class="block text-sm font-medium text-gray-300 mb-1">Port</label> |
| <input type="number" id="port" value="22" |
| class="w-full px-3 py-2 bg-gray-700 border border-gray-600 rounded-md text-white focus:outline-none focus:ring-2 focus:ring-green-500"> |
| </div> |
| <div> |
| <label for="username" class="block text-sm font-medium text-gray-300 mb-1">Username</label> |
| <input type="text" id="username" placeholder="root" |
| class="w-full px-3 py-2 bg-gray-700 border border-gray-600 rounded-md text-white focus:outline-none focus:ring-2 focus:ring-green-500"> |
| </div> |
| <div> |
| <label for="password" class="block text-sm font-medium text-gray-300 mb-1">Password</label> |
| <div class="flex"> |
| <input type="password" id="password" placeholder="••••••••" |
| class="w-full px-3 py-2 bg-gray-700 border border-gray-600 rounded-l-md text-white focus:outline-none focus:ring-2 focus:ring-green-500"> |
| <button id="toggle-password" class="px-3 bg-gray-600 border border-gray-600 rounded-r-md"> |
| <i class="fas fa-eye"></i> |
| </button> |
| </div> |
| </div> |
| </div> |
| |
| <div class="flex space-x-3"> |
| <button id="connect-btn" class="px-4 py-2 bg-green-600 hover:bg-green-700 rounded-md font-medium flex items-center"> |
| <i class="fas fa-plug mr-2"></i> Connect |
| </button> |
| <button id="disconnect-btn" class="px-4 py-2 bg-red-600 hover:bg-red-700 rounded-md font-medium flex items-center opacity-50 cursor-not-allowed" disabled> |
| <i class="fas fa-power-off mr-2"></i> Disconnect |
| </button> |
| <button id="clear-btn" class="px-4 py-2 bg-blue-600 hover:bg-blue-700 rounded-md font-medium flex items-center"> |
| <i class="fas fa-broom mr-2"></i> Clear |
| </button> |
| </div> |
| </div> |
| |
| <div class="terminal mb-4" id="terminal"> |
| <div class="output"> |
| <span class="prompt">webssh-client$</span> <span class="command">Welcome to WebSSH Client</span><br> |
| <span class="output">This is a browser-based SSH client interface. Enter your connection details above and click Connect to establish a session.</span><br><br> |
| <span class="prompt">webssh-client$</span> <span class="command">status</span><br> |
| <span class="output">Current status: <span class="error">Disconnected</span></span><br><br> |
| <span class="prompt">webssh-client$</span> <span id="cursor" class="cursor"></span> |
| </div> |
| </div> |
| |
| <div class="bg-gray-800 rounded-lg shadow-lg p-4"> |
| <div class="flex items-center"> |
| <input type="text" id="command-input" placeholder="Enter command..." |
| class="flex-grow px-3 py-2 bg-gray-700 border border-gray-600 rounded-l-md text-white focus:outline-none focus:ring-2 focus:ring-green-500" disabled> |
| <button id="send-btn" class="px-4 py-2 bg-green-600 hover:bg-green-700 rounded-r-md font-medium flex items-center" disabled> |
| <i class="fas fa-paper-plane mr-2"></i> Send |
| </button> |
| </div> |
| <div class="mt-3 flex flex-wrap gap-2"> |
| <button class="quick-command px-3 py-1 bg-gray-700 hover:bg-gray-600 rounded text-sm">ls -la</button> |
| <button class="quick-command px-3 py-1 bg-gray-700 hover:bg-gray-600 rounded text-sm">cd /var/www</button> |
| <button class="quick-command px-3 py-1 bg-gray-700 hover:bg-gray-600 rounded text-sm">df -h</button> |
| <button class="quick-command px-3 py-1 bg-gray-700 hover:bg-gray-600 rounded text-sm">top</button> |
| <button class="quick-command px-3 py-1 bg-gray-700 hover:bg-gray-600 rounded text-sm">ping google.com</button> |
| </div> |
| </div> |
| |
| <div class="mt-6 text-center text-gray-400 text-sm"> |
| <p>Note: This is a frontend simulation. In a real implementation, you would need a backend service to establish actual SSH connections.</p> |
| </div> |
| </div> |
| </div> |
|
|
| <script> |
| document.addEventListener('DOMContentLoaded', function() { |
| |
| const terminal = document.getElementById('terminal'); |
| const commandInput = document.getElementById('command-input'); |
| const sendBtn = document.getElementById('send-btn'); |
| const connectBtn = document.getElementById('connect-btn'); |
| const disconnectBtn = document.getElementById('disconnect-btn'); |
| const clearBtn = document.getElementById('clear-btn'); |
| const togglePassword = document.getElementById('toggle-password'); |
| const passwordInput = document.getElementById('password'); |
| const connectionStatus = document.getElementById('connection-status'); |
| const quickCommands = document.querySelectorAll('.quick-command'); |
| |
| |
| let isConnected = false; |
| let currentPrompt = 'webssh-client$'; |
| |
| |
| togglePassword.addEventListener('click', function() { |
| if (passwordInput.type === 'password') { |
| passwordInput.type = 'text'; |
| togglePassword.innerHTML = '<i class="fas fa-eye-slash"></i>'; |
| } else { |
| passwordInput.type = 'password'; |
| togglePassword.innerHTML = '<i class="fas fa-eye"></i>'; |
| } |
| }); |
| |
| |
| connectBtn.addEventListener('click', function() { |
| const host = document.getElementById('host').value; |
| const port = document.getElementById('port').value; |
| const username = document.getElementById('username').value; |
| const password = document.getElementById('password').value; |
| |
| if (!host || !username || !password) { |
| appendToTerminal('error', 'Please fill in all connection details'); |
| return; |
| } |
| |
| |
| simulateConnection(host, port, username, password); |
| }); |
| |
| |
| disconnectBtn.addEventListener('click', function() { |
| simulateDisconnection(); |
| }); |
| |
| |
| clearBtn.addEventListener('click', function() { |
| terminal.innerHTML = ` |
| <div class="output"> |
| <span class="prompt">${currentPrompt}</span> <span id="cursor" class="cursor"></span> |
| </div> |
| `; |
| }); |
| |
| |
| sendBtn.addEventListener('click', sendCommand); |
| |
| |
| quickCommands.forEach(btn => { |
| btn.addEventListener('click', async function() { |
| if (isConnected) { |
| commandInput.value = this.textContent; |
| await sendCommand(); |
| } |
| }); |
| }); |
| |
| |
| commandInput.addEventListener('keypress', function(e) { |
| if (e.key === 'Enter') { |
| sendCommand(); |
| } |
| }); |
| |
| async function sendCommand() { |
| const command = commandInput.value.trim(); |
| if (!command) return; |
| |
| appendToTerminal('command', command); |
| commandInput.value = ''; |
| |
| |
| const response = await simulateCommandResponse(command); |
| appendToTerminal('output', response); |
| } |
| |
| function appendToTerminal(type, text) { |
| const outputDiv = terminal.querySelector('.output:last-child'); |
| |
| if (type === 'command') { |
| outputDiv.innerHTML = outputDiv.innerHTML.replace('<span id="cursor" class="cursor"></span>', ''); |
| outputDiv.innerHTML += `<span class="prompt">${currentPrompt}</span> <span class="command">${text}</span><br>`; |
| } |
| else if (type === 'output') { |
| outputDiv.innerHTML += `<span class="output">${text}</span><br>`; |
| } |
| else if (type === 'error') { |
| outputDiv.innerHTML += `<span class="error">${text}</span><br>`; |
| } |
| |
| |
| terminal.innerHTML += ` |
| <div class="output"> |
| <span class="prompt">${currentPrompt}</span> <span id="cursor" class="cursor"></span> |
| </div> |
| `; |
| |
| |
| terminal.scrollTop = terminal.scrollHeight; |
| } |
| |
| function simulateConnection(host, port, username, password) { |
| isConnected = true; |
| connectBtn.disabled = true; |
| disconnectBtn.disabled = false; |
| commandInput.disabled = false; |
| sendBtn.disabled = false; |
| connectionStatus.textContent = 'Connected'; |
| connectionStatus.className = 'px-3 py-1 rounded-full text-xs font-semibold bg-green-600'; |
| |
| appendToTerminal('command', `ssh ${username}@${host} -p ${port}`); |
| |
| |
| setTimeout(() => { |
| appendToTerminal('output', `Connecting to ${host} on port ${port}...`); |
| }, 500); |
| |
| setTimeout(() => { |
| appendToTerminal('output', `Authenticating as ${username}...`); |
| }, 1000); |
| |
| setTimeout(() => { |
| appendToTerminal('output', `Welcome to Ubuntu 20.04.4 LTS (GNU/Linux 5.4.0-109-generic x86_64)`); |
| appendToTerminal('output', `Last login: Mon Jun 12 14:30:22 2023 from 192.168.1.100`); |
| currentPrompt = `${username}@${host.split('.')[0]}:~$`; |
| |
| |
| const lastOutput = terminal.querySelector('.output:last-child'); |
| lastOutput.innerHTML = `<span class="prompt">${currentPrompt}</span> <span id="cursor" class="cursor"></span>`; |
| }, 1500); |
| } |
| |
| function simulateDisconnection() { |
| appendToTerminal('command', 'exit'); |
| |
| setTimeout(() => { |
| appendToTerminal('output', 'Connection to remote host closed.'); |
| isConnected = false; |
| connectBtn.disabled = false; |
| disconnectBtn.disabled = true; |
| commandInput.disabled = true; |
| sendBtn.disabled = true; |
| connectionStatus.textContent = 'Disconnected'; |
| connectionStatus.className = 'px-3 py-1 rounded-full text-xs font-semibold bg-gray-700'; |
| currentPrompt = 'webssh-client$'; |
| }, 500); |
| } |
| |
| async function executeRealPing(host) { |
| try { |
| const response = await fetch(`https://networkcalc.com/api/ping/${host}`); |
| const data = await response.json(); |
| if (data.status === 'success') { |
| return data.output; |
| } else { |
| return `Ping failed: ${data.message || 'Unknown error'}`; |
| } |
| } catch (error) { |
| return `Error: ${error.message}`; |
| } |
| } |
| |
| async function simulateCommandResponse(command) { |
| if (command.startsWith('ping ')) { |
| const host = command.split(' ')[1]; |
| if (host) { |
| return await executeRealPing(host); |
| } |
| return 'Usage: ping <hostname or IP>'; |
| } |
| else if (command === 'ls -la') { |
| return `total 72 |
| drwxr-xr-x 5 root root 4096 Jun 5 10:15 . |
| drwxr-xr-x 3 root root 4096 May 20 09:30 .. |
| -rw-r--r-- 1 root root 148 Aug 17 2022 .bashrc |
| -rw-r--r-- 1 root root 377 Aug 17 2022 .profile |
| drwx------ 2 root root 4096 Jun 5 10:15 .ssh |
| drwxr-xr-x 2 root root 4096 May 20 09:30 logs |
| drwxr-xr-x 6 root root 4096 May 20 09:30 www`; |
| } |
| else if (command === 'pwd') { |
| return '/home/user'; |
| } |
| else if (command === 'whoami') { |
| return 'user'; |
| } |
| else if (command === 'date') { |
| return new Date().toString(); |
| } |
| else if (command.startsWith('ping')) { |
| return `PING google.com (142.250.190.46) 56(84) bytes of data. |
| 64 bytes from 142.250.190.46: icmp_seq=1 ttl=117 time=12.3 ms |
| 64 bytes from 142.250.190.46: icmp_seq=2 ttl=117 time=11.8 ms |
| 64 bytes from 142.250.190.46: icmp_seq=3 ttl=117 time=12.1 ms |
| |
| --- google.com ping statistics --- |
| 3 packets transmitted, 3 received, 0% packet loss, time 2003ms |
| rtt min/avg/max/mdev = 11.800/12.066/12.300/0.200 ms`; |
| } |
| else if (command === 'top') { |
| return `top - 14:30:45 up 1 day, 3:45, 1 user, load average: 0.00, 0.01, 0.05 |
| Tasks: 125 total, 1 running, 124 sleeping, 0 stopped, 0 zombie |
| %Cpu(s): 0.3 us, 0.2 sy, 0.0 ni, 99.5 id, 0.0 wa, 0.0 hi, 0.0 si, 0.0 st |
| MiB Mem : 3950.8 total, 123.4 free, 1920.3 used, 1907.1 buff/cache |
| MiB Swap: 2048.0 total, 2048.0 free, 0.0 used. 1800.0 avail Mem`; |
| } |
| else if (command === 'df -h') { |
| return `Filesystem Size Used Avail Use% Mounted on |
| udev 2.0G 0 2.0G 0% /dev |
| tmpfs 395M 1.2M 394M 1% /run |
| /dev/sda1 39G 15G 23G 40% / |
| tmpfs 2.0G 0 2.0G 0% /dev/shm |
| tmpfs 5.0M 0 5.0M 0% /run/lock |
| tmpfs 2.0G 0 2.0G 0% /sys/fs/cgroup |
| /dev/sda15 105M 5.3M 100M 5% /boot/efi |
| tmpfs 395M 0 395M 0% /run/user/1000`; |
| } |
| else if (command === 'clear') { |
| terminal.innerHTML = ` |
| <div class="output"> |
| <span class="prompt">${currentPrompt}</span> <span id="cursor" class="cursor"></span> |
| </div> |
| `; |
| return ''; |
| } |
| else { |
| return `${command}: command not found`; |
| } |
| } |
| }); |
| </script> |
| <p style="border-radius: 8px; text-align: center; font-size: 12px; color: #fff; margin-top: 16px;position: fixed; left: 8px; bottom: 8px; z-index: 10; background: rgba(0, 0, 0, 0.8); padding: 4px 8px;">Made with <img src="https://deepsite.hf.co/logo.svg" alt="DeepSite Logo" style="width: 16px; height: 16px; vertical-align: middle;display:inline-block;margin-right:3px;filter:brightness(0) invert(1);"><a href="https://deepsite.hf.co" style="color: #fff;text-decoration: underline;" target="_blank" >DeepSite</a> - 🧬 <a href="https://deepsite.hf.co?remix=oxyle/ssha" style="color: #fff;text-decoration: underline;" target="_blank" >Remix</a></p></body> |
| </html> |