First Commit
This commit is contained in:
commit
52d6fcd203
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/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'.
|
||||
```
|
73
docs/index.md
Normal file
73
docs/index.md
Normal file
@ -0,0 +1,73 @@
|
||||
# What is PyserSSH
|
||||
|
||||
PyserSSH is a library for remote control your code with ssh client. The aim is to provide a scriptable SSH server which can be made to behave like any SSH-enabled device.
|
||||
|
||||
This project is part from [damp11113-library](https://github.com/damp11113/damp11113-library)
|
||||
|
||||
This Server use port **2222** for default port
|
||||
|
||||
!!! 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!).
|
||||
|
||||
## Install
|
||||
Install from pypi
|
||||
```bash
|
||||
pip install PyserSSH
|
||||
```
|
||||
Install from github
|
||||
```bash
|
||||
pip install git+https://github.com/damp11113/PyserSSH.git
|
||||
```
|
||||
|
||||
## Quick Example
|
||||
```py linenums="1"
|
||||
import os
|
||||
|
||||
from PyserSSH import Server, Send, AccountManager
|
||||
|
||||
useraccount = AccountManager()
|
||||
useraccount.add_account("admin", "") # create user without password
|
||||
|
||||
ssh = Server(useraccount)
|
||||
|
||||
@ssh.on_user("command")
|
||||
def command(client, command: str):
|
||||
if command == "hello":
|
||||
Send(client, "world!")
|
||||
|
||||
ssh.run(os.path.join(os.path.dirname(os.path.realpath(__file__)), 'private_key.pem'))
|
||||
```
|
||||
|
||||
This example you can connect with `ssh admin@localhost -p 2222` and press enter on login
|
||||
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.
|
||||
|
||||
For run this demo you can use this command
|
||||
```
|
||||
$ python -m PyserSSH
|
||||
```
|
||||
then
|
||||
```
|
||||
Do you want to run demo? (y/n): y
|
||||
```
|
||||
But if no [damp11113-library](https://github.com/damp11113/damp11113-library)
|
||||
```
|
||||
No 'damp11113-library'
|
||||
This demo is require 'damp11113-library' for run
|
||||
```
|
||||
you need to install [damp11113-library](https://github.com/damp11113/damp11113-library) for run this demo by choose `y` or `yes` in lowercase or uppercase
|
||||
```
|
||||
Do you want to install 'damp11113-library'? (y/n): y
|
||||
```
|
||||
For exit demo you can use `ctrl+c` or use `shutdown now` in PyserSSH shell **(not in real terminal)**
|
||||
|
||||
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.
|
13
docs/showcase.md
Normal file
13
docs/showcase.md
Normal file
@ -0,0 +1,13 @@
|
||||
# PyserSSH 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
|
||||
|
||||

|
||||
|
||||
## 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
|
||||
|
||||

|
38
docs/system/client.md
Normal file
38
docs/system/client.md
Normal file
@ -0,0 +1,38 @@
|
||||
# Client
|
||||
`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
|
||||
```
|
||||
|
53
mkdocs.yml
Normal file
53
mkdocs.yml
Normal file
@ -0,0 +1,53 @@
|
||||
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:
|
||||
- mkdocs-video:
|
||||
is_video: True
|
||||
video_muted: True
|
||||
video_controls: True
|
Loading…
x
Reference in New Issue
Block a user