diff options
author | Daniel Baumann <daniel.baumann@open-infrastructure.net> | 2023-02-13 19:43:51 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@open-infrastructure.net> | 2023-02-13 19:43:51 +0000 |
commit | f73f2356820468344757dbb9d7f3ec73ece7bf66 (patch) | |
tree | cc4d1f8559ab8d0e73f4efed80c1f5c866501a12 | |
parent | Reworking container version command in python. (diff) | |
download | compute-tools-next+web.tar.xz compute-tools-next+web.zip |
Updating.next+web
Signed-off-by: Daniel Baumann <daniel.baumann@open-infrastructure.net>
2144 files changed, 324453 insertions, 0 deletions
diff --git a/web/Makefile b/web/Makefile new file mode 100644 index 0000000..090f923 --- /dev/null +++ b/web/Makefile @@ -0,0 +1,4 @@ +all: + a2disconf csp + a2disconf no-frames + a2enmod cgi diff --git a/web/TMP/tools.html b/web/TMP/tools.html new file mode 100644 index 0000000..6b8d23a --- /dev/null +++ b/web/TMP/tools.html @@ -0,0 +1,273 @@ +<!doctype html> +<html lang="en"> + <head> + <meta charset="utf-8"> + <meta name="viewport" content="width=device-width, initial-scale=1"> + <meta name="author" content="system-administration@open-infrastructure.net"> + <meta name="description" content="Open Infrastructure"> + <meta name="generator" content="open-infrastructure.net"> + <title>{hostname}</title> + + <link rel="canonical" href="https://open-infrastructure.net"> + <link rel="icon" href="/favicon.svg" type="image/svg+xml"> + + <!-- Bootstrap core CSS --> + <link href="/_static/bootstrap/css/bootstrap.min.css" rel="stylesheet"> + + <!-- Custom styles for this template --> + <link href="/_static/bootstrap-icons/bootstrap-icons.css" rel="stylesheet"> + <link href="/_static/dejavu-fonts/dejavu-fonts.css" rel="stylesheet"> + + <link href="/_static/local/font.css" rel="stylesheet"> + <link href="/_static/local/icon.css" rel="stylesheet"> + </head> + + <body> + <nav class="navbar navbar-expand-md navbar-dark fixed-top" style="background: #a40000"> + <div class="container-fluid"> + <a class="navbar-brand" href="/"><b>{hostname}</b></a> + <button class="navbar-toggler" type="button" data-bs-toggle="collapse" data-bs-target="#navbarCollapse" aria-controls="navbarCollapse" aria-expanded="false" aria-label="Toggle navigation"> + <span class="navbar-toggler-icon"></span> + </button> + <div style="width: 4em"></div> + <div class="collapse navbar-collapse" id="navbarCollapse"> + <ul class="navbar-nav me-auto mb-2 mb-md-0"> + <li class="nav-item"> + <a class="nav-link active" aria-current="page" href="/systems">Systems</a> + </li> + <li><div style="width: 1em"></div></li> + <li class="nav-item"> + <a class="nav-link active" aria-current="page" href="/tools">Tools</a> + </li> + <li><div style="width: 1em"></div></li> + <li class="nav-item"> + <a class="nav-link active" aria-current="page" href="/ttyd">ttyd</a> + </li> + <li><div style="width: 1em"></div></li> + <li class="nav-item"> + <a class="nav-link active" aria-current="page" href="/netdata">netdata</a> + </li> + </ul> + </div> + </div> + </nav> + + <div class="container"> + <main> + <!-- Begin content --> + + <main role="main" class="container"> + + <div class="content"> + +<a name="top"></a> +<h1><i class="fa-fw far fa-tools"></i> Tools <small>(<a href="/tools/api">API</a>)</small></h1> +<div style="height: 2em"></div> + +<script src="/_static/jquery/jquery.min.js"></script> + +<script> + $(document).ready(function(){ + $("[type=button]").click(function() { + var command = $(this).data("command"); + var protocol = $("input[name='protocol']:checked").val(); + var target = document.getElementById("target").value; + var cgi = command + "&protocol=" + protocol + "&target=" + target; + $.ajax({url: cgi, success: function(result){ + $("#output").text(result); + document.getElementById('output-hidden').style.display = 'block'; + $(document).scrollTop( $("#output").offset().top -125); + }}); + }); + + $("[type=reset]").click(function() { + $("#dual-stack").click(); + $('.btn-group').find('reset').removeClass('active') + .end().find('[type="reset"]').prop('checked', false); + document.getElementById('output-hidden').style.display = 'none'; + $("#target").focus(); + $("#target").prop('autofocus'); + }); + }); +</script> + +<style type="text/css"> + label, [type="button"], [type="reset"], [type="text"] { + margin-top: 0.5em; + } +</style> + +<form id="form"> + <div class="form-group"> + <div class="row"> + <div class="col-md-6"> + <b>Target</b> + <input id="target" placeholder="IP address/subnet, FQDN, ASN, Internet resources..." style="width: 100%;" type="text" autofocus /> + + <div style="height: 1em"></div> + </div> + + <div class="col-md-6"> + <b>Settings</b><br /> + <input class="btn btn-light btn-sm" type="reset" value="Reset" /> + + <div class="btn-group btn-group-toggle" data-toggle="buttons"> + <label class="btn btn-light btn-sm active"> + <input type="radio" name="protocol" id="dual-stack" value="dual-stack" checked> Dual-stack + </label> + <label class="btn btn-light btn-sm"> + <input type="radio" name="protocol" id="ipv4-only" value="ipv4-only"> IPv4-only + </label> + <label class="btn btn-light btn-sm"> + <input type="radio" name="protocol" id="ipv6-only" value="ipv6-only"> IPv6-only + </label> + </div> + + <div style="height: 1em"></div> + </div> + </div> + </div> +</form> + +<hr /> + +<div class="row"> + <div class="col-md-6"> + <b>Network</b><br /> + <button type="button" class="btn btn-success" data-command="/tools.py?command=ping">ping</button> + <button type="button" class="btn btn-success" data-command="/tools.py?command=traceroute">traceroute</button> + <button type="button" class="btn btn-success" data-command="/tools.py?command=tcptraceroute">tcptraceroute</button> + <button type="button" class="btn btn-success" data-command="/tools.py?command=whois">whois</button> + + <div style="height: 1em"></div> + + <b>Security</b><br /> + <button type="button" class="btn btn-warning" data-command="/tools.py?command=nmap">nmap</button> + <button type="button" class="btn btn-warning" data-command="/tools.py?command=ssh-audit">ssh-audit</button> + <button type="button" class="btn btn-warning" data-command="/tools.py?command=testssl">testssl</button> + + <div style="height: 1em"></div> + + <b>other</b><br /> + <button type="button" class="btn btn-info" data-command="/tools.py?command=my-ip&target=none">My IP</button> + <button type="button" class="btn btn-info" data-command="/tools.py?command=my-browser&target=none">My browser</button> + + <div style="height: 1em"></div> + </div> + + <div class="col-md-6"> + <b>DNS</b><br /> + <small><b>Address-related records</b></small><br /> + <button type="button" class="btn btn-primary" data-command="/tools.py?command=kdig&query=ANY">ANY</button> + <button type="button" class="btn btn-primary" data-command="/tools.py?command=kdig&query=A">A</button> + <button type="button" class="btn btn-primary" data-command="/tools.py?command=kdig&query=AAAA">AAAA</button> + <button type="button" class="btn btn-primary" data-command="/tools.py?command=kdig&query=CNAME">CNAME</button> + <button type="button" class="btn btn-primary" data-command="/tools.py?command=kdig&query=DNAME">DNAME</button> + <button type="button" class="btn btn-primary" data-command="/tools.py?command=kdig&query=PTR">PTR</button> + + <div style="height: 1em"></div> + + <small><b>Informational records</b></small><br /> + <button type="button" class="btn btn-info" data-command="/tools.py?command=kdig&query=APL">APL</button> + <button type="button" class="btn btn-info" data-command="/tools.py?command=kdig&query=HINFO">HINFO</button> + <button type="button" class="btn btn-info" data-command="/tools.py?command=kdig&query=LOC">LOC</button> + <button type="button" class="btn btn-info" data-command="/tools.py?command=kdig&query=RP">RP</button> + <button type="button" class="btn btn-info" data-command="/tools.py?command=kdig&query=SOA">SOA</button> + <button type="button" class="btn btn-info" data-command="/tools.py?command=kdig&query=SRV">SRV</button> + <button type="button" class="btn btn-info" data-command="/tools.py?command=kdig&query=TXT">TXT</button> + + <div style="height: 1em"></div> + + <small><b>DNSSEC records</b></small><br /> + <button type="button" class="btn btn-secondary" data-command="/tools.py?command=kdig&query=CDNSKEY">CDNSKEY</button> + <button type="button" class="btn btn-secondary" data-command="/tools.py?command=kdig&query=CDS">CDS</button> + <button type="button" class="btn btn-secondary" data-command="/tools.py?command=kdig&query=DNSKEY">DNSKEY</button> + <button type="button" class="btn btn-secondary" data-command="/tools.py?command=kdig&query=DS">DS</button> + <button type="button" class="btn btn-secondary" data-command="/tools.py?command=kdig&query=RRSIG">RRSIG</button> + + <div style="height: 1em"></div> + + <small><b>Security-related records</b></small><br /> + <button type="button" class="btn btn-warning" data-command="/tools.py?command=kdig&query=CAA">CAA</button> + <button type="button" class="btn btn-warning" data-command="/tools.py?command=kdig&query=NSEC3">NSEC3</button> + <button type="button" class="btn btn-warning" data-command="/tools.py?command=kdig&query=NSEC3PARAM">NSEC3PARAM</button> + <button type="button" class="btn btn-warning" data-command="/tools.py?command=kdig&query=SSHFP">SSHFP</button> + <button type="button" class="btn btn-warning" data-command="/tools.py?command=kdig&query=TLSA">TLSA</button> + + <div style="height: 1em"></div> + + <small><b>other records and types</b></small><br /> + <button type="button" class="btn btn-success" data-command="/tools.py?command=kdig&query=AXFR">AXFR*</button> + <button type="button" class="btn btn-success" data-command="/tools.py?command=kdig&query=MX">MX</button> + <button type="button" class="btn btn-success" data-command="/tools.py?command=kdig&query=NS">NS</button> + + <div style="height: 1em"></div> + + <small><b>Legacy records</b></small><br /> + <button type="button" class="btn btn-danger" data-command="/tools.py?command=kdig&query=NSEC">NSEC</button> + <button type="button" class="btn btn-danger" data-command="/tools.py?command=kdig&query=SPF">SPF</button> + + <div style="height: 1em"></div> + </div> +</div> + +<div class="row"> + <div class="col-md-6"> + <small><b>Notes:</b> + <ul> + <li>testssl can take up to 5min (with currently no output until the end)</li> + </ul></small> + + <div style="height: 1em"></div> + </div> + + <div class="col-md-6"> + <small><b>*</b> only available for BFH authoritative zones</small> + + <div style="height: 1em"></div> + </div> +</div> + +<hr /> + +<div id="output-hidden" style="display: none;"> +<a name="output"></a> +<a href="#top"><button type="button" class="btn btn-light btn-sm float-right">↑</button></a><br /> +<b>Output</b><br /> +<pre> +<textarea id="output" readonly rows="25" style="background: #f1f1f1; width: 100%;"></textarea> +</pre> +</div> + +<div style="height: 1em"></div> + + + </div> + + </main><!-- /.container --> + + + + + <!-- End content --> + </main> + + <div style="height: 4em"></div> + + <footer class="d-flex flex-wrap justify-content-between align-items-center py-3 my-4 border-top"> + <p class="col-md-4 mb-0 text-muted">© 2022</p> + + <ul class="nav col-md-4 justify-content-end"> + <li class="nav-item"><a href="https://open-infrastructure.net/contact" class="nav-link px-2 text-muted">Contact</a></li> + <li class="nav-item"><a href="https://open-infrastructure.net/legal" class="nav-link px-2 text-muted">Legal</a></li> + </ul> + </footer> + </div> + + <!-- Bootstrap core JS --> + <script src="/_static/popperjs/popper.min.js"></script> + <script src="/_static/bootstrap/js/bootstrap.min.js"></script> + + <!-- Custom scripts for this template --> + </body> +</html> diff --git a/web/TMP/tools.py b/web/TMP/tools.py new file mode 100755 index 0000000..c8dab03 --- /dev/null +++ b/web/TMP/tools.py @@ -0,0 +1,269 @@ +#!/usr/bin/python3 + +# Copyright (C) 2013-2021 Daniel Baumann <daniel@debian.org> +# +# SPDX-License-Identifier: GPL-3.0+ +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +# Dependencies: +# sudo apt install iputils-ping traceroute whois nmap ssh-audit testssl.sh geoip-bin geoip-database knot-dnsutils +# sudo apt install python3-pygments + +from cgi import FieldStorage +from datetime import datetime +import ipaddress +from os import getenv +from subprocess import Popen, PIPE +from sys import exit + +def filter_nameservers(servers, protocol): + nameservers= [] + + for server in servers: + name = server.rstrip().rstrip('.') + + if protocol == 'ipv6-only': + command = 'kdig -6' + options = ' -t AAAA +short -q ' + elif protocol == 'ipv4-only': + command = 'kdig -4' + options = ' -t A +short -q ' + else: + command = 'kdig' + options = ' +short -q ' + + command_line = (command + options + name).split() + kdig = Popen(command_line, stdout=PIPE) + address = kdig.stdout.readline() + + if address: + nameservers.append(name) + + return nameservers + +def get_nameserver(name, protocol): + nameservers = [] + + if protocol == 'ipv6-only': + command = 'kdig -6' + elif protocol == 'ipv4-only': + command = 'kdig -4' + else: + command = 'kdig' + + options = ' -t NS +short -q ' + + command_line = (command + options + name).split() + kdig = Popen(command_line, stdout=PIPE) + servers = kdig.stdout.readlines() + + count = 0 + while not servers and count < 10: + name = name.split('.') + del name[0] + name = '.'.join(name) + + command_line = (command + options + name).split() + kdig = Popen(command_line, stdout=PIPE) + servers = kdig.stdout.readlines() + + count += 1 + + names = [] + for server in servers: + name = server.rstrip().decode('utf-8').rstrip('.') + names.append(name) + + nameservers = filter_nameservers(names, protocol) + return nameservers + +def run_command(command): + process = Popen(command, stdout=PIPE) + empty_lines = 0 + while True: + line = process.stdout.readline().rstrip() + if not line: + empty_lines = empty_lines + 1 + if empty_lines > 2: + break + else: + print() + else: + empty_lines = 0 + yield line.decode('utf-8') + +def main(): + form = FieldStorage() + + if form.getvalue("command"): + Command = form.getvalue("command").split()[0] + + if "target" in form: + Target = form.getvalue("target").split()[0] + + if "protocol" in form: + Protocol = form.getvalue("protocol").split()[0] + + if "query" in form: + Query = form.getvalue("query").split()[0] + + if Command and Protocol and Target: + print('Content-Type: text/html\n') + + Date = datetime.now().strftime("%Y-%m-%d %H:%M:%S") + + if Command == 'kdig': + if Protocol == 'ipv6-only': + options = ' -6' + elif Protocol == 'ipv4-only': + options = ' -4' + else: + options = '' + + if Query == 'PTR': + arpa = ipaddress.ip_address(Target).reverse_pointer + + nameserver = get_nameserver(arpa, Protocol) + + protocol_passed = False + + for server in nameserver: + check_options = options + ' @' + server + ' -t ' + Query + ' -q ' + + command_line = (Command + ' +short' + check_options + arpa).split() + kdig = Popen(command_line, stdout=PIPE) + protocol_check = kdig.stdout.readline() + + if protocol_check: + protocol_passed = True + break + + if not protocol_passed: + print('IPv6-only query but no IPv6 enabled nameserver available for ' + Target + '\n\n') + print('--') + print('Run: ' + str(command_line)) + print('Date: ' + Date) + + exit(0) + + options = options + ' @' + server + ' -x ' + else: + nameserver = get_nameserver(Target, Protocol) + + protocol_passed = False + + for server in nameserver: + check_options = options + ' @' + server + ' -t ' + Query + ' -q ' + + command_line = (Command + ' +short' + check_options + Target).split() + kdig = Popen(command_line, stdout=PIPE) + protocol_check = kdig.stdout.readline() + + if protocol_check: + protocol_passed = True + break + + if not protocol_passed: + print('IPv6-only query but no IPv6 enabled nameserver available for ' + Target + '\n\n') + print('--') + print('Run: ' + str(command_line)) + print('Date: ' + Date) + + exit(0) + + options = options + ' @' + server + ' -t ' + Query + ' -q ' + elif Command == 'ping': + if Protocol == 'ipv6-only': + options = ' -6' + elif Protocol == 'ipv4-only': + options = ' -4' + else: + options = '' + options = options + ' -c3 ' + elif Command == 'traceroute': + if Protocol == 'ipv6-only': + options = ' -6' + elif Protocol == 'ipv4-only': + options = ' -4' + else: + options = '' + options = options + ' ' + elif Command == 'tcptraceroute': + Command = 'traceroute' + if Protocol == 'ipv6-only': + options = ' -6' + elif Protocol == 'ipv4-only': + options = ' -4' + else: + options = '' + options = options + ' -T ' + elif Command == 'nmap': + if Protocol == 'ipv6-only': + options = ' -6' + else: + options = ' ' + #-O -T5 + elif Command == 'ssh-audit': + if Protocol == 'ipv6-only': + options = ' -6' + elif Protocol == 'ipv4-only': + options = ' -4' + else: + options = '' + options = options + ' --no-colors ' + elif Command == 'testssl': + options = ' --color 0 ' + elif Command == 'whois': + options = ' -H ' + else: + options = ' ' + + if Command == 'my-ip': + command_line = '' + + ip_address = getenv('REMOTE_ADDR') + print('IP address: ' + ip_address) + + # TODO: show reverse DNS + + if ':' in ip_address: + print('IP version: IPv6') + process = Popen(['geoiplookup6', ip_address], stdout=PIPE) + else: + print('IP version: IPv4') + process = Popen(['geoiplookup', ip_address], stdout=PIPE) + + geoiplookup = process.stdout.readline().rstrip() + country = geoiplookup.decode('utf-8').split(':')[1] + print('Country:' + country + '\n\n') + elif Command == 'my-browser': + command_line = '' + print('User-Agent: ' + getenv('HTTP_USER_AGENT', 'n/a') + '\n\n') + else: + command_line = Command + options + Target + + for path in run_command(command_line.split()): + print(path) + + print('--') + print('Date: ' + Date) + + if command_line: + print('Run: ' + command_line) + + exit(0) + +if __name__ == '__main__': + main() diff --git a/web/TMP/tools/api/index.html b/web/TMP/tools/api/index.html new file mode 100644 index 0000000..a5f22f2 --- /dev/null +++ b/web/TMP/tools/api/index.html @@ -0,0 +1,11 @@ +<html> + <h1>tools.bfh.info</h1> + + <h2>API</h2> + + <ul> + <li><a href="/tools/api/v0/ip/address">/tools/api/v0/ip/address</a></li> + <li><a href="/tools/api/v0/ipv4/address">/tools/api/v0/ipv4/address</a></li> + <li><a href="/tools/api/v0/ipv6/address">/tools/api/v0/ipv6/address</a></li> + </ul> +</html> diff --git a/web/TMP/tools/api/v0/dns/a/index.py b/web/TMP/tools/api/v0/dns/a/index.py new file mode 100755 index 0000000..88b1b03 --- /dev/null +++ b/web/TMP/tools/api/v0/dns/a/index.py @@ -0,0 +1,93 @@ +#!/usr/bin/python3 + +# Copyright (C) 2013-2021 Daniel Baumann <daniel@debian.org> +# +# SPDX-License-Identifier: GPL-3.0+ +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +from ipaddress import ip_address +from json import dumps +from os import getenv +from subprocess import Popen, PIPE +from sys import exit + +from pygments import highlight +from pygments.lexers import JsonLexer +from pygments.formatters import TerminalFormatter + +def run_command(command): + process = Popen(command, stdout=PIPE) + empty_lines = 0 + while True: + line = process.stdout.readline().rstrip() + if not line: + empty_lines = empty_lines + 1 + if empty_lines > 2: + break + else: + print() + else: + empty_lines = 0 + yield line.decode('utf-8') + +def v0_dns_a(): + a = 'google.com' + cgi = getenv('GATEWAY_INTERFACE') + + #command_line = 'kdig +json A ' + a + ' | jq -r -M \'.answer | .[] | .rdata\'' + command_line = 'kdig +json A ' + a + + kdig = Popen(command_line.split(), stdout=PIPE) + +# try: +# ip = str(ip_address(address)) +# if ip_address(address).version == 4: +# ip_version = 'ipv4' +# elif ip_address(address).version == 6: +# ip_version = 'ipv6' +# else: +# ip_version = None +# message = 'valid IP address' +# status = True +# except ValueError: +# ip = None +# ip_version = None +# message = 'invalid IP address' +# status = False + + status = True + message = 'valid DNS record' + + json = \ + { + 'data': { + 'record': a, + }, + 'meta': { + 'status': status, + 'message': message, + }, + } + + if cgi: + print('Content-Type: application/json\n') + print(dumps(json)) + else: + print(highlight(dumps(json, indent=4), JsonLexer(), TerminalFormatter())) + + exit(0) + +if __name__ == '__main__': + v0_dns_a() diff --git a/web/TMP/tools/api/v0/ip/address/index.py b/web/TMP/tools/api/v0/ip/address/index.py new file mode 100755 index 0000000..49e4971 --- /dev/null +++ b/web/TMP/tools/api/v0/ip/address/index.py @@ -0,0 +1,70 @@ +#!/usr/bin/python3 + +# Copyright (C) 2013-2021 Daniel Baumann <daniel@debian.org> +# +# SPDX-License-Identifier: GPL-3.0+ +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +from ipaddress import ip_address +from json import dumps +from os import getenv +from sys import exit + +from pygments import highlight +from pygments.lexers import JsonLexer +from pygments.formatters import TerminalFormatter + +def v0_ip_address(): + address = getenv('REMOTE_ADDR') + cgi = getenv('GATEWAY_INTERFACE') + + try: + ip = str(ip_address(address)) + if ip_address(address).version == 4: + ip_version = 'ipv4' + elif ip_address(address).version == 6: + ip_version = 'ipv6' + else: + ip_version = None + message = 'valid IP address' + status = True + except ValueError: + ip = None + ip_version = None + message = 'invalid IP address' + status = False + + json = \ + { + 'data': { + 'ip_address': ip, + 'ip_version': ip_version, + }, + 'meta': { + 'status': status, + 'message': message, + }, + } + + if cgi: + print('Content-Type: application/json\n') + print(dumps(json)) + else: + print(highlight(dumps(json, indent=4), JsonLexer(), TerminalFormatter())) + + exit(0) + +if __name__ == '__main__': + v0_ip_address() diff --git a/web/TMP/tools/api/v0/ipv4/address/index.py b/web/TMP/tools/api/v0/ipv4/address/index.py new file mode 100755 index 0000000..7a08c34 --- /dev/null +++ b/web/TMP/tools/api/v0/ipv4/address/index.py @@ -0,0 +1,62 @@ +#!/usr/bin/python3 + +# Copyright (C) 2013-2021 Daniel Baumann <daniel@debian.org> +# +# SPDX-License-Identifier: GPL-3.0+ +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +from ipaddress import IPv4Address +from json import dumps +from os import getenv +from sys import exit + +from pygments import highlight +from pygments.lexers import JsonLexer +from pygments.formatters import TerminalFormatter + +def v0_ipv4_address(): + address = getenv('REMOTE_ADDR') + cgi = getenv('GATEWAY_INTERFACE') + + try: + ip = str(IPv4Address(address)) + message = 'valid IPv4 address' + status = True + except ValueError: + ip = None + message = 'invalid IPv4 address' + status = False + + json = \ + { + 'data': { + 'ipv4_address': ip, + }, + 'meta': { + 'status': status, + 'message': message, + }, + } + + if cgi: + print('Content-Type: application/json\n') + print(dumps(json)) + else: + print(highlight(dumps(json, indent=4), JsonLexer(), TerminalFormatter())) + + exit(0) + +if __name__ == '__main__': + v0_ipv4_address() diff --git a/web/TMP/tools/api/v0/ipv6/address/index.py b/web/TMP/tools/api/v0/ipv6/address/index.py new file mode 100755 index 0000000..0746a83 --- /dev/null +++ b/web/TMP/tools/api/v0/ipv6/address/index.py @@ -0,0 +1,62 @@ +#!/usr/bin/python3 + +# Copyright (C) 2013-2021 Daniel Baumann <daniel@debian.org> +# +# SPDX-License-Identifier: GPL-3.0+ +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +from ipaddress import IPv6Address +from json import dumps +from os import getenv +from sys import exit + +from pygments import highlight +from pygments.lexers import JsonLexer +from pygments.formatters import TerminalFormatter + +def v0_ipv6_address(): + address = getenv('REMOTE_ADDR') + cgi = getenv('GATEWAY_INTERFACE') + + try: + ip = str(IPv6Address(address)) + message = 'valid IPv6 address' + status = True + except ValueError: + ip = None + message = 'invalid IPv6 address' + status = False + + json = \ + { + 'data': { + 'ipv6_address': ip, + }, + 'meta': { + 'status': status, + 'message': message, + }, + } + + if cgi: + print('Content-Type: application/json\n') + print(dumps(json)) + else: + print(highlight(dumps(json, indent=4), JsonLexer(), TerminalFormatter())) + + exit(0) + +if __name__ == '__main__': + v0_ipv6_address() diff --git a/web/TODO.txt b/web/TODO.txt new file mode 100644 index 0000000..99d5611 --- /dev/null +++ b/web/TODO.txt @@ -0,0 +1,10 @@ +* debug knopf um ttyd zu killen/restarten +* netdata: refresh every 5min +* add container-shell ttyd + + + +- put container-list output in a ajax refreshable area/box and refresh automatically every n minutes +- add manual refresh button +- add auto refresh toggle +- add 'drop-down' button to switch between 'cnt console' and 'cnt enter' diff --git a/web/_static/asciinema-player.v3.0.1 b/web/_static/asciinema-player.v3.0.1 new file mode 100644 index 0000000..b8d6937 --- /dev/null +++ b/web/_static/asciinema-player.v3.0.1 @@ -0,0 +1 @@ +https://github.com/asciinema/asciinema-player/releases diff --git a/web/_static/asciinema-player/asciinema-player.css b/web/_static/asciinema-player/asciinema-player.css new file mode 100644 index 0000000..6a8a3cc --- /dev/null +++ b/web/_static/asciinema-player/asciinema-player.css @@ -0,0 +1,2508 @@ +.asciinema-player-wrapper { + outline: none; + height: 100%; + display: flex; + justify-content: center; +} +.asciinema-player-wrapper .title-bar { + display: none; + top: -78px; + transition: top 0.15s linear; + position: absolute; + left: 0; + right: 0; + box-sizing: content-box; + font-size: 20px; + line-height: 1em; + padding: 15px; + font-family: sans-serif; + color: white; + background-color: rgba(0, 0, 0, 0.8); +} +.asciinema-player-wrapper .title-bar img { + vertical-align: middle; + height: 48px; + margin-right: 16px; +} +.asciinema-player-wrapper .title-bar a { + color: white; + text-decoration: underline; +} +.asciinema-player-wrapper .title-bar a:hover { + text-decoration: none; +} +.asciinema-player-wrapper:fullscreen { + background-color: #000; + width: 100%; + -webkit-align-items: center; + align-items: center; +} +.asciinema-player-wrapper:fullscreen .asciinema-player { + position: static; +} +.asciinema-player-wrapper:fullscreen .title-bar { + display: initial; +} +.asciinema-player-wrapper:fullscreen.hud .title-bar { + top: 0; +} +.asciinema-player-wrapper:-webkit-full-screen { + background-color: #000; + width: 100%; + -webkit-align-items: center; + align-items: center; +} +.asciinema-player-wrapper:-webkit-full-screen .asciinema-player { + position: static; +} +.asciinema-player-wrapper:-webkit-full-screen .title-bar { + display: initial; +} +.asciinema-player-wrapper:-webkit-full-screen.hud .title-bar { + top: 0; +} +.asciinema-player-wrapper:-moz-full-screen { + background-color: #000; + width: 100%; + -webkit-align-items: center; + align-items: center; +} +.asciinema-player-wrapper:-moz-full-screen .asciinema-player { + position: static; +} +.asciinema-player-wrapper:-moz-full-screen .title-bar { + display: initial; +} +.asciinema-player-wrapper:-moz-full-screen.hud .title-bar { + top: 0; +} +.asciinema-player-wrapper:-ms-fullscreen { + background-color: #000; + width: 100%; + -webkit-align-items: center; + align-items: center; +} +.asciinema-player-wrapper:-ms-fullscreen .asciinema-player { + position: static; +} +.asciinema-player-wrapper:-ms-fullscreen .title-bar { + display: initial; +} +.asciinema-player-wrapper:-ms-fullscreen.hud .title-bar { + top: 0; +} +.asciinema-player-wrapper .asciinema-player { + text-align: left; + display: inline-block; + padding: 0px; + position: relative; + box-sizing: content-box; + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; + overflow: hidden; + max-width: 100%; + border-radius: 4px; + font-size: 12px; +} +.asciinema-terminal { + box-sizing: content-box; + -moz-box-sizing: content-box; + -webkit-box-sizing: content-box; + overflow: hidden; + padding: 0; + margin: 0px; + display: block; + white-space: pre; + border: 0; + word-wrap: normal; + word-break: normal; + border-radius: 0; + border-style: solid; + cursor: text; + border-width: 0.75em; + font-family: Consolas, Menlo, 'Bitstream Vera Sans Mono', monospace, 'Powerline Symbols'; +} +.asciinema-terminal .line { + letter-spacing: normal; + overflow: hidden; +} +.asciinema-terminal .line span { + padding: 0; + display: inline-block; + height: 100%; +} +.asciinema-terminal .line { + display: block; + width: 200%; +} +.asciinema-terminal .line .cursor-a { + display: inline-block; +} +.asciinema-terminal .line .cursor-b { + display: none; + border-radius: 0.05em; +} +.asciinema-terminal .line .blink { + visibility: hidden; +} +.asciinema-terminal.cursor .line .cursor-a { + display: none; +} +.asciinema-terminal.cursor .line .cursor-b { + display: inline-block; +} +.asciinema-terminal.blink .line .blink { + visibility: visible; +} +.asciinema-terminal .bright { + font-weight: bold; +} +.asciinema-terminal .underline { + text-decoration: underline; +} +.asciinema-terminal .italic { + font-style: italic; +} +.asciinema-terminal .strikethrough { + text-decoration: line-through; +} +.asciinema-player .loading > .asciinema-terminal { + background-color: transparent; +} +.asciinema-player .control-bar { + width: 100%; + height: 32px; + background: rgba(0, 0, 0, 0.8); + /* no gradient fallback */ + background: -moz-linear-gradient(top, rgba(0, 0, 0, 0.5) 0%, #000000 25%, #000000 100%); + /* FF3.6-15 */ + background: -webkit-linear-gradient(top, rgba(0, 0, 0, 0.5) 0%, #000000 25%, #000000 100%); + /* Chrome10-25,Safari5.1-6 */ + background: linear-gradient(to bottom, rgba(0, 0, 0, 0.5) 0%, #000000 25%, #000000 100%); + /* W3C, IE10+, FF16+, Chrome26+, Opera12+, Safari7+ */ + color: #bbb; + box-sizing: content-box; + line-height: 1; + position: absolute; + bottom: -35px; + left: 0; + transition: bottom 0.15s linear; + -webkit-touch-callout: none; + -webkit-user-select: none; + -khtml-user-select: none; + -moz-user-select: none; + -ms-user-select: none; + user-select: none; + z-index: 30; +} +.asciinema-player .control-bar * { + box-sizing: inherit; + font-size: 0; +} +.asciinema-player .control-bar svg.icon path { + fill: #bbb; +} +.asciinema-player .control-bar .playback-button { + display: block; + float: left; + cursor: pointer; + height: 12px; + width: 12px; + padding: 10px; +} +.asciinema-player .control-bar .playback-button svg { + height: 12px; + width: 12px; +} +.asciinema-player .control-bar .timer { + display: block; + float: left; + width: 50px; + height: 100%; + text-align: center; + font-family: Helvetica, Arial, sans-serif; + font-size: 11px; + font-weight: bold; + line-height: 32px; + cursor: default; +} +.asciinema-player .control-bar .timer span { + display: inline-block; + font-size: inherit; +} +.asciinema-player .control-bar .timer .time-remaining { + display: none; +} +.asciinema-player .control-bar .timer:hover .time-elapsed { + display: none; +} +.asciinema-player .control-bar .timer:hover .time-remaining { + display: inline; +} +.asciinema-player .control-bar .progressbar { + display: block; + overflow: hidden; + height: 100%; + padding: 0 10px; +} +.asciinema-player .control-bar .progressbar .bar { + display: block; + cursor: default; + height: 100%; + padding-top: 15px; + font-size: 0; +} +.asciinema-player .control-bar .progressbar .bar .gutter { + display: block; + height: 3px; + background-color: #333; +} +.asciinema-player .control-bar .progressbar .bar .gutter span { + display: inline-block; + height: 100%; + background-color: #bbb; + border-radius: 3px; +} +.asciinema-player .control-bar.seekable .progressbar .bar { + cursor: pointer; +} +.asciinema-player .control-bar .fullscreen-button { + display: block; + float: right; + width: 14px; + height: 14px; + padding: 9px; + cursor: pointer; +} +.asciinema-player .control-bar .fullscreen-button svg { + width: 14px; + height: 14px; +} +.asciinema-player .control-bar .fullscreen-button svg:first-child { + display: inline; +} +.asciinema-player .control-bar .fullscreen-button svg:last-child { + display: none; +} +.asciinema-player-wrapper.hud .control-bar { + bottom: 0px; +} +.asciinema-player-wrapper:fullscreen .fullscreen-button svg:first-child { + display: none; +} +.asciinema-player-wrapper:fullscreen .fullscreen-button svg:last-child { + display: inline; +} +.asciinema-player-wrapper:-webkit-full-screen .fullscreen-button svg:first-child { + display: none; +} +.asciinema-player-wrapper:-webkit-full-screen .fullscreen-button svg:last-child { + display: inline; +} +.asciinema-player-wrapper:-moz-full-screen .fullscreen-button svg:first-child { + display: none; +} +.asciinema-player-wrapper:-moz-full-screen .fullscreen-button svg:last-child { + display: inline; +} +.asciinema-player-wrapper:-ms-fullscreen .fullscreen-button svg:first-child { + display: none; +} +.asciinema-player-wrapper:-ms-fullscreen .fullscreen-button svg:last-child { + display: inline; +} +.asciinema-player .loading { + z-index: 10; + background-repeat: no-repeat; + background-position: center; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + display: flex; + justify-content: center; + align-items: center; +} +.asciinema-player .start-prompt { + z-index: 10; + background-repeat: no-repeat; + background-position: center; + position: absolute; + top: 0; + left: 0; + right: 0; + bottom: 0; + z-index: 20; + cursor: pointer; +} +.asciinema-player .start-prompt .play-button { + font-size: 0px; + position: absolute; + left: 0; + top: 0; + right: 0; + bottom: 0; + text-align: center; + color: white; + height: 80px; + max-height: 66%; + margin: auto; +} +.asciinema-player .start-prompt .play-button div { + height: 100%; +} +.asciinema-player .start-prompt .play-button div span { + height: 100%; + display: block; +} +.asciinema-player .start-prompt .play-button div span svg { + height: 100%; +} +.asciinema-terminal .fg-16 { + color: #000000; +} +.asciinema-terminal .bg-16 { + background-color: #000000; +} +.asciinema-terminal .fg-17 { + color: #00005f; +} +.asciinema-terminal .bg-17 { + background-color: #00005f; +} +.asciinema-terminal .fg-18 { + color: #000087; +} +.asciinema-terminal .bg-18 { + background-color: #000087; +} +.asciinema-terminal .fg-19 { + color: #0000af; +} +.asciinema-terminal .bg-19 { + background-color: #0000af; +} +.asciinema-terminal .fg-20 { + color: #0000d7; +} +.asciinema-terminal .bg-20 { + background-color: #0000d7; +} +.asciinema-terminal .fg-21 { + color: #0000ff; +} +.asciinema-terminal .bg-21 { + background-color: #0000ff; +} +.asciinema-terminal .fg-22 { + color: #005f00; +} +.asciinema-terminal .bg-22 { + background-color: #005f00; +} +.asciinema-terminal .fg-23 { + color: #005f5f; +} +.asciinema-terminal .bg-23 { + background-color: #005f5f; +} +.asciinema-terminal .fg-24 { + color: #005f87; +} +.asciinema-terminal .bg-24 { + background-color: #005f87; +} +.asciinema-terminal .fg-25 { + color: #005faf; +} +.asciinema-terminal .bg-25 { + background-color: #005faf; +} +.asciinema-terminal .fg-26 { + color: #005fd7; +} +.asciinema-terminal .bg-26 { + background-color: #005fd7; +} +.asciinema-terminal .fg-27 { + color: #005fff; +} +.asciinema-terminal .bg-27 { + background-color: #005fff; +} +.asciinema-terminal .fg-28 { + color: #008700; +} +.asciinema-terminal .bg-28 { + background-color: #008700; +} +.asciinema-terminal .fg-29 { + color: #00875f; +} +.asciinema-terminal .bg-29 { + background-color: #00875f; +} +.asciinema-terminal .fg-30 { + color: #008787; +} +.asciinema-terminal .bg-30 { + background-color: #008787; +} +.asciinema-terminal .fg-31 { + color: #0087af; +} +.asciinema-terminal .bg-31 { + background-color: #0087af; +} +.asciinema-terminal .fg-32 { + color: #0087d7; +} +.asciinema-terminal .bg-32 { + background-color: #0087d7; +} +.asciinema-terminal .fg-33 { + color: #0087ff; +} +.asciinema-terminal .bg-33 { + background-color: #0087ff; +} +.asciinema-terminal .fg-34 { + color: #00af00; +} +.asciinema-terminal .bg-34 { + background-color: #00af00; +} +.asciinema-terminal .fg-35 { + color: #00af5f; +} +.asciinema-terminal .bg-35 { + background-color: #00af5f; +} +.asciinema-terminal .fg-36 { + color: #00af87; +} +.asciinema-terminal .bg-36 { + background-color: #00af87; +} +.asciinema-terminal .fg-37 { + color: #00afaf; +} +.asciinema-terminal .bg-37 { + background-color: #00afaf; +} +.asciinema-terminal .fg-38 { + color: #00afd7; +} +.asciinema-terminal .bg-38 { + background-color: #00afd7; +} +.asciinema-terminal .fg-39 { + color: #00afff; +} +.asciinema-terminal .bg-39 { + background-color: #00afff; +} +.asciinema-terminal .fg-40 { + color: #00d700; +} +.asciinema-terminal .bg-40 { + background-color: #00d700; +} +.asciinema-terminal .fg-41 { + color: #00d75f; +} +.asciinema-terminal .bg-41 { + background-color: #00d75f; +} +.asciinema-terminal .fg-42 { + color: #00d787; +} +.asciinema-terminal .bg-42 { + background-color: #00d787; +} +.asciinema-terminal .fg-43 { + color: #00d7af; +} +.asciinema-terminal .bg-43 { + background-color: #00d7af; +} +.asciinema-terminal .fg-44 { + color: #00d7d7; +} +.asciinema-terminal .bg-44 { + background-color: #00d7d7; +} +.asciinema-terminal .fg-45 { + color: #00d7ff; +} +.asciinema-terminal .bg-45 { + background-color: #00d7ff; +} +.asciinema-terminal .fg-46 { + color: #00ff00; +} +.asciinema-terminal .bg-46 { + background-color: #00ff00; +} +.asciinema-terminal .fg-47 { + color: #00ff5f; +} +.asciinema-terminal .bg-47 { + background-color: #00ff5f; +} +.asciinema-terminal .fg-48 { + color: #00ff87; +} +.asciinema-terminal .bg-48 { + background-color: #00ff87; +} +.asciinema-terminal .fg-49 { + color: #00ffaf; +} +.asciinema-terminal .bg-49 { + background-color: #00ffaf; +} +.asciinema-terminal .fg-50 { + color: #00ffd7; +} +.asciinema-terminal .bg-50 { + background-color: #00ffd7; +} +.asciinema-terminal .fg-51 { + color: #00ffff; +} +.asciinema-terminal .bg-51 { + background-color: #00ffff; +} +.asciinema-terminal .fg-52 { + color: #5f0000; +} +.asciinema-terminal .bg-52 { + background-color: #5f0000; +} +.asciinema-terminal .fg-53 { + color: #5f005f; +} +.asciinema-terminal .bg-53 { + background-color: #5f005f; +} +.asciinema-terminal .fg-54 { + color: #5f0087; +} +.asciinema-terminal .bg-54 { + background-color: #5f0087; +} +.asciinema-terminal .fg-55 { + color: #5f00af; +} +.asciinema-terminal .bg-55 { + background-color: #5f00af; +} +.asciinema-terminal .fg-56 { + color: #5f00d7; +} +.asciinema-terminal .bg-56 { + background-color: #5f00d7; +} +.asciinema-terminal .fg-57 { + color: #5f00ff; +} +.asciinema-terminal .bg-57 { + background-color: #5f00ff; +} +.asciinema-terminal .fg-58 { + color: #5f5f00; +} +.asciinema-terminal .bg-58 { + background-color: #5f5f00; +} +.asciinema-terminal .fg-59 { + color: #5f5f5f; +} +.asciinema-terminal .bg-59 { + background-color: #5f5f5f; +} +.asciinema-terminal .fg-60 { + color: #5f5f87; +} +.asciinema-terminal .bg-60 { + background-color: #5f5f87; +} +.asciinema-terminal .fg-61 { + color: #5f5faf; +} +.asciinema-terminal .bg-61 { + background-color: #5f5faf; +} +.asciinema-terminal .fg-62 { + color: #5f5fd7; +} +.asciinema-terminal .bg-62 { + background-color: #5f5fd7; +} +.asciinema-terminal .fg-63 { + color: #5f5fff; +} +.asciinema-terminal .bg-63 { + background-color: #5f5fff; +} +.asciinema-terminal .fg-64 { + color: #5f8700; +} +.asciinema-terminal .bg-64 { + background-color: #5f8700; +} +.asciinema-terminal .fg-65 { + color: #5f875f; +} +.asciinema-terminal .bg-65 { + background-color: #5f875f; +} +.asciinema-terminal .fg-66 { + color: #5f8787; +} +.asciinema-terminal .bg-66 { + background-color: #5f8787; +} +.asciinema-terminal .fg-67 { + color: #5f87af; +} +.asciinema-terminal .bg-67 { + background-color: #5f87af; +} +.asciinema-terminal .fg-68 { + color: #5f87d7; +} +.asciinema-terminal .bg-68 { + background-color: #5f87d7; +} +.asciinema-terminal .fg-69 { + color: #5f87ff; +} +.asciinema-terminal .bg-69 { + background-color: #5f87ff; +} +.asciinema-terminal .fg-70 { + color: #5faf00; +} +.asciinema-terminal .bg-70 { + background-color: #5faf00; +} +.asciinema-terminal .fg-71 { + color: #5faf5f; +} +.asciinema-terminal .bg-71 { + background-color: #5faf5f; +} +.asciinema-terminal .fg-72 { + color: #5faf87; +} +.asciinema-terminal .bg-72 { + background-color: #5faf87; +} +.asciinema-terminal .fg-73 { + color: #5fafaf; +} +.asciinema-terminal .bg-73 { + background-color: #5fafaf; +} +.asciinema-terminal .fg-74 { + color: #5fafd7; +} +.asciinema-terminal .bg-74 { + background-color: #5fafd7; +} +.asciinema-terminal .fg-75 { + color: #5fafff; +} +.asciinema-terminal .bg-75 { + background-color: #5fafff; +} +.asciinema-terminal .fg-76 { + color: #5fd700; +} +.asciinema-terminal .bg-76 { + background-color: #5fd700; +} +.asciinema-terminal .fg-77 { + color: #5fd75f; +} +.asciinema-terminal .bg-77 { + background-color: #5fd75f; +} +.asciinema-terminal .fg-78 { + color: #5fd787; +} +.asciinema-terminal .bg-78 { + background-color: #5fd787; +} +.asciinema-terminal .fg-79 { + color: #5fd7af; +} +.asciinema-terminal .bg-79 { + background-color: #5fd7af; +} +.asciinema-terminal .fg-80 { + color: #5fd7d7; +} +.asciinema-terminal .bg-80 { + background-color: #5fd7d7; +} +.asciinema-terminal .fg-81 { + color: #5fd7ff; +} +.asciinema-terminal .bg-81 { + background-color: #5fd7ff; +} +.asciinema-terminal .fg-82 { + color: #5fff00; +} +.asciinema-terminal .bg-82 { + background-color: #5fff00; +} +.asciinema-terminal .fg-83 { + color: #5fff5f; +} +.asciinema-terminal .bg-83 { + background-color: #5fff5f; +} +.asciinema-terminal .fg-84 { + color: #5fff87; +} +.asciinema-terminal .bg-84 { + background-color: #5fff87; +} +.asciinema-terminal .fg-85 { + color: #5fffaf; +} +.asciinema-terminal .bg-85 { + background-color: #5fffaf; +} +.asciinema-terminal .fg-86 { + color: #5fffd7; +} +.asciinema-terminal .bg-86 { + background-color: #5fffd7; +} +.asciinema-terminal .fg-87 { + color: #5fffff; +} +.asciinema-terminal .bg-87 { + background-color: #5fffff; +} +.asciinema-terminal .fg-88 { + color: #870000; +} +.asciinema-terminal .bg-88 { + background-color: #870000; +} +.asciinema-terminal .fg-89 { + color: #87005f; +} +.asciinema-terminal .bg-89 { + background-color: #87005f; +} +.asciinema-terminal .fg-90 { + color: #870087; +} +.asciinema-terminal .bg-90 { + background-color: #870087; +} +.asciinema-terminal .fg-91 { + color: #8700af; +} +.asciinema-terminal .bg-91 { + background-color: #8700af; +} +.asciinema-terminal .fg-92 { + color: #8700d7; +} +.asciinema-terminal .bg-92 { + background-color: #8700d7; +} +.asciinema-terminal .fg-93 { + color: #8700ff; +} +.asciinema-terminal .bg-93 { + background-color: #8700ff; +} +.asciinema-terminal .fg-94 { + color: #875f00; +} +.asciinema-terminal .bg-94 { + background-color: #875f00; +} +.asciinema-terminal .fg-95 { + color: #875f5f; +} +.asciinema-terminal .bg-95 { + background-color: #875f5f; +} +.asciinema-terminal .fg-96 { + color: #875f87; +} +.asciinema-terminal .bg-96 { + background-color: #875f87; +} +.asciinema-terminal .fg-97 { + color: #875faf; +} +.asciinema-terminal .bg-97 { + background-color: #875faf; +} +.asciinema-terminal .fg-98 { + color: #875fd7; +} +.asciinema-terminal .bg-98 { + background-color: #875fd7; +} +.asciinema-terminal .fg-99 { + color: #875fff; +} +.asciinema-terminal .bg-99 { + background-color: #875fff; +} +.asciinema-terminal .fg-100 { + color: #878700; +} +.asciinema-terminal .bg-100 { + background-color: #878700; +} +.asciinema-terminal .fg-101 { + color: #87875f; +} +.asciinema-terminal .bg-101 { + background-color: #87875f; +} +.asciinema-terminal .fg-102 { + color: #878787; +} +.asciinema-terminal .bg-102 { + background-color: #878787; +} +.asciinema-terminal .fg-103 { + color: #8787af; +} +.asciinema-terminal .bg-103 { + background-color: #8787af; +} +.asciinema-terminal .fg-104 { + color: #8787d7; +} +.asciinema-terminal .bg-104 { + background-color: #8787d7; +} +.asciinema-terminal .fg-105 { + color: #8787ff; +} +.asciinema-terminal .bg-105 { + background-color: #8787ff; +} +.asciinema-terminal .fg-106 { + color: #87af00; +} +.asciinema-terminal .bg-106 { + background-color: #87af00; +} +.asciinema-terminal .fg-107 { + color: #87af5f; +} +.asciinema-terminal .bg-107 { + background-color: #87af5f; +} +.asciinema-terminal .fg-108 { + color: #87af87; +} +.asciinema-terminal .bg-108 { + background-color: #87af87; +} +.asciinema-terminal .fg-109 { + color: #87afaf; +} +.asciinema-terminal .bg-109 { + background-color: #87afaf; +} +.asciinema-terminal .fg-110 { + color: #87afd7; +} +.asciinema-terminal .bg-110 { + background-color: #87afd7; +} +.asciinema-terminal .fg-111 { + color: #87afff; +} +.asciinema-terminal .bg-111 { + background-color: #87afff; +} +.asciinema-terminal .fg-112 { + color: #87d700; +} +.asciinema-terminal .bg-112 { + background-color: #87d700; +} +.asciinema-terminal .fg-113 { + color: #87d75f; +} +.asciinema-terminal .bg-113 { + background-color: #87d75f; +} +.asciinema-terminal .fg-114 { + color: #87d787; +} +.asciinema-terminal .bg-114 { + background-color: #87d787; +} +.asciinema-terminal .fg-115 { + color: #87d7af; +} +.asciinema-terminal .bg-115 { + background-color: #87d7af; +} +.asciinema-terminal .fg-116 { + color: #87d7d7; +} +.asciinema-terminal .bg-116 { + background-color: #87d7d7; +} +.asciinema-terminal .fg-117 { + color: #87d7ff; +} +.asciinema-terminal .bg-117 { + background-color: #87d7ff; +} +.asciinema-terminal .fg-118 { + color: #87ff00; +} +.asciinema-terminal .bg-118 { + background-color: #87ff00; +} +.asciinema-terminal .fg-119 { + color: #87ff5f; +} +.asciinema-terminal .bg-119 { + background-color: #87ff5f; +} +.asciinema-terminal .fg-120 { + color: #87ff87; +} +.asciinema-terminal .bg-120 { + background-color: #87ff87; +} +.asciinema-terminal .fg-121 { + color: #87ffaf; +} +.asciinema-terminal .bg-121 { + background-color: #87ffaf; +} +.asciinema-terminal .fg-122 { + color: #87ffd7; +} +.asciinema-terminal .bg-122 { + background-color: #87ffd7; +} +.asciinema-terminal .fg-123 { + color: #87ffff; +} +.asciinema-terminal .bg-123 { + background-color: #87ffff; +} +.asciinema-terminal .fg-124 { + color: #af0000; +} +.asciinema-terminal .bg-124 { + background-color: #af0000; +} +.asciinema-terminal .fg-125 { + color: #af005f; +} +.asciinema-terminal .bg-125 { + background-color: #af005f; +} +.asciinema-terminal .fg-126 { + color: #af0087; +} +.asciinema-terminal .bg-126 { + background-color: #af0087; +} +.asciinema-terminal .fg-127 { + color: #af00af; +} +.asciinema-terminal .bg-127 { + background-color: #af00af; +} +.asciinema-terminal .fg-128 { + color: #af00d7; +} +.asciinema-terminal .bg-128 { + background-color: #af00d7; +} +.asciinema-terminal .fg-129 { + color: #af00ff; +} +.asciinema-terminal .bg-129 { + background-color: #af00ff; +} +.asciinema-terminal .fg-130 { + color: #af5f00; +} +.asciinema-terminal .bg-130 { + background-color: #af5f00; +} +.asciinema-terminal .fg-131 { + color: #af5f5f; +} +.asciinema-terminal .bg-131 { + background-color: #af5f5f; +} +.asciinema-terminal .fg-132 { + color: #af5f87; +} +.asciinema-terminal .bg-132 { + background-color: #af5f87; +} +.asciinema-terminal .fg-133 { + color: #af5faf; +} +.asciinema-terminal .bg-133 { + background-color: #af5faf; +} +.asciinema-terminal .fg-134 { + color: #af5fd7; +} +.asciinema-terminal .bg-134 { + background-color: #af5fd7; +} +.asciinema-terminal .fg-135 { + color: #af5fff; +} +.asciinema-terminal .bg-135 { + background-color: #af5fff; +} +.asciinema-terminal .fg-136 { + color: #af8700; +} +.asciinema-terminal .bg-136 { + background-color: #af8700; +} +.asciinema-terminal .fg-137 { + color: #af875f; +} +.asciinema-terminal .bg-137 { + background-color: #af875f; +} +.asciinema-terminal .fg-138 { + color: #af8787; +} +.asciinema-terminal .bg-138 { + background-color: #af8787; +} +.asciinema-terminal .fg-139 { + color: #af87af; +} +.asciinema-terminal .bg-139 { + background-color: #af87af; +} +.asciinema-terminal .fg-140 { + color: #af87d7; +} +.asciinema-terminal .bg-140 { + background-color: #af87d7; +} +.asciinema-terminal .fg-141 { + color: #af87ff; +} +.asciinema-terminal .bg-141 { + background-color: #af87ff; +} +.asciinema-terminal .fg-142 { + color: #afaf00; +} +.asciinema-terminal .bg-142 { + background-color: #afaf00; +} +.asciinema-terminal .fg-143 { + color: #afaf5f; +} +.asciinema-terminal .bg-143 { + background-color: #afaf5f; +} +.asciinema-terminal .fg-144 { + color: #afaf87; +} +.asciinema-terminal .bg-144 { + background-color: #afaf87; +} +.asciinema-terminal .fg-145 { + color: #afafaf; +} +.asciinema-terminal .bg-145 { + background-color: #afafaf; +} +.asciinema-terminal .fg-146 { + color: #afafd7; +} +.asciinema-terminal .bg-146 { + background-color: #afafd7; +} +.asciinema-terminal .fg-147 { + color: #afafff; +} +.asciinema-terminal .bg-147 { + background-color: #afafff; +} +.asciinema-terminal .fg-148 { + color: #afd700; +} +.asciinema-terminal .bg-148 { + background-color: #afd700; +} +.asciinema-terminal .fg-149 { + color: #afd75f; +} +.asciinema-terminal .bg-149 { + background-color: #afd75f; +} +.asciinema-terminal .fg-150 { + color: #afd787; +} +.asciinema-terminal .bg-150 { + background-color: #afd787; +} +.asciinema-terminal .fg-151 { + color: #afd7af; +} +.asciinema-terminal .bg-151 { + background-color: #afd7af; +} +.asciinema-terminal .fg-152 { + color: #afd7d7; +} +.asciinema-terminal .bg-152 { + background-color: #afd7d7; +} +.asciinema-terminal .fg-153 { + color: #afd7ff; +} +.asciinema-terminal .bg-153 { + background-color: #afd7ff; +} +.asciinema-terminal .fg-154 { + color: #afff00; +} +.asciinema-terminal .bg-154 { + background-color: #afff00; +} +.asciinema-terminal .fg-155 { + color: #afff5f; +} +.asciinema-terminal .bg-155 { + background-color: #afff5f; +} +.asciinema-terminal .fg-156 { + color: #afff87; +} +.asciinema-terminal .bg-156 { + background-color: #afff87; +} +.asciinema-terminal .fg-157 { + color: #afffaf; +} +.asciinema-terminal .bg-157 { + background-color: #afffaf; +} +.asciinema-terminal .fg-158 { + color: #afffd7; +} +.asciinema-terminal .bg-158 { + background-color: #afffd7; +} +.asciinema-terminal .fg-159 { + color: #afffff; +} +.asciinema-terminal .bg-159 { + background-color: #afffff; +} +.asciinema-terminal .fg-160 { + color: #d70000; +} +.asciinema-terminal .bg-160 { + background-color: #d70000; +} +.asciinema-terminal .fg-161 { + color: #d7005f; +} +.asciinema-terminal .bg-161 { + background-color: #d7005f; +} +.asciinema-terminal .fg-162 { + color: #d70087; +} +.asciinema-terminal .bg-162 { + background-color: #d70087; +} +.asciinema-terminal .fg-163 { + color: #d700af; +} +.asciinema-terminal .bg-163 { + background-color: #d700af; +} +.asciinema-terminal .fg-164 { + color: #d700d7; +} +.asciinema-terminal .bg-164 { + background-color: #d700d7; +} +.asciinema-terminal .fg-165 { + color: #d700ff; +} +.asciinema-terminal .bg-165 { + background-color: #d700ff; +} +.asciinema-terminal .fg-166 { + color: #d75f00; +} +.asciinema-terminal .bg-166 { + background-color: #d75f00; +} +.asciinema-terminal .fg-167 { + color: #d75f5f; +} +.asciinema-terminal .bg-167 { + background-color: #d75f5f; +} +.asciinema-terminal .fg-168 { + color: #d75f87; +} +.asciinema-terminal .bg-168 { + background-color: #d75f87; +} +.asciinema-terminal .fg-169 { + color: #d75faf; +} +.asciinema-terminal .bg-169 { + background-color: #d75faf; +} +.asciinema-terminal .fg-170 { + color: #d75fd7; +} +.asciinema-terminal .bg-170 { + background-color: #d75fd7; +} +.asciinema-terminal .fg-171 { + color: #d75fff; +} +.asciinema-terminal .bg-171 { + background-color: #d75fff; +} +.asciinema-terminal .fg-172 { + color: #d78700; +} +.asciinema-terminal .bg-172 { + background-color: #d78700; +} +.asciinema-terminal .fg-173 { + color: #d7875f; +} +.asciinema-terminal .bg-173 { + background-color: #d7875f; +} +.asciinema-terminal .fg-174 { + color: #d78787; +} +.asciinema-terminal .bg-174 { + background-color: #d78787; +} +.asciinema-terminal .fg-175 { + color: #d787af; +} +.asciinema-terminal .bg-175 { + background-color: #d787af; +} +.asciinema-terminal .fg-176 { + color: #d787d7; +} +.asciinema-terminal .bg-176 { + background-color: #d787d7; +} +.asciinema-terminal .fg-177 { + color: #d787ff; +} +.asciinema-terminal .bg-177 { + background-color: #d787ff; +} +.asciinema-terminal .fg-178 { + color: #d7af00; +} +.asciinema-terminal .bg-178 { + background-color: #d7af00; +} +.asciinema-terminal .fg-179 { + color: #d7af5f; +} +.asciinema-terminal .bg-179 { + background-color: #d7af5f; +} +.asciinema-terminal .fg-180 { + color: #d7af87; +} +.asciinema-terminal .bg-180 { + background-color: #d7af87; +} +.asciinema-terminal .fg-181 { + color: #d7afaf; +} +.asciinema-terminal .bg-181 { + background-color: #d7afaf; +} +.asciinema-terminal .fg-182 { + color: #d7afd7; +} +.asciinema-terminal .bg-182 { + background-color: #d7afd7; +} +.asciinema-terminal .fg-183 { + color: #d7afff; +} +.asciinema-terminal .bg-183 { + background-color: #d7afff; +} +.asciinema-terminal .fg-184 { + color: #d7d700; +} +.asciinema-terminal .bg-184 { + background-color: #d7d700; +} +.asciinema-terminal .fg-185 { + color: #d7d75f; +} +.asciinema-terminal .bg-185 { + background-color: #d7d75f; +} +.asciinema-terminal .fg-186 { + color: #d7d787; +} +.asciinema-terminal .bg-186 { + background-color: #d7d787; +} +.asciinema-terminal .fg-187 { + color: #d7d7af; +} +.asciinema-terminal .bg-187 { + background-color: #d7d7af; +} +.asciinema-terminal .fg-188 { + color: #d7d7d7; +} +.asciinema-terminal .bg-188 { + background-color: #d7d7d7; +} +.asciinema-terminal .fg-189 { + color: #d7d7ff; +} +.asciinema-terminal .bg-189 { + background-color: #d7d7ff; +} +.asciinema-terminal .fg-190 { + color: #d7ff00; +} +.asciinema-terminal .bg-190 { + background-color: #d7ff00; +} +.asciinema-terminal .fg-191 { + color: #d7ff5f; +} +.asciinema-terminal .bg-191 { + background-color: #d7ff5f; +} +.asciinema-terminal .fg-192 { + color: #d7ff87; +} +.asciinema-terminal .bg-192 { + background-color: #d7ff87; +} +.asciinema-terminal .fg-193 { + color: #d7ffaf; +} +.asciinema-terminal .bg-193 { + background-color: #d7ffaf; +} +.asciinema-terminal .fg-194 { + color: #d7ffd7; +} +.asciinema-terminal .bg-194 { + background-color: #d7ffd7; +} +.asciinema-terminal .fg-195 { + color: #d7ffff; +} +.asciinema-terminal .bg-195 { + background-color: #d7ffff; +} +.asciinema-terminal .fg-196 { + color: #ff0000; +} +.asciinema-terminal .bg-196 { + background-color: #ff0000; +} +.asciinema-terminal .fg-197 { + color: #ff005f; +} +.asciinema-terminal .bg-197 { + background-color: #ff005f; +} +.asciinema-terminal .fg-198 { + color: #ff0087; +} +.asciinema-terminal .bg-198 { + background-color: #ff0087; +} +.asciinema-terminal .fg-199 { + color: #ff00af; +} +.asciinema-terminal .bg-199 { + background-color: #ff00af; +} +.asciinema-terminal .fg-200 { + color: #ff00d7; +} +.asciinema-terminal .bg-200 { + background-color: #ff00d7; +} +.asciinema-terminal .fg-201 { + color: #ff00ff; +} +.asciinema-terminal .bg-201 { + background-color: #ff00ff; +} +.asciinema-terminal .fg-202 { + color: #ff5f00; +} +.asciinema-terminal .bg-202 { + background-color: #ff5f00; +} +.asciinema-terminal .fg-203 { + color: #ff5f5f; +} +.asciinema-terminal .bg-203 { + background-color: #ff5f5f; +} +.asciinema-terminal .fg-204 { + color: #ff5f87; +} +.asciinema-terminal .bg-204 { + background-color: #ff5f87; +} +.asciinema-terminal .fg-205 { + color: #ff5faf; +} +.asciinema-terminal .bg-205 { + background-color: #ff5faf; +} +.asciinema-terminal .fg-206 { + color: #ff5fd7; +} +.asciinema-terminal .bg-206 { + background-color: #ff5fd7; +} +.asciinema-terminal .fg-207 { + color: #ff5fff; +} +.asciinema-terminal .bg-207 { + background-color: #ff5fff; +} +.asciinema-terminal .fg-208 { + color: #ff8700; +} +.asciinema-terminal .bg-208 { + background-color: #ff8700; +} +.asciinema-terminal .fg-209 { + color: #ff875f; +} +.asciinema-terminal .bg-209 { + background-color: #ff875f; +} +.asciinema-terminal .fg-210 { + color: #ff8787; +} +.asciinema-terminal .bg-210 { + background-color: #ff8787; +} +.asciinema-terminal .fg-211 { + color: #ff87af; +} +.asciinema-terminal .bg-211 { + background-color: #ff87af; +} +.asciinema-terminal .fg-212 { + color: #ff87d7; +} +.asciinema-terminal .bg-212 { + background-color: #ff87d7; +} +.asciinema-terminal .fg-213 { + color: #ff87ff; +} +.asciinema-terminal .bg-213 { + background-color: #ff87ff; +} +.asciinema-terminal .fg-214 { + color: #ffaf00; +} +.asciinema-terminal .bg-214 { + background-color: #ffaf00; +} +.asciinema-terminal .fg-215 { + color: #ffaf5f; +} +.asciinema-terminal .bg-215 { + background-color: #ffaf5f; +} +.asciinema-terminal .fg-216 { + color: #ffaf87; +} +.asciinema-terminal .bg-216 { + background-color: #ffaf87; +} +.asciinema-terminal .fg-217 { + color: #ffafaf; +} +.asciinema-terminal .bg-217 { + background-color: #ffafaf; +} +.asciinema-terminal .fg-218 { + color: #ffafd7; +} +.asciinema-terminal .bg-218 { + background-color: #ffafd7; +} +.asciinema-terminal .fg-219 { + color: #ffafff; +} +.asciinema-terminal .bg-219 { + background-color: #ffafff; +} +.asciinema-terminal .fg-220 { + color: #ffd700; +} +.asciinema-terminal .bg-220 { + background-color: #ffd700; +} +.asciinema-terminal .fg-221 { + color: #ffd75f; +} +.asciinema-terminal .bg-221 { + background-color: #ffd75f; +} +.asciinema-terminal .fg-222 { + color: #ffd787; +} +.asciinema-terminal .bg-222 { + background-color: #ffd787; +} +.asciinema-terminal .fg-223 { + color: #ffd7af; +} +.asciinema-terminal .bg-223 { + background-color: #ffd7af; +} +.asciinema-terminal .fg-224 { + color: #ffd7d7; +} +.asciinema-terminal .bg-224 { + background-color: #ffd7d7; +} +.asciinema-terminal .fg-225 { + color: #ffd7ff; +} +.asciinema-terminal .bg-225 { + background-color: #ffd7ff; +} +.asciinema-terminal .fg-226 { + color: #ffff00; +} +.asciinema-terminal .bg-226 { + background-color: #ffff00; +} +.asciinema-terminal .fg-227 { + color: #ffff5f; +} +.asciinema-terminal .bg-227 { + background-color: #ffff5f; +} +.asciinema-terminal .fg-228 { + color: #ffff87; +} +.asciinema-terminal .bg-228 { + background-color: #ffff87; +} +.asciinema-terminal .fg-229 { + color: #ffffaf; +} +.asciinema-terminal .bg-229 { + background-color: #ffffaf; +} +.asciinema-terminal .fg-230 { + color: #ffffd7; +} +.asciinema-terminal .bg-230 { + background-color: #ffffd7; +} +.asciinema-terminal .fg-231 { + color: #ffffff; +} +.asciinema-terminal .bg-231 { + background-color: #ffffff; +} +.asciinema-terminal .fg-232 { + color: #080808; +} +.asciinema-terminal .bg-232 { + background-color: #080808; +} +.asciinema-terminal .fg-233 { + color: #121212; +} +.asciinema-terminal .bg-233 { + background-color: #121212; +} +.asciinema-terminal .fg-234 { + color: #1c1c1c; +} +.asciinema-terminal .bg-234 { + background-color: #1c1c1c; +} +.asciinema-terminal .fg-235 { + color: #262626; +} +.asciinema-terminal .bg-235 { + background-color: #262626; +} +.asciinema-terminal .fg-236 { + color: #303030; +} +.asciinema-terminal .bg-236 { + background-color: #303030; +} +.asciinema-terminal .fg-237 { + color: #3a3a3a; +} +.asciinema-terminal .bg-237 { |