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