Compare commits
No commits in common. "main" and "master" have entirely different histories.
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@ -0,0 +1,2 @@
|
||||
docs/video/
|
||||
side/
|
2
LICENSE
2
LICENSE
@ -1,6 +1,6 @@
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2024 damp11113
|
||||
Copyright (c) 2024 dharm pimsen
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
|
||||
|
4
docs/Images/PyserSSH.drawio.svg
Normal file
4
docs/Images/PyserSSH.drawio.svg
Normal file
File diff suppressed because one or more lines are too long
After Width: | Height: | Size: 612 KiB |
BIN
docs/Images/dialogext/menudialog.png
Normal file
BIN
docs/Images/dialogext/menudialog.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
BIN
docs/Images/dialogext/textdialog.png
Normal file
BIN
docs/Images/dialogext/textdialog.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 11 KiB |
BIN
docs/Images/dialogext/textinputdialog.png
Normal file
BIN
docs/Images/dialogext/textinputdialog.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 12 KiB |
BIN
docs/Images/dialogext/textinputdialogwithpasswordinput.png
Normal file
BIN
docs/Images/dialogext/textinputdialogwithpasswordinput.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 11 KiB |
BIN
docs/Videos/demo0.mp4
Normal file
BIN
docs/Videos/demo0.mp4
Normal file
Binary file not shown.
BIN
docs/Videos/demo1.mp4
Normal file
BIN
docs/Videos/demo1.mp4
Normal file
Binary file not shown.
BIN
docs/Videos/demo2.mp4
Normal file
BIN
docs/Videos/demo2.mp4
Normal file
Binary file not shown.
45
docs/extensions/dialog.md
Normal file
45
docs/extensions/dialog.md
Normal file
@ -0,0 +1,45 @@
|
||||
# Dialog
|
||||
```py
|
||||
import PyserSSH.extensions.dialog as dialog
|
||||
```
|
||||
Dialog extension is a nifty little tool.
|
||||
This extension actually recreates standard Windows dialog boxes in a text environment using ANSI escape control codes.
|
||||
It is installed in library by default.
|
||||
|
||||
## Text Dialog
|
||||
This dialog show only text
|
||||
```py
|
||||
DL = dialog.TextDialog(client, "Hello World")
|
||||
DL.render()
|
||||
```
|
||||

|
||||
|
||||
## Menu Dialog
|
||||
This dialog use for choose list
|
||||
```py
|
||||
Mylist = ["Item 1", "Item 2", "Item 3", "Item 4", "Item 5"]
|
||||
|
||||
DL = dialog.MenuDialog(client, Mylist)
|
||||
DL.render()
|
||||
print(DL.output()) # output when user is selected
|
||||
```
|
||||

|
||||
|
||||
## Input Dialog
|
||||
This dialog use for input string or password
|
||||
!!! Bug "Bug"
|
||||
Maybe you can't backspace to clear all inputted when you type too fast
|
||||
```py
|
||||
DL = dialog.TextInputDialog(client)
|
||||
DL.render()
|
||||
print(DL.output()) # output when user is typed and entered
|
||||
```
|
||||

|
||||
|
||||
password input
|
||||
```py
|
||||
DL = dialog.TextInputDialog(client, password=True)
|
||||
DL.render()
|
||||
print(DL.output()) # output when user is typed and entered password
|
||||
```
|
||||

|
110
docs/extensions/xhandler.md
Normal file
110
docs/extensions/xhandler.md
Normal file
@ -0,0 +1,110 @@
|
||||
# XHandler
|
||||
```py
|
||||
import PyserSSH.extensions.XHandler as XHandler
|
||||
```
|
||||
XHandler is eXternal Handler. Coding your command like discord.py
|
||||
|
||||
## Setup
|
||||
You can enable XHandler by
|
||||
```py
|
||||
XH = XHandler()
|
||||
ssh = Server(XHandler=XH)
|
||||
```
|
||||
This enable is disable `command` event and enable 2 event. [click here](../system/events/extension.md) goto XHandler event.
|
||||
|
||||
## Quick Example
|
||||
```py
|
||||
@XH.command()
|
||||
def calculate(client, mode="add", x=3, y=1, hello=False):
|
||||
"""Perform mathematical operations."""
|
||||
x, y, = int(x), int(y)
|
||||
if mode == "add":
|
||||
Send(client, x + y)
|
||||
elif mode == "sub":
|
||||
Send(client, x - y)
|
||||
elif mode == "mul":
|
||||
Send(client, x * y)
|
||||
elif mode == "div":
|
||||
Send(client, x / y)
|
||||
|
||||
if hello:
|
||||
Send(client, "Hello World!")
|
||||
```
|
||||
```bash
|
||||
> calculate
|
||||
4
|
||||
```
|
||||
this command you can custom value by use `-` in your command
|
||||
```bash
|
||||
> calculate -mode sub
|
||||
2
|
||||
> calculate -x 5 -y 2
|
||||
7
|
||||
> calculate -x 5 -y 2 -mode mul
|
||||
10
|
||||
```
|
||||
you can use `--` for boolean only
|
||||
```bash
|
||||
> calculate --hello
|
||||
4
|
||||
Hello World!
|
||||
```
|
||||
|
||||
## Help command
|
||||
You can disable help command by `enablehelp=False`
|
||||
|
||||
```bash
|
||||
> help
|
||||
No Category:
|
||||
calculate - Perform mathematical operations.
|
||||
```
|
||||
you can use `help <command>` for more command info
|
||||
```bash
|
||||
> help calculate
|
||||
calculate
|
||||
Perform mathematical operations.
|
||||
Usage: calculate [-mode add] [-x 3] [-y 1] [--hello]
|
||||
```
|
||||
## Error
|
||||
You can show error input command by `showusageonworng=False`
|
||||
|
||||
### Command Not Found
|
||||
```bash
|
||||
> hello
|
||||
hello not found
|
||||
```
|
||||
#### Handle
|
||||
You can handle command not found by using `.commandnotfound`
|
||||
```py
|
||||
def notfound(client, command):
|
||||
# your process
|
||||
|
||||
XH.commandnotfound = notfound
|
||||
```
|
||||
|
||||
### Missing argument
|
||||
if enable `showusageonworng`
|
||||
```bash
|
||||
> hello
|
||||
hello
|
||||
|
||||
Usage: hello <testvalue>
|
||||
```
|
||||
or if disable `showusageonworng`
|
||||
```bash
|
||||
Missing required argument 'testvalue' for command 'hello'
|
||||
```
|
||||
|
||||
### Invalid argument
|
||||
if enable `showusageonworng`
|
||||
```bash
|
||||
> hello -testvalue
|
||||
hello
|
||||
|
||||
Usage: hello <testvalue>
|
||||
```
|
||||
or if disable `showusageonworng`
|
||||
```bash
|
||||
> hello -testvalue
|
||||
Invalid number of arguments for command 'hello'.
|
||||
```
|
238
docs/history.md
Normal file
238
docs/history.md
Normal file
@ -0,0 +1,238 @@
|
||||
# History of PyserSSH
|
||||
|
||||
**PyserSSH Version 1.0 (Filename: "test277.py")**
|
||||
|
||||
*Date Created: September 3, 2023*
|
||||
|
||||
PyserSSH began as an experimental project aimed at addressing the lack of suitable SSH server libraries available for Python. Initially, it was developed solely for research purposes. The project was driven by the need for a customizable SSH server solution that could be tailored to specific requirements not met by existing libraries. As the project progressed, its potential to evolve into a fully functional and practical library became evident, leading to the decision to develop PyserSSH into a more robust tool for use in both software and server applications.
|
||||
|
||||
## Before PyserSSH
|
||||
Before creating PyserSSH, we evaluated several existing libraries:
|
||||
|
||||
### SSHim
|
||||
SSShim is an SSH server library designed primarily for testing SSH clients. It is discontinued and not suitable for real-world use. It allows simple interactions with the user, such as input text, but lacks ease of use for more complex scenarios.
|
||||
|
||||
**Example Code:**
|
||||
```python
|
||||
import logging
|
||||
logging.basicConfig(level='DEBUG')
|
||||
logger = logging.getLogger()
|
||||
|
||||
import sshim, re
|
||||
|
||||
def hello_world(script):
|
||||
script.write('Please enter your name: ')
|
||||
groups = script.expect(re.compile('(?P<name>.*)')).groupdict()
|
||||
logger.info('%(name)s just connected', **groups)
|
||||
script.writeline('Hello %(name)s!' % groups)
|
||||
|
||||
server = sshim.Server(hello_world, port=3000)
|
||||
try:
|
||||
server.run()
|
||||
except KeyboardInterrupt:
|
||||
server.stop()
|
||||
```
|
||||
**Observation:** While SSHim successfully receives user input, it is not very user-friendly or flexible for real-world applications.
|
||||
|
||||
### Twisted
|
||||
|
||||
Twisted is a comprehensive event-driven networking engine in Python. It provides an SSH server implementation but is known for its complexity, making it less accessible to new users.
|
||||
|
||||
**Example Code ([Thank For this gist](https://gist.github.com/michaellihs/d2070d7a6d3bb65be18c)):**
|
||||
```python
|
||||
from twisted.conch import avatar, recvline
|
||||
from twisted.conch.interfaces import IConchUser, ISession
|
||||
from twisted.conch.ssh import factory, keys, session
|
||||
from twisted.conch.insults import insults
|
||||
from twisted.cred import portal, checkers
|
||||
from twisted.internet import reactor
|
||||
from zope.interface import implements
|
||||
|
||||
class SSHDemoProtocol(recvline.HistoricRecvLine):
|
||||
def __init__(self, user):
|
||||
self.user = user
|
||||
|
||||
def connectionMade(self):
|
||||
recvline.HistoricRecvLine.connectionMade(self)
|
||||
self.terminal.write("Welcome to my test SSH server.")
|
||||
self.terminal.nextLine()
|
||||
self.do_help()
|
||||
self.showPrompt()
|
||||
|
||||
def showPrompt(self):
|
||||
self.terminal.write("$ ")
|
||||
|
||||
def getCommandFunc(self, cmd):
|
||||
return getattr(self, 'do_' + cmd, None)
|
||||
|
||||
def lineReceived(self, line):
|
||||
line = line.strip()
|
||||
if line:
|
||||
print(line)
|
||||
with open('logfile.log', 'w') as f:
|
||||
f.write(line + '\n')
|
||||
cmdAndArgs = line.split()
|
||||
cmd = cmdAndArgs[0]
|
||||
args = cmdAndArgs[1:]
|
||||
func = self.getCommandFunc(cmd)
|
||||
if func:
|
||||
try:
|
||||
func(*args)
|
||||
except Exception as e:
|
||||
self.terminal.write("Error: %s" % e)
|
||||
self.terminal.nextLine()
|
||||
else:
|
||||
self.terminal.write("No such command.")
|
||||
self.terminal.nextLine()
|
||||
self.showPrompt()
|
||||
|
||||
def do_help(self):
|
||||
publicMethods = [funcname for funcname in dir(self) if funcname.startswith('do_')]
|
||||
commands = [cmd.replace('do_', '', 1) for cmd in publicMethods]
|
||||
self.terminal.write("Commands: " + " ".join(commands))
|
||||
self.terminal.nextLine()
|
||||
|
||||
def do_echo(self, *args):
|
||||
self.terminal.write(" ".join(args))
|
||||
self.terminal.nextLine()
|
||||
|
||||
def do_whoami(self):
|
||||
self.terminal.write(self.user.username)
|
||||
self.terminal.nextLine()
|
||||
|
||||
def do_quit(self):
|
||||
self.terminal.write("Thanks for playing!")
|
||||
self.terminal.nextLine()
|
||||
self.terminal.loseConnection()
|
||||
|
||||
def do_clear(self):
|
||||
self.terminal.reset()
|
||||
|
||||
class SSHDemoAvatar(avatar.ConchUser):
|
||||
implements(ISession)
|
||||
|
||||
def __init__(self, username):
|
||||
avatar.ConchUser.__init__(self)
|
||||
self.username = username
|
||||
self.channelLookup.update({'session': session.SSHSession})
|
||||
|
||||
def openShell(self, protocol):
|
||||
serverProtocol = insults.ServerProtocol(SSHDemoProtocol, self)
|
||||
serverProtocol.makeConnection(protocol)
|
||||
protocol.makeConnection(session.wrapProtocol(serverProtocol))
|
||||
|
||||
def getPty(self, terminal, windowSize, attrs):
|
||||
return None
|
||||
|
||||
def execCommand(self, protocol, cmd):
|
||||
raise NotImplementedError()
|
||||
|
||||
def closed(self):
|
||||
pass
|
||||
|
||||
class SSHDemoRealm(object):
|
||||
implements(portal.IRealm)
|
||||
|
||||
def requestAvatar(self, avatarId, mind, *interfaces):
|
||||
if IConchUser in interfaces:
|
||||
return interfaces[0], SSHDemoAvatar(avatarId), lambda: None
|
||||
else:
|
||||
raise NotImplementedError("No supported interfaces found.")
|
||||
|
||||
def getRSAKeys():
|
||||
with open('id_rsa') as privateBlobFile:
|
||||
privateBlob = privateBlobFile.read()
|
||||
privateKey = keys.Key.fromString(data=privateBlob)
|
||||
|
||||
with open('id_rsa.pub') as publicBlobFile:
|
||||
publicBlob = publicBlobFile.read()
|
||||
publicKey = keys.Key.fromString(data=publicBlob)
|
||||
|
||||
return publicKey, privateKey
|
||||
|
||||
if __name__ == "__main__":
|
||||
sshFactory = factory.SSHFactory()
|
||||
sshFactory.portal = portal.Portal(SSHDemoRealm())
|
||||
|
||||
users = {'admin': 'aaa', 'guest': 'bbb'}
|
||||
sshFactory.portal.registerChecker(
|
||||
checkers.InMemoryUsernamePasswordDatabaseDontUse(**users))
|
||||
pubKey, privKey = getRSAKeys()
|
||||
sshFactory.publicKeys = {'ssh-rsa': pubKey}
|
||||
sshFactory.privateKeys = {'ssh-rsa': privKey}
|
||||
reactor.listenTCP(22222, sshFactory)
|
||||
reactor.run()
|
||||
```
|
||||
**Observation:** While Twisted provides a comprehensive SSH server implementation, it is quite complex for new users and requires significant setup and configuration.
|
||||
|
||||
### Paramiko
|
||||
|
||||
Paramiko is a Python library for SSH protocol implementation. It supports both SSH client and server functionalities but is primarily used for SSH client tasks. It is well-documented and widely used, providing a more straightforward approach for SSH operations compared to more complex frameworks.
|
||||
|
||||
**Example Code:**
|
||||
```python
|
||||
import paramiko
|
||||
|
||||
class SimpleSSHServer(paramiko.ServerInterface):
|
||||
def __init__(self):
|
||||
self.event = paramiko.Event()
|
||||
self.event.set()
|
||||
|
||||
def check_channel_request(self, kind, channel):
|
||||
if kind == 'session':
|
||||
return paramiko.OPEN_SUCCEEDED
|
||||
return paramiko.FAILURE
|
||||
|
||||
def check_auth_password(self, username, password):
|
||||
if username == 'test' and password == 'password':
|
||||
return paramiko.AUTH_SUCCESSFUL
|
||||
return paramiko.AUTH_FAILED
|
||||
|
||||
def handle_client(client_socket):
|
||||
transport = paramiko.Transport(client_socket)
|
||||
transport.add_server_key(paramiko.RSAKey.generate(2048))
|
||||
server = SimpleSSHServer()
|
||||
transport.start_server(server=server)
|
||||
|
||||
channel = transport.accept(20)
|
||||
if channel is None:
|
||||
print("No channel.")
|
||||
return
|
||||
|
||||
channel.send("Hello from Paramiko SSH server!")
|
||||
channel.recv(1024)
|
||||
|
||||
transport.close()
|
||||
|
||||
if __name__ == "__main__":
|
||||
import socket
|
||||
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||
server_socket.bind(('0.0.0.0', 2200))
|
||||
server_socket.listen(100)
|
||||
|
||||
while True:
|
||||
client_socket, addr = server_socket.accept()
|
||||
handle_client(client_socket)
|
||||
```
|
||||
**Observation:** Paramiko is straightforward and well-suited for implementing SSH clients and servers. However, it requires additional code for handling specific server features and authentication mechanisms.
|
||||
|
||||
## Reconversion to PyserSSH
|
||||
In contrast to SSHim, Twisted, and Paramiko, PyserSSH aims to simplify SSH server implementation. The following example illustrates how PyserSSH makes it easier to handle user input and interactions:
|
||||
|
||||
```python
|
||||
from PyserSSH import Server, Send, wait_input, AccountManager
|
||||
|
||||
account = AccountManager(anyuser=True)
|
||||
server = Server(account, inputsystem=False)
|
||||
|
||||
@server.on_user("connect")
|
||||
def hello_world(client):
|
||||
name = wait_input(client, "Please enter your name: ")
|
||||
Send(client, f"Hello {name}!")
|
||||
|
||||
server.run("your private key")
|
||||
```
|
||||
|
||||
### Advantages of PyserSSH
|
||||
- **Simplicity:** PyserSSH provides an intuitive and user-friendly API, making it easier for developers to create and manage SSH servers.
|
||||
- **Flexibility:** PyserSSH offers the functionality needed for more complex interactions while maintaining a straightforward setup and usage.
|
66
docs/index.md
Normal file
66
docs/index.md
Normal file
@ -0,0 +1,66 @@
|
||||
# What is PyserSSH
|
||||
|
||||
PyserSSH is a free and open-source Python library designed to facilitate the creation of customizable SSH terminal servers. Initially developed for research purposes to address the lack of suitable SSH server libraries in Python, PyserSSH provides a flexible and user-friendly solution for implementing SSH servers, making it easier for developers to handle user interactions and command processing.
|
||||
|
||||
The project was started by a solo developer to create a more accessible and flexible tool for managing SSH connections and commands. It offers a simplified API compared to other libraries, such as Paramiko, SSHim, and Twisted, which are either outdated or complex for new users.
|
||||
|
||||
This project is part from [damp11113-library](https://github.com/damp11113/damp11113-library)
|
||||
|
||||

|
||||
|
||||
!!! warning "Cursor scroll in progress"
|
||||
This current version the Cursor scroll is in development! it very ugly! if you use right now.
|
||||
To try Cursor scroll you can enable by `disable_scroll_with_arrow=False` in `Server()`
|
||||
(not recommend to enable on this version it very ugly!).
|
||||
|
||||
## Some small PyserSSH history
|
||||
PyserSSH version [1.0](https://github.com/DPSoftware-Foundation/PyserSSH/releases/download/Legacy/PyserSSH10.py) (real filename is "test277.py") was created in 2023/9/3 for experimental purposes only. Because I couldn't find the best ssh server library for python and I started this project only for research. But I have time to develop this research into a real library for use. In software or server.
|
||||
|
||||
read full history from this [page](./history.html)
|
||||
|
||||
## Install
|
||||
Install from pypi
|
||||
```bash
|
||||
pip install PyserSSH
|
||||
```
|
||||
Install with [openRemoDesk](https://github.com/DPSoftware-Foundation/openRemoDesk) protocol
|
||||
```bash
|
||||
pip install PyserSSH[RemoDesk]
|
||||
```
|
||||
Install from Github
|
||||
```bash
|
||||
pip install git+https://github.com/damp11113/PyserSSH.git
|
||||
```
|
||||
Install from DPCloudev Git
|
||||
```bash
|
||||
pip install git+https://git.damp11113.xyz/DPSoftware-Foundation/PyserSSH.git
|
||||
```
|
||||
|
||||
## Quick Example
|
||||
This Server use port **2222** for default port
|
||||
```py linenums="1"
|
||||
from PyserSSH import Server, Send, AccountManager
|
||||
|
||||
useraccount = AccountManager(anyuser=True)
|
||||
ssh = Server(useraccount)
|
||||
|
||||
@ssh.on_user("command")
|
||||
def command(client, command: str):
|
||||
if command == "hello":
|
||||
Send(client, "world!")
|
||||
|
||||
ssh.run("your private key file")
|
||||
```
|
||||
|
||||
This example you can connect with `ssh localhost -p 2222`
|
||||
If you input `hello` the response is `world`
|
||||
|
||||
## Demo
|
||||
https://github.com/damp11113/PyserSSH/assets/64675096/49bef3e2-3b15-4b64-b88e-3ca84a955de7
|
||||
|
||||
!!! warning "Need to changing"
|
||||
For use in product please **generate new private key**! If you still use this demo private key maybe your product getting **hacked**! up to 90%. Please don't use this demo private key for real product.
|
||||
|
||||
I intend to leaked private key because that key i generated new. I recommend to generate new key if you want to use on your host because that key is for demo only.
|
||||
why i talk about this? because when i push private key into this repo in next 5 min++ i getting new email from GitGuardian. in that email say "
|
||||
GitGuardian has detected the following RSA Private Key exposed within your GitHub account" i dont knows what is GitGuardian and i not install this app into my account.
|
19
docs/showcase.md
Normal file
19
docs/showcase.md
Normal file
@ -0,0 +1,19 @@
|
||||
# Showcase
|
||||
|
||||
The following project have been developed with PyserSSH by various developers and show the superiority of ssh server. PyserSSH is a fast, easy to use and powerful python cross-platform ssh server library (Windows, Linux and MacOS) available under a permissive MIT license.
|
||||
|
||||
## Demo 1
|
||||
[Demo 1](https://github.com/damp11113/PyserSSH/blob/main/src/PyserSSH/demo/demo1.py) is simple command with can interact to user. Build by PyserSSH v4.0
|
||||
|
||||
<video controls>
|
||||
<source src="Videos/demo1.mp4" type="video/mp4">
|
||||
Your browser does not support the video tag.
|
||||
</video>
|
||||
|
||||
## SRT Karaoke (Demo 2)
|
||||
[Demo 2](https://github.com/damp11113/PyserSSH/blob/main/src/PyserSSH/demo/demo2.py) is simple srt file karaoke player with no sound. Build by PyserSSH v4.5 (v5.0)
|
||||
|
||||
<video controls>
|
||||
<source src="Videos/demo2.mp4" type="video/mp4">
|
||||
Your browser does not support the video tag.
|
||||
</video>
|
48
docs/system/client.md
Normal file
48
docs/system/client.md
Normal file
@ -0,0 +1,48 @@
|
||||
# Client
|
||||
|
||||
!!! success "PyserSSH 5.0x"
|
||||
In new version of PyserSSH or version 5.0
|
||||
It very easy to use and more infomation for client
|
||||
|
||||
Don't worry for old code because in client it has backward compatibility for old code
|
||||
|
||||
Like "client["channel"]" to "client.channel"
|
||||
|
||||
|
||||
`client` is use for infomation and control user
|
||||
|
||||
this is structure
|
||||
```py
|
||||
{
|
||||
"current_user": None,
|
||||
"channel": channel,
|
||||
"last_activity_time": None,
|
||||
"connecttype": None,
|
||||
"last_login_time": None,
|
||||
"windowsize": {},
|
||||
"x11": {},
|
||||
"prompt": None,
|
||||
"inputbuffer": None,
|
||||
"peername": peername
|
||||
}
|
||||
```
|
||||
|
||||
`current_user` is username
|
||||
|
||||
`channel` is for socket channel
|
||||
|
||||
`last_activity_time` is last activity time (timestamp)
|
||||
|
||||
`connecttype` has 2 type: ssh and sftp
|
||||
|
||||
`last_login_time` is last login time (timestamp)
|
||||
|
||||
`windowsize` is terminal size
|
||||
|
||||
`x11` is x11 info from client
|
||||
|
||||
`prompt` is the symbol or message indicating that the system is ready to receive a command from the user.
|
||||
|
||||
`inputbuffer` is buffer from inputsystem
|
||||
|
||||
`peername` is user peername
|
20
docs/system/events/extension.md
Normal file
20
docs/system/events/extension.md
Normal file
@ -0,0 +1,20 @@
|
||||
# Extension event (XHandler only)
|
||||
To handle the event can use `on_user()` decorator
|
||||
|
||||
This extension have only [XHandler](../../extensions/xhandler.md) and `command` event is not called if enable XHandler
|
||||
|
||||
## beforexhandler
|
||||
Called when user entered command before XHandler command
|
||||
```py
|
||||
@ssh.on_user("beforexhandler")
|
||||
def before(client, command):
|
||||
# do something
|
||||
```
|
||||
|
||||
## afterxhandler
|
||||
Called when user entered command after XHandler command
|
||||
```py
|
||||
@ssh.on_user("afterxhandler")
|
||||
def after(client, command):
|
||||
# do something
|
||||
```
|
130
docs/system/events/index.md
Normal file
130
docs/system/events/index.md
Normal file
@ -0,0 +1,130 @@
|
||||
# Server Event
|
||||
|
||||
To handle the event can use `on_user()` decorator
|
||||
|
||||
## connect
|
||||
Called when user connected to server and authenticated
|
||||
```py
|
||||
@ssh.on_user("connect")
|
||||
def connect(client):
|
||||
# do something
|
||||
```
|
||||
## connectsftp
|
||||
Called when user connected to server and authenticated with sftp
|
||||
```py
|
||||
@ssh.on_user("connectsftp")
|
||||
def connectsftp(client):
|
||||
# do something
|
||||
```
|
||||
|
||||
## auth (only usexternalauth=True in Server())
|
||||
Called when user press enter to server and authenticating
|
||||
|
||||
```py
|
||||
ssh = Server(usexternalauth=True)
|
||||
|
||||
@ssh.on_user("auth")
|
||||
def auth(data):
|
||||
# do something
|
||||
return
|
||||
```
|
||||
### data
|
||||
```py
|
||||
{
|
||||
"username": ...,
|
||||
"password": ...,
|
||||
}
|
||||
```
|
||||
**return** True/False
|
||||
|
||||
|
||||
## connectpty
|
||||
Called when user connected to server and authenticated with pty request (terminal info)
|
||||
|
||||
```py
|
||||
@ssh.on_user("connectpty")
|
||||
def connectpty(client, data):
|
||||
# do something
|
||||
```
|
||||
|
||||
### data
|
||||
```py
|
||||
{
|
||||
"term": ...,
|
||||
"width": ...,
|
||||
"height": ...,
|
||||
"pixelwidth": ...,
|
||||
"pixelheight": ...,
|
||||
"modes": ...
|
||||
}
|
||||
```
|
||||
|
||||
## resized
|
||||
Called when user resized terminal
|
||||
```py
|
||||
@ssh.on_user("resized")
|
||||
def resized(client, data):
|
||||
# do something
|
||||
```
|
||||
|
||||
### data
|
||||
```py
|
||||
{
|
||||
"width": ...,
|
||||
"height": ...,
|
||||
"pixelwidth": ...,
|
||||
"pixelheight": ...
|
||||
}
|
||||
```
|
||||
## command
|
||||
Called when user entered command
|
||||
|
||||
```py
|
||||
@ssh.on_user("command")
|
||||
def command(client, command):
|
||||
# do something
|
||||
```
|
||||
|
||||
## type
|
||||
Called press key (no ansi)
|
||||
```py
|
||||
@ssh.on_user("type")
|
||||
def type(client, key):
|
||||
# do something
|
||||
```
|
||||
|
||||
## rawtype
|
||||
Called press key
|
||||
```py
|
||||
@ssh.on_user("rawtype")
|
||||
def rawtype(client, key):
|
||||
# do something
|
||||
```
|
||||
|
||||
## error
|
||||
Called when inside command event error
|
||||
```py
|
||||
@ssh.on_user("error")
|
||||
def error(client, error):
|
||||
# do something
|
||||
```
|
||||
|
||||
## disconnected
|
||||
Called when user is exited (safe exit)
|
||||
|
||||
```py
|
||||
@ssh.on_user("disconnected")
|
||||
def disconnected(client):
|
||||
# do something
|
||||
```
|
||||
|
||||
## timeout
|
||||
Called when user is timeout (on inputsystem only)
|
||||
|
||||
|
||||
```py
|
||||
@ssh.on_user("timeout")
|
||||
def timeout(client):
|
||||
# do something
|
||||
```
|
||||
|
49
mkdocs.yml
Normal file
49
mkdocs.yml
Normal file
@ -0,0 +1,49 @@
|
||||
site_name: PyserSSH
|
||||
copyright: Copyright © 2023 - 2024 DPSoftware Foundation
|
||||
theme:
|
||||
name: material
|
||||
palette:
|
||||
# Palette toggle for light mode
|
||||
- media: "(prefers-color-scheme: light)"
|
||||
scheme: default
|
||||
toggle:
|
||||
icon: material/brightness-7
|
||||
name: Switch to dark mode
|
||||
|
||||
# Palette toggle for dark mode
|
||||
- media: "(prefers-color-scheme: dark)"
|
||||
scheme: slate
|
||||
toggle:
|
||||
icon: material/brightness-4
|
||||
name: Switch to light mode
|
||||
|
||||
features:
|
||||
- content.code.annotate
|
||||
- content.code.select
|
||||
- navigation.tabs
|
||||
|
||||
markdown_extensions:
|
||||
- pymdownx.highlight:
|
||||
anchor_linenums: true
|
||||
line_spans: __span
|
||||
pygments_lang_class: true
|
||||
- pymdownx.emoji:
|
||||
emoji_index: !!python/name:material.extensions.emoji.twemoji
|
||||
emoji_generator: !!python/name:material.extensions.emoji.to_svg
|
||||
- pymdownx.inlinehilite
|
||||
- pymdownx.snippets
|
||||
- pymdownx.superfences
|
||||
- attr_list
|
||||
- admonition
|
||||
- pymdownx.details
|
||||
- pymdownx.superfences
|
||||
- md_in_html
|
||||
|
||||
extra:
|
||||
generator: false
|
||||
social:
|
||||
- icon: fontawesome/brands/github
|
||||
link: https://github.com/damp11113/PyserSSH
|
||||
|
||||
plugins:
|
||||
- offline
|
Loading…
x
Reference in New Issue
Block a user