pywebexec 1.1.2__py3-none-any.whl → 1.4.12__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -5,14 +5,23 @@
5
5
  <link rel="icon" href="/static/images/favicon.svg" type="image/svg+xml">
6
6
  <title>{{ title }}</title>
7
7
  <link rel="stylesheet" href="/static/css/style.css">
8
+ <link rel="stylesheet" href="/static/css/xterm.css">
8
9
  </head>
9
10
  <body>
10
- <h2>{{ title }}</h2>
11
- <form id="launchForm">
11
+ <div id="dimmer" class="dimmer">
12
+ <div class="dimmer-text">Server not available</div>
13
+ </div>
14
+ <h2><span class="status-icon title-icon"></span>{{ title }}</h2>
15
+ <form id="launchForm" class="form-inline">
12
16
  <label for="commandName">Command</label>
13
- <select id="commandName" name="commandName"></select>
14
- <label for="params">Params</label>
15
- <input type="text" id="params" name="params">
17
+ <div class="input-group">
18
+ <input type="text" id="commandName" name="commandName" size=5 autocomplete="off" style="width: 100px;" autofocus>
19
+ <div id="showCommandListButton" class="show-command-list-button">
20
+ <span class="arrow">&#9660;</span>
21
+ </div>
22
+ <select id="commandList" class="command-list" size="20"></select>
23
+ <input type="text" id="params" name="params" oninput="this.style.width = ((this.value.length + 1) * 8) + 'px';">
24
+ </div>
16
25
  <button type="submit">Run</button>
17
26
  </form>
18
27
  <div class="table-container" id="tableContainer">
@@ -20,11 +29,10 @@
20
29
  <thead>
21
30
  <tr>
22
31
  <th>ID</th>
23
- <th>Status</th>
24
32
  <th>Start Time</th>
25
33
  <th>Duration</th>
26
- <th>Exit</th>
27
34
  <th>Command</th>
35
+ <th>Status</th>
28
36
  <th>Action</th>
29
37
  <th>Output</th>
30
38
  </tr>
@@ -36,6 +44,14 @@
36
44
  <div class="resizer" id="resizer"></div>
37
45
  </div>
38
46
  <div id="output" class="output"></div>
47
+ <div class="slider-container">
48
+ <input type="range" id="outputSlider" min="0" max="100" value="100">
49
+ <label for="outputSlider"><span id="outputPercentage">100%</span></label>
50
+ </div>
51
+ <script src="/static/js/xterm/ansi_up.min.js"></script>
52
+ <script src="/static/js/xterm/xterm.js"></script>
53
+ <script src="/static/js/xterm/xterm-addon-fit.js"></script>
39
54
  <script type="text/javascript" src="/static/js/script.js"></script>
55
+ <script type="text/javascript" src="/static/js/commands.js"></script>
40
56
  </body>
41
57
  </html>
@@ -0,0 +1,24 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="UTF-8">
5
+ <link rel="icon" href="/static/images/favicon.svg" type="image/svg+xml">
6
+ <title id="outputTitle">Command Output</title>
7
+ <link rel="stylesheet" href="/static/css/style.css">
8
+ <link rel="stylesheet" href="/static/css/xterm.css">
9
+ </head>
10
+ <body>
11
+ <div id="dimmer" class="dimmer">
12
+ <div class="dimmer-text">Server not available</div>
13
+ </div>
14
+ <div id="output" class="output"></div>
15
+ <div class="slider-container">
16
+ <input type="range" id="outputSlider" min="0" max="100" value="100">
17
+ <label for="outputSlider"><span id="outputPercentage">100%</span></label>
18
+ </div>
19
+ <script src="/static/js/xterm/ansi_up.min.js"></script>
20
+ <script src="/static/js/xterm/xterm.js"></script>
21
+ <script src="/static/js/xterm/xterm-addon-fit.js"></script>
22
+ <script type="text/javascript" src="/static/js/popup.js"></script>
23
+ </body>
24
+ </html>
pywebexec/version.py CHANGED
@@ -12,5 +12,5 @@ __version__: str
12
12
  __version_tuple__: VERSION_TUPLE
13
13
  version_tuple: VERSION_TUPLE
14
14
 
15
- __version__ = version = '1.1.2'
16
- __version_tuple__ = version_tuple = (1, 1, 2)
15
+ __version__ = version = '1.4.12'
16
+ __version_tuple__ = version_tuple = (1, 4, 12)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: pywebexec
3
- Version: 1.1.2
3
+ Version: 1.4.12
4
4
  Summary: Simple Python HTTP Exec Server
5
5
  Home-page: https://github.com/joknarf/pywebexec
6
6
  Author: Franck Jouvanceau
@@ -30,13 +30,12 @@ License: MIT License
30
30
  Project-URL: Homepage, https://github.com/joknarf/pywebexec
31
31
  Project-URL: Documentation, https://github.com/joknarf/pywebexec/blob/main/README.md
32
32
  Project-URL: Repository, https://github.com/joknarf/pywebexec.git
33
- Keywords: http,fileserver,browser,explorer
33
+ Keywords: http,server,remote commands,api,website
34
34
  Classifier: Development Status :: 5 - Production/Stable
35
35
  Classifier: Intended Audience :: System Administrators
36
36
  Classifier: License :: OSI Approved :: MIT License
37
37
  Classifier: Operating System :: POSIX
38
38
  Classifier: Operating System :: Unix
39
- Classifier: Operating System :: Microsoft :: Windows
40
39
  Classifier: Operating System :: MacOS
41
40
  Classifier: Programming Language :: Python
42
41
  Classifier: Programming Language :: Python :: 3
@@ -57,17 +56,18 @@ Requires-Dist: python-daemon>=2.3.2
57
56
  Requires-Dist: cryptography>=40.0.2
58
57
  Requires-Dist: Flask>=2.0.3
59
58
  Requires-Dist: Flask-HTTPAuth>=4.8.0
59
+ Requires-Dist: pexpect>=4.9.0
60
60
  Requires-Dist: gunicorn>=21.2.0
61
61
  Requires-Dist: ldap3>=2.9.1
62
62
 
63
63
  [![Pypi version](https://img.shields.io/pypi/v/pywebexec.svg)](https://pypi.org/project/pywebexec/)
64
64
  ![example](https://github.com/joknarf/pywebexec/actions/workflows/python-publish.yml/badge.svg)
65
65
  [![Licence](https://img.shields.io/badge/licence-MIT-blue.svg)](https://shields.io/)
66
- [![](https://pepy.tech/badge/pywebexec)](https://pepy.tech/project/pywebexec)
66
+ [![PyPI Downloads](https://static.pepy.tech/badge/pywebexec)](https://pepy.tech/projects/pywebexec)
67
67
  [![Python versions](https://img.shields.io/badge/python-3.6+-blue.svg)](https://shields.io/)
68
68
 
69
69
  # pywebexec
70
- Simple Python HTTP(S) API/Web Command Launcher
70
+ Simple Python HTTP(S) API/Web Command Launcher and Terminal sharing
71
71
 
72
72
  ## Install
73
73
  ```
@@ -79,11 +79,13 @@ $ pip install pywebexec
79
79
  * put in a directory the scripts/commands/links to commands you want to expose
80
80
  * start http server serving current directory executables listening on 0.0.0.0 port 8080
81
81
  ```shell
82
- $ pywebexec
82
+ $ pywebexec -d <dir>
83
83
  ```
84
84
 
85
85
  * Launch commands with params/view live output/Status using browser
86
- ![pywebexec](https://github.com/user-attachments/assets/d352cc23-1552-4b79-a6ff-f02f05cf328e)
86
+ * Share your terminal output using `pywebexec -d <dir> term`
87
+
88
+ ![pywebexecnew9](https://github.com/user-attachments/assets/a57864ab-c5ee-4301-addd-cc68abc90f15)
87
89
 
88
90
  all commands output / statuses are available in the executables directory in subdirectory `.web_status`
89
91
 
@@ -91,16 +93,19 @@ all commands output / statuses are available in the executables directory in sub
91
93
 
92
94
  * Serve executables in a directory
93
95
  * Launch commands with params from web browser or API call
96
+ * multiple share terminal output
94
97
  * Follow live output
98
+ * Replay terminal history
95
99
  * Stop command
96
100
  * Relaunch command
97
101
  * HTTPS support
98
102
  * HTTPS self-signed certificate generator
99
103
  * Basic Auth
100
- * LDAP(S)
104
+ * LDAP(S) password check/group member
105
+ * Safe url token generation
101
106
  * Can be started as a daemon (POSIX)
102
- * uses gunicorn to serve http/https
103
- * compatible Linux/MacOS
107
+ * Uses gunicorn to serve http/https
108
+ * Linux/MacOS compatible
104
109
 
105
110
  ## Customize server
106
111
  ```shell
@@ -108,7 +113,30 @@ $ pywebexec --dir ~/myscripts --listen 0.0.0.0 --port 8080 --title myscripts
108
113
  $ pywebexec -d ~/myscripts -l 0.0.0.0 -p 8080 -t myscripts
109
114
  ```
110
115
 
111
- ## Basic auth
116
+ ## Sharing terminals
117
+
118
+ * start server and share tty in one command
119
+ ```shell
120
+ $ pywebexec -d ~/webshare shareterm
121
+ ```
122
+ * share tty with an already pywebexec server started
123
+ ```shell
124
+ $ pywebexec -d ~/webshare term
125
+ ```
126
+ if another user need to share his terminal, he need to have write permission on `<dir>/.web_status` directory.
127
+
128
+ ## Safe url token
129
+
130
+ * generate safe url, use the url to access the server
131
+ ```shell
132
+ $ pywebexec -T
133
+ $ pywebexec --tokenurl
134
+ Starting server:
135
+ http://<host>:8080?token=jSTWiNgEVkddeEJ7I97x2ekOeaiXs2mErRSKNxm3DP0
136
+ http://x.x.x.x:8080?token=jSTWiNgEVkddeEJ7I97x2ekOeaiXs2mErRSKNxm3DP0
137
+ ```
138
+
139
+ ## Basic auth
112
140
 
113
141
  * single user/password
114
142
  ```shell
@@ -122,7 +150,7 @@ Generated password is given if no `--pasword` option
122
150
  $ export PYWEBEXEC_LDAP_SERVER=ldap://ldap.forumsys.com:389
123
151
  $ export PYWEBEXEC_LDAP_BIND_DN="cn=read-only-admin,dc=example,dc=com"
124
152
  $ export PYWEBEXEC_LDAP_BIND_PASSWORD="password"
125
- $ export PYWEBEXEC_LDAP_GROUPS=ou=mathematicians,ou=scientists
153
+ $ export PYWEBEXEC_LDAP_GROUPS="ou=mathematicians,ou=scientists"
126
154
  $ export PYWEBEXEC_LDAP_USER_ID="uid"
127
155
  $ export PYWEBEXEC_LDAP_BASE_DN="dc=example,dc=com"
128
156
  $ pywebexec
@@ -131,14 +159,14 @@ $ pywebexec
131
159
 
132
160
  * Generate auto-signed certificate and start https server
133
161
  ```shell
134
- $ pywebfs --gencert
135
- $ pywebfs --g
162
+ $ pywebexec --gencert
163
+ $ pywebexec --g
136
164
  ```
137
165
 
138
166
  * Start https server using existing certificate
139
167
  ```shell
140
- $ pywebfs --cert /pathto/host.cert --key /pathto/host.key
141
- $ pywebfs -c /pathto/host.cert -k /pathto/host.key
168
+ $ pywebexec --cert /pathto/host.cert --key /pathto/host.key
169
+ $ pywebexec -c /pathto/host.cert -k /pathto/host.key
142
170
  ```
143
171
 
144
172
  ## Launch server as a daemon
@@ -148,12 +176,14 @@ $ pywebexec start
148
176
  $ pywebexec status
149
177
  $ pywebexec stop
150
178
  ```
151
- * log of server are stored in directory `[.config/].pywebexec/pywebexec_<listen>:<port>.log`
179
+ * log of server are stored in directory `~/[.config/].pywebexec/pywebexec_<listen>:<port>.log`
152
180
 
153
181
  ## Launch command through API
154
182
 
155
183
  ```shell
156
- $ curl http://myhost:8080/run_script -H 'Content-Type: application/json' -X POST -d '{ "script_name":"myscript", "param":["param1", ...]}
184
+ $ curl http://myhost:8080/run_command -H 'Content-Type: application/json' -X POST -d '{ "command":"myscript", "params":["param1", ...]}'
185
+ $ curl http://myhost:8080/command_status/<command_id>
186
+ $ curl http://myhost:8080/command_output/<command_id> -H "Accept: text/plain"
157
187
  ```
158
188
 
159
189
  ## API reference
@@ -164,6 +194,6 @@ $ curl http://myhost:8080/run_script -H 'Content-Type: application/json' -X POST
164
194
  | POST | /run_command | command: str<br>params: array[str] | command_id: uuid<br>message: str |
165
195
  | POST | /stop_command/command_id | | message: str |
166
196
  | GET | /command_status/command_id | | command_id: uuid<br>command: str<br>params: array[str]<br>start_time: isotime<br>end_time: isotime<br>status: str<br>exit_code: int<br>last_output_line: str |
167
- | GET | /command_output/command_id | | output: str<br>status: str |
197
+ | GET | /command_output/command_id | offset: int | output: str<br>status: str<br>links: { next: str } |
168
198
  | GET | /commands | | array of<br>command_id: uuid<br>command: str<br>start_time: isotime<br>end_time: isotime<br>status: str<br>exit_code: int<br>last_output_line: str |
169
199
  | GET | /executables | | array of str |
@@ -0,0 +1,31 @@
1
+ pywebexec/__init__.py,sha256=4spIsVaF8RJt8S58AG_wWoORRNkws9Iwqprj27C3ljM,99
2
+ pywebexec/pywebexec.py,sha256=bo_rh0wsEkcOXltOZMiZlojqABCAQqDM33cJGUUmnrU,26922
3
+ pywebexec/version.py,sha256=Zv4TpC5V6FOmlNNowuZivqOrr2E0lJ1Gpdzj7o5gDYw,413
4
+ pywebexec/static/css/Consolas NF.ttf,sha256=DJEOzF0eqZ-kxu3Gs_VE8X0NJqiobBzmxWDGpdgGRxI,1313900
5
+ pywebexec/static/css/style.css,sha256=sDBhZ-csW5THIKfTDsHqxCSg6rIJ91Oh15sjw_HjJo4,5702
6
+ pywebexec/static/css/xterm.css,sha256=gy8_LGA7Q61DUf8ElwFQzHqHMBQnbbEmpgZcbdgeSHI,5383
7
+ pywebexec/static/images/aborted.svg,sha256=_mP43hU5QdRLFZIknBgjx-dIXrHgQG23-QV27ApXK2A,381
8
+ pywebexec/static/images/copy.svg,sha256=d9OwtGh5GzzZHzYcDrLfNxZYLth1Q64x7bRyYxu4Px0,622
9
+ pywebexec/static/images/copy_ok.svg,sha256=mEqUVUhSq8xaJK2msQkxRawnz_KwlCZ-tok8QS6hJ3g,451
10
+ pywebexec/static/images/down-arrow.svg,sha256=4TclEmntMvKk_F_ADXgTpGtviYo826EDmmZiGE7HQBI,121
11
+ pywebexec/static/images/failed.svg,sha256=ADZ7IKrUyOXtqpivnz3VcH0-Wru-I5MOi3OJAkI3hxk,1439
12
+ pywebexec/static/images/favicon.svg,sha256=9gSN5Oak1zTWhTCyutlupPBKUxcbdoVt7dvhk8xvEug,1224
13
+ pywebexec/static/images/popup.svg,sha256=0Bl9A_v5cBsMPn6FnOlVWlAQKgd2zqiWQbhjcL9BDzI,559
14
+ pywebexec/static/images/running.gif,sha256=iYuzQGkMxrakSIwt6gPieKCImGZoSAHmU5MUNZa7cpw,25696
15
+ pywebexec/static/images/success.svg,sha256=PJDcCSTevJh7rkfSFLtc7P0pbeh8PVQBS8DaOLQemmc,489
16
+ pywebexec/static/js/commands.js,sha256=8JDb3Q55EJOYf2Q9Uy6qEuqAnn1oGjM0RndgQ4aOjqo,7725
17
+ pywebexec/static/js/popup.js,sha256=i7BPBh6oS0Q6H528DwP6KwJ8CKh7ULwm1rLHSbyvDhk,4656
18
+ pywebexec/static/js/script.js,sha256=QlYuIdvolTwxkJtgp7-X1IRM9Hr8D08iQCyCzZjv3hk,12255
19
+ pywebexec/static/js/xterm/LICENSE,sha256=EU1P4eXTull-_T9I80VuwnJXubB-zLzUl3xpEYj2T1M,1083
20
+ pywebexec/static/js/xterm/ansi_up.min.js,sha256=KNGV0vEr30hNqKQimTAvGVy-icD5A1JqMQTtvYtKR2Y,13203
21
+ pywebexec/static/js/xterm/xterm-addon-fit.js,sha256=Pprm9pZe4SadVXS5Bc8b9VnC9Ex4QlWwA0pxOH53Gck,1460
22
+ pywebexec/static/js/xterm/xterm.js,sha256=Bzka76jZwEhVt_LlS0e0qMw7ryGa1p5qfxFyeohphBo,283371
23
+ pywebexec/templates/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
24
+ pywebexec/templates/index.html,sha256=DYtT555wSNhnFtzzHhPMWJireynCJNnAuTytpoORQeE,2321
25
+ pywebexec/templates/popup.html,sha256=T6_tAOUoA58sA1oxB5pb8i42RenoMdCsH8T86Gccb6Q,945
26
+ pywebexec-1.4.12.dist-info/LICENSE,sha256=gRJf0JPT_wsZJsUGlWPTS8Vypfl9vQ1qjp6sNbKykuA,1064
27
+ pywebexec-1.4.12.dist-info/METADATA,sha256=cCiJmWvh3DHBVJa0uRdM6-oMEBFyU3g0nSNxrhz5Y1I,7724
28
+ pywebexec-1.4.12.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
29
+ pywebexec-1.4.12.dist-info/entry_points.txt,sha256=l52GBkPCXRkmlHfEyoVauyfBdg8o-CAtC8qQpOIjJK0,55
30
+ pywebexec-1.4.12.dist-info/top_level.txt,sha256=vHoHyzngrfGdm_nM7Xn_5iLmaCrf10XO1EhldgNLEQ8,10
31
+ pywebexec-1.4.12.dist-info/RECORD,,
@@ -1 +0,0 @@
1
- <svg viewBox="0 0 1024 1024" class="icon" version="1.1" xmlns="http://www.w3.org/2000/svg" fill="#000000"><g id="SVGRepo_bgCarrier" stroke-width="0"></g><g id="SVGRepo_tracerCarrier" stroke-linecap="round" stroke-linejoin="round"></g><g id="SVGRepo_iconCarrier"><path d="M661.333333 170.666667l253.866667 34.133333-209.066667 209.066667zM362.666667 853.333333L108.8 819.2l209.066667-209.066667zM170.666667 362.666667L204.8 108.8l209.066667 209.066667z" fill="#4949d1"></path><path d="M198.4 452.266667l-89.6 17.066666c-2.133333 14.933333-2.133333 27.733333-2.133333 42.666667 0 98.133333 34.133333 192 98.133333 264.533333l64-55.466666C219.733333 663.466667 192 588.8 192 512c0-19.2 2.133333-40.533333 6.4-59.733333zM512 106.666667c-115.2 0-217.6 49.066667-292.266667 125.866666l59.733334 59.733334C339.2 230.4 420.266667 192 512 192c19.2 0 40.533333 2.133333 59.733333 6.4l14.933334-83.2C563.2 108.8 537.6 106.666667 512 106.666667zM825.6 571.733333l89.6-17.066666c2.133333-14.933333 2.133333-27.733333 2.133333-42.666667 0-93.866667-32-185.6-91.733333-258.133333l-66.133333 53.333333c46.933333 57.6 72.533333 130.133333 72.533333 202.666667 0 21.333333-2.133333 42.666667-6.4 61.866666zM744.533333 731.733333C684.8 793.6 603.733333 832 512 832c-19.2 0-40.533333-2.133333-59.733333-6.4l-14.933334 83.2c25.6 4.266667 51.2 6.4 74.666667 6.4 115.2 0 217.6-49.066667 292.266667-125.866667l-59.733334-57.6z" fill="#4949d1"></path><path d="M853.333333 661.333333l-34.133333 253.866667-209.066667-209.066667z" fill="#4949d1"></path></g></svg>
@@ -1,20 +0,0 @@
1
- pywebexec/__init__.py,sha256=4spIsVaF8RJt8S58AG_wWoORRNkws9Iwqprj27C3ljM,99
2
- pywebexec/pywebexec.py,sha256=mRvTAK8O9VtGPqUdQxIeYBzpjLYkYVru1rzWmS3Ui5Q,21149
3
- pywebexec/version.py,sha256=nmVMEP2kpLDIzjgS-U1taCdJbVrmv_k8ao6RojGcvRg,411
4
- pywebexec/static/css/style.css,sha256=NiBoOzZ35eBM1ZP2HFNda-dzOsAv4xRPh3vsvVgLL9c,2513
5
- pywebexec/static/images/aborted.svg,sha256=_mP43hU5QdRLFZIknBgjx-dIXrHgQG23-QV27ApXK2A,381
6
- pywebexec/static/images/copy.svg,sha256=d9OwtGh5GzzZHzYcDrLfNxZYLth1Q64x7bRyYxu4Px0,622
7
- pywebexec/static/images/copy_ok.svg,sha256=mEqUVUhSq8xaJK2msQkxRawnz_KwlCZ-tok8QS6hJ3g,451
8
- pywebexec/static/images/failed.svg,sha256=ADZ7IKrUyOXtqpivnz3VcH0-Wru-I5MOi3OJAkI3hxk,1439
9
- pywebexec/static/images/favicon.svg,sha256=ti80IfuDZwIvQcmJxkOeUaB1iMsiyOPmQmVO-h0y1IU,1126
10
- pywebexec/static/images/running.svg,sha256=vBpiG6ClNUNCArkwsyqK7O-qhIKJX1NI7MSjclNSp_8,1537
11
- pywebexec/static/images/success.svg,sha256=PJDcCSTevJh7rkfSFLtc7P0pbeh8PVQBS8DaOLQemmc,489
12
- pywebexec/static/js/script.js,sha256=RrlozMlUx_7MJTf7IG98rzJsLgwEMyEV9bSW6QpQdZw,7088
13
- pywebexec/templates/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
14
- pywebexec/templates/index.html,sha256=Q3tubZjBzq4v1aV_BDFSvAKnoim-wKo3EkE_pkA2jm4,1302
15
- pywebexec-1.1.2.dist-info/LICENSE,sha256=gRJf0JPT_wsZJsUGlWPTS8Vypfl9vQ1qjp6sNbKykuA,1064
16
- pywebexec-1.1.2.dist-info/METADATA,sha256=7f5boEeNnoqAijinCKAqx-gPL_tGLOxdLe1Jdp9xYVI,6736
17
- pywebexec-1.1.2.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
18
- pywebexec-1.1.2.dist-info/entry_points.txt,sha256=l52GBkPCXRkmlHfEyoVauyfBdg8o-CAtC8qQpOIjJK0,55
19
- pywebexec-1.1.2.dist-info/top_level.txt,sha256=vHoHyzngrfGdm_nM7Xn_5iLmaCrf10XO1EhldgNLEQ8,10
20
- pywebexec-1.1.2.dist-info/RECORD,,