├── .gitignore
├── run.bat
├── setup.bat
├── server-python3
├── requirements.txt
├── config.py
├── websocket_terminal.py
├── logs.py
├── wspty
│ ├── BaseTerminal.py
│ ├── SocketTerminal.py
│ ├── EchoTerminal.py
│ ├── EncodedTerminal.py
│ ├── WebsocketBinding.py
│ ├── SshTerminal.py
│ ├── pipe.py
│ └── PromptTerminal.py
├── test
│ └── test.py
└── server.py
├── run
├── setup
├── docs
└── ss_mc.png
├── client
└── src
│ ├── style.css
│ ├── index.html
│ ├── wspty.js
│ ├── script.js
│ └── lib
│ └── xterm.css
├── LICENSE
└── README.md
/.gitignore:
--------------------------------------------------------------------------------
1 | /.idea/
2 | __pycache__/
3 |
--------------------------------------------------------------------------------
/run.bat:
--------------------------------------------------------------------------------
1 | python3 server-python3/websocket_terminal.py %*
2 |
--------------------------------------------------------------------------------
/setup.bat:
--------------------------------------------------------------------------------
1 | pip3 install -r server-python3/requirements.txt
2 |
--------------------------------------------------------------------------------
/server-python3/requirements.txt:
--------------------------------------------------------------------------------
1 | paramiko
2 | eventlet
3 | flask
4 |
--------------------------------------------------------------------------------
/run:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | python3 server-python3/websocket_terminal.py "$@"
3 |
--------------------------------------------------------------------------------
/setup:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 | pip3 install -r server-python3/requirements.txt
3 |
--------------------------------------------------------------------------------
/docs/ss_mc.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/sorgloomer/websocket_terminal/HEAD/docs/ss_mc.png
--------------------------------------------------------------------------------
/server-python3/config.py:
--------------------------------------------------------------------------------
1 | import sys
2 | DEBUG = False
3 | if '--debug' in sys.argv:
4 | DEBUG = True
5 | sys.argv.remove('--debug')
6 |
7 | CLIENT_DIR = 'src'
8 |
--------------------------------------------------------------------------------
/server-python3/websocket_terminal.py:
--------------------------------------------------------------------------------
1 | def main():
2 | import logs
3 | logs.setup()
4 | import server
5 | server.main()
6 |
7 |
8 | if __name__ == '__main__':
9 | main()
10 |
--------------------------------------------------------------------------------
/server-python3/logs.py:
--------------------------------------------------------------------------------
1 | def setup():
2 | import config
3 | import logging
4 | level = logging.INFO
5 | if config.DEBUG:
6 | level = logging.DEBUG
7 | logging.basicConfig(level=level)
8 |
--------------------------------------------------------------------------------
/server-python3/wspty/BaseTerminal.py:
--------------------------------------------------------------------------------
1 | class BaseTerminal:
2 | def send(self, msg: bytes):
3 | raise NotImplementedError('send')
4 |
5 | def resize(self, cols: int, rows: int):
6 | pass
7 |
8 | def recv(self, count: int=None):
9 | raise NotImplementedError('recv')
10 |
11 | def close(self):
12 | pass
13 |
--------------------------------------------------------------------------------
/server-python3/wspty/SocketTerminal.py:
--------------------------------------------------------------------------------
1 | from .BaseTerminal import BaseTerminal
2 |
3 |
4 | class SocketTerminal(BaseTerminal):
5 | def __init__(self, socket):
6 | super().__init__()
7 | self.socket = socket
8 |
9 | def send(self, data):
10 | return self.socket.sendall(data)
11 |
12 | def recv(self, count=None):
13 | return self.socket.recv(count)
14 |
--------------------------------------------------------------------------------
/server-python3/wspty/EchoTerminal.py:
--------------------------------------------------------------------------------
1 | from .BaseTerminal import BaseTerminal
2 | from eventlet.queue import Queue
3 |
4 |
5 | class EchoTerminal(BaseTerminal):
6 | def __init__(self):
7 | super().__init__()
8 | self._queue = Queue()
9 |
10 | def send(self, data):
11 | self._queue.put(data)
12 |
13 | def recv(self, count=None):
14 | return self._queue.get()
15 |
--------------------------------------------------------------------------------
/client/src/style.css:
--------------------------------------------------------------------------------
1 | html, body {
2 | width: 100%;
3 | height: 100%;
4 | padding: 0;
5 | }
6 |
7 | html, body, #term-container {
8 | margin: 0;
9 | overflow: hidden;
10 | background: black;
11 | }
12 |
13 | #term-container {
14 | display: block;
15 | position: relative;
16 | padding: 5px;
17 | }
18 |
19 | /* https://github.com/sourcelair/xterm.js/issues/357 */
20 | .terminal .xterm-helper-textarea {
21 | top: 0 !important;
22 | }
23 |
--------------------------------------------------------------------------------
/client/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | wspty
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/server-python3/wspty/EncodedTerminal.py:
--------------------------------------------------------------------------------
1 | import codecs
2 |
3 |
4 | class EncodedTerminal:
5 | def __init__(self, terminal, encoding='utf8', chunk_size=4096):
6 | self.terminal = terminal
7 | self.encoder = codecs.getincrementalencoder(encoding)()
8 | self.decoder = codecs.getincrementaldecoder(encoding)()
9 | self.encoding = encoding
10 | self.chunk_size = chunk_size
11 |
12 | def write(self, data_str):
13 | return self.terminal.send(self.encoder.encode(data_str))
14 |
15 | def resize(self, cols, rows):
16 | return self.terminal.resize(cols, rows)
17 |
18 | def read(self):
19 | return self.decoder.decode(self.terminal.recv(self.chunk_size))
20 |
21 | def close(self):
22 | return self.terminal.close()
23 |
--------------------------------------------------------------------------------
/server-python3/wspty/WebsocketBinding.py:
--------------------------------------------------------------------------------
1 | import json
2 |
3 |
4 | class DataPacket:
5 | def __init__(self, msg):
6 | self.data = msg.get('data')
7 | resize = msg.get('resize')
8 | if resize is not None:
9 | resize = (int(resize.get('width', 80)), int(resize.get('height', 24)))
10 | self.resize = resize
11 |
12 |
13 | class WebsocketBinding:
14 | def __init__(self, ws):
15 | self.websocket = ws
16 |
17 | def send(self, data_str):
18 | self.websocket.send(json.dumps({'data': str(data_str)}))
19 |
20 | def send_error(self, error_str):
21 | self.websocket.send(json.dumps({'error': str(error_str)}))
22 |
23 | def receive(self):
24 | data = self.websocket.wait()
25 | if data is None:
26 | return None
27 | return DataPacket(json.loads(data))
28 |
29 | def close(self):
30 | self.websocket.close()
31 |
--------------------------------------------------------------------------------
/client/src/wspty.js:
--------------------------------------------------------------------------------
1 |
2 | function WsptyClient() {
3 | this._connection = null;
4 | };
5 |
6 | WsptyClient.prototype.connect = function(options) {
7 | this._connection = options.ws;
8 |
9 | this._connection.onopen = function() {
10 | options.onConnect();
11 | };
12 |
13 | this._connection.onmessage = function(evt) {
14 | var data = JSON.parse(evt.data);
15 | if (data.error !== undefined) {
16 | options.onError(data.error);
17 | }
18 | if (data.data !== undefined) {
19 | options.onData(data.data);
20 | }
21 | };
22 |
23 | this._connection.onclose = function(evt) {
24 | options.onClose();
25 | };
26 | };
27 |
28 | WsptyClient.prototype.send = function(data) {
29 | this._connection.send(JSON.stringify({'data': data}));
30 | };
31 |
32 | WsptyClient.prototype.resize = function(cols, rows) {
33 | this._connection.send(JSON.stringify({'resize': { width: cols, height: rows }}));
34 | };
35 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2016 Tamás Hegedűs
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # websocket_terminal
2 |
3 | A cross-platform python3 server that bridges either ssh or raw tcp to the browser via websocket.
4 |
5 | # Quickstart
6 |
7 |
8 | ### 1. Clone and start
9 |
10 | ```
11 | git clone https://github.com/sorgloomer/websocket_terminal.git
12 | cd websocket_terminal
13 | pip3 install -r requirements.txt
14 | python3 websocket_terminal.py
15 | ```
16 |
17 | ### 2. Navigate browser
18 |
19 | Open one of the following links in a browser:
20 |
21 | Local ssh:
22 |
23 | ```
24 | http://localhost:5002?kind=ssh&username=&password=
25 | ```
26 |
27 | Remote ssh:
28 |
29 | ```
30 | http://localhost:5002?kind=ssh&username=&password=&hostname=
31 | ```
32 |
33 | ### 3. Enjoy
34 |
35 | 
36 |
37 | # Remarks
38 |
39 | Currently only password authentication is supported for ssh. The username and password is sent in plaintext via **http or https** in the default implementation!
40 |
41 | # Credits
42 |
43 | Thanks to aluzzardi for the wssh project, which inspired this one. The websocket and json based protocol is entirely the same as in wssh.
44 |
45 | Greenlet and wsgi implementation: eventlet
46 |
47 | Python ssh client: paramiko
48 |
49 | Browser side terminal: xterm.js
50 |
--------------------------------------------------------------------------------
/server-python3/wspty/SshTerminal.py:
--------------------------------------------------------------------------------
1 | import paramiko
2 | from .BaseTerminal import BaseTerminal
3 |
4 |
5 | class SshTerminal(BaseTerminal):
6 | def __init__(self, hostname='localhost', port=22, username=None, password=None, term=None):
7 | if term is None:
8 | term = 'xterm'
9 | super().__init__()
10 | self._term = term
11 | self._ssh = paramiko.SSHClient()
12 | self._ssh.set_missing_host_key_policy(
13 | paramiko.AutoAddPolicy())
14 | self._channel = None
15 | self._hostname = hostname
16 | self._port = port
17 | self._username = username
18 | self._password = password
19 | self._open()
20 |
21 | def _open(self):
22 | self._ssh.connect(
23 | hostname=self._hostname,
24 | port=self._port,
25 | username=self._username,
26 | password=self._password,
27 | look_for_keys=False
28 | )
29 | self._channel = self._ssh.invoke_shell(self._term)
30 |
31 | def send(self, data):
32 | return self._channel.send(data)
33 |
34 | def recv(self, count=None):
35 | return self._channel.recv(count)
36 |
37 | def close(self):
38 | return self._ssh.close()
39 |
40 | def resize(self, cols, rows):
41 | return self._channel.resize_pty(cols, rows)
42 |
--------------------------------------------------------------------------------
/server-python3/test/test.py:
--------------------------------------------------------------------------------
1 | import threading
2 | import sys
3 | import subprocess
4 |
5 |
6 | import eventlet
7 | import eventlet.tpool
8 | import eventlet.green.subprocess
9 | from eventlet import green
10 |
11 |
12 | eventlet.monkey_patch()
13 |
14 |
15 | def consume(stream, pref=b'T> '):
16 | print("CHK consume 1")
17 | p = pref
18 | while True:
19 | print("CHK consume 2")
20 | data = stream.read(1024)
21 | print("CHK consume 3")
22 | if not data:
23 | break
24 | if p:
25 | data = p + data
26 | p = None
27 | sys.stdout.buffer.write(data.replace(b'\n', b'\n' + pref))
28 | print("CHK consume 4")
29 | sys.stdout.flush()
30 | print("CHK consume 5")
31 |
32 |
33 | def start_daemon_thread(fn):
34 | thread = threading.Thread(target=fn)
35 | thread.daemon = True
36 | print("CHK start_daemon_thread 1")
37 | thread.start()
38 | print("CHK start_daemon_thread 2")
39 | return thread
40 |
41 |
42 | def consume_input():
43 | print("CHK consume_input input")
44 | while True:
45 | line = input() + '\n'
46 | print("CHK consume_input line", line)
47 | proc.stdin.write(bytes(line, 'ascii'))
48 | proc.stdin.flush()
49 |
50 |
51 | proc = green.subprocess.Popen("cmd", stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, bufsize=0)
52 |
53 |
54 | def spawn(fn):
55 | print("CHK spawn")
56 | return start_daemon_thread(fn)
57 | #return eventlet.spawn(fn)
58 | #return eventlet.tpool.execute(fn)
59 |
60 |
61 | thread1 = spawn(lambda: consume(proc.stdout, b"T> "))
62 | thread2 = spawn(lambda: consume(proc.stderr, b"E> "))
63 | print("CHK sleeping")
64 | eventlet.sleep(2)
65 |
66 | consume_input()
67 |
--------------------------------------------------------------------------------
/server-python3/wspty/pipe.py:
--------------------------------------------------------------------------------
1 | import eventlet
2 | import eventlet.event
3 |
4 | import logging
5 | logger = logging.getLogger(__name__)
6 |
7 |
8 | class GreenletRace:
9 | def __init__(self, tasks):
10 | self._event = eventlet.event.Event()
11 | self._tasks = [eventlet.spawn(self._wrap, fn) for fn in tasks]
12 |
13 | def _resolve(self, value=None):
14 | if not self._event.ready():
15 | self._event.send(value)
16 |
17 | def _reject(self, reason):
18 | if not self._event.ready():
19 | self._event.send_exception(reason)
20 |
21 | def _wrap(self, fn):
22 | try:
23 | self._resolve(fn())
24 | except BaseException as e:
25 | self._reject(e)
26 |
27 | def wait(self):
28 | self._event.wait()
29 |
30 | def kill_all(self):
31 | for greenthread in self._tasks:
32 | greenthread.kill()
33 |
34 |
35 | class TerminalPipe:
36 | def __init__(self, ws_binding, terminal):
37 | self.ws_binding = ws_binding
38 | self.terminal = terminal
39 | self._tasks = None
40 |
41 | def pipe(self):
42 | try:
43 | self._tasks = GreenletRace([
44 | self._pty_to_ws,
45 | self._ws_to_pty
46 | ])
47 | self._tasks.wait()
48 | finally:
49 | self.close()
50 |
51 | def _pty_to_ws(self):
52 | while True:
53 | data = self.terminal.read()
54 | if not data:
55 | break
56 | self.ws_binding.send(data)
57 |
58 | def _ws_to_pty(self):
59 | while True:
60 | msg = self.ws_binding.receive()
61 | if not msg:
62 | break
63 | if msg.resize is not None:
64 | self.terminal.resize(*msg.resize)
65 | if msg.data is not None:
66 | self.terminal.write(msg.data)
67 |
68 | def close(self):
69 | if self._tasks is not None:
70 | self._tasks.kill_all()
71 |
72 |
73 | def pipe(ws_binding, terminal):
74 | TerminalPipe(ws_binding, terminal).pipe()
75 |
--------------------------------------------------------------------------------
/client/src/script.js:
--------------------------------------------------------------------------------
1 |
2 | function openTerminal() {
3 | var client = new WsptyClient();
4 | var term = new Terminal();
5 | var container = document.getElementById('term-container');
6 | term.open(container);
7 |
8 |
9 |
10 | function debounce(fn) {
11 | // throttle to 4 calls per second,
12 | // call 3 more times after last debounced call
13 | // because zoom seems to be asynchronous in chrome,
14 | // and character measurement returns wrong values for
15 | // a short time
16 | var tid = null, counter = 0;
17 | return function() {
18 | counter = 3;
19 | if (tid === null) {
20 | tid = setInterval(function() {
21 | if (--counter < 1) {
22 | clearTimeout(tid);
23 | tid = null;
24 | }
25 | fn();
26 | }, 250);
27 | }
28 | };
29 | }
30 |
31 | function measureChar(subjectRow) {
32 | var contentBuffer = subjectRow.innerHTML;
33 | subjectRow.style.display = 'inline';
34 | subjectRow.innerHTML = 'W'; // Common character for measuring width, although on monospace
35 | var characterWidth = subjectRow.getBoundingClientRect().width;
36 | subjectRow.style.display = ''; // Revert style before calculating height, since they differ.
37 | var characterHeight = parseInt(subjectRow.offsetHeight);
38 | subjectRow.innerHTML = contentBuffer;
39 | return { width: characterWidth, height: characterHeight };
40 | }
41 |
42 |
43 | function fitTerminal() {
44 | var subjectRow = term.rowContainer.firstElementChild;
45 | var charSize = measureChar(subjectRow);
46 | // 10px padding
47 | var ww = window.innerWidth - 10, wh = window.innerHeight - 10;
48 | container.style.width = ww + 'px';
49 | container.style.height = wh + 'px';
50 | // 17px scrollbar
51 | var cols = Math.floor((ww - 17) / charSize.width);
52 | var rows = Math.floor(wh / charSize.height);
53 | term.resize(cols, rows);
54 | }
55 |
56 | var debouncedFitTerminal = debounce(function() {
57 | fitTerminal();
58 | });
59 | window.addEventListener('resize', function() {
60 | setTimeout(debouncedFitTerminal, 1000);
61 | debouncedFitTerminal();
62 | });
63 | fitTerminal();
64 |
65 | term.on('data', function(data) {
66 | client.send(data);
67 | });
68 | term.on('resize', function(geom) {
69 | client.resize(geom.cols, geom.rows);
70 | });
71 | term.write('Connecting...\r\n');
72 |
73 | var wsProtocol = location.protocol === 'http:' ? 'ws' : 'wss';
74 | var endpoint = wsProtocol + '://' + location.host + '/wssh' + location.search;
75 | client.connect({
76 | ws: new WebSocket(endpoint),
77 | onError: function(error) {
78 | term.writeln('Error: ' + error);
79 | },
80 | onConnect: function() {
81 | // Erase our connecting message
82 | // term.write('\x1b[2K\r');
83 | client.resize(term.cols, term.rows);
84 | },
85 | onClose: function() {
86 | term.write('\r\nConnection closed by peer');
87 | },
88 | onData: function(data) {
89 | term.write(data);
90 | }
91 | });
92 | }
93 |
94 | window.addEventListener('load', function() {
95 | openTerminal();
96 | });
97 |
--------------------------------------------------------------------------------
/server-python3/wspty/PromptTerminal.py:
--------------------------------------------------------------------------------
1 | import subprocess
2 | import sys
3 |
4 | import eventlet.queue
5 | import eventlet.tpool
6 | import eventlet.green.subprocess
7 | from eventlet import green
8 | from eventlet.greenpool import GreenPool
9 |
10 | from .BaseTerminal import BaseTerminal
11 |
12 | import logging
13 | logger = logging.getLogger(__name__)
14 |
15 |
16 | class SubprocessTerminal(BaseTerminal):
17 | def __init__(self, cmd):
18 | self.process = make_simple_process(cmd)
19 | self.queue = eventlet.queue.Queue()
20 | self.greenpool = self._start_consume()
21 |
22 | def _start_consume(self):
23 | greenpool = GreenPool(5)
24 | greenpool.spawn_n(self._consume_stream, self.process.stdout)
25 | greenpool.spawn_n(self._consume_stream, self.process.stderr)
26 | return greenpool
27 |
28 | def _consume_stream(self, stream):
29 | while True:
30 | data = stream.read()
31 | if not data:
32 | break
33 | self._send_to_slave(data)
34 |
35 | def recv(self, count=None):
36 | return self.master_to_slave(self.queue.get())
37 |
38 | def _send_to_slave(self, data):
39 | self.queue.put(data)
40 |
41 | def send(self, data):
42 | data = self.slave_to_master(data)
43 | self.process.stdin.write(data)
44 |
45 | def slave_to_master(self, x):
46 | return x
47 |
48 | def master_to_slave(self, x):
49 | return x
50 |
51 | def close(self):
52 | self.process.kill()
53 |
54 |
55 | class LinuxTerminal(SubprocessTerminal):
56 | def __init__(self, cmd=None):
57 | if cmd is None:
58 | cmd = ['bash']
59 | import shlex
60 | cmd = " ".join(map(shlex.quote, cmd))
61 | cmd = ['script', '-qfc', cmd, '/dev/null']
62 | super().__init__(cmd)
63 |
64 |
65 | class WindowsTerminal(SubprocessTerminal):
66 | def __init__(self, cmd=None):
67 | if cmd is None:
68 | cmd = ['cmd']
69 | super().__init__(cmd)
70 |
71 | def slave_to_master(self, data):
72 | data = data.replace(b'\r', b'\r\n')
73 | self._send_to_slave(data)
74 | return data
75 |
76 | def master_to_slave(self, x):
77 | return x.replace(b'\n', b'\r\n')
78 |
79 |
80 | class NonBlockingSimplePipe:
81 | def __init__(self, stream):
82 | logger.debug("NonBlockingSimplePipe.__init__ type(stream) == {}".format(type(stream)))
83 | logger.debug("NonBlockingSimplePipe.__init__ type(stream).__name__ == {!r}".format(type(stream).__name__))
84 | self.needs_thread = not is_greenpipe(stream)
85 | self.stream = stream
86 |
87 | def read(self):
88 | if self.needs_thread:
89 | return eventlet.tpool.execute(self._read)
90 | return self._read()
91 |
92 | def write(self, data):
93 | if self.needs_thread:
94 | return eventlet.tpool.execute(self._write, data)
95 | return self._write(data)
96 |
97 | def _read(self):
98 | return self.stream.read(2048)
99 |
100 | def _write(self, data):
101 | self.stream.write(data)
102 | self.stream.flush()
103 |
104 |
105 | class NonBlockingSimpleProcess:
106 | def __init__(self, cmd):
107 | self.proc = make_subprocess(cmd)
108 | self.stdin = NonBlockingSimplePipe(self.proc.stdin)
109 | self.stdout = NonBlockingSimplePipe(self.proc.stdout)
110 | self.stderr = NonBlockingSimplePipe(self.proc.stderr)
111 |
112 | def kill(self):
113 | self.proc.kill()
114 |
115 |
116 | def is_greenpipe(obj):
117 | # GreenFileIO is not exposed and GreenPipe is not a class, so checking by name
118 | return type(obj).__name__ == "GreenFileIO"
119 |
120 |
121 | def os_terminal():
122 | return OS_TERMINALS[sys.platform]()
123 |
124 |
125 | def make_subprocess(obj):
126 | def green_popen(cmd):
127 | p = subprocess.PIPE
128 | return green.subprocess.Popen(cmd, stdin=p, stdout=p, stderr=p, bufsize=0)
129 | if isinstance(obj, str):
130 | return green_popen([obj])
131 | if isinstance(obj, list):
132 | return green_popen(obj)
133 | if isinstance(obj, subprocess.Popen):
134 | return obj
135 | if isinstance(obj, green.subprocess.Popen):
136 | return obj
137 | raise Exception("Invalid argument to make_subprocess: {}".format(type(obj)))
138 |
139 |
140 | def make_simple_process(obj):
141 | if isinstance(obj, NonBlockingSimpleProcess):
142 | return obj
143 | proc = make_subprocess(obj)
144 | return NonBlockingSimpleProcess(proc)
145 |
146 |
147 | OS_TERMINALS = {
148 | 'linux': LinuxTerminal,
149 | 'win32': WindowsTerminal
150 | }
151 |
--------------------------------------------------------------------------------
/server-python3/server.py:
--------------------------------------------------------------------------------
1 | import os
2 | import urllib.parse
3 |
4 | import eventlet
5 | import eventlet.green.socket
6 | # eventlet.monkey_patch()
7 | import eventlet.websocket
8 | import eventlet.wsgi
9 | import wspty.pipe
10 | from flask import Flask, request, redirect
11 | from wspty.EchoTerminal import EchoTerminal
12 | from wspty.EncodedTerminal import EncodedTerminal
13 | from wspty.WebsocketBinding import WebsocketBinding
14 |
15 | import config
16 |
17 |
18 | def make_app():
19 | app = Flask(__name__)
20 | app.static_folder = get_static_folder()
21 | print("Serving static files from: " + app.static_folder)
22 |
23 | @app.route('/')
24 | def index():
25 | newurl = b'/static/index.html'
26 | if request.query_string:
27 | newurl = newurl + b'?' + request.query_string
28 | return redirect(newurl)
29 | return app
30 |
31 |
32 | def parse_query(qstr):
33 | return {k: v[0] for k, v in urllib.parse.parse_qs(qstr).items()}
34 |
35 |
36 | def debug(s):
37 | app.logger.debug(s)
38 |
39 |
40 | class TerminalFactory:
41 | def __init__(self, args_dict, allow_unsafe=False):
42 | self.kind = args_dict['kind']
43 | self.hostname = args_dict.get('hostname', 'localhost')
44 | self.port = int(args_dict.get('port', '22'))
45 | self.username = args_dict.get('username')
46 | self.password = args_dict.get('password')
47 | self.term = args_dict.get('term')
48 | self.encoding = args_dict.get('encoding', 'utf8')
49 | self.allow_unsafe = allow_unsafe
50 |
51 | def create_binary(self):
52 | if self.kind == 'ssh':
53 | from wspty.SshTerminal import SshTerminal
54 | return SshTerminal(
55 | self.hostname, self.port, self.username, self.password, self.term
56 | )
57 | if self.kind == 'raw':
58 | from wspty.SocketTerminal import SocketTerminal
59 | sock = eventlet.green.socket.socket()
60 | ip = eventlet.green.socket.gethostbyname(self.hostname)
61 | sock.connect((ip, self.port))
62 | return SocketTerminal(sock)
63 | if self.kind == 'echo':
64 | return EchoTerminal()
65 | if self.kind == 'prompt':
66 | if not self.allow_unsafe:
67 | raise Exception("kind {} is disabled".format(self.kind))
68 | from wspty import PromptTerminal
69 | return PromptTerminal.os_terminal()
70 | raise NotImplemented('kind: {}'.format(self.kind))
71 |
72 | def create(self):
73 | return EncodedTerminal(self.create_binary(), self.encoding)
74 |
75 |
76 | class DefaultRootApp:
77 | def __init__(self):
78 | self._app_handle_wssh = eventlet.websocket.WebSocketWSGI(self.handle_wssh)
79 | self.allow_unsafe = False
80 |
81 | def handle_wssh(self, ws):
82 | debug('Creating terminal with remote {remote}'.format(
83 | remote=ws.environ.get('REMOTE_ADDR'),
84 | ))
85 |
86 | ws_binding = WebsocketBinding(ws)
87 | query = parse_query(ws.environ.get('QUERY_STRING', ''))
88 | terminal = None
89 | try:
90 | kind, terminal = self.create_terminal(query)
91 | ws_binding.send('Connected to %s\r\n' % (kind,))
92 | wspty.pipe.pipe(ws_binding, terminal)
93 | except BaseException as e:
94 | ws_binding.send_error(e)
95 | raise
96 | finally:
97 | if terminal:
98 | terminal.close()
99 |
100 | debug('Closing terminal normally with remote {remote}'.format(
101 | remote=ws.environ.get('REMOTE_ADDR'),
102 | ))
103 | return ''
104 |
105 | def create_terminal(self, obj):
106 | factory = TerminalFactory(obj, self.allow_unsafe)
107 | return factory.kind, factory.create()
108 |
109 | def handler(self, env, *args):
110 | route = env["PATH_INFO"]
111 | if route == '/wssh':
112 | return self._app_handle_wssh(env, *args)
113 | else:
114 | return app(env, *args)
115 |
116 |
117 | def make_parser():
118 | import argparse
119 | parser = argparse.ArgumentParser(description='Websocket Terminal server')
120 | parser.add_argument('-l', '--listen', default='', help='Listen on interface (default all)')
121 | parser.add_argument('-p', '--port', default=5002, type=int, help='Listen on port')
122 | parser.add_argument('--unsafe', action='store_true', help='Allow unauthenticated connections to local machine')
123 | return parser
124 |
125 |
126 | def start(interface, port, root_app_handler):
127 | conn = (interface, port)
128 | listener = eventlet.listen(conn)
129 | print('listening on {0}:{1}'.format(*conn))
130 | try:
131 | eventlet.wsgi.server(listener, root_app_handler)
132 | except KeyboardInterrupt:
133 | pass
134 |
135 |
136 | def start_default(interface, port, allow_unsafe=False, root_app_cls=DefaultRootApp):
137 | root_app = root_app_cls()
138 | root_app.allow_unsafe = allow_unsafe
139 | start(interface, port, root_app.handler)
140 |
141 |
142 | def main():
143 | args = make_parser().parse_args()
144 | start_default(args.listen, args.port, args.unsafe)
145 |
146 |
147 | def get_static_folder():
148 | path_root = os.path.join(os.path.dirname(os.path.realpath(__file__)), '../client')
149 | path_root = os.path.join(path_root, config.CLIENT_DIR)
150 | return os.path.abspath(path_root)
151 |
152 |
153 | app = make_app()
154 |
155 | if __name__ == '__main__':
156 | main()
157 |
--------------------------------------------------------------------------------
/client/src/lib/xterm.css:
--------------------------------------------------------------------------------
1 | /**
2 | * xterm.js: xterm, in the browser
3 | * Copyright (c) 2014-2016, SourceLair Private Company (www.sourcelair.com (MIT License)
4 | * Copyright (c) 2012-2013, Christopher Jeffrey (MIT License)
5 | * https://github.com/chjj/term.js
6 | *
7 | * Permission is hereby granted, free of charge, to any person obtaining a copy
8 | * of this software and associated documentation files (the "Software"), to deal
9 | * in the Software without restriction, including without limitation the rights
10 | * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 | * copies of the Software, and to permit persons to whom the Software is
12 | * furnished to do so, subject to the following conditions:
13 | *
14 | * The above copyright notice and this permission notice shall be included in
15 | * all copies or substantial portions of the Software.
16 | *
17 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 | * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 | * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 | * THE SOFTWARE.
24 | *
25 | * Originally forked from (with the author's permission):
26 | * Fabrice Bellard's javascript vt100 for jslinux:
27 | * http://bellard.org/jslinux/
28 | * Copyright (c) 2011 Fabrice Bellard
29 | * The original design remains. The terminal itself
30 | * has been extended to include xterm CSI codes, among
31 | * other features.
32 | */
33 |
34 | /*
35 | * Default style for xterm.js
36 | */
37 |
38 | .terminal {
39 | background-color: #000;
40 | color: #fff;
41 | font-family: courier-new, courier, monospace;
42 | font-feature-settings: "liga" 0;
43 | position: relative;
44 | }
45 |
46 | .terminal.focus,
47 | .terminal:focus {
48 | outline: none;
49 | }
50 |
51 | .terminal .xterm-helpers {
52 | position: absolute;
53 | top: 0;
54 | }
55 |
56 | .terminal .xterm-helper-textarea {
57 | /*
58 | * HACK: to fix IE's blinking cursor
59 | * Move textarea out of the screen to the far left, so that the cursor is not visible.
60 | */
61 | position: absolute;
62 | opacity: 0;
63 | left: -9999em;
64 | top: 0;
65 | width: 0;
66 | height: 0;
67 | z-index: -10;
68 | /** Prevent wrapping so the IME appears against the textarea at the correct position */
69 | white-space: nowrap;
70 | overflow: hidden;
71 | resize: none;
72 | }
73 |
74 | .terminal a {
75 | color: inherit;
76 | text-decoration: none;
77 | }
78 |
79 | .terminal a:hover {
80 | cursor: pointer;
81 | text-decoration: underline;
82 | }
83 |
84 | .terminal a.xterm-invalid-link:hover {
85 | cursor: text;
86 | text-decoration: none;
87 | }
88 |
89 | .terminal.focus:not(.xterm-cursor-style-underline):not(.xterm-cursor-style-bar) .terminal-cursor {
90 | background-color: #fff;
91 | color: #000;
92 | }
93 |
94 | .terminal:not(.focus) .terminal-cursor {
95 | outline: 1px solid #fff;
96 | outline-offset: -1px;
97 | background-color: transparent;
98 | }
99 |
100 | .terminal:not(.xterm-cursor-style-underline):not(.xterm-cursor-style-bar).focus.xterm-cursor-blink-on .terminal-cursor {
101 | background-color: transparent;
102 | color: inherit;
103 | }
104 |
105 | .terminal.xterm-cursor-style-bar .terminal-cursor,
106 | .terminal.xterm-cursor-style-underline .terminal-cursor {
107 | position: relative;
108 | }
109 | .terminal.xterm-cursor-style-bar .terminal-cursor::before,
110 | .terminal.xterm-cursor-style-underline .terminal-cursor::before {
111 | content: "";
112 | display: block;
113 | position: absolute;
114 | background-color: #fff;
115 | }
116 | .terminal.xterm-cursor-style-bar .terminal-cursor::before {
117 | top: 0;
118 | bottom: 0;
119 | left: 0;
120 | width: 1px;
121 | }
122 | .terminal.xterm-cursor-style-underline .terminal-cursor::before {
123 | bottom: 0;
124 | left: 0;
125 | right: 0;
126 | height: 1px;
127 | }
128 | .terminal.xterm-cursor-style-bar.focus.xterm-cursor-blink.xterm-cursor-blink-on .terminal-cursor::before,
129 | .terminal.xterm-cursor-style-underline.focus.xterm-cursor-blink.xterm-cursor-blink-on .terminal-cursor::before {
130 | background-color: transparent;
131 | }
132 | .terminal.xterm-cursor-style-bar.focus.xterm-cursor-blink .terminal-cursor::before,
133 | .terminal.xterm-cursor-style-underline.focus.xterm-cursor-blink .terminal-cursor::before {
134 | background-color: #fff;
135 | }
136 |
137 | .terminal .composition-view {
138 | background: #000;
139 | color: #FFF;
140 | display: none;
141 | position: absolute;
142 | white-space: nowrap;
143 | z-index: 1;
144 | }
145 |
146 | .terminal .composition-view.active {
147 | display: block;
148 | }
149 |
150 | .terminal .xterm-viewport {
151 | /* On OS X this is required in order for the scroll bar to appear fully opaque */
152 | background-color: #000;
153 | overflow-y: scroll;
154 | }
155 |
156 | .terminal .xterm-wide-char,
157 | .terminal .xterm-normal-char {
158 | display: inline-block;
159 | }
160 |
161 | .terminal .xterm-rows {
162 | position: absolute;
163 | left: 0;
164 | top: 0;
165 | }
166 |
167 | .terminal .xterm-rows > div {
168 | /* Lines containing spans and text nodes ocassionally wrap despite being the same width (#327) */
169 | white-space: nowrap;
170 | }
171 |
172 | .terminal .xterm-scroll-area {
173 | visibility: hidden;
174 | }
175 |
176 | .terminal .xterm-char-measure-element {
177 | display: inline-block;
178 | visibility: hidden;
179 | position: absolute;
180 | left: -9999em;
181 | }
182 |
183 | /*
184 | * Determine default colors for xterm.js
185 | */
186 | .terminal .xterm-bold {
187 | font-weight: bold;
188 | }
189 |
190 | .terminal .xterm-underline {
191 | text-decoration: underline;
192 | }
193 |
194 | .terminal .xterm-blink {
195 | text-decoration: blink;
196 | }
197 |
198 | .terminal .xterm-hidden {
199 | visibility: hidden;
200 | }
201 |
202 | .terminal .xterm-color-0 {
203 | color: #2e3436;
204 | }
205 |
206 | .terminal .xterm-bg-color-0 {
207 | background-color: #2e3436;
208 | }
209 |
210 | .terminal .xterm-color-1 {
211 | color: #cc0000;
212 | }
213 |
214 | .terminal .xterm-bg-color-1 {
215 | background-color: #cc0000;
216 | }
217 |
218 | .terminal .xterm-color-2 {
219 | color: #4e9a06;
220 | }
221 |
222 | .terminal .xterm-bg-color-2 {
223 | background-color: #4e9a06;
224 | }
225 |
226 | .terminal .xterm-color-3 {
227 | color: #c4a000;
228 | }
229 |
230 | .terminal .xterm-bg-color-3 {
231 | background-color: #c4a000;
232 | }
233 |
234 | .terminal .xterm-color-4 {
235 | color: #3465a4;
236 | }
237 |
238 | .terminal .xterm-bg-color-4 {
239 | background-color: #3465a4;
240 | }
241 |
242 | .terminal .xterm-color-5 {
243 | color: #75507b;
244 | }
245 |
246 | .terminal .xterm-bg-color-5 {
247 | background-color: #75507b;
248 | }
249 |
250 | .terminal .xterm-color-6 {
251 | color: #06989a;
252 | }
253 |
254 | .terminal .xterm-bg-color-6 {
255 | background-color: #06989a;
256 | }
257 |
258 | .terminal .xterm-color-7 {
259 | color: #d3d7cf;
260 | }
261 |
262 | .terminal .xterm-bg-color-7 {
263 | background-color: #d3d7cf;
264 | }
265 |
266 | .terminal .xterm-color-8 {
267 | color: #555753;
268 | }
269 |
270 | .terminal .xterm-bg-color-8 {
271 | background-color: #555753;
272 | }
273 |
274 | .terminal .xterm-color-9 {
275 | color: #ef2929;
276 | }
277 |
278 | .terminal .xterm-bg-color-9 {
279 | background-color: #ef2929;
280 | }
281 |
282 | .terminal .xterm-color-10 {
283 | color: #8ae234;
284 | }
285 |
286 | .terminal .xterm-bg-color-10 {
287 | background-color: #8ae234;
288 | }
289 |
290 | .terminal .xterm-color-11 {
291 | color: #fce94f;
292 | }
293 |
294 | .terminal .xterm-bg-color-11 {
295 | background-color: #fce94f;
296 | }
297 |
298 | .terminal .xterm-color-12 {
299 | color: #729fcf;
300 | }
301 |
302 | .terminal .xterm-bg-color-12 {
303 | background-color: #729fcf;
304 | }
305 |
306 | .terminal .xterm-color-13 {
307 | color: #ad7fa8;
308 | }
309 |
310 | .terminal .xterm-bg-color-13 {
311 | background-color: #ad7fa8;
312 | }
313 |
314 | .terminal .xterm-color-14 {
315 | color: #34e2e2;
316 | }
317 |
318 | .terminal .xterm-bg-color-14 {
319 | background-color: #34e2e2;
320 | }
321 |
322 | .terminal .xterm-color-15 {
323 | color: #eeeeec;
324 | }
325 |
326 | .terminal .xterm-bg-color-15 {
327 | background-color: #eeeeec;
328 | }
329 |
330 | .terminal .xterm-color-16 {
331 | color: #000000;
332 | }
333 |
334 | .terminal .xterm-bg-color-16 {
335 | background-color: #000000;
336 | }
337 |
338 | .terminal .xterm-color-17 {
339 | color: #00005f;
340 | }
341 |
342 | .terminal .xterm-bg-color-17 {
343 | background-color: #00005f;
344 | }
345 |
346 | .terminal .xterm-color-18 {
347 | color: #000087;
348 | }
349 |
350 | .terminal .xterm-bg-color-18 {
351 | background-color: #000087;
352 | }
353 |
354 | .terminal .xterm-color-19 {
355 | color: #0000af;
356 | }
357 |
358 | .terminal .xterm-bg-color-19 {
359 | background-color: #0000af;
360 | }
361 |
362 | .terminal .xterm-color-20 {
363 | color: #0000d7;
364 | }
365 |
366 | .terminal .xterm-bg-color-20 {
367 | background-color: #0000d7;
368 | }
369 |
370 | .terminal .xterm-color-21 {
371 | color: #0000ff;
372 | }
373 |
374 | .terminal .xterm-bg-color-21 {
375 | background-color: #0000ff;
376 | }
377 |
378 | .terminal .xterm-color-22 {
379 | color: #005f00;
380 | }
381 |
382 | .terminal .xterm-bg-color-22 {
383 | background-color: #005f00;
384 | }
385 |
386 | .terminal .xterm-color-23 {
387 | color: #005f5f;
388 | }
389 |
390 | .terminal .xterm-bg-color-23 {
391 | background-color: #005f5f;
392 | }
393 |
394 | .terminal .xterm-color-24 {
395 | color: #005f87;
396 | }
397 |
398 | .terminal .xterm-bg-color-24 {
399 | background-color: #005f87;
400 | }
401 |
402 | .terminal .xterm-color-25 {
403 | color: #005faf;
404 | }
405 |
406 | .terminal .xterm-bg-color-25 {
407 | background-color: #005faf;
408 | }
409 |
410 | .terminal .xterm-color-26 {
411 | color: #005fd7;
412 | }
413 |
414 | .terminal .xterm-bg-color-26 {
415 | background-color: #005fd7;
416 | }
417 |
418 | .terminal .xterm-color-27 {
419 | color: #005fff;
420 | }
421 |
422 | .terminal .xterm-bg-color-27 {
423 | background-color: #005fff;
424 | }
425 |
426 | .terminal .xterm-color-28 {
427 | color: #008700;
428 | }
429 |
430 | .terminal .xterm-bg-color-28 {
431 | background-color: #008700;
432 | }
433 |
434 | .terminal .xterm-color-29 {
435 | color: #00875f;
436 | }
437 |
438 | .terminal .xterm-bg-color-29 {
439 | background-color: #00875f;
440 | }
441 |
442 | .terminal .xterm-color-30 {
443 | color: #008787;
444 | }
445 |
446 | .terminal .xterm-bg-color-30 {
447 | background-color: #008787;
448 | }
449 |
450 | .terminal .xterm-color-31 {
451 | color: #0087af;
452 | }
453 |
454 | .terminal .xterm-bg-color-31 {
455 | background-color: #0087af;
456 | }
457 |
458 | .terminal .xterm-color-32 {
459 | color: #0087d7;
460 | }
461 |
462 | .terminal .xterm-bg-color-32 {
463 | background-color: #0087d7;
464 | }
465 |
466 | .terminal .xterm-color-33 {
467 | color: #0087ff;
468 | }
469 |
470 | .terminal .xterm-bg-color-33 {
471 | background-color: #0087ff;
472 | }
473 |
474 | .terminal .xterm-color-34 {
475 | color: #00af00;
476 | }
477 |
478 | .terminal .xterm-bg-color-34 {
479 | background-color: #00af00;
480 | }
481 |
482 | .terminal .xterm-color-35 {
483 | color: #00af5f;
484 | }
485 |
486 | .terminal .xterm-bg-color-35 {
487 | background-color: #00af5f;
488 | }
489 |
490 | .terminal .xterm-color-36 {
491 | color: #00af87;
492 | }
493 |
494 | .terminal .xterm-bg-color-36 {
495 | background-color: #00af87;
496 | }
497 |
498 | .terminal .xterm-color-37 {
499 | color: #00afaf;
500 | }
501 |
502 | .terminal .xterm-bg-color-37 {
503 | background-color: #00afaf;
504 | }
505 |
506 | .terminal .xterm-color-38 {
507 | color: #00afd7;
508 | }
509 |
510 | .terminal .xterm-bg-color-38 {
511 | background-color: #00afd7;
512 | }
513 |
514 | .terminal .xterm-color-39 {
515 | color: #00afff;
516 | }
517 |
518 | .terminal .xterm-bg-color-39 {
519 | background-color: #00afff;
520 | }
521 |
522 | .terminal .xterm-color-40 {
523 | color: #00d700;
524 | }
525 |
526 | .terminal .xterm-bg-color-40 {
527 | background-color: #00d700;
528 | }
529 |
530 | .terminal .xterm-color-41 {
531 | color: #00d75f;
532 | }
533 |
534 | .terminal .xterm-bg-color-41 {
535 | background-color: #00d75f;
536 | }
537 |
538 | .terminal .xterm-color-42 {
539 | color: #00d787;
540 | }
541 |
542 | .terminal .xterm-bg-color-42 {
543 | background-color: #00d787;
544 | }
545 |
546 | .terminal .xterm-color-43 {
547 | color: #00d7af;
548 | }
549 |
550 | .terminal .xterm-bg-color-43 {
551 | background-color: #00d7af;
552 | }
553 |
554 | .terminal .xterm-color-44 {
555 | color: #00d7d7;
556 | }
557 |
558 | .terminal .xterm-bg-color-44 {
559 | background-color: #00d7d7;
560 | }
561 |
562 | .terminal .xterm-color-45 {
563 | color: #00d7ff;
564 | }
565 |
566 | .terminal .xterm-bg-color-45 {
567 | background-color: #00d7ff;
568 | }
569 |
570 | .terminal .xterm-color-46 {
571 | color: #00ff00;
572 | }
573 |
574 | .terminal .xterm-bg-color-46 {
575 | background-color: #00ff00;
576 | }
577 |
578 | .terminal .xterm-color-47 {
579 | color: #00ff5f;
580 | }
581 |
582 | .terminal .xterm-bg-color-47 {
583 | background-color: #00ff5f;
584 | }
585 |
586 | .terminal .xterm-color-48 {
587 | color: #00ff87;
588 | }
589 |
590 | .terminal .xterm-bg-color-48 {
591 | background-color: #00ff87;
592 | }
593 |
594 | .terminal .xterm-color-49 {
595 | color: #00ffaf;
596 | }
597 |
598 | .terminal .xterm-bg-color-49 {
599 | background-color: #00ffaf;
600 | }
601 |
602 | .terminal .xterm-color-50 {
603 | color: #00ffd7;
604 | }
605 |
606 | .terminal .xterm-bg-color-50 {
607 | background-color: #00ffd7;
608 | }
609 |
610 | .terminal .xterm-color-51 {
611 | color: #00ffff;
612 | }
613 |
614 | .terminal .xterm-bg-color-51 {
615 | background-color: #00ffff;
616 | }
617 |
618 | .terminal .xterm-color-52 {
619 | color: #5f0000;
620 | }
621 |
622 | .terminal .xterm-bg-color-52 {
623 | background-color: #5f0000;
624 | }
625 |
626 | .terminal .xterm-color-53 {
627 | color: #5f005f;
628 | }
629 |
630 | .terminal .xterm-bg-color-53 {
631 | background-color: #5f005f;
632 | }
633 |
634 | .terminal .xterm-color-54 {
635 | color: #5f0087;
636 | }
637 |
638 | .terminal .xterm-bg-color-54 {
639 | background-color: #5f0087;
640 | }
641 |
642 | .terminal .xterm-color-55 {
643 | color: #5f00af;
644 | }
645 |
646 | .terminal .xterm-bg-color-55 {
647 | background-color: #5f00af;
648 | }
649 |
650 | .terminal .xterm-color-56 {
651 | color: #5f00d7;
652 | }
653 |
654 | .terminal .xterm-bg-color-56 {
655 | background-color: #5f00d7;
656 | }
657 |
658 | .terminal .xterm-color-57 {
659 | color: #5f00ff;
660 | }
661 |
662 | .terminal .xterm-bg-color-57 {
663 | background-color: #5f00ff;
664 | }
665 |
666 | .terminal .xterm-color-58 {
667 | color: #5f5f00;
668 | }
669 |
670 | .terminal .xterm-bg-color-58 {
671 | background-color: #5f5f00;
672 | }
673 |
674 | .terminal .xterm-color-59 {
675 | color: #5f5f5f;
676 | }
677 |
678 | .terminal .xterm-bg-color-59 {
679 | background-color: #5f5f5f;
680 | }
681 |
682 | .terminal .xterm-color-60 {
683 | color: #5f5f87;
684 | }
685 |
686 | .terminal .xterm-bg-color-60 {
687 | background-color: #5f5f87;
688 | }
689 |
690 | .terminal .xterm-color-61 {
691 | color: #5f5faf;
692 | }
693 |
694 | .terminal .xterm-bg-color-61 {
695 | background-color: #5f5faf;
696 | }
697 |
698 | .terminal .xterm-color-62 {
699 | color: #5f5fd7;
700 | }
701 |
702 | .terminal .xterm-bg-color-62 {
703 | background-color: #5f5fd7;
704 | }
705 |
706 | .terminal .xterm-color-63 {
707 | color: #5f5fff;
708 | }
709 |
710 | .terminal .xterm-bg-color-63 {
711 | background-color: #5f5fff;
712 | }
713 |
714 | .terminal .xterm-color-64 {
715 | color: #5f8700;
716 | }
717 |
718 | .terminal .xterm-bg-color-64 {
719 | background-color: #5f8700;
720 | }
721 |
722 | .terminal .xterm-color-65 {
723 | color: #5f875f;
724 | }
725 |
726 | .terminal .xterm-bg-color-65 {
727 | background-color: #5f875f;
728 | }
729 |
730 | .terminal .xterm-color-66 {
731 | color: #5f8787;
732 | }
733 |
734 | .terminal .xterm-bg-color-66 {
735 | background-color: #5f8787;
736 | }
737 |
738 | .terminal .xterm-color-67 {
739 | color: #5f87af;
740 | }
741 |
742 | .terminal .xterm-bg-color-67 {
743 | background-color: #5f87af;
744 | }
745 |
746 | .terminal .xterm-color-68 {
747 | color: #5f87d7;
748 | }
749 |
750 | .terminal .xterm-bg-color-68 {
751 | background-color: #5f87d7;
752 | }
753 |
754 | .terminal .xterm-color-69 {
755 | color: #5f87ff;
756 | }
757 |
758 | .terminal .xterm-bg-color-69 {
759 | background-color: #5f87ff;
760 | }
761 |
762 | .terminal .xterm-color-70 {
763 | color: #5faf00;
764 | }
765 |
766 | .terminal .xterm-bg-color-70 {
767 | background-color: #5faf00;
768 | }
769 |
770 | .terminal .xterm-color-71 {
771 | color: #5faf5f;
772 | }
773 |
774 | .terminal .xterm-bg-color-71 {
775 | background-color: #5faf5f;
776 | }
777 |
778 | .terminal .xterm-color-72 {
779 | color: #5faf87;
780 | }
781 |
782 | .terminal .xterm-bg-color-72 {
783 | background-color: #5faf87;
784 | }
785 |
786 | .terminal .xterm-color-73 {
787 | color: #5fafaf;
788 | }
789 |
790 | .terminal .xterm-bg-color-73 {
791 | background-color: #5fafaf;
792 | }
793 |
794 | .terminal .xterm-color-74 {
795 | color: #5fafd7;
796 | }
797 |
798 | .terminal .xterm-bg-color-74 {
799 | background-color: #5fafd7;
800 | }
801 |
802 | .terminal .xterm-color-75 {
803 | color: #5fafff;
804 | }
805 |
806 | .terminal .xterm-bg-color-75 {
807 | background-color: #5fafff;
808 | }
809 |
810 | .terminal .xterm-color-76 {
811 | color: #5fd700;
812 | }
813 |
814 | .terminal .xterm-bg-color-76 {
815 | background-color: #5fd700;
816 | }
817 |
818 | .terminal .xterm-color-77 {
819 | color: #5fd75f;
820 | }
821 |
822 | .terminal .xterm-bg-color-77 {
823 | background-color: #5fd75f;
824 | }
825 |
826 | .terminal .xterm-color-78 {
827 | color: #5fd787;
828 | }
829 |
830 | .terminal .xterm-bg-color-78 {
831 | background-color: #5fd787;
832 | }
833 |
834 | .terminal .xterm-color-79 {
835 | color: #5fd7af;
836 | }
837 |
838 | .terminal .xterm-bg-color-79 {
839 | background-color: #5fd7af;
840 | }
841 |
842 | .terminal .xterm-color-80 {
843 | color: #5fd7d7;
844 | }
845 |
846 | .terminal .xterm-bg-color-80 {
847 | background-color: #5fd7d7;
848 | }
849 |
850 | .terminal .xterm-color-81 {
851 | color: #5fd7ff;
852 | }
853 |
854 | .terminal .xterm-bg-color-81 {
855 | background-color: #5fd7ff;
856 | }
857 |
858 | .terminal .xterm-color-82 {
859 | color: #5fff00;
860 | }
861 |
862 | .terminal .xterm-bg-color-82 {
863 | background-color: #5fff00;
864 | }
865 |
866 | .terminal .xterm-color-83 {
867 | color: #5fff5f;
868 | }
869 |
870 | .terminal .xterm-bg-color-83 {
871 | background-color: #5fff5f;
872 | }
873 |
874 | .terminal .xterm-color-84 {
875 | color: #5fff87;
876 | }
877 |
878 | .terminal .xterm-bg-color-84 {
879 | background-color: #5fff87;
880 | }
881 |
882 | .terminal .xterm-color-85 {
883 | color: #5fffaf;
884 | }
885 |
886 | .terminal .xterm-bg-color-85 {
887 | background-color: #5fffaf;
888 | }
889 |
890 | .terminal .xterm-color-86 {
891 | color: #5fffd7;
892 | }
893 |
894 | .terminal .xterm-bg-color-86 {
895 | background-color: #5fffd7;
896 | }
897 |
898 | .terminal .xterm-color-87 {
899 | color: #5fffff;
900 | }
901 |
902 | .terminal .xterm-bg-color-87 {
903 | background-color: #5fffff;
904 | }
905 |
906 | .terminal .xterm-color-88 {
907 | color: #870000;
908 | }
909 |
910 | .terminal .xterm-bg-color-88 {
911 | background-color: #870000;
912 | }
913 |
914 | .terminal .xterm-color-89 {
915 | color: #87005f;
916 | }
917 |
918 | .terminal .xterm-bg-color-89 {
919 | background-color: #87005f;
920 | }
921 |
922 | .terminal .xterm-color-90 {
923 | color: #870087;
924 | }
925 |
926 | .terminal .xterm-bg-color-90 {
927 | background-color: #870087;
928 | }
929 |
930 | .terminal .xterm-color-91 {
931 | color: #8700af;
932 | }
933 |
934 | .terminal .xterm-bg-color-91 {
935 | background-color: #8700af;
936 | }
937 |
938 | .terminal .xterm-color-92 {
939 | color: #8700d7;
940 | }
941 |
942 | .terminal .xterm-bg-color-92 {
943 | background-color: #8700d7;
944 | }
945 |
946 | .terminal .xterm-color-93 {
947 | color: #8700ff;
948 | }
949 |
950 | .terminal .xterm-bg-color-93 {
951 | background-color: #8700ff;
952 | }
953 |
954 | .terminal .xterm-color-94 {
955 | color: #875f00;
956 | }
957 |
958 | .terminal .xterm-bg-color-94 {
959 | background-color: #875f00;
960 | }
961 |
962 | .terminal .xterm-color-95 {
963 | color: #875f5f;
964 | }
965 |
966 | .terminal .xterm-bg-color-95 {
967 | background-color: #875f5f;
968 | }
969 |
970 | .terminal .xterm-color-96 {
971 | color: #875f87;
972 | }
973 |
974 | .terminal .xterm-bg-color-96 {
975 | background-color: #875f87;
976 | }
977 |
978 | .terminal .xterm-color-97 {
979 | color: #875faf;
980 | }
981 |
982 | .terminal .xterm-bg-color-97 {
983 | background-color: #875faf;
984 | }
985 |
986 | .terminal .xterm-color-98 {
987 | color: #875fd7;
988 | }
989 |
990 | .terminal .xterm-bg-color-98 {
991 | background-color: #875fd7;
992 | }
993 |
994 | .terminal .xterm-color-99 {
995 | color: #875fff;
996 | }
997 |
998 | .terminal .xterm-bg-color-99 {
999 | background-color: #875fff;
1000 | }
1001 |
1002 | .terminal .xterm-color-100 {
1003 | color: #878700;
1004 | }
1005 |
1006 | .terminal .xterm-bg-color-100 {
1007 | background-color: #878700;
1008 | }
1009 |
1010 | .terminal .xterm-color-101 {
1011 | color: #87875f;
1012 | }
1013 |
1014 | .terminal .xterm-bg-color-101 {
1015 | background-color: #87875f;
1016 | }
1017 |
1018 | .terminal .xterm-color-102 {
1019 | color: #878787;
1020 | }
1021 |
1022 | .terminal .xterm-bg-color-102 {
1023 | background-color: #878787;
1024 | }
1025 |
1026 | .terminal .xterm-color-103 {
1027 | color: #8787af;
1028 | }
1029 |
1030 | .terminal .xterm-bg-color-103 {
1031 | background-color: #8787af;
1032 | }
1033 |
1034 | .terminal .xterm-color-104 {
1035 | color: #8787d7;
1036 | }
1037 |
1038 | .terminal .xterm-bg-color-104 {
1039 | background-color: #8787d7;
1040 | }
1041 |
1042 | .terminal .xterm-color-105 {
1043 | color: #8787ff;
1044 | }
1045 |
1046 | .terminal .xterm-bg-color-105 {
1047 | background-color: #8787ff;
1048 | }
1049 |
1050 | .terminal .xterm-color-106 {
1051 | color: #87af00;
1052 | }
1053 |
1054 | .terminal .xterm-bg-color-106 {
1055 | background-color: #87af00;
1056 | }
1057 |
1058 | .terminal .xterm-color-107 {
1059 | color: #87af5f;
1060 | }
1061 |
1062 | .terminal .xterm-bg-color-107 {
1063 | background-color: #87af5f;
1064 | }
1065 |
1066 | .terminal .xterm-color-108 {
1067 | color: #87af87;
1068 | }
1069 |
1070 | .terminal .xterm-bg-color-108 {
1071 | background-color: #87af87;
1072 | }
1073 |
1074 | .terminal .xterm-color-109 {
1075 | color: #87afaf;
1076 | }
1077 |
1078 | .terminal .xterm-bg-color-109 {
1079 | background-color: #87afaf;
1080 | }
1081 |
1082 | .terminal .xterm-color-110 {
1083 | color: #87afd7;
1084 | }
1085 |
1086 | .terminal .xterm-bg-color-110 {
1087 | background-color: #87afd7;
1088 | }
1089 |
1090 | .terminal .xterm-color-111 {
1091 | color: #87afff;
1092 | }
1093 |
1094 | .terminal .xterm-bg-color-111 {
1095 | background-color: #87afff;
1096 | }
1097 |
1098 | .terminal .xterm-color-112 {
1099 | color: #87d700;
1100 | }
1101 |
1102 | .terminal .xterm-bg-color-112 {
1103 | background-color: #87d700;
1104 | }
1105 |
1106 | .terminal .xterm-color-113 {
1107 | color: #87d75f;
1108 | }
1109 |
1110 | .terminal .xterm-bg-color-113 {
1111 | background-color: #87d75f;
1112 | }
1113 |
1114 | .terminal .xterm-color-114 {
1115 | color: #87d787;
1116 | }
1117 |
1118 | .terminal .xterm-bg-color-114 {
1119 | background-color: #87d787;
1120 | }
1121 |
1122 | .terminal .xterm-color-115 {
1123 | color: #87d7af;
1124 | }
1125 |
1126 | .terminal .xterm-bg-color-115 {
1127 | background-color: #87d7af;
1128 | }
1129 |
1130 | .terminal .xterm-color-116 {
1131 | color: #87d7d7;
1132 | }
1133 |
1134 | .terminal .xterm-bg-color-116 {
1135 | background-color: #87d7d7;
1136 | }
1137 |
1138 | .terminal .xterm-color-117 {
1139 | color: #87d7ff;
1140 | }
1141 |
1142 | .terminal .xterm-bg-color-117 {
1143 | background-color: #87d7ff;
1144 | }
1145 |
1146 | .terminal .xterm-color-118 {
1147 | color: #87ff00;
1148 | }
1149 |
1150 | .terminal .xterm-bg-color-118 {
1151 | background-color: #87ff00;
1152 | }
1153 |
1154 | .terminal .xterm-color-119 {
1155 | color: #87ff5f;
1156 | }
1157 |
1158 | .terminal .xterm-bg-color-119 {
1159 | background-color: #87ff5f;
1160 | }
1161 |
1162 | .terminal .xterm-color-120 {
1163 | color: #87ff87;
1164 | }
1165 |
1166 | .terminal .xterm-bg-color-120 {
1167 | background-color: #87ff87;
1168 | }
1169 |
1170 | .terminal .xterm-color-121 {
1171 | color: #87ffaf;
1172 | }
1173 |
1174 | .terminal .xterm-bg-color-121 {
1175 | background-color: #87ffaf;
1176 | }
1177 |
1178 | .terminal .xterm-color-122 {
1179 | color: #87ffd7;
1180 | }
1181 |
1182 | .terminal .xterm-bg-color-122 {
1183 | background-color: #87ffd7;
1184 | }
1185 |
1186 | .terminal .xterm-color-123 {
1187 | color: #87ffff;
1188 | }
1189 |
1190 | .terminal .xterm-bg-color-123 {
1191 | background-color: #87ffff;
1192 | }
1193 |
1194 | .terminal .xterm-color-124 {
1195 | color: #af0000;
1196 | }
1197 |
1198 | .terminal .xterm-bg-color-124 {
1199 | background-color: #af0000;
1200 | }
1201 |
1202 | .terminal .xterm-color-125 {
1203 | color: #af005f;
1204 | }
1205 |
1206 | .terminal .xterm-bg-color-125 {
1207 | background-color: #af005f;
1208 | }
1209 |
1210 | .terminal .xterm-color-126 {
1211 | color: #af0087;
1212 | }
1213 |
1214 | .terminal .xterm-bg-color-126 {
1215 | background-color: #af0087;
1216 | }
1217 |
1218 | .terminal .xterm-color-127 {
1219 | color: #af00af;
1220 | }
1221 |
1222 | .terminal .xterm-bg-color-127 {
1223 | background-color: #af00af;
1224 | }
1225 |
1226 | .terminal .xterm-color-128 {
1227 | color: #af00d7;
1228 | }
1229 |
1230 | .terminal .xterm-bg-color-128 {
1231 | background-color: #af00d7;
1232 | }
1233 |
1234 | .terminal .xterm-color-129 {
1235 | color: #af00ff;
1236 | }
1237 |
1238 | .terminal .xterm-bg-color-129 {
1239 | background-color: #af00ff;
1240 | }
1241 |
1242 | .terminal .xterm-color-130 {
1243 | color: #af5f00;
1244 | }
1245 |
1246 | .terminal .xterm-bg-color-130 {
1247 | background-color: #af5f00;
1248 | }
1249 |
1250 | .terminal .xterm-color-131 {
1251 | color: #af5f5f;
1252 | }
1253 |
1254 | .terminal .xterm-bg-color-131 {
1255 | background-color: #af5f5f;
1256 | }
1257 |
1258 | .terminal .xterm-color-132 {
1259 | color: #af5f87;
1260 | }
1261 |
1262 | .terminal .xterm-bg-color-132 {
1263 | background-color: #af5f87;
1264 | }
1265 |
1266 | .terminal .xterm-color-133 {
1267 | color: #af5faf;
1268 | }
1269 |
1270 | .terminal .xterm-bg-color-133 {
1271 | background-color: #af5faf;
1272 | }
1273 |
1274 | .terminal .xterm-color-134 {
1275 | color: #af5fd7;
1276 | }
1277 |
1278 | .terminal .xterm-bg-color-134 {
1279 | background-color: #af5fd7;
1280 | }
1281 |
1282 | .terminal .xterm-color-135 {
1283 | color: #af5fff;
1284 | }
1285 |
1286 | .terminal .xterm-bg-color-135 {
1287 | background-color: #af5fff;
1288 | }
1289 |
1290 | .terminal .xterm-color-136 {
1291 | color: #af8700;
1292 | }
1293 |
1294 | .terminal .xterm-bg-color-136 {
1295 | background-color: #af8700;
1296 | }
1297 |
1298 | .terminal .xterm-color-137 {
1299 | color: #af875f;
1300 | }
1301 |
1302 | .terminal .xterm-bg-color-137 {
1303 | background-color: #af875f;
1304 | }
1305 |
1306 | .terminal .xterm-color-138 {
1307 | color: #af8787;
1308 | }
1309 |
1310 | .terminal .xterm-bg-color-138 {
1311 | background-color: #af8787;
1312 | }
1313 |
1314 | .terminal .xterm-color-139 {
1315 | color: #af87af;
1316 | }
1317 |
1318 | .terminal .xterm-bg-color-139 {
1319 | background-color: #af87af;
1320 | }
1321 |
1322 | .terminal .xterm-color-140 {
1323 | color: #af87d7;
1324 | }
1325 |
1326 | .terminal .xterm-bg-color-140 {
1327 | background-color: #af87d7;
1328 | }
1329 |
1330 | .terminal .xterm-color-141 {
1331 | color: #af87ff;
1332 | }
1333 |
1334 | .terminal .xterm-bg-color-141 {
1335 | background-color: #af87ff;
1336 | }
1337 |
1338 | .terminal .xterm-color-142 {
1339 | color: #afaf00;
1340 | }
1341 |
1342 | .terminal .xterm-bg-color-142 {
1343 | background-color: #afaf00;
1344 | }
1345 |
1346 | .terminal .xterm-color-143 {
1347 | color: #afaf5f;
1348 | }
1349 |
1350 | .terminal .xterm-bg-color-143 {
1351 | background-color: #afaf5f;
1352 | }
1353 |
1354 | .terminal .xterm-color-144 {
1355 | color: #afaf87;
1356 | }
1357 |
1358 | .terminal .xterm-bg-color-144 {
1359 | background-color: #afaf87;
1360 | }
1361 |
1362 | .terminal .xterm-color-145 {
1363 | color: #afafaf;
1364 | }
1365 |
1366 | .terminal .xterm-bg-color-145 {
1367 | background-color: #afafaf;
1368 | }
1369 |
1370 | .terminal .xterm-color-146 {
1371 | color: #afafd7;
1372 | }
1373 |
1374 | .terminal .xterm-bg-color-146 {
1375 | background-color: #afafd7;
1376 | }
1377 |
1378 | .terminal .xterm-color-147 {
1379 | color: #afafff;
1380 | }
1381 |
1382 | .terminal .xterm-bg-color-147 {
1383 | background-color: #afafff;
1384 | }
1385 |
1386 | .terminal .xterm-color-148 {
1387 | color: #afd700;
1388 | }
1389 |
1390 | .terminal .xterm-bg-color-148 {
1391 | background-color: #afd700;
1392 | }
1393 |
1394 | .terminal .xterm-color-149 {
1395 | color: #afd75f;
1396 | }
1397 |
1398 | .terminal .xterm-bg-color-149 {
1399 | background-color: #afd75f;
1400 | }
1401 |
1402 | .terminal .xterm-color-150 {
1403 | color: #afd787;
1404 | }
1405 |
1406 | .terminal .xterm-bg-color-150 {
1407 | background-color: #afd787;
1408 | }
1409 |
1410 | .terminal .xterm-color-151 {
1411 | color: #afd7af;
1412 | }
1413 |
1414 | .terminal .xterm-bg-color-151 {
1415 | background-color: #afd7af;
1416 | }
1417 |
1418 | .terminal .xterm-color-152 {
1419 | color: #afd7d7;
1420 | }
1421 |
1422 | .terminal .xterm-bg-color-152 {
1423 | background-color: #afd7d7;
1424 | }
1425 |
1426 | .terminal .xterm-color-153 {
1427 | color: #afd7ff;
1428 | }
1429 |
1430 | .terminal .xterm-bg-color-153 {
1431 | background-color: #afd7ff;
1432 | }
1433 |
1434 | .terminal .xterm-color-154 {
1435 | color: #afff00;
1436 | }
1437 |
1438 | .terminal .xterm-bg-color-154 {
1439 | background-color: #afff00;
1440 | }
1441 |
1442 | .terminal .xterm-color-155 {
1443 | color: #afff5f;
1444 | }
1445 |
1446 | .terminal .xterm-bg-color-155 {
1447 | background-color: #afff5f;
1448 | }
1449 |
1450 | .terminal .xterm-color-156 {
1451 | color: #afff87;
1452 | }
1453 |
1454 | .terminal .xterm-bg-color-156 {
1455 | background-color: #afff87;
1456 | }
1457 |
1458 | .terminal .xterm-color-157 {
1459 | color: #afffaf;
1460 | }
1461 |
1462 | .terminal .xterm-bg-color-157 {
1463 | background-color: #afffaf;
1464 | }
1465 |
1466 | .terminal .xterm-color-158 {
1467 | color: #afffd7;
1468 | }
1469 |
1470 | .terminal .xterm-bg-color-158 {
1471 | background-color: #afffd7;
1472 | }
1473 |
1474 | .terminal .xterm-color-159 {
1475 | color: #afffff;
1476 | }
1477 |
1478 | .terminal .xterm-bg-color-159 {
1479 | background-color: #afffff;
1480 | }
1481 |
1482 | .terminal .xterm-color-160 {
1483 | color: #d70000;
1484 | }
1485 |
1486 | .terminal .xterm-bg-color-160 {
1487 | background-color: #d70000;
1488 | }
1489 |
1490 | .terminal .xterm-color-161 {
1491 | color: #d7005f;
1492 | }
1493 |
1494 | .terminal .xterm-bg-color-161 {
1495 | background-color: #d7005f;
1496 | }
1497 |
1498 | .terminal .xterm-color-162 {
1499 | color: #d70087;
1500 | }
1501 |
1502 | .terminal .xterm-bg-color-162 {
1503 | background-color: #d70087;
1504 | }
1505 |
1506 | .terminal .xterm-color-163 {
1507 | color: #d700af;
1508 | }
1509 |
1510 | .terminal .xterm-bg-color-163 {
1511 | background-color: #d700af;
1512 | }
1513 |
1514 | .terminal .xterm-color-164 {
1515 | color: #d700d7;
1516 | }
1517 |
1518 | .terminal .xterm-bg-color-164 {
1519 | background-color: #d700d7;
1520 | }
1521 |
1522 | .terminal .xterm-color-165 {
1523 | color: #d700ff;
1524 | }
1525 |
1526 | .terminal .xterm-bg-color-165 {
1527 | background-color: #d700ff;
1528 | }
1529 |
1530 | .terminal .xterm-color-166 {
1531 | color: #d75f00;
1532 | }
1533 |
1534 | .terminal .xterm-bg-color-166 {
1535 | background-color: #d75f00;
1536 | }
1537 |
1538 | .terminal .xterm-color-167 {
1539 | color: #d75f5f;
1540 | }
1541 |
1542 | .terminal .xterm-bg-color-167 {
1543 | background-color: #d75f5f;
1544 | }
1545 |
1546 | .terminal .xterm-color-168 {
1547 | color: #d75f87;
1548 | }
1549 |
1550 | .terminal .xterm-bg-color-168 {
1551 | background-color: #d75f87;
1552 | }
1553 |
1554 | .terminal .xterm-color-169 {
1555 | color: #d75faf;
1556 | }
1557 |
1558 | .terminal .xterm-bg-color-169 {
1559 | background-color: #d75faf;
1560 | }
1561 |
1562 | .terminal .xterm-color-170 {
1563 | color: #d75fd7;
1564 | }
1565 |
1566 | .terminal .xterm-bg-color-170 {
1567 | background-color: #d75fd7;
1568 | }
1569 |
1570 | .terminal .xterm-color-171 {
1571 | color: #d75fff;
1572 | }
1573 |
1574 | .terminal .xterm-bg-color-171 {
1575 | background-color: #d75fff;
1576 | }
1577 |
1578 | .terminal .xterm-color-172 {
1579 | color: #d78700;
1580 | }
1581 |
1582 | .terminal .xterm-bg-color-172 {
1583 | background-color: #d78700;
1584 | }
1585 |
1586 | .terminal .xterm-color-173 {
1587 | color: #d7875f;
1588 | }
1589 |
1590 | .terminal .xterm-bg-color-173 {
1591 | background-color: #d7875f;
1592 | }
1593 |
1594 | .terminal .xterm-color-174 {
1595 | color: #d78787;
1596 | }
1597 |
1598 | .terminal .xterm-bg-color-174 {
1599 | background-color: #d78787;
1600 | }
1601 |
1602 | .terminal .xterm-color-175 {
1603 | color: #d787af;
1604 | }
1605 |
1606 | .terminal .xterm-bg-color-175 {
1607 | background-color: #d787af;
1608 | }
1609 |
1610 | .terminal .xterm-color-176 {
1611 | color: #d787d7;
1612 | }
1613 |
1614 | .terminal .xterm-bg-color-176 {
1615 | background-color: #d787d7;
1616 | }
1617 |
1618 | .terminal .xterm-color-177 {
1619 | color: #d787ff;
1620 | }
1621 |
1622 | .terminal .xterm-bg-color-177 {
1623 | background-color: #d787ff;
1624 | }
1625 |
1626 | .terminal .xterm-color-178 {
1627 | color: #d7af00;
1628 | }
1629 |
1630 | .terminal .xterm-bg-color-178 {
1631 | background-color: #d7af00;
1632 | }
1633 |
1634 | .terminal .xterm-color-179 {
1635 | color: #d7af5f;
1636 | }
1637 |
1638 | .terminal .xterm-bg-color-179 {
1639 | background-color: #d7af5f;
1640 | }
1641 |
1642 | .terminal .xterm-color-180 {
1643 | color: #d7af87;
1644 | }
1645 |
1646 | .terminal .xterm-bg-color-180 {
1647 | background-color: #d7af87;
1648 | }
1649 |
1650 | .terminal .xterm-color-181 {
1651 | color: #d7afaf;
1652 | }
1653 |
1654 | .terminal .xterm-bg-color-181 {
1655 | background-color: #d7afaf;
1656 | }
1657 |
1658 | .terminal .xterm-color-182 {
1659 | color: #d7afd7;
1660 | }
1661 |
1662 | .terminal .xterm-bg-color-182 {
1663 | background-color: #d7afd7;
1664 | }
1665 |
1666 | .terminal .xterm-color-183 {
1667 | color: #d7afff;
1668 | }
1669 |
1670 | .terminal .xterm-bg-color-183 {
1671 | background-color: #d7afff;
1672 | }
1673 |
1674 | .terminal .xterm-color-184 {
1675 | color: #d7d700;
1676 | }
1677 |
1678 | .terminal .xterm-bg-color-184 {
1679 | background-color: #d7d700;
1680 | }
1681 |
1682 | .terminal .xterm-color-185 {
1683 | color: #d7d75f;
1684 | }
1685 |
1686 | .terminal .xterm-bg-color-185 {
1687 | background-color: #d7d75f;
1688 | }
1689 |
1690 | .terminal .xterm-color-186 {
1691 | color: #d7d787;
1692 | }
1693 |
1694 | .terminal .xterm-bg-color-186 {
1695 | background-color: #d7d787;
1696 | }
1697 |
1698 | .terminal .xterm-color-187 {
1699 | color: #d7d7af;
1700 | }
1701 |
1702 | .terminal .xterm-bg-color-187 {
1703 | background-color: #d7d7af;
1704 | }
1705 |
1706 | .terminal .xterm-color-188 {
1707 | color: #d7d7d7;
1708 | }
1709 |
1710 | .terminal .xterm-bg-color-188 {
1711 | background-color: #d7d7d7;
1712 | }
1713 |
1714 | .terminal .xterm-color-189 {
1715 | color: #d7d7ff;
1716 | }
1717 |
1718 | .terminal .xterm-bg-color-189 {
1719 | background-color: #d7d7ff;
1720 | }
1721 |
1722 | .terminal .xterm-color-190 {
1723 | color: #d7ff00;
1724 | }
1725 |
1726 | .terminal .xterm-bg-color-190 {
1727 | background-color: #d7ff00;
1728 | }
1729 |
1730 | .terminal .xterm-color-191 {
1731 | color: #d7ff5f;
1732 | }
1733 |
1734 | .terminal .xterm-bg-color-191 {
1735 | background-color: #d7ff5f;
1736 | }
1737 |
1738 | .terminal .xterm-color-192 {
1739 | color: #d7ff87;
1740 | }
1741 |
1742 | .terminal .xterm-bg-color-192 {
1743 | background-color: #d7ff87;
1744 | }
1745 |
1746 | .terminal .xterm-color-193 {
1747 | color: #d7ffaf;
1748 | }
1749 |
1750 | .terminal .xterm-bg-color-193 {
1751 | background-color: #d7ffaf;
1752 | }
1753 |
1754 | .terminal .xterm-color-194 {
1755 | color: #d7ffd7;
1756 | }
1757 |
1758 | .terminal .xterm-bg-color-194 {
1759 | background-color: #d7ffd7;
1760 | }
1761 |
1762 | .terminal .xterm-color-195 {
1763 | color: #d7ffff;
1764 | }
1765 |
1766 | .terminal .xterm-bg-color-195 {
1767 | background-color: #d7ffff;
1768 | }
1769 |
1770 | .terminal .xterm-color-196 {
1771 | color: #ff0000;
1772 | }
1773 |
1774 | .terminal .xterm-bg-color-196 {
1775 | background-color: #ff0000;
1776 | }
1777 |
1778 | .terminal .xterm-color-197 {
1779 | color: #ff005f;
1780 | }
1781 |
1782 | .terminal .xterm-bg-color-197 {
1783 | background-color: #ff005f;
1784 | }
1785 |
1786 | .terminal .xterm-color-198 {
1787 | color: #ff0087;
1788 | }
1789 |
1790 | .terminal .xterm-bg-color-198 {
1791 | background-color: #ff0087;
1792 | }
1793 |
1794 | .terminal .xterm-color-199 {
1795 | color: #ff00af;
1796 | }
1797 |
1798 | .terminal .xterm-bg-color-199 {
1799 | background-color: #ff00af;
1800 | }
1801 |
1802 | .terminal .xterm-color-200 {
1803 | color: #ff00d7;
1804 | }
1805 |
1806 | .terminal .xterm-bg-color-200 {
1807 | background-color: #ff00d7;
1808 | }
1809 |
1810 | .terminal .xterm-color-201 {
1811 | color: #ff00ff;
1812 | }
1813 |
1814 | .terminal .xterm-bg-color-201 {
1815 | background-color: #ff00ff;
1816 | }
1817 |
1818 | .terminal .xterm-color-202 {
1819 | color: #ff5f00;
1820 | }
1821 |
1822 | .terminal .xterm-bg-color-202 {
1823 | background-color: #ff5f00;
1824 | }
1825 |
1826 | .terminal .xterm-color-203 {
1827 | color: #ff5f5f;
1828 | }
1829 |
1830 | .terminal .xterm-bg-color-203 {
1831 | background-color: #ff5f5f;
1832 | }
1833 |
1834 | .terminal .xterm-color-204 {
1835 | color: #ff5f87;
1836 | }
1837 |
1838 | .terminal .xterm-bg-color-204 {
1839 | background-color: #ff5f87;
1840 | }
1841 |
1842 | .terminal .xterm-color-205 {
1843 | color: #ff5faf;
1844 | }
1845 |
1846 | .terminal .xterm-bg-color-205 {
1847 | background-color: #ff5faf;
1848 | }
1849 |
1850 | .terminal .xterm-color-206 {
1851 | color: #ff5fd7;
1852 | }
1853 |
1854 | .terminal .xterm-bg-color-206 {
1855 | background-color: #ff5fd7;
1856 | }
1857 |
1858 | .terminal .xterm-color-207 {
1859 | color: #ff5fff;
1860 | }
1861 |
1862 | .terminal .xterm-bg-color-207 {
1863 | background-color: #ff5fff;
1864 | }
1865 |
1866 | .terminal .xterm-color-208 {
1867 | color: #ff8700;
1868 | }
1869 |
1870 | .terminal .xterm-bg-color-208 {
1871 | background-color: #ff8700;
1872 | }
1873 |
1874 | .terminal .xterm-color-209 {
1875 | color: #ff875f;
1876 | }
1877 |
1878 | .terminal .xterm-bg-color-209 {
1879 | background-color: #ff875f;
1880 | }
1881 |
1882 | .terminal .xterm-color-210 {
1883 | color: #ff8787;
1884 | }
1885 |
1886 | .terminal .xterm-bg-color-210 {
1887 | background-color: #ff8787;
1888 | }
1889 |
1890 | .terminal .xterm-color-211 {
1891 | color: #ff87af;
1892 | }
1893 |
1894 | .terminal .xterm-bg-color-211 {
1895 | background-color: #ff87af;
1896 | }
1897 |
1898 | .terminal .xterm-color-212 {
1899 | color: #ff87d7;
1900 | }
1901 |
1902 | .terminal .xterm-bg-color-212 {
1903 | background-color: #ff87d7;
1904 | }
1905 |
1906 | .terminal .xterm-color-213 {
1907 | color: #ff87ff;
1908 | }
1909 |
1910 | .terminal .xterm-bg-color-213 {
1911 | background-color: #ff87ff;
1912 | }
1913 |
1914 | .terminal .xterm-color-214 {
1915 | color: #ffaf00;
1916 | }
1917 |
1918 | .terminal .xterm-bg-color-214 {
1919 | background-color: #ffaf00;
1920 | }
1921 |
1922 | .terminal .xterm-color-215 {
1923 | color: #ffaf5f;
1924 | }
1925 |
1926 | .terminal .xterm-bg-color-215 {
1927 | background-color: #ffaf5f;
1928 | }
1929 |
1930 | .terminal .xterm-color-216 {
1931 | color: #ffaf87;
1932 | }
1933 |
1934 | .terminal .xterm-bg-color-216 {
1935 | background-color: #ffaf87;
1936 | }
1937 |
1938 | .terminal .xterm-color-217 {
1939 | color: #ffafaf;
1940 | }
1941 |
1942 | .terminal .xterm-bg-color-217 {
1943 | background-color: #ffafaf;
1944 | }
1945 |
1946 | .terminal .xterm-color-218 {
1947 | color: #ffafd7;
1948 | }
1949 |
1950 | .terminal .xterm-bg-color-218 {
1951 | background-color: #ffafd7;
1952 | }
1953 |
1954 | .terminal .xterm-color-219 {
1955 | color: #ffafff;
1956 | }
1957 |
1958 | .terminal .xterm-bg-color-219 {
1959 | background-color: #ffafff;
1960 | }
1961 |
1962 | .terminal .xterm-color-220 {
1963 | color: #ffd700;
1964 | }
1965 |
1966 | .terminal .xterm-bg-color-220 {
1967 | background-color: #ffd700;
1968 | }
1969 |
1970 | .terminal .xterm-color-221 {
1971 | color: #ffd75f;
1972 | }
1973 |
1974 | .terminal .xterm-bg-color-221 {
1975 | background-color: #ffd75f;
1976 | }
1977 |
1978 | .terminal .xterm-color-222 {
1979 | color: #ffd787;
1980 | }
1981 |
1982 | .terminal .xterm-bg-color-222 {
1983 | background-color: #ffd787;
1984 | }
1985 |
1986 | .terminal .xterm-color-223 {
1987 | color: #ffd7af;
1988 | }
1989 |
1990 | .terminal .xterm-bg-color-223 {
1991 | background-color: #ffd7af;
1992 | }
1993 |
1994 | .terminal .xterm-color-224 {
1995 | color: #ffd7d7;
1996 | }
1997 |
1998 | .terminal .xterm-bg-color-224 {
1999 | background-color: #ffd7d7;
2000 | }
2001 |
2002 | .terminal .xterm-color-225 {
2003 | color: #ffd7ff;
2004 | }
2005 |
2006 | .terminal .xterm-bg-color-225 {
2007 | background-color: #ffd7ff;
2008 | }
2009 |
2010 | .terminal .xterm-color-226 {
2011 | color: #ffff00;
2012 | }
2013 |
2014 | .terminal .xterm-bg-color-226 {
2015 | background-color: #ffff00;
2016 | }
2017 |
2018 | .terminal .xterm-color-227 {
2019 | color: #ffff5f;
2020 | }
2021 |
2022 | .terminal .xterm-bg-color-227 {
2023 | background-color: #ffff5f;
2024 | }
2025 |
2026 | .terminal .xterm-color-228 {
2027 | color: #ffff87;
2028 | }
2029 |
2030 | .terminal .xterm-bg-color-228 {
2031 | background-color: #ffff87;
2032 | }
2033 |
2034 | .terminal .xterm-color-229 {
2035 | color: #ffffaf;
2036 | }
2037 |
2038 | .terminal .xterm-bg-color-229 {
2039 | background-color: #ffffaf;
2040 | }
2041 |
2042 | .terminal .xterm-color-230 {
2043 | color: #ffffd7;
2044 | }
2045 |
2046 | .terminal .xterm-bg-color-230 {
2047 | background-color: #ffffd7;
2048 | }
2049 |
2050 | .terminal .xterm-color-231 {
2051 | color: #ffffff;
2052 | }
2053 |
2054 | .terminal .xterm-bg-color-231 {
2055 | background-color: #ffffff;
2056 | }
2057 |
2058 | .terminal .xterm-color-232 {
2059 | color: #080808;
2060 | }
2061 |
2062 | .terminal .xterm-bg-color-232 {
2063 | background-color: #080808;
2064 | }
2065 |
2066 | .terminal .xterm-color-233 {
2067 | color: #121212;
2068 | }
2069 |
2070 | .terminal .xterm-bg-color-233 {
2071 | background-color: #121212;
2072 | }
2073 |
2074 | .terminal .xterm-color-234 {
2075 | color: #1c1c1c;
2076 | }
2077 |
2078 | .terminal .xterm-bg-color-234 {
2079 | background-color: #1c1c1c;
2080 | }
2081 |
2082 | .terminal .xterm-color-235 {
2083 | color: #262626;
2084 | }
2085 |
2086 | .terminal .xterm-bg-color-235 {
2087 | background-color: #262626;
2088 | }
2089 |
2090 | .terminal .xterm-color-236 {
2091 | color: #303030;
2092 | }
2093 |
2094 | .terminal .xterm-bg-color-236 {
2095 | background-color: #303030;
2096 | }
2097 |
2098 | .terminal .xterm-color-237 {
2099 | color: #3a3a3a;
2100 | }
2101 |
2102 | .terminal .xterm-bg-color-237 {
2103 | background-color: #3a3a3a;
2104 | }
2105 |
2106 | .terminal .xterm-color-238 {
2107 | color: #444444;
2108 | }
2109 |
2110 | .terminal .xterm-bg-color-238 {
2111 | background-color: #444444;
2112 | }
2113 |
2114 | .terminal .xterm-color-239 {
2115 | color: #4e4e4e;
2116 | }
2117 |
2118 | .terminal .xterm-bg-color-239 {
2119 | background-color: #4e4e4e;
2120 | }
2121 |
2122 | .terminal .xterm-color-240 {
2123 | color: #585858;
2124 | }
2125 |
2126 | .terminal .xterm-bg-color-240 {
2127 | background-color: #585858;
2128 | }
2129 |
2130 | .terminal .xterm-color-241 {
2131 | color: #626262;
2132 | }
2133 |
2134 | .terminal .xterm-bg-color-241 {
2135 | background-color: #626262;
2136 | }
2137 |
2138 | .terminal .xterm-color-242 {
2139 | color: #6c6c6c;
2140 | }
2141 |
2142 | .terminal .xterm-bg-color-242 {
2143 | background-color: #6c6c6c;
2144 | }
2145 |
2146 | .terminal .xterm-color-243 {
2147 | color: #767676;
2148 | }
2149 |
2150 | .terminal .xterm-bg-color-243 {
2151 | background-color: #767676;
2152 | }
2153 |
2154 | .terminal .xterm-color-244 {
2155 | color: #808080;
2156 | }
2157 |
2158 | .terminal .xterm-bg-color-244 {
2159 | background-color: #808080;
2160 | }
2161 |
2162 | .terminal .xterm-color-245 {
2163 | color: #8a8a8a;
2164 | }
2165 |
2166 | .terminal .xterm-bg-color-245 {
2167 | background-color: #8a8a8a;
2168 | }
2169 |
2170 | .terminal .xterm-color-246 {
2171 | color: #949494;
2172 | }
2173 |
2174 | .terminal .xterm-bg-color-246 {
2175 | background-color: #949494;
2176 | }
2177 |
2178 | .terminal .xterm-color-247 {
2179 | color: #9e9e9e;
2180 | }
2181 |
2182 | .terminal .xterm-bg-color-247 {
2183 | background-color: #9e9e9e;
2184 | }
2185 |
2186 | .terminal .xterm-color-248 {
2187 | color: #a8a8a8;
2188 | }
2189 |
2190 | .terminal .xterm-bg-color-248 {
2191 | background-color: #a8a8a8;
2192 | }
2193 |
2194 | .terminal .xterm-color-249 {
2195 | color: #b2b2b2;
2196 | }
2197 |
2198 | .terminal .xterm-bg-color-249 {
2199 | background-color: #b2b2b2;
2200 | }
2201 |
2202 | .terminal .xterm-color-250 {
2203 | color: #bcbcbc;
2204 | }
2205 |
2206 | .terminal .xterm-bg-color-250 {
2207 | background-color: #bcbcbc;
2208 | }
2209 |
2210 | .terminal .xterm-color-251 {
2211 | color: #c6c6c6;
2212 | }
2213 |
2214 | .terminal .xterm-bg-color-251 {
2215 | background-color: #c6c6c6;
2216 | }
2217 |
2218 | .terminal .xterm-color-252 {
2219 | color: #d0d0d0;
2220 | }
2221 |
2222 | .terminal .xterm-bg-color-252 {
2223 | background-color: #d0d0d0;
2224 | }
2225 |
2226 | .terminal .xterm-color-253 {
2227 | color: #dadada;
2228 | }
2229 |
2230 | .terminal .xterm-bg-color-253 {
2231 | background-color: #dadada;
2232 | }
2233 |
2234 | .terminal .xterm-color-254 {
2235 | color: #e4e4e4;
2236 | }
2237 |
2238 | .terminal .xterm-bg-color-254 {
2239 | background-color: #e4e4e4;
2240 | }
2241 |
2242 | .terminal .xterm-color-255 {
2243 | color: #eeeeee;
2244 | }
2245 |
2246 | .terminal .xterm-bg-color-255 {
2247 | background-color: #eeeeee;
2248 | }
2249 |
--------------------------------------------------------------------------------