commit 52d6fcd203c30fc129ede5e55684c8bb0875bfb3 Author: damp11113 Date: Wed Jun 19 22:33:28 2024 +0700 First Commit diff --git a/docs/Images/dialogext/menudialog.png b/docs/Images/dialogext/menudialog.png new file mode 100644 index 0000000..a468822 Binary files /dev/null and b/docs/Images/dialogext/menudialog.png differ diff --git a/docs/Images/dialogext/textdialog.png b/docs/Images/dialogext/textdialog.png new file mode 100644 index 0000000..b588dad Binary files /dev/null and b/docs/Images/dialogext/textdialog.png differ diff --git a/docs/Images/dialogext/textinputdialog.png b/docs/Images/dialogext/textinputdialog.png new file mode 100644 index 0000000..da7a32f Binary files /dev/null and b/docs/Images/dialogext/textinputdialog.png differ diff --git a/docs/Images/dialogext/textinputdialogwithpasswordinput.png b/docs/Images/dialogext/textinputdialogwithpasswordinput.png new file mode 100644 index 0000000..c40499c Binary files /dev/null and b/docs/Images/dialogext/textinputdialogwithpasswordinput.png differ diff --git a/docs/Videos/demo1.mp4 b/docs/Videos/demo1.mp4 new file mode 100644 index 0000000..f2e6565 Binary files /dev/null and b/docs/Videos/demo1.mp4 differ diff --git a/docs/Videos/demo2.mp4 b/docs/Videos/demo2.mp4 new file mode 100644 index 0000000..0a1b5c8 Binary files /dev/null and b/docs/Videos/demo2.mp4 differ diff --git a/docs/extensions/dialog.md b/docs/extensions/dialog.md new file mode 100644 index 0000000..8caaf5f --- /dev/null +++ b/docs/extensions/dialog.md @@ -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() +``` +![Text Dialog](../Images/dialogext/textdialog.png) + +## 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 +``` +![Menu Dialog](../Images/dialogext/menudialog.png) + +## 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 +``` +![Text Input Dialog](../Images/dialogext/textinputdialog.png) + +password input +```py +DL = dialog.TextInputDialog(client, password=True) +DL.render() +print(DL.output()) # output when user is typed and entered password +``` +![Text Input Dialog with password input](../Images/dialogext/textinputdialogwithpasswordinput.png) diff --git a/docs/extensions/xhandler.md b/docs/extensions/xhandler.md new file mode 100644 index 0000000..ce2e0d4 --- /dev/null +++ b/docs/extensions/xhandler.md @@ -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 ` 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 +``` +or if disable `showusageonworng` +```bash +Missing required argument 'testvalue' for command 'hello' +``` + +### Invalid argument +if enable `showusageonworng` +```bash +> hello -testvalue +hello + +Usage: hello +``` +or if disable `showusageonworng` +```bash +> hello -testvalue +Invalid number of arguments for command 'hello'. +``` diff --git a/docs/index.md b/docs/index.md new file mode 100644 index 0000000..6af5209 --- /dev/null +++ b/docs/index.md @@ -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. \ No newline at end of file diff --git a/docs/showcase.md b/docs/showcase.md new file mode 100644 index 0000000..f5af8bc --- /dev/null +++ b/docs/showcase.md @@ -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 + +![type:video](Videos/demo1.mp4) + +## 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 + +![type:video](Videos/demo2.mp4) \ No newline at end of file diff --git a/docs/system/client.md b/docs/system/client.md new file mode 100644 index 0000000..1c80604 --- /dev/null +++ b/docs/system/client.md @@ -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 \ No newline at end of file diff --git a/docs/system/events/extension.md b/docs/system/events/extension.md new file mode 100644 index 0000000..25d6b3e --- /dev/null +++ b/docs/system/events/extension.md @@ -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 +``` \ No newline at end of file diff --git a/docs/system/events/index.md b/docs/system/events/index.md new file mode 100644 index 0000000..64bf601 --- /dev/null +++ b/docs/system/events/index.md @@ -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 +``` + diff --git a/mkdocs.yml b/mkdocs.yml new file mode 100644 index 0000000..c451e01 --- /dev/null +++ b/mkdocs.yml @@ -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 \ No newline at end of file