172 lines
6.3 KiB
Python
172 lines
6.3 KiB
Python
import sys
|
|
import os
|
|
from PyQt6.QtWidgets import (QApplication, QMainWindow, QWidget, QVBoxLayout, QHBoxLayout,
|
|
QLineEdit, QPushButton, QTextEdit, QFileDialog, QLabel)
|
|
from PyQt6.QtCore import QThread, pyqtSignal
|
|
import paramiko
|
|
|
|
class SSHThread(QThread):
|
|
output_received = pyqtSignal(str)
|
|
|
|
def __init__(self, client, command):
|
|
super().__init__()
|
|
self.client = client
|
|
self.command = command
|
|
|
|
def run(self):
|
|
stdin, stdout, stderr = self.client.exec_command(self.command)
|
|
for line in stdout:
|
|
self.output_received.emit(line.strip())
|
|
for line in stderr:
|
|
self.output_received.emit(line.strip())
|
|
|
|
class SSHWindow(QMainWindow):
|
|
def __init__(self):
|
|
super().__init__()
|
|
self.setWindowTitle("Enhanced SSH Frontend")
|
|
self.setGeometry(100, 100, 800, 600)
|
|
|
|
self.client = None
|
|
|
|
central_widget = QWidget()
|
|
layout = QVBoxLayout()
|
|
|
|
connection_layout = QHBoxLayout()
|
|
self.host_input = QLineEdit()
|
|
self.host_input.setPlaceholderText("Host")
|
|
connection_layout.addWidget(self.host_input)
|
|
|
|
self.user_input = QLineEdit()
|
|
self.user_input.setPlaceholderText("Username")
|
|
connection_layout.addWidget(self.user_input)
|
|
|
|
self.password_input = QLineEdit()
|
|
self.password_input.setPlaceholderText("Password")
|
|
self.password_input.setEchoMode(QLineEdit.EchoMode.Password)
|
|
connection_layout.addWidget(self.password_input)
|
|
|
|
self.connect_button = QPushButton("Connect")
|
|
self.connect_button.clicked.connect(self.connect_ssh)
|
|
connection_layout.addWidget(self.connect_button)
|
|
|
|
self.disconnect_button = QPushButton("Disconnect")
|
|
self.disconnect_button.clicked.connect(self.disconnect_ssh)
|
|
self.disconnect_button.setEnabled(False)
|
|
connection_layout.addWidget(self.disconnect_button)
|
|
|
|
layout.addLayout(connection_layout)
|
|
|
|
self.output_area = QTextEdit()
|
|
self.output_area.setReadOnly(True)
|
|
layout.addWidget(self.output_area)
|
|
|
|
command_layout = QHBoxLayout()
|
|
self.command_input = QLineEdit()
|
|
self.command_input.setPlaceholderText("Enter command")
|
|
command_layout.addWidget(self.command_input)
|
|
|
|
self.execute_button = QPushButton("Execute")
|
|
self.execute_button.clicked.connect(self.execute_command)
|
|
command_layout.addWidget(self.execute_button)
|
|
|
|
layout.addLayout(command_layout)
|
|
|
|
file_transfer_layout = QHBoxLayout()
|
|
self.upload_button = QPushButton("Upload File")
|
|
self.upload_button.clicked.connect(self.upload_file)
|
|
file_transfer_layout.addWidget(self.upload_button)
|
|
|
|
self.download_button = QPushButton("Download File")
|
|
self.download_button.clicked.connect(self.download_file)
|
|
file_transfer_layout.addWidget(self.download_button)
|
|
|
|
layout.addLayout(file_transfer_layout)
|
|
|
|
self.status_label = QLabel("Not connected")
|
|
layout.addWidget(self.status_label)
|
|
|
|
central_widget.setLayout(layout)
|
|
self.setCentralWidget(central_widget)
|
|
|
|
def connect_ssh(self):
|
|
host = self.host_input.text()
|
|
username = self.user_input.text()
|
|
password = self.password_input.text()
|
|
|
|
try:
|
|
self.client = paramiko.SSHClient()
|
|
self.client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
|
|
self.client.connect(hostname=host, username=username, password=password)
|
|
self.status_label.setText(f"Connected to {host}")
|
|
self.connect_button.setEnabled(False)
|
|
self.disconnect_button.setEnabled(True)
|
|
self.output_area.append(f"Connected to {host}\n")
|
|
except paramiko.AuthenticationException:
|
|
self.output_area.append("Authentication failed.\n")
|
|
except Exception as e:
|
|
self.output_area.append(f"Error: {str(e)}\n")
|
|
|
|
def disconnect_ssh(self):
|
|
if self.client:
|
|
self.client.close()
|
|
self.client = None
|
|
self.status_label.setText("Not connected")
|
|
self.connect_button.setEnabled(True)
|
|
self.disconnect_button.setEnabled(False)
|
|
self.output_area.append("Disconnected\n")
|
|
|
|
def execute_command(self):
|
|
if not self.client:
|
|
self.output_area.append("Not connected. Please connect first.\n")
|
|
return
|
|
|
|
command = self.command_input.text()
|
|
self.output_area.append(f"$ {command}\n")
|
|
self.command_input.clear()
|
|
|
|
self.ssh_thread = SSHThread(self.client, command)
|
|
self.ssh_thread.output_received.connect(self.update_output)
|
|
self.ssh_thread.start()
|
|
|
|
def update_output(self, output):
|
|
self.output_area.append(output + "\n")
|
|
|
|
def upload_file(self):
|
|
if not self.client:
|
|
self.output_area.append("Not connected. Please connect first.\n")
|
|
return
|
|
|
|
file_path, _ = QFileDialog.getOpenFileName(self, "Select File to Upload")
|
|
if file_path:
|
|
try:
|
|
sftp = self.client.open_sftp()
|
|
remote_path = f"/home/{self.user_input.text()}/{os.path.basename(file_path)}"
|
|
sftp.put(file_path, remote_path)
|
|
sftp.close()
|
|
self.output_area.append(f"Uploaded {file_path} to {remote_path}\n")
|
|
except Exception as e:
|
|
self.output_area.append(f"Upload failed: {str(e)}\n")
|
|
|
|
def download_file(self):
|
|
if not self.client:
|
|
self.output_area.append("Not connected. Please connect first.\n")
|
|
return
|
|
|
|
remote_path, ok = QFileDialog.getText(self, "Download File", "Enter remote file path:")
|
|
if ok and remote_path:
|
|
try:
|
|
sftp = self.client.open_sftp()
|
|
local_path, _ = QFileDialog.getSaveFileName(self, "Save File As")
|
|
if local_path:
|
|
sftp.get(remote_path, local_path)
|
|
sftp.close()
|
|
self.output_area.append(f"Downloaded {remote_path} to {local_path}\n")
|
|
except Exception as e:
|
|
self.output_area.append(f"Download failed: {str(e)}\n")
|
|
|
|
if __name__ == "__main__":
|
|
app = QApplication(sys.argv)
|
|
window = SSHWindow()
|
|
window.show()
|
|
sys.exit(app.exec())
|
|
|