Fbrowser/bsshpy.py
Stan de0082611a added a ssh frontend called best ssh python or
bsshpy for short.
 Changes to be committed:
	new file:   bsshpy.py ssh frontend
	modified:   readme.txt updated some needs more
2024-06-29 13:47:43 -05:00

171 lines
6.2 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())