pywebexec 1.3.1__py3-none-any.whl → 1.3.3__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.
- pywebexec/pywebexec.py +7 -1
- pywebexec/static/css/Consolas NF.ttf +0 -0
- pywebexec/static/css/style.css +15 -0
- pywebexec/static/js/script.js +48 -25
- pywebexec/templates/index.html +4 -0
- pywebexec/version.py +2 -2
- {pywebexec-1.3.1.dist-info → pywebexec-1.3.3.dist-info}/METADATA +1 -1
- {pywebexec-1.3.1.dist-info → pywebexec-1.3.3.dist-info}/RECORD +12 -11
- {pywebexec-1.3.1.dist-info → pywebexec-1.3.3.dist-info}/LICENSE +0 -0
- {pywebexec-1.3.1.dist-info → pywebexec-1.3.3.dist-info}/WHEEL +0 -0
- {pywebexec-1.3.1.dist-info → pywebexec-1.3.3.dist-info}/entry_points.txt +0 -0
- {pywebexec-1.3.1.dist-info → pywebexec-1.3.3.dist-info}/top_level.txt +0 -0
pywebexec/pywebexec.py
CHANGED
@@ -17,6 +17,7 @@ from socket import gethostname, gethostbyname_ex, gethostbyaddr, inet_aton, inet
|
|
17
17
|
import ssl
|
18
18
|
import re
|
19
19
|
import pwd
|
20
|
+
import platform
|
20
21
|
from secrets import token_urlsafe
|
21
22
|
|
22
23
|
if os.environ.get('PYWEBEXEC_LDAP_SERVER'):
|
@@ -327,7 +328,12 @@ def parseargs():
|
|
327
328
|
user = pwd.getpwuid(os.getuid())[0]
|
328
329
|
update_command_status(command_id, 'running', command="term", params=[user,os.ttyname(sys.stdout.fileno())], start_time=start_time, user=user)
|
329
330
|
output_file_path = get_output_file_path(command_id)
|
330
|
-
|
331
|
+
if platform.system() == 'Darwin':
|
332
|
+
script_opt = '-F'
|
333
|
+
else:
|
334
|
+
script_opt = '-f'
|
335
|
+
res = os.system(f"script {script_opt} {output_file_path}")
|
336
|
+
|
331
337
|
end_time = datetime.now().isoformat()
|
332
338
|
update_command_status(command_id, status="success", end_time=end_time, exit_code=res)
|
333
339
|
sys.exit(res)
|
Binary file
|
pywebexec/static/css/style.css
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
@font-face {
|
2
|
+
font-family: 'Consolas NF';
|
3
|
+
src: url('/static/css/Consolas NF.ttf');
|
4
|
+
font-weight: 400;
|
5
|
+
font-style: normal;
|
6
|
+
}
|
1
7
|
body {
|
2
8
|
font-family: Arial, sans-serif;
|
3
9
|
overflow: hidden;
|
@@ -256,4 +262,13 @@ body.dimmed * {
|
|
256
262
|
span {
|
257
263
|
letter-spacing: -0.03px !important;
|
258
264
|
}
|
265
|
+
.slider-container {
|
266
|
+
display: flex;
|
267
|
+
align-items: center;
|
268
|
+
gap: 10px;
|
269
|
+
margin-top: 10px;
|
270
|
+
}
|
271
|
+
#outputSlider {
|
272
|
+
width: 100%;
|
273
|
+
}
|
259
274
|
|
pywebexec/static/js/script.js
CHANGED
@@ -1,39 +1,46 @@
|
|
1
1
|
let currentCommandId = null;
|
2
2
|
let outputInterval = null;
|
3
3
|
let nextOutputLink = null;
|
4
|
+
let fullOutput = '';
|
5
|
+
|
6
|
+
|
7
|
+
function initTerminal()
|
8
|
+
{
|
9
|
+
return new Terminal({
|
10
|
+
cursorBlink: false,
|
11
|
+
cursorHidden: true,
|
12
|
+
disableStdin: true,
|
13
|
+
convertEol: true,
|
14
|
+
fontFamily: 'Consolas NF, monospace, courier-new, courier',
|
15
|
+
scrollback: 999999,
|
16
|
+
theme: {
|
17
|
+
background: '#111412',
|
18
|
+
black: '#111412',
|
19
|
+
green: '#088a5b',
|
20
|
+
blue: "#2760aa",
|
21
|
+
red: '#ba1611',
|
22
|
+
yellow: "#cf8700",
|
23
|
+
magenta: "#4c3d80",
|
24
|
+
cyan: "#00a7aa",
|
25
|
+
brightBlack: "#243C4F",
|
26
|
+
brightBlue: "#5584b1",
|
27
|
+
},
|
28
|
+
rescaleOverlappingGlyphs: true,
|
29
|
+
});
|
30
|
+
}
|
31
|
+
let terminal = initTerminal()
|
4
32
|
|
5
|
-
const terminal = new Terminal({
|
6
|
-
cursorBlink: false,
|
7
|
-
cursorHidden: true,
|
8
|
-
disableStdin: true,
|
9
|
-
convertEol: true,
|
10
|
-
fontFamily: 'Consolas NF, monospace, courier-new, courier',
|
11
|
-
scrollback: 999999,
|
12
|
-
theme: {
|
13
|
-
background: '#111412',
|
14
|
-
black: '#111412',
|
15
|
-
green: '#088a5b',
|
16
|
-
blue: "#2760aa",
|
17
|
-
red: '#ba1611',
|
18
|
-
yellow: "#cf8700",
|
19
|
-
magenta: "#4c3d80",
|
20
|
-
cyan: "#00a7aa",
|
21
|
-
brightBlack: "#243C4F",
|
22
|
-
brightBlue: "#5584b1",
|
23
|
-
},
|
24
|
-
rescaleOverlappingGlyphs: true,
|
25
|
-
});
|
26
33
|
const fitAddon = new FitAddon.FitAddon();
|
27
34
|
terminal.loadAddon(fitAddon);
|
28
35
|
terminal.open(document.getElementById('output'));
|
29
36
|
fitAddon.fit();
|
37
|
+
|
30
38
|
function getTokenParam() {
|
31
39
|
const urlParams = new URLSearchParams(window.location.search);
|
32
40
|
return urlParams.get('token') ? `?token=${urlParams.get('token')}` : '';
|
33
41
|
}
|
34
42
|
const urlToken = getTokenParam();
|
35
43
|
|
36
|
-
|
37
44
|
terminal.onSelectionChange(() => {
|
38
45
|
const selectionText = terminal.getSelection();
|
39
46
|
if (selectionText) {
|
@@ -43,7 +50,6 @@ terminal.onSelectionChange(() => {
|
|
43
50
|
}
|
44
51
|
});
|
45
52
|
|
46
|
-
|
47
53
|
document.getElementById('launchForm').addEventListener('submit', async (event) => {
|
48
54
|
event.preventDefault();
|
49
55
|
const commandName = document.getElementById('commandName').value;
|
@@ -122,7 +128,8 @@ async function fetchOutput(url) {
|
|
122
128
|
terminal.write(data.error);
|
123
129
|
clearInterval(outputInterval);
|
124
130
|
} else {
|
125
|
-
|
131
|
+
fullOutput += data.output;
|
132
|
+
updateTerminalOutput();
|
126
133
|
nextOutputLink = data.links.next;
|
127
134
|
if (data.status != 'running') {
|
128
135
|
clearInterval(outputInterval);
|
@@ -134,11 +141,14 @@ async function fetchOutput(url) {
|
|
134
141
|
}
|
135
142
|
|
136
143
|
async function viewOutput(command_id) {
|
144
|
+
document.getElementById('outputSlider').value = 100;
|
137
145
|
adjustOutputHeight();
|
138
146
|
currentCommandId = command_id;
|
139
147
|
nextOutputLink = `/command_output/${command_id}${urlToken}`;
|
140
148
|
clearInterval(outputInterval);
|
141
149
|
terminal.clear();
|
150
|
+
terminal.reset();
|
151
|
+
fullOutput = '';
|
142
152
|
try {
|
143
153
|
const response = await fetch(`/command_status/${command_id}${urlToken}`);
|
144
154
|
if (!response.ok) {
|
@@ -246,7 +256,7 @@ function adjustOutputHeight() {
|
|
246
256
|
const outputDiv = document.getElementById('output');
|
247
257
|
const windowHeight = window.innerHeight;
|
248
258
|
const outputTop = outputDiv.getBoundingClientRect().top;
|
249
|
-
const maxHeight = windowHeight - outputTop -
|
259
|
+
const maxHeight = windowHeight - outputTop - 60; // Adjusted for slider height
|
250
260
|
outputDiv.style.height = `${maxHeight}px`;
|
251
261
|
fitAddon.fit();
|
252
262
|
}
|
@@ -274,6 +284,19 @@ function initResizer() {
|
|
274
284
|
}
|
275
285
|
}
|
276
286
|
|
287
|
+
function updateTerminalOutput() {
|
288
|
+
const slider = document.getElementById('outputSlider');
|
289
|
+
const percentage = slider.value;
|
290
|
+
const outputLength = Math.floor((fullOutput.length * percentage) / 100);
|
291
|
+
const limitedOutput = fullOutput.slice(0, outputLength);
|
292
|
+
terminal.clear();
|
293
|
+
terminal.reset();
|
294
|
+
terminal.write(limitedOutput);
|
295
|
+
document.getElementById('outputPercentage').innerText = `${percentage}%`;
|
296
|
+
}
|
297
|
+
|
298
|
+
document.getElementById('outputSlider').addEventListener('input', updateTerminalOutput);
|
299
|
+
|
277
300
|
window.addEventListener('resize', adjustOutputHeight);
|
278
301
|
window.addEventListener('load', initResizer);
|
279
302
|
|
pywebexec/templates/index.html
CHANGED
@@ -44,6 +44,10 @@
|
|
44
44
|
<div class="resizer" id="resizer"></div>
|
45
45
|
</div>
|
46
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>
|
47
51
|
<script src="/static/js/xterm/ansi_up.min.js"></script>
|
48
52
|
<script src="/static/js/xterm/xterm.js"></script>
|
49
53
|
<script src="/static/js/xterm/xterm-addon-fit.js"></script>
|
pywebexec/version.py
CHANGED
@@ -1,7 +1,8 @@
|
|
1
1
|
pywebexec/__init__.py,sha256=4spIsVaF8RJt8S58AG_wWoORRNkws9Iwqprj27C3ljM,99
|
2
|
-
pywebexec/pywebexec.py,sha256=
|
3
|
-
pywebexec/version.py,sha256=
|
4
|
-
pywebexec/static/css/
|
2
|
+
pywebexec/pywebexec.py,sha256=b-lypYr27O-t-YTUJs0pIWiDPsBE0eSQwSBqfNdkYR4,25618
|
3
|
+
pywebexec/version.py,sha256=VriGPi1kVXIBM0YGAuhpE803XR-FNq1JvTW1Kz2us08,411
|
4
|
+
pywebexec/static/css/Consolas NF.ttf,sha256=DJEOzF0eqZ-kxu3Gs_VE8X0NJqiobBzmxWDGpdgGRxI,1313900
|
5
|
+
pywebexec/static/css/style.css,sha256=iLX6k1hoWLinZWyqtbH50U-0hND2M-5_Zr1U1UC_gos,5578
|
5
6
|
pywebexec/static/css/xterm.css,sha256=gy8_LGA7Q61DUf8ElwFQzHqHMBQnbbEmpgZcbdgeSHI,5383
|
6
7
|
pywebexec/static/images/aborted.svg,sha256=_mP43hU5QdRLFZIknBgjx-dIXrHgQG23-QV27ApXK2A,381
|
7
8
|
pywebexec/static/images/copy.svg,sha256=d9OwtGh5GzzZHzYcDrLfNxZYLth1Q64x7bRyYxu4Px0,622
|
@@ -12,16 +13,16 @@ pywebexec/static/images/favicon.svg,sha256=ti80IfuDZwIvQcmJxkOeUaB1iMsiyOPmQmVO-
|
|
12
13
|
pywebexec/static/images/running.gif,sha256=iYuzQGkMxrakSIwt6gPieKCImGZoSAHmU5MUNZa7cpw,25696
|
13
14
|
pywebexec/static/images/success.svg,sha256=PJDcCSTevJh7rkfSFLtc7P0pbeh8PVQBS8DaOLQemmc,489
|
14
15
|
pywebexec/static/js/commands.js,sha256=VdMeCop9V5KwsR2v1J_OY1xFE7tJUYgcMg_lh2VGNjs,7476
|
15
|
-
pywebexec/static/js/script.js,sha256=
|
16
|
+
pywebexec/static/js/script.js,sha256=NCjnVd-i8zUE3qvu7UqUHBt_IcbnnUUKVGlp7XbFzic,10913
|
16
17
|
pywebexec/static/js/xterm/LICENSE,sha256=EU1P4eXTull-_T9I80VuwnJXubB-zLzUl3xpEYj2T1M,1083
|
17
18
|
pywebexec/static/js/xterm/ansi_up.min.js,sha256=KNGV0vEr30hNqKQimTAvGVy-icD5A1JqMQTtvYtKR2Y,13203
|
18
19
|
pywebexec/static/js/xterm/xterm-addon-fit.js,sha256=Pprm9pZe4SadVXS5Bc8b9VnC9Ex4QlWwA0pxOH53Gck,1460
|
19
20
|
pywebexec/static/js/xterm/xterm.js,sha256=Bzka76jZwEhVt_LlS0e0qMw7ryGa1p5qfxFyeohphBo,283371
|
20
21
|
pywebexec/templates/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
21
|
-
pywebexec/templates/index.html,sha256=
|
22
|
-
pywebexec-1.3.
|
23
|
-
pywebexec-1.3.
|
24
|
-
pywebexec-1.3.
|
25
|
-
pywebexec-1.3.
|
26
|
-
pywebexec-1.3.
|
27
|
-
pywebexec-1.3.
|
22
|
+
pywebexec/templates/index.html,sha256=DYtT555wSNhnFtzzHhPMWJireynCJNnAuTytpoORQeE,2321
|
23
|
+
pywebexec-1.3.3.dist-info/LICENSE,sha256=gRJf0JPT_wsZJsUGlWPTS8Vypfl9vQ1qjp6sNbKykuA,1064
|
24
|
+
pywebexec-1.3.3.dist-info/METADATA,sha256=A69MhlrTDRfLv8tzyDJSdVFccYSaHNFsE5JHq_Qz8rM,7397
|
25
|
+
pywebexec-1.3.3.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
|
26
|
+
pywebexec-1.3.3.dist-info/entry_points.txt,sha256=l52GBkPCXRkmlHfEyoVauyfBdg8o-CAtC8qQpOIjJK0,55
|
27
|
+
pywebexec-1.3.3.dist-info/top_level.txt,sha256=vHoHyzngrfGdm_nM7Xn_5iLmaCrf10XO1EhldgNLEQ8,10
|
28
|
+
pywebexec-1.3.3.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|