Browse Source

Index cleaned

sigi 1 week ago
parent
commit
09570845e3

+ 2 - 0
.gitignore

@@ -0,0 +1,2 @@
+contrib/
+

+ 0 - 6
contrib/PingPanel/DEBIAN/README.Debian

@@ -1,6 +0,0 @@
-pingpanel for Debian
--------------------
-
-<possible notes regarding this package - if none, delete this file>
-
- -- Siegrist(SystemLoesungen) <PSS@ZweierNet.ch>  Tue, 12 Mar 2024 17:20:53 +0100

+ 0 - 14
contrib/PingPanel/DEBIAN/control

@@ -1,14 +0,0 @@
-Source: pingpanel
-Section: net
-Priority: optional
-Maintainer: Siegrist(SystemLoesungen) <PSS@ZweierNet.ch>
-Version: 0.9.9
-Homepage: http://pingpanel.ZweierNet.ch
-Rules-Requires-Root: no
-Package: pingpanel
-Architecture: all
-Depends: python3 (>= 3.6), python3-tornado (>= 6.0), fping (>= 5.0)
-Description: PingPanel monitoring of network devices
- PingPanel is a utility for monitoring network devices
- and provides a web-based service, the panel, for 
- displaying the captured statuses.

+ 0 - 3
contrib/PingPanel/DEBIAN/pingpanel.conffiles

@@ -1,3 +0,0 @@
-/etc/default/pingpanel
-/opt/PingPanel/config.cfg
-

+ 0 - 13
contrib/PingPanel/DEBIAN/postinst

@@ -1,13 +0,0 @@
-#!/bin/sh
-set -e
-
-if [ -f /opt/PingPanel/config.cfg.TMPINST ]
-	then
-		cp --preserve=all /opt/PingPanel/config.cfg /opt/PingPanel/config.cfg.dpkg-NEW
-		mv /opt/PingPanel/config.cfg.TMPINST /opt/PingPanel/config.cfg
-fi
-
-if [ -f /etc/default/pingpanel.TMPINST ]
-    then
-        mv /etc/default/pingpanel.TMPINST /etc/default/pingpanel
-fi

+ 0 - 12
contrib/PingPanel/DEBIAN/preinst

@@ -1,12 +0,0 @@
-#!/bin/sh
-set -e
-
-if [ -f /opt/PingPanel/config.cfg ]
-	then
-		cp --preserve=all /opt/PingPanel/config.cfg /opt/PingPanel/config.cfg.TMPINST
-fi
-
-if [ -f /etc/default/pingpanel ]
-    then
-        cp --preserve=all /etc/default/pingpanel /etc/default/pingpanel.TMPINST
-fi

+ 0 - 14
contrib/PingPanel/etc/default/pingpanel

@@ -1,14 +0,0 @@
-# /etc/default/pingpanel
-
-# Defaults for pingpanel initscript. This file is sourced by /etc/init.d/pingpanel.
-# all vars used in /etc/init.d/pingpanel can be set here.
-#
-
-# Configfile (Standard: config.cfg)
-CONFIG=/opt/PingPanel/config.cfg
-
-# the path to logfile
-LOGFILE=/var/log/pingpanel.log
-
-# Options to pass to PingPanel.py
-#PINGPANEL_OPTS=""

+ 0 - 79
contrib/PingPanel/etc/init.d/pingpanel

@@ -1,79 +0,0 @@
-#!/bin/sh
-#
-# /etc/init.d/pingpanel                  Startup script for the PingPanel process
-#
-### BEGIN INIT INFO
-# Provides:          pingpanel
-# Required-Start:    $remote_fs
-# Required-Stop:     $remote_fs
-# Default-Start:     2 3 4 5
-# Default-Stop:      0 1 6
-# Short-Description: PingPanel monitoring of network devices
-# Description:       PingPanel is a utility for monitoring network devices
-#                    and provides a web-based service, the panel, for
-#                                        displaying the captured statuses.
-### END INIT INFO
-
-. /lib/lsb/init-functions
-
-DAEMON=/opt/PingPanel/PingPanel.py
-CONFIG=/opt/PingPanel/config.cfg
-NAME=pingpanel
-DESC="PingPanel monitor service"
-LOGFILE=/var/log/pingpanel.log
-PINGPANEL_OPTS=
-
-set -e
-
-# Check if DAEMON binary exist
-[ -f $DAEMON ] || exit 0
-
-[ -f "/etc/default/$NAME" ] && . /etc/default/$NAME
-
-PINGPANEL_OPTS="-c $CONFIG $PINGPANEL_OPTS"
-
-case "$1" in
-  start)
-    log_daemon_msg "Starting $DESC" "$NAME"
-	
-	start_daemon /usr/bin/python3 -u $DAEMON $PINGPANEL_OPTS 1>>$LOGFILE 2>>$LOGFILE &
-
-    if pgrep -f $DAEMON
-    then
-      log_success_msg "$DAEMON running."
-    else
-      log_failure_msg "$DAEMON start FAILED!"
-    fi
-    ;;
-  stop)
-    log_daemon_msg "Stopping $DESC" "$NAME"
-
-    kill -9 $(pgrep -f $DAEMON)
-    if pgrep -f $DAEMON
-    then
-      log_end_msg 1
-    else
-      log_end_msg 0
-    fi
-    ;;
-  restart)
-    $0 stop
-    sleep 2
-    $0 start
-    ;;
-  status)
-    if pgrep -f $DAEMON
-	then
-      log_end_msg 0
-      exit 0
-    else
-      log_end_msg 1
-      exit 1
-    fi
-    ;;
-  *)
-    log_action_msg "Usage: /etc/init.d/$NAME {start|stop|restart|status}"
-    ;;
-esac
-
-exit 0

+ 0 - 80
contrib/PingPanel/opt/PingPanel/INSTALL.txt

@@ -1,80 +0,0 @@
-* PingPanel INSTALL.txt (C) 2024 by Siegrist(SystemLösungen) <pingpanel@zweiernet.ch>
-
-INSTALL
-========
-
-On Debian/Ubuntu related systems install with:
-----------------------------------------------
-- #dpkg -i  pingpanel_<version>_all.deb
-
-You may encounter problems like:
-	dpkg: dependency problems prevent configuration of pingpanel:
-	 pingpanel depends on python3-tornado (>= 6.0); however:
-	  Package python3-tornado is not installed.
-	 pingpanel depends on fping (>= 5.0); however:
-	  Package fping is not installed.
-	  
-Then, check the dependencies with:
-- #apt-get check
-and install the dependencies with:
-- #apt --fix-broken install
-Afterwards the pingpanel package ist fully instsalled under /opt/PingPanel/.
-
-The daemon start file pingpanel in the init.d/ directory is in the standard LSB format for SysV systems.
-So, on systemd related systems at least use:
-- #systemctl daemon-reload
-
-After all, start the PingPanel Daemon:
-- #service pingpanel start
-
-
-
-On other systems using the tar-archive:
----------------------------------------
-- #cd /opt
-- #tar xvfz pingpanel_<version>.tar.gz
-
-Requirements:
-- python3-tornado >= 6.0 (https://www.tornadoweb.org/en/stable/)
-- fping >= 5.0 (https://fping.org/)
-
-The directory ./etc.example contains startup file in ./init.d and a default pingpanel file under ./default.
-If you want to use a different installation directory, you must adjust the default file 
-and/or the init.d startup script to the appropriate pathes and names.
-
-After all, start the PingPanel Daemon:
-- #/etc/init.d/pingpanel start
-
-
-Configuration
--------------
-The configuration is made in the config.cfg file located in the installation directory.
-All parameters are documented in this file.
-If you want to use a name other than config.cfg, you can specify this in the /etc/default/pingpanel file
-or with the -c <filename> param to the PingPanel.py script.
-
-All Messages are written to the file /var/log/pingpanel.log, unless 
-you define a different name in /etc/default/pingpanel.
-
-
-Upgrade
-========
-
-On Debian/Ubuntu related systems upgrade with:
-----------------------------------------------
-- #dpkg -i  pingpanel_<version>_all.deb
-
-The configuration files (config.cfg and /etc/default/pingpanel) will be preserved.
-New files will be given the prefix .dpkg-NEW.
-Adjust your config.cfg file with the new paramameters from .dpkg-NEW.
-
-Restart the PingPanel Daemon.
-
-
-On other systems using the tar-archive:
----------------------------------------
-Install the tar-file in a new empty directory and then copy the relevant files to your active install-dir.
-
-
-
-sigi

+ 0 - 793
contrib/PingPanel/opt/PingPanel/PingPanel.py

@@ -1,793 +0,0 @@
-#!/usr/bin/env python3
-
-# Copyright 2024 by Siegrist(SystemLoesungen) <PSS@ZweierNet.ch>
-
-# 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.
-
-
-#import datetime
-from datetime import datetime
-import os
-import errno
-import configparser
-import time
-import signal
-import sys
-import subprocess
-import re
-import argparse
-from threading import Thread
-import json
-
-import tornado.ioloop
-import tornado.web
-import tornado.websocket
-from tornado.gen import sleep
-import asyncio
-
-VERSION = '0.9.9'
-
-konfig_file = 'config.cfg'
-s_certfile = 'server.crt'
-s_keyfile = 'server.key'
-ws_method = 'ws'
-host_dict = dict()
-failed_pingc = dict()
-loop_interval = 3
-listen_port = 8888
-listen_addr = '0.0.0.0'
-anz_hosts = 0
-
-fping_parameter = []
-fping_cmd = 'fping'
-
-def signal_handler(signal, frame):
-	print('\nCtrl+C, keyboardInterrupt detected!')
-	sys.exit(0) 
-signal.signal(signal.SIGINT, signal_handler)
-
-
-config = configparser.ConfigParser(delimiters=('='), comment_prefixes=('#'), allow_no_value=False, strict=True, empty_lines_in_values=False)
-def read_config():
-	try:
-		if config.read([konfig_file]) != []:
-			pass
-		else:
-			print("Configfile '" + konfig_file + "' not found!")
-			sys.exit()
-	except configparser.DuplicateSectionError as e:
-		print("Error: Duplicate Section '%s' not allowed." % str(e.section))
-		sys.exit()
-	except configparser.DuplicateOptionError as e:
-		print("Error: Duplicate Option '%s' in Section '%s' not allowed." % ( str(e.option), str(e.section) ))
-		sys.exit()
-	except configparser.Error as e:
-		print("Error in Configfile: %s." % str(e))
-		sys.exit()
-	
-	#print(config.sections())
-	global anz_hosts
-	for sect in config.sections():
-		for key in config[sect]:
-			if (sect == "Main"):
-				try:
-					global loop_interval
-					loop_interval = int(config["Main"]["LoopInterval"])
-				except KeyError:
-					pass
-				try:
-					global listen_port
-					listen_port = int(config["Main"]["ListenPort"])
-				except KeyError:
-					pass
-				try:
-					global listen_addr
-					listen_addr = str(config["Main"]["ListenAddr"])
-				except KeyError:
-					pass
-				try:
-					title_add = str(config["Main"]["TitleAdd"])
-				except KeyError:
-					config["Main"]["TitleAdd"] = ''
-				try:
-					global ws_method
-					if ( str(config["Main"]["UseHTTPS"]) ):
-						ws_method = 'wss'
-						s_certfile = str(config["Main"]["CertFile"])
-						s_keyfile = str(config["Main"]["KeyFile"])
-						apath = os.path.dirname(os.path.abspath(__file__))
-						if not file_exists(s_certfile):
-							print("CertFile not readable or does not exist: %s" % apath + '/' + s_certfile)
-							sys.exit()
-						if not file_exists(s_keyfile):
-							print("KeyFile not readable or does not exist: %s" % apath + '/' + s_keyfile)
-							sys.exit()
-				except KeyError:
-					pass
-			else:
-				#host_dict[key] = config[sect][key]
-				host_dict[key] = sect.replace(' ','_')
-				failed_pingc[key] = 0
-				anz_hosts += 1
-			if args.v: print(sect + ": " + key + " = " + config[sect][key])
-	print("Pinging " + str(anz_hosts) + " Devices in total.")
-	
-def cmd_exists(cmd):
-	path = os.environ["PATH"].split(os.pathsep)
-
-	for prefix in path:
-		filename = os.path.join(prefix, cmd)
-		executable = os.access(filename, os.X_OK)
-		is_not_directory = os.path.isfile(filename)
-		if executable and is_not_directory:
-			return True
-	return False
-
-def file_exists(file):
-	filename = os.path.dirname(os.path.abspath(__file__)) + '/' + file
-	if os.access(filename, os.R_OK):
-		return True
-	return False
-
-
-def create_fpingparam():
-	global fping_parameter
-	global fping_cmd
-	
-	try:
-		fping_parameter.append(config["Main"]["fpingCommand"])
-		fping_cmd = config["Main"]["fpingCommand"]
-	except KeyError:
-		fping_parameter.append(fping_cmd)
-		
-	fping_parameter += ['--quiet', '--vcount=3']
-	
-	try:
-		fping_parameter.append('--interval=' + config["Main"]["Fping-interval"])
-	except KeyError:
-		fping_parameter.append('--interval=1')
-	try:
-		fping_parameter.append('--period=' + config["Main"]["Fping-period"])
-	except KeyError:
-		fping_parameter.append('--period=100')
-	try:
-		fping_parameter.append('--size=' + config["Main"]["Fping-size"])
-	except KeyError:
-		pass
-
-
-def ping(ip, packets=1, timeout=2):
-	comd = ['ping', '-c', str(packets), '-w', str(timeout), ip]
-	res = subprocess.run(comd, stdin=subprocess.DEVNULL, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
-	return res.returncode == 0
-	
-def fping(ips):
-	#comd = ['fping', '--quiet', '--interval=2', '--vcount=3', '--period=100'] + ips
-	comd = fping_parameter + ips
-	
-	res = subprocess.run(comd, stdin=subprocess.DEVNULL, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)	#, universal_newlines = True)
-	if args.v:
-		print("fping finished: " + datetime.now().strftime("%H:%M:%S"))
-		if res.returncode == 2:
-			print("fping: any IP addresses were not found !")
-		elif res.returncode == 3:
-			print("fping: invalid command line arguments !")
-		elif res.returncode == 4:
-			print("fping: system call failure !")
-		
-	#print("RET:"+str(res.returncode))
-	return res.stdout.decode("utf-8")
-
-
-# Pinging Loop
-async def PingLoop():
-		print("PingLoop gestartet.")
-		# sleep for a moment
-		while True:
-			await asyncio.sleep(3)
-			# Sinnlos wenn niemend zuschaut:
-			if ( len(BroadcastHandler.clients) < 1 ):
-				continue
-			
-			for host, name in host_dict.items():
-				#print("ping host: " + host)
-				if ping(host,1,2):
-					line = {
-						"host": host, "status": "OK"
-					}
-					BroadcastHandler.broadcast(line)
-				else:
-					line = {
-						"host": host, "status": "FAILED"
-					}
-					BroadcastHandler.broadcast(line)
-		
-		# End while True
-		
-# Fping Loop
-async def FpingLoop():
-		print("FpingLoop ready.")
-		ip_list = list(host_dict.keys())
-		create_fpingparam()
-		
-		# check for ping command
-		if not cmd_exists(fping_cmd):
-			print("Exit with Error: fping command not found or not executable: '%s'" % fping_cmd)
-			sys.exit(1)
-
-		if args.v:
-			tmp_cmd = [] + fping_parameter + ip_list
-			comd_out = ' '.join(tmp_cmd)
-			comd_out.replace("'", "")
-			print('ping command used: "' + comd_out + '"')
-		
-		# The Loop
-		while True:
-			
-			# Sinnlos wenn niemend zuschaut:
-			if ( len(BroadcastHandler.clients) < 1 ):
-				await asyncio.sleep(3)
-				continue
-			
-			ac_time = datetime.now().strftime("%H:%M:%S")
-			if args.v: print("call fping: " + ac_time)
-			ret = fping(ip_list)
-			rl = ret.splitlines()
-			json_bc = []
-			for line in rl:
-				host,rtims = line.split(' : ')
-				if ( re.search(r"duplicate", rtims, flags=re.I) ):
-					#print(host+": "+rtims)
-					continue
-				host = host.strip()
-				rtims = rtims.strip()
-				ux_sect = 'ux_' + host_dict[host]
-				
-				if re.search(r"[\d\.]+ [\d\.]+ [\d\.]+", rtims):
-					#print(host+" OK")
-					json_bc.append({
-						"host": host, "status": "OK", "rtt": rtims, "actime": ac_time, "sect": ux_sect
-					})
-					failed_pingc[host] = 0
-					#BroadcastHandler.broadcast(line)
-				elif re.search(r"[\d\.]+ [\d\.]+ -", rtims) or re.search(r"[\d\.]+ - [\d\.]+", rtims) or re.search(r"- [\d\.]+ [\d\.]+", rtims):
-					#print(host+" OK")
-					json_bc.append({
-						"host": host, "status": "OK", "rtt": rtims, "actime": ac_time, "sect": ux_sect
-					})
-					failed_pingc[host] = 0
-					#BroadcastHandler.broadcast(line)
-				elif re.search(r"- - -", rtims):
-					#print(host+" FAILED")
-					if failed_pingc[host] < int(config["Main"]["FlashThreshold"]):
-						json_bc.append({
-							"host": host, "status": "NEWFAIL", "rtt": rtims, "actime": ac_time, "sect": ux_sect
-						})
-						failed_pingc[host] += 1
-					else:
-						json_bc.append({
-							"host": host, "status": "FAILED", "rtt": rtims, "actime": ac_time, "sect": ux_sect
-						})
-						failed_pingc[host] = int(config["Main"]["FlashThreshold"]) + 1
-					#BroadcastHandler.broadcast(line)
-				elif re.search(r"[\d\.]+", rtims):
-					#print(host+" HALB")
-					json_bc.append({
-						"host": host, "status": "HALB", "rtt": rtims, "actime": ac_time, "sect": ux_sect
-					})
-					failed_pingc[host] = 0
-					#BroadcastHandler.broadcast(line)
-				else:
-					print(host+" ???????????????????")
-				
-			#print(json.dumps(json_bc, separators=(',', ':'), ensure_ascii=False))
-			BroadcastHandler.broadcast(json_bc)
-			
-			# sleep for Config-LoopInterval
-			if ( len(BroadcastHandler.clients) >= 1 ):
-				await asyncio.sleep(loop_interval)
-		# End while True
-
-
-
-class BroadcastHandler(tornado.websocket.WebSocketHandler):
-	clients = []
-
-	def open(self):
-		o_time = datetime.now().strftime("%d.%m.%y %H:%M")
-		if not re.search(r"^/websocket$", self.request.uri):
-			log_msg = '"Bad request uri"'
-			print("%s: Client %s: WebSocket Open-Error: %s " % (o_time, self.request.remote_ip, log_msg))
-			self.close(1111)
-			return
-		BroadcastHandler.clients.append(self)
-		print("%s: Client %s: WebSocket opened: %s " % (o_time, self.request.remote_ip, self.request))		# oder "self.request.remote_ip" etc. / oder "self.__dict__"
-
-	def on_close(self):
-		BroadcastHandler.clients.remove(self)
-		c_time = datetime.now().strftime("%d.%m.%y %H:%M")
-		if ( self.close_code ):
-			print("%s: Client %s: WebSocket closed: %s (close_code: %d)" % (c_time, self.request.remote_ip, self.request, self.close_code))
-		else:
-			print("%s: Client %s: WebSocket undefined closed." % (c_time, self.request.remote_ip))
-		
-
-	@classmethod
-	def broadcast(cls, message):
-		errored = []
-		for client in cls.clients:
-			#print("Broadcasted: %s" % message)
-			#print("Broadcasted: %s" % client.request.remote_ip)
-			try:
-				client.write_message(json.dumps(message, separators=(',', ':'), ensure_ascii=False))
-				#print("Broadcasted: %s" % message)
-			except tornado.websocket.WebSocketClosedError:
-				print("Error sending Broadcast message: WebSocketClosedError() raised")
-				errored.append(client)
-			except tornado.websocket.Exception as e:
-				print("Error sending message: " + str(e))
-				errored.append(client)
-				
-		for conn in errored:
-			cls.clients.remove(conn)
-
-class WWWSocketHandler(tornado.web.RequestHandler):
-	#@tornado.gen.coroutine
-	def prepare(self):
-		#if self.request.protocol == 'http':
-		#	print("mmmm" + self.request.protocol)
-		pass
-			
-	def get(self):
-		#print(self.request.headers)
-		#print(self.__dict__)
-		if not re.search(r"^/$", self.request.uri):
-			return
-		html_modal01 = create_html_modal01()
-		html_tab = create_html_table()
-		self.write(html_html % (config["Main"]["TitleAdd"], ws_method, self.request.host, html_css, html_tab, html_modal01))
-	def on_connection_close(self):
-		print("RequestHandler on_connection_close(): " + str(self.__dict__))
-
-async def test():
-	while True:
-		print("test")
-		await asyncio.sleep(5)
-		
-	
-def make_app():
-	abs_path = os.path.dirname(os.path.abspath(__file__))
-	web_app = tornado.web.Application([
-		(r"^/websocket$", BroadcastHandler),
-		(r"/", WWWSocketHandler),
-		(r'/css/(.+\.css)', tornado.web.StaticFileHandler, {'path': abs_path + '/'}),
-		(r'/img/(.+\.gif)', tornado.web.StaticFileHandler, {'path': abs_path + '/'}),
-		(r'/(favicon.ico)', tornado.web.StaticFileHandler, {'path': abs_path + '/'}),
-	],debug=False,websocket_ping_interval=10,websocket_ping_timeout=30)
-	
-	if ws_method == 'ws':
-		# http method in use:
-		print("Serving HTTP and ws.")
-		print("Listen on "+listen_addr+" Port "+str(listen_port)+" (http://"+listen_addr+":"+str(listen_port)+"/).")
-		return web_app
-	
-	# https method in use:
-	print("Serving HTTPS and wss.")
-	print("Listen on "+listen_addr+" Port "+str(listen_port)+" (https://"+listen_addr+":"+str(listen_port)+"/).")
-	http_server = tornado.httpserver.HTTPServer(web_app,
-	    ssl_options = {
-	    "certfile": abs_path + '/' + s_certfile,
-	    "keyfile": abs_path + '/' + s_keyfile,
-	    }
-	)
-	
-	return http_server
-	
-	
-async def main():
-	app = make_app()
-	try:
-		app.listen(int(listen_port), str(listen_addr))
-	except OSError as e:
-		if e.errno == errno.EADDRINUSE:
-			print("listen(): 'EADDRINUSE': " + str(e.args[1]))
-			sys.exit(1)
-		else:
-			raise
-			
-	#await asyncio.gather(PingLoop(), return_exceptions=True)
-	
-	#await asyncio.gather(PingLoop())
-	await asyncio.gather(FpingLoop())
-		
-
-
-# ------ Div -------------------------------
-
-
-def create_html_table():
-	html_tab = ""
-	html_tab += '<div id="top_header" class="top_header w3-black">'
-	html_tab += '<span class="w3-left tbars" style="text-align: left;">V'+VERSION+' by <a href="https://pss.zweiernet.ch" target="_blank">PSS</a><br><span style="font-size:1em;opacity:0.8;background-color:#4e4ec4;cursor:pointer;" onclick="document.getElementById(\'modal_01\').style.display=\'block\'">&nbsp;<span class="w3-text-white w3-monospace"><b>i</b></span> &#x2754; </span></span>'
-	html_tab += '<span class="w3-center top_head_tit">PingPanel<span class="top_head_tit_pfix"> ' + config["Main"]["TitleAdd"] + '</span></span>'
-	html_tab += '<span class="w3-right tbars"><span id="cur_actime" style="text-align: right;color: #22ff00;font-weight: bold;"> </span><br><button id="close_button" onclick="socket_close(1000)" class="sbutt">stop</button><br></span>'
-	html_tab += '</div>\n'
-	html_tab += '<div class="w3-container">'
-	for sect in config.sections():
-		if (sect == "Main"):
-			continue
-		html_tab += '<div class="w3-container" style="padding: 0;font-size:14px;">'
-		sect_x = sect.replace(' ','_')
-		clickId = 'accord_' + sect_x
-		html_tab += '<br><div onclick="Accordion(\'' + clickId + '\')" class="w3-container w3-teal" style="padding: 3px 10px;margin-top: 5px;box-shadow: 0 2px 5px 0 #04040424,0 2px 10px 0 #040404c4;letter-spacing: 2px;cursor: pointer;text-shadow: 0 0 0px #fff;">' + sect + '<span id="ux_' + sect_x + '" class="w3-right"></span></div>\n'
-		html_tab += '<div id="' + clickId + '" class="w3-show">'
-		for key in config[sect]:
-			tkey = key.replace('.', '_')
-			html_tab += '<div class="w3-left si3-dark-grey w3-border w3-border-teal tooltip" style="text-align: center;margin: 1px; min-width: 13ch; padding: 4px min(3px, 1vw) !important;box-shadow:3px 2px 4px #000 !important;">'
-			html_tab += '<span class="w3-card-2 tooltiptext">'+config[sect][key]+'<br><span id="ttip_' + tkey + '" class="ttip_small"></span></span>'
-			html_tab += '<span id="' + tkey + '" class="ip_num">' + key + '</span><br><span id="stat_' + tkey + '" class="w3-center"></span></div>'
-		html_tab += '</div>\n</div>\n'
-	html_tab += '</div>\n'
-
-	
-	return html_tab
-		
-		
-		
-
-html_html = '''
-<!doctype html>
-<html>
-    <header>
-    	<title>PingPanel %s</title>
-		<meta name="viewport" content="width=device-width, initial-scale=1">
-		<meta charset="UTF-8"> 
-        <script type="text/javascript">
-        	window.onload = start_websocket();
-        	function start_websocket() {
-            	var ws = new WebSocket("%s://%s/websocket");
-            	ws.onmessage = function (evt) {
-            		//let test = evt.data.replace(/'/g, '"');		// needed " by JSON.parse
-            		//var json_arr = JSON.parse(test);
-            		var json_arr = JSON.parse(evt.data);
-            		var cur_actime = "";
-            		
-            		// Colortable counters initialisation
-            		let M_red = new Map();
-            		let M_green = new Map();
-            		let M_yellow = new Map();
-            		for( let i = 0; i < json_arr.length; i++ ) {
-            			if ( M_red.has(json_arr[i].sect) ) {
-            				continue;
-            			} else {
-            				M_red.set(json_arr[i].sect, 0);
-            				M_green.set(json_arr[i].sect, 0);
-            				M_yellow.set(json_arr[i].sect, 0);
-            			}
-            		}
-
-            		// DOM Updates
-            		for(let i = 0; i < json_arr.length; i++) {
-            			var data_obj = json_arr[i];
-            			cur_actime = data_obj.actime;
-            	   		var cur_host = data_obj.host;
-            	   		var cur_status = data_obj.status;
-            	   		var cur_sect_ux = data_obj.sect;
-            	   		var cur_rtt = data_obj.rtt;
-            	   		cur_rtt = cur_rtt.replace(/ /g,' \/ ');
-            	   		var uc_cur_host = cur_host.replace(/\./g,'_');
-            	   		document.getElementById(uc_cur_host).textContent = cur_host;
-            	   		var stat_id = 'stat_' + uc_cur_host;
-            	   		var ttip_id = 'ttip_' + uc_cur_host;
-            	   		if (cur_status == 'OK') {
-            	   			M_green.set(cur_sect_ux, M_green.get(cur_sect_ux) + 1);
-            	   			document.getElementById(stat_id).innerHTML = '<img src="/img/green_on.gif">';
-            	   			document.getElementById(ttip_id).innerHTML = '<b>RTT</b>: '+cur_rtt;
-            	   		} else if (cur_status == 'FAILED') {
-            	   			M_red.set(cur_sect_ux, M_red.get(cur_sect_ux) + 1);
-            	   			document.getElementById(stat_id).innerHTML = '<img src="/img/red_on.gif">';
-            	   			document.getElementById(ttip_id).innerHTML = '<b>RTT</b>: '+cur_rtt;
-            	   		} else if (cur_status == 'NEWFAIL') {
-            	   			M_red.set(cur_sect_ux, M_red.get(cur_sect_ux) + 1);
-            	   			document.getElementById(stat_id).innerHTML = '<img src="/img/red_anim.gif">';
-            	   			document.getElementById(ttip_id).innerHTML = '<b>RTT</b>: '+cur_rtt;
-            	   		} else {
-            	   			M_yellow.set(cur_sect_ux, M_yellow.get(cur_sect_ux) + 1);
-            	   			document.getElementById(stat_id).innerHTML = '<img src="/img/yellow_on.gif">';
-            	   			document.getElementById(ttip_id).innerHTML = '<b>RTT</b>: '+cur_rtt;
-            	   		}
-            	   	} // End for
-            	   	document.getElementById('cur_actime').innerHTML = cur_actime;
-            	   	for (let [sect, val] of M_red) {
-            	   		document.getElementById(sect).innerHTML = '<span class="unreach_r"><span class="red_r">'+M_red.get(sect).toString().padStart(3, " ")+'</span> | <span class="yellow_r">'+M_yellow.get(sect).toString().padStart(3, " ")+'</span> | <span class="green_r">'+M_green.get(sect).toString().padStart(3, " ")+'</span></span>';
-            	   	}
-            	};
-            	
-            	ws.onclose = function(evt) {
-   					//alert("WebSocket closed.");
-   					document.getElementById('cur_actime').innerHTML = '<span style="color:red;">stopped</span>';
-   					document.getElementById('close_button').style.opacity = "0.3";
-   					//document.getElementById('modal_alert_text').style.display='block';
-   					//document.getElementById('modal_alert_text').innerHTML = 'WebSocket closed.';
-				};
-				ws.onerror = function(evt) {
-   					alert("WebSocket closed due to an error.");
-   					document.getElementById('cur_actime').innerHTML = '<span style="color:red;">Error</span>';
-   					document.getElementById('close_button').style.opacity = "0.3";
-				};
-				socket_close = (code) => {
-					document.getElementById('close_button').style.opacity = "0.3";
-					ws.close(code);
-				};
-            };
-            
-            function Accordion(id) {
-            	var x = document.getElementById(id);	//alert(x);   //.previousSibling.getElementsByTagName("*").item(0).innerHTML);
-				if (x.className.indexOf("w3-show") == -1) {
-					x.className = "w3-show";
-				} else { 
-					x.className = x.className.replace("w3-show", "w3-hide");
-				}
-			};
-        </script>
-        <script>
-        // modal handling
-		var modal = document.getElementById('modal_01');
-		// When the user clicks anywhere outside of the modal, close it
-		window.onclick = function(event) {
-			if (event.target == modal) {
-		    	modal.style.display = "none";
-			}
-		}
-        </script>
-        
-        <link rel="stylesheet" href="/css/w3.css">
-        <style>
-        	%s
-        </style>
-    </header>
-    <body>
-        <div id="main">%s</div>\n
-        <p><br></p>
-        
-        <div id="modal_01" class="w3-modal modal_01" onclick="this.style.display='none'">
-        	<div class="w3-modal-content modal_01_text">
-    			<div class="w3-container">
-  					<h4 style="font-variant:small-caps;letter-spacing:3px;">PingPanel</h4>
-  					%s
-  				</div>
-  			</div>
-		</div>
-    </body>
-</html>
-'''
-
-html_css = '''
-body {
-    background: #333;
-    font-family: Verdana, Arial, sans-serif;
-    color: #ddd;
-    line-height: 110%;
-    font-size: 13px;
-}
-.red { color: red; }
-.green { color: #0f0; }
-.yellow { color: yellow; }
-.red_r { color: red; white-space: pre; text-align: right; font-family: monospace;text-shadow: 0px -0px 0px #f44;}
-.green_r { color: #0f0; white-space: pre; text-align: right;; font-family: monospace;}
-.yellow_r { color: yellow; white-space: pre; text-align: right;; font-family: monospace;}
-.ip_num { font-size: 80%; }
-
-.si3-dark-grey{color:#fff!important;background-color:#626262!important;text-shadow: 0 0 0px #fff, 0 0 1px #000;}
-
-.top_header {
-  text-align: center;
-  padding: 5px 10px; height: 43px;
-  box-shadow: 0px 1px 9px 1px #c3d0cd78 !important;
-  position: sticky;
-  z-index: 100;
-  top: 0px;
-}
-
-.tbars {
-  color: #aaa;
-  font-size: 11px;
-  font-stretch: semi-expanded;
-}
-
-.unreach_r {
-  background-color:#313131;
-  padding-left:5px;
-  padding-right:5px;
-  letter-spacing: 0px;
-  border-radius: 2px;
-  font-weight: bold;
-  font-size: 12px;
-}
-
-.modal_01 {
-  
-}
-.modal_01_text {
-  background-color: #000;
-  color: #f0f0ca;
-  line-height: 120%;
-  font-size: 1.1em;
-}
-
-.sbutt {
-  border: none;
-  display: inline-block;
-  vertical-align: middle;
-  overflow: hidden;
-  text-decoration: none;
-  text-align: center;
-  cursor: pointer;
-  white-space: nowrap;
-  border-radius: 4px;
-  padding: 0px 8px !important;
-  background-color: #9b9b9b !important;
-  color: #000 !important;
-}
-
-.top_head_tit {
-  font-size: 22px;
-  font-variant: small-caps;
-  letter-spacing: 4px;
-  top: 0.3em;
-  position: sticky;
-}
-.top_head_tit_pfix {
-  font-size: 0.5em;
-  font-variant: small-caps;
-  letter-spacing: 0px;
-}
-
-.ttip_small {
-  font-size: 64%;
-  text-align: center;
-  padding-top: 6px;
-}
- 
-
-.tooltip {
-  position: relative;
-  display: inline-block;
-  border-bottom: 1px dotted black;
-}
-
-.tooltip .tooltiptext {
-  font-family: Verdana, 'PT Sans Caption', Arial, sans-serif;
-  visibility: hidden;
-  width: 170px;
-  background-color: black;
-  color: #fff;
-  text-align: center;
-  font-size: 17px;
-  border-radius: 6px;
-  padding: 5px 5px;
-  position: absolute;
-  z-index: 1;
-  top: 120%;
-  left: 50%;
-  margin-left: -60px;
-  line-height: 1.1em;
-  text-shadow: 0 0 0 #a8a8a8 !important;
-}
-
-.tooltip .tooltiptext::after {
-  content: "";
-  position: absolute;
-  bottom: 100%;
-  left: 50%;
-  margin-left: -5px;
-  border-width: 5px;
-  border-style: solid;
-  border-color: transparent transparent black transparent;
-}
-
-.tooltip:hover .tooltiptext {
-  visibility: visible;
-}
-
-.sticky {
-  position: fixed;
-  top: 0;
-  width: 100%;
-}
-
-.sticky + .content {
-  padding-top: 50px;
-}
-
-'''
-
-def create_html_modal01():
-	html_modal = '''
-<p style="font-size:1.2em;font-variant:small-caps;letter-spacing:3px;font-style:italic;text-decoration:underline">Info</p>
- Config File: 
- 	''' + konfig_file + '''<br>
- Total number of Devices: _NUM_HOSTS_ <br>
- LoopInterval: 
- 	''' + str(loop_interval) + ''' s<br>
- FlashThreshold: 
- 	''' + str(config["Main"]["FlashThreshold"]) + ''' rounds<br>
- fping: 
-	''' + fping_parameter[2].replace('--','') + '''<br>
- fping: 
-	''' + fping_parameter[3].replace('--','') + ''' ms<br>
- fping: 
-	''' + fping_parameter[4].replace('--','') + ''' ms<br>
-<br> 
-
-<p style="font-size:1.2em;font-variant:small-caps;letter-spacing:3px;font-style:italic;text-decoration:underline">Help</p>
-The PingPanel board provides the header and the configured, expandable and collapsible sections with the corresponding devices to be monitored.<br>
-
-Among other things, the header contains the current time (<span class="green">green</span>) of the last ping run 
-or the status "stopped" (<span class="red">red</span>) if the connection to the server has been lost or the "Stop" button below has been pressed.<br>
-Pressing the "Stop" button terminates the connection to the server and, if no other client is active, the server pauses the ping rounds.<p>
-
-The blue-green <span class="w3-teal">section bars</span> contain the name of the section and consolidated information about the status of the devices in this section.<br>
-The section bars can be expanded and collapsed by clicking or tapping on them.<br>
-Consolidated status information <img src="/img/stat-inf.gif"> is divided into <span class="red">failed</span>, 
-<span class="yellow">partially answered</span> and <span class="green">answered</span> ping requests.<br>
-
-Each monitored device displays its IP address and status. By hovering over or tapping on it its comment 
-is displayed and the three ping RTT's of each ping round is reported.<p>
-
-A <span class="red">flashing red</span> status light indicates that the device has recently not responded during 'FlashThreshold' ping rounds.<br>
-A <span class="red">red</span> status light indicates that the device has not answered any of the three pings.<br>
-A <span class="yellow">yellow</span> status light indicates that the device has answered one of three pings.<br>
-A <span class="green">green</span> status light indicates that the device has answered to all three or at least two pings.<br>
-<p></p>
-<p> </p>
-
-
-
-
-
-
-
-
-	'''
-
-	html_modal = html_modal.replace('_NUM_HOSTS_', str(anz_hosts))
-
-	return html_modal
-
-
-
-# -------- MAIN ------------------------------
-if __name__ == "__main__":
-	
-	print("PingPanel v"+VERSION+" by PSS -- started at " + datetime.now().strftime("%F %H:%M:%S"))
-	# Commandline parsing
-	parser = argparse.ArgumentParser(description='PingPanel V'+VERSION+"\n2024 by sigi",
-                                   formatter_class=argparse.RawDescriptionHelpFormatter)
-	parser.add_argument('-c', help="Alternative configuration file (standard: config.cfg)", type=str, metavar='config-file')
-	parser.add_argument('-v', help="Verbose mode", action="store_true")
-	args = parser.parse_args()
-	if args.c:
-		konfig_file = args.c
-	print("Configfile: " + konfig_file)
-	
-	
-	# Config
-	read_config()
-	
-	
-	# create the app
-	asyncio.run(main())
-
-
-# ------
-
-

+ 0 - 18
contrib/PingPanel/opt/PingPanel/changelog

@@ -1,18 +0,0 @@
-v0.9.6 / 18.7.24, sigi:
-	- Corr: handling duplicate ping answers (ICMP replys).
-	- formatting status information fileds.
-	
-v0.9.7 / 30.7.24, sigi:
-	- Acceleration: relocation of json handling from frontend to backend.
-	- some CSS cosmetics.
-	
-v0.9.8 / 12.8.24, sigi:
-	- implementing secure HTTPS connections on both, webserver and websocket.
-	- Added HTTPS params in config.cfg.
-	- Changed: 'Title' param renamed to 'TitleAdd' in config.cfg as it is now an addendum to the title.
-	
-v0.9.9 / 1.4.25, sigi:
-	- Corr: configfile handling.
-	- Added: fping parameter --size can now be set in PingPanel's config.cfg.
-
-

+ 0 - 104
contrib/PingPanel/opt/PingPanel/config.cfg

@@ -1,104 +0,0 @@
-#-- Main Section:
-## ! Do not change nor delete the Main-Section name ([Main]) !
-## ! Do not use quotation marks, neither for keys nor for values !
-[Main]
-
-## The title addendum to PingPanel on top of the site and in the browser window title.
-## Pay attention to the length when using on smartphones.
-TitleAdd = 
-
-## Port the Webserver listen on:
-ListenPort = 8888
-
-## Address the Webserver is bound on:
-ListenAddr = 0.0.0.0
-
-## Using secure HTTPS conections:
-## Using HTTPS, comment out the following three parameters.
-## Of course, the file names are freely choosable here, relative to the current directory.
-#UseHTTPS = true
-#CertFile = server.crt
-#KeyFile = server.key
-
-
-## Location of the 'fping' command, without any quotation marks (defaults to: fping)
-fpingCommand = fping
-
-#-- fping related parameters (see https://fping.org/fping.8.html):
-## Fping-interval:
-##- from manpage - The minimum amount of time (in milliseconds) between sending a ping packet to any target
-##- from manpage - (default is 10, minimum is 1).
-## Increasing this value has a major impact on the runtime of a single ping round when a high number of hosts are pinged.
-## PingPanel default is 1.
-Fping-interval = 1
-
-## Fping-period:
-##- from manpage - This parameter sets the time in milliseconds that fping waits between successive
-##- from manpage - packets to an individual target. Default is 1000 and minimum is 10.
-## PingPanel default is 100.
-Fping-period = 100
-
-## Fping-size:
-##- from manpage - Number of bytes of ping data to send. The minimum size (normally 12) allows room for the data 
-##- from manpage - that fping needs to do its work (sequence number, timestamp). The reported received data size includes the 
-##- from manpage - IP header (normally 20 bytes) and ICMP header (8 bytes), so the minimum total size is 40 bytes. 
-##- from manpage - Default is 56, as in ping. Maximum is the theoretical maximum IP datagram size (64K), though most systems 
-##- from manpage - limit this to a smaller, system-dependent number.
-## PingPanel default is fping default 56.
-#Fping-size = 56
-
-#-- End fping related params
-
-
-## LoopInterval:
-## The time that the program sleeps (in seconds) between ping runs (default is 3).
-## Since the ping is executed asynchronously, this LoopInterval is the waiting time between two completed
-## consecutive ping subprocesses. The time required by the ping subprocess itself depends on the number of hosts
-## and the fping parameters defined above. Tip: fiddle around with the shown fping command (argument PingPanel -v)
-## within the Linux 'time' command to find the optimal value for your needs.
-LoopInterval = 3
-
-## FlashThreshold:
-## Number of ping rounds for which a host does not respond until the status light changes from flashing red to permanently red.
-FlashThreshold = 3
-
-
-#-- User specified sections follow
-## The following sections consist of a section name followed by IP-Addresses with an associated comment.
-## The section name must be in square brackets and is case-sensitive. At least one section name must exist.
-## IP-Addresses can be in IPv4 or in IPv6 format and are delimited by an equal-sign (=) from comment.
-## Everything after the equal-sign is considered a comment. HTML-Tags are allowed in comment, but be careful
-## not to overload the page.
-## The comment can be omitted.
-## Leading and trailing whitespace is removed from comment and IP-Address by the program.
-[LOCAL]
-192.168.1.1		= One
-192.168.1.2		= Two
-192.168.1.3		= Three
-192.168.1.4		= Four
-192.168.1.7		= Seven
-192.168.1.8		= Eight
-192.168.1.9	= 
-192.168.1.10	= Router Number Ten
-192.168.1.11	= Switch Number Eleven
-
-
-[Zum Fröhlichen Zehnernetz]
-10.0.0.1    = happy 1
-10.0.0.2    = happy 2
-10.0.0.3    = happy 3
-10.0.0.4    = happy 4
-10.0.0.5    = happy 5
-10.0.1.100  = 
-
-
-[REMOTE]
-212.51.140.225			= <span style="color: yellow">ZweierNet.ch</span>
-2a02:168:6229::10		= <span style="color: blue">ZweierNet.ch IPv6</span>
-8.8.8.8					= The Quad Eight
-2001:4860:4860::8888 	= Quad Eight IPv6
-9.9.9.9					= The Nines
-2620:fe::9				= The Nines IPv6
-1.1.1.1					= The One and One and One and One
-2606:4700:4700::1111 	= The Ones IPv6
-

+ 0 - 6
contrib/PingPanel/opt/PingPanel/create_server-certificate.sh

@@ -1,6 +0,0 @@
-#!/bin/bash
-
-openssl req  -nodes -new -x509 -days 3650 -keyout server.key -out server.crt
-
-echo "Server certificate created: 'server.crt', Keyfile: 'server.key'"
-

+ 0 - 14
contrib/PingPanel/opt/PingPanel/etc.example/default/pingpanel

@@ -1,14 +0,0 @@
-# /etc/default/pingpanel
-
-# Defaults for pingpanel initscript. This file is sourced by /etc/init.d/pingpanel.
-# all vars used in /etc/init.d/pingpanel can be set here.
-#
-
-# Configfile (Standard: config.cfg)
-CONFIG=/opt/PingPanel/config.cfg
-
-# the path to logfile
-LOGFILE=/var/log/pingpanel.log
-
-# Options to pass to PingPanel.py
-#PINGPANEL_OPTS=""

+ 0 - 79
contrib/PingPanel/opt/PingPanel/etc.example/init.d/pingpanel

@@ -1,79 +0,0 @@
-#!/bin/sh
-#
-# /etc/init.d/pingpanel                  Startup script for the PingPanel process
-#
-### BEGIN INIT INFO
-# Provides:          pingpanel
-# Required-Start:    $remote_fs
-# Required-Stop:     $remote_fs
-# Default-Start:     2 3 4 5
-# Default-Stop:      0 1 6
-# Short-Description: PingPanel monitoring of network devices
-# Description:       PingPanel is a utility for monitoring network devices
-#                    and provides a web-based service, the panel, for
-#                                        displaying the captured statuses.
-### END INIT INFO
-
-. /lib/lsb/init-functions
-
-DAEMON=/opt/PingPanel/PingPanel.py
-CONFIG=/opt/PingPanel/config.cfg
-NAME=pingpanel
-DESC="PingPanel monitor service"
-LOGFILE=/var/log/pingpanel.log
-PINGPANEL_OPTS=
-
-set -e
-
-# Check if DAEMON binary exist
-[ -f $DAEMON ] || exit 0
-
-[ -f "/etc/default/$NAME" ] && . /etc/default/$NAME
-
-PINGPANEL_OPTS="-c $CONFIG $PINGPANEL_OPTS"
-
-case "$1" in
-  start)
-    log_daemon_msg "Starting $DESC" "$NAME"
-	
-	start_daemon /usr/bin/python3 -u $DAEMON $PINGPANEL_OPTS 1>>$LOGFILE 2>>$LOGFILE &
-
-    if pgrep -f $DAEMON
-    then
-      log_success_msg "$DAEMON running."
-    else
-      log_failure_msg "$DAEMON start FAILED!"
-    fi
-    ;;
-  stop)
-    log_daemon_msg "Stopping $DESC" "$NAME"
-
-    kill -9 $(pgrep -f $DAEMON)
-    if pgrep -f $DAEMON
-    then
-      log_end_msg 1
-    else
-      log_end_msg 0
-    fi
-    ;;
-  restart)
-    $0 stop
-    sleep 2
-    $0 start
-    ;;
-  status)
-    if pgrep -f $DAEMON
-	then
-      log_end_msg 0
-      exit 0
-    else
-      log_end_msg 1
-      exit 1
-    fi
-    ;;
-  *)
-    log_action_msg "Usage: /etc/init.d/$NAME {start|stop|restart|status}"
-    ;;
-esac
-
-exit 0

BIN
contrib/PingPanel/opt/PingPanel/favicon.ico


BIN
contrib/PingPanel/opt/PingPanel/green_on.gif


BIN
contrib/PingPanel/opt/PingPanel/red_anim.gif


BIN
contrib/PingPanel/opt/PingPanel/red_on.gif


+ 0 - 20
contrib/PingPanel/opt/PingPanel/server.crt

@@ -1,20 +0,0 @@
------BEGIN CERTIFICATE-----
-MIIDQTCCAimgAwIBAgIUAjtvqb5ffp4CZ96HrvIu+7rCY1wwDQYJKoZIhvcNAQEL
-BQAwMDELMAkGA1UEBhMCY2gxEzARBgNVBAgMClNvbWUtU3RhdGUxDDAKBgNVBAoM
-A1BTUzAeFw0yNDAyMTMxNzQzMDFaFw0zNDAyMTAxNzQzMDFaMDAxCzAJBgNVBAYT
-AmNoMRMwEQYDVQQIDApTb21lLVN0YXRlMQwwCgYDVQQKDANQU1MwggEiMA0GCSqG
-SIb3DQEBAQUAA4IBDwAwggEKAoIBAQDmRv9bQ9mGOrgxxXX/5ilhmZu0dCsn7j43
-Vv2dQ1ZTnW6k3DZzFk693xFbtJ+2EJkHhUhqS0IQbZI9fhnKR6yfMUJ7uip1ifdd
-bnrMH6H+xRHjbf+Gjmh6N2x5q0x0woCUo/gcvbQuJdY8EoC57TuuBNx83/G3pIi6
-Pute7K6H4S9bnKkB/Xf2UohxNCmU5fUMikgXoRMjqt9xV8gRV62CT+MFJ4z8am0L
-6f5okMsx17zJCGECcVVMMPEQdhv1s3cjvVJqcPEoAdLAPZPIy9JPk28dF1evjw+w
-IBnITNYY1z/k52sizKMWC/lu0d51TMGTQUvcs/X2OH3Yl+WUNQcRAgMBAAGjUzBR
-MB0GA1UdDgQWBBTHgEb2mzUty1qi2SF1oguPF++MxTAfBgNVHSMEGDAWgBTHgEb2
-mzUty1qi2SF1oguPF++MxTAPBgNVHRMBAf8EBTADAQH/MA0GCSqGSIb3DQEBCwUA
-A4IBAQDlI21Lsa+Iz4KVGCoSSC39U2a27c549vQTaY9BsRhEpNh+U515CIHCLBoI
-ADK9Jh76DF/ie6BoHRPaCkoK3CSBOLOr4uB8jUSZrOT67RmnerZIcQQYboquNJFC
-nV97RpL2ri0UdzoocvF6GHms+kNccq81D1p5SmMJSdEj5YVtzQMzpLzmOaWIqN2J
-ld0TGvce6rId9JxIXUOcahgod0GWYsMZdgCs8i+SFgLm8BQPmdk/JybTiWRjcW+c
-q3xL2mGQDoHd01m1YRKKKgHjguAAVkrDSRc3ulGPjLR1w222ugtHIfB6gvYRJ8WI
-DgbnzF+V8eoe6w7W1bqjZ8a3D6XW
------END CERTIFICATE-----

+ 0 - 28
contrib/PingPanel/opt/PingPanel/server.key

@@ -1,28 +0,0 @@
------BEGIN PRIVATE KEY-----
-MIIEwAIBADANBgkqhkiG9w0BAQEFAASCBKowggSmAgEAAoIBAQDmRv9bQ9mGOrgx
-xXX/5ilhmZu0dCsn7j43Vv2dQ1ZTnW6k3DZzFk693xFbtJ+2EJkHhUhqS0IQbZI9
-fhnKR6yfMUJ7uip1ifddbnrMH6H+xRHjbf+Gjmh6N2x5q0x0woCUo/gcvbQuJdY8
-EoC57TuuBNx83/G3pIi6Pute7K6H4S9bnKkB/Xf2UohxNCmU5fUMikgXoRMjqt9x
-V8gRV62CT+MFJ4z8am0L6f5okMsx17zJCGECcVVMMPEQdhv1s3cjvVJqcPEoAdLA
-PZPIy9JPk28dF1evjw+wIBnITNYY1z/k52sizKMWC/lu0d51TMGTQUvcs/X2OH3Y
-l+WUNQcRAgMBAAECggEBAIWTqYzHTucOKMq2QDywxlBXSnri6CXBjVWMoJEY/nqC
-WCxJkUwxJHv/aZJItFxoRFyYc+k0vp3I8Yu6Gju8V+YALRCYbQjBfzwzWggOUWn3
-5uiGZjMnaHN8su/g7fjM2sleVA5X/KzIRf2SvhkcBAJtz3igbxaX2rgux1nI8XTf
-kVXVwbYZEj0bpg6JoEa8mQ2NxxykBAlTEbKm/vY9PMKtBbRUvmkThRBPRXk0C/zz
-nOvqW3qyuYlZ3rC0UXJ/YEo9QiNOlbYg2qiizAJ3zSDD7K4rgXXFFI/wYP2PiHyT
-nQ2zRiuG4e9ey2xS5eAKc827BShhLfO2WmSRZRDyAAECgYEA+JtkPGWBfcwM/wN0
-BUUfLAJWgOjdKKWMpmHR7LKsPQfqyEFZLkTPTzi7y43PPIoztpkmXDMTrj/+WjPS
-lOizzvhh+N4+ov+HBqOinFyQ45p7QCvz3ft1x9173aFlmjjKQNjWg/jexMqarYHU
-RsiThQPzIsDMHXhrDWU/cbnVEXECgYEA7SAQnamqCRmV5IL6cHv4/tfyj7tnd4wv
-R6zg48re0CfMDS4URwc3QA/Pqwo1BiLnFQ8UZKsRcu0JYHzVgZ4f2odjBiZfmtcW
-sp7HAKc/kXN4oazhpXBkM2zl2El8T55aZkHUAGJMl64hmduMH4Ut5cVLBDzVKc4m
-jnAIqDNuf6ECgYEArlkD5dtmAdv9bUZ1slB0eP+2vLcSirP3PKQzfaUcZ7zKqeAy
-c+Fr5eoqwalVIebmN3OWVGi5r6VPcuEPGMFNgKPuyYLLOLKtdjmCC9hbAFPRhgKN
-ByuXwTAR8y+COrMDHJE1d94sFKTl7zKytWVrF4jalY/SVgSiRwWvhclGpPECgYEA
-ncR7yaqc6zkOtd8/aZ/SZxye0mrJyIyI2JN5fZX48V3JMeu6qhdu9zyN2ysLZG3M
-egJyexgmn+R+HKhyFa9zWh5CEFFvwsHg5C8oEJM2hDvjww4Xg89nm5+UvXcHMqIV
-W3vo5eiBNVoyGQAuFrqxcvL1mngvC4WRuato1yCBIIECgYEApsoZlRbXM4qMxw8Y
-OFireME2BrSORuguP/AVO/mghE4kOzi5JlJW44kt4fEFqDKaEmnL81C4El4mVWG9
-RozIXpXmZycsxfg8mihtZbgKOkicucup2/jVhcGup/Z0ZJemwBw/M7jJOFrfhJwJ
-U5zQfe8TG0JOLcK41N2c2lXn6Xo=
------END PRIVATE KEY-----

BIN
contrib/PingPanel/opt/PingPanel/stat-inf.gif


+ 0 - 236
contrib/PingPanel/opt/PingPanel/w3.css

@@ -1,236 +0,0 @@
-/* W3.CSS 4.15 December 2020 by Jan Egil and Borge Refsnes */
-html{box-sizing:border-box}*,*:before,*:after{box-sizing:inherit}
-/* Extract from normalize.css by Nicolas Gallagher and Jonathan Neal git.io/normalize */
-html{-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0}
-article,aside,details,figcaption,figure,footer,header,main,menu,nav,section{display:block}summary{display:list-item}
-audio,canvas,progress,video{display:inline-block}progress{vertical-align:baseline}
-audio:not([controls]){display:none;height:0}[hidden],template{display:none}
-a{background-color:transparent}a:active,a:hover{outline-width:0}
-abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted}
-b,strong{font-weight:bolder}dfn{font-style:italic}mark{background:#ff0;color:#000}
-small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline}
-sub{bottom:-0.25em}sup{top:-0.5em}figure{margin:1em 40px}img{border-style:none}
-code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}hr{box-sizing:content-box;height:0;overflow:visible}
-button,input,select,textarea,optgroup{font:inherit;margin:0}optgroup{font-weight:bold}
-button,input{overflow:visible}button,select{text-transform:none}
-button,[type=button],[type=reset],[type=submit]{-webkit-appearance:button}
-button::-moz-focus-inner,[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner{border-style:none;padding:0}
-button:-moz-focusring,[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring{outline:1px dotted ButtonText}
-fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:.35em .625em .75em}
-legend{color:inherit;display:table;max-width:100%;padding:0;white-space:normal}textarea{overflow:auto}
-[type=checkbox],[type=radio]{padding:0}
-[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto}
-[type=search]{-webkit-appearance:textfield;outline-offset:-2px}
-[type=search]::-webkit-search-decoration{-webkit-appearance:none}
-::-webkit-file-upload-button{-webkit-appearance:button;font:inherit}
-/* End extract */
-html,body{font-family:Verdana,sans-serif;font-size:15px;line-height:1.5}html{overflow-x:hidden}
-h1{font-size:36px}h2{font-size:30px}h3{font-size:24px}h4{font-size:20px}h5{font-size:18px}h6{font-size:16px}
-.w3-serif{font-family:serif}.w3-sans-serif{font-family:sans-serif}.w3-cursive{font-family:cursive}.w3-monospace{font-family:monospace}
-h1,h2,h3,h4,h5,h6{font-family:"Segoe UI",Arial,sans-serif;font-weight:400;margin:10px 0}.w3-wide{letter-spacing:4px}
-hr{border:0;border-top:1px solid #eee;margin:20px 0}
-.w3-image{max-width:100%;height:auto}img{vertical-align:middle}a{color:inherit}
-.w3-table,.w3-table-all{border-collapse:collapse;border-spacing:0;width:100%;display:table}.w3-table-all{border:1px solid #ccc}
-.w3-bordered tr,.w3-table-all tr{border-bottom:1px solid #ddd}.w3-striped tbody tr:nth-child(even){background-color:#f1f1f1}
-.w3-table-all tr:nth-child(odd){background-color:#fff}.w3-table-all tr:nth-child(even){background-color:#f1f1f1}
-.w3-hoverable tbody tr:hover,.w3-ul.w3-hoverable li:hover{background-color:#ccc}.w3-centered tr th,.w3-centered tr td{text-align:center}
-.w3-table td,.w3-table th,.w3-table-all td,.w3-table-all th{padding:8px 8px;display:table-cell;text-align:left;vertical-align:top}
-.w3-table th:first-child,.w3-table td:first-child,.w3-table-all th:first-child,.w3-table-all td:first-child{padding-left:16px}
-.w3-btn,.w3-button{border:none;display:inline-block;padding:8px 16px;vertical-align:middle;overflow:hidden;text-decoration:none;color:inherit;background-color:inherit;text-align:center;cursor:pointer;white-space:nowrap}
-.w3-btn:hover{box-shadow:0 8px 16px 0 rgba(0,0,0,0.2),0 6px 20px 0 rgba(0,0,0,0.19)}
-.w3-btn,.w3-button{-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none}   
-.w3-disabled,.w3-btn:disabled,.w3-button:disabled{cursor:not-allowed;opacity:0.3}.w3-disabled *,:disabled *{pointer-events:none}
-.w3-btn.w3-disabled:hover,.w3-btn:disabled:hover{box-shadow:none}
-.w3-badge,.w3-tag{background-color:#000;color:#fff;display:inline-block;padding-left:8px;padding-right:8px;text-align:center}.w3-badge{border-radius:50%}
-.w3-ul{list-style-type:none;padding:0;margin:0}.w3-ul li{padding:8px 16px;border-bottom:1px solid #ddd}.w3-ul li:last-child{border-bottom:none}
-.w3-tooltip,.w3-display-container{position:relative}.w3-tooltip .w3-text{display:none}.w3-tooltip:hover .w3-text{display:inline-block}
-.w3-ripple:active{opacity:0.5}.w3-ripple{transition:opacity 0s}
-.w3-input{padding:8px;display:block;border:none;border-bottom:1px solid #ccc;width:100%}
-.w3-select{padding:9px 0;width:100%;border:none;border-bottom:1px solid #ccc}
-.w3-dropdown-click,.w3-dropdown-hover{position:relative;display:inline-block;cursor:pointer}
-.w3-dropdown-hover:hover .w3-dropdown-content{display:block}
-.w3-dropdown-hover:first-child,.w3-dropdown-click:hover{background-color:#ccc;color:#000}
-.w3-dropdown-hover:hover > .w3-button:first-child,.w3-dropdown-click:hover > .w3-button:first-child{background-color:#ccc;color:#000}
-.w3-dropdown-content{cursor:auto;color:#000;background-color:#fff;display:none;position:absolute;min-width:160px;margin:0;padding:0;z-index:1}
-.w3-check,.w3-radio{width:24px;height:24px;position:relative;top:6px}
-.w3-sidebar{height:100%;width:200px;background-color:#fff;position:fixed!important;z-index:1;overflow:auto}
-.w3-bar-block .w3-dropdown-hover,.w3-bar-block .w3-dropdown-click{width:100%}
-.w3-bar-block .w3-dropdown-hover .w3-dropdown-content,.w3-bar-block .w3-dropdown-click .w3-dropdown-content{min-width:100%}
-.w3-bar-block .w3-dropdown-hover .w3-button,.w3-bar-block .w3-dropdown-click .w3-button{width:100%;text-align:left;padding:8px 16px}
-.w3-main,#main{transition:margin-left .4s}
-.w3-modal{z-index:3;display:none;padding-top:100px;position:fixed;left:0;top:0;width:100%;height:100%;overflow:auto;background-color:rgb(0,0,0);background-color:rgba(0,0,0,0.4)}
-.w3-modal-content{margin:auto;background-color:#fff;position:relative;padding:0;outline:0;width:600px}
-.w3-bar{width:100%;overflow:hidden}.w3-center .w3-bar{display:inline-block;width:auto}
-.w3-bar .w3-bar-item{padding:8px 16px;float:left;width:auto;border:none;display:block;outline:0}
-.w3-bar .w3-dropdown-hover,.w3-bar .w3-dropdown-click{position:static;float:left}
-.w3-bar .w3-button{white-space:normal}
-.w3-bar-block .w3-bar-item{width:100%;display:block;padding:8px 16px;text-align:left;border:none;white-space:normal;float:none;outline:0}
-.w3-bar-block.w3-center .w3-bar-item{text-align:center}.w3-block{display:block;width:100%}
-.w3-responsive{display:block;overflow-x:auto}
-.w3-container:after,.w3-container:before,.w3-panel:after,.w3-panel:before,.w3-row:after,.w3-row:before,.w3-row-padding:after,.w3-row-padding:before,
-.w3-cell-row:before,.w3-cell-row:after,.w3-clear:after,.w3-clear:before,.w3-bar:before,.w3-bar:after{content:"";display:table;clear:both}
-.w3-col,.w3-half,.w3-third,.w3-twothird,.w3-threequarter,.w3-quarter{float:left;width:100%}
-.w3-col.s1{width:8.33333%}.w3-col.s2{width:16.66666%}.w3-col.s3{width:24.99999%}.w3-col.s4{width:33.33333%}
-.w3-col.s5{width:41.66666%}.w3-col.s6{width:49.99999%}.w3-col.s7{width:58.33333%}.w3-col.s8{width:66.66666%}
-.w3-col.s9{width:74.99999%}.w3-col.s10{width:83.33333%}.w3-col.s11{width:91.66666%}.w3-col.s12{width:99.99999%}
-@media (min-width:601px){.w3-col.m1{width:8.33333%}.w3-col.m2{width:16.66666%}.w3-col.m3,.w3-quarter{width:24.99999%}.w3-col.m4,.w3-third{width:33.33333%}
-.w3-col.m5{width:41.66666%}.w3-col.m6,.w3-half{width:49.99999%}.w3-col.m7{width:58.33333%}.w3-col.m8,.w3-twothird{width:66.66666%}
-.w3-col.m9,.w3-threequarter{width:74.99999%}.w3-col.m10{width:83.33333%}.w3-col.m11{width:91.66666%}.w3-col.m12{width:99.99999%}}
-@media (min-width:993px){.w3-col.l1{width:8.33333%}.w3-col.l2{width:16.66666%}.w3-col.l3{width:24.99999%}.w3-col.l4{width:33.33333%}
-.w3-col.l5{width:41.66666%}.w3-col.l6{width:49.99999%}.w3-col.l7{width:58.33333%}.w3-col.l8{width:66.66666%}
-.w3-col.l9{width:74.99999%}.w3-col.l10{width:83.33333%}.w3-col.l11{width:91.66666%}.w3-col.l12{width:99.99999%}}
-.w3-rest{overflow:hidden}.w3-stretch{margin-left:-16px;margin-right:-16px}
-.w3-content,.w3-auto{margin-left:auto;margin-right:auto}.w3-content{max-width:980px}.w3-auto{max-width:1140px}
-.w3-cell-row{display:table;width:100%}.w3-cell{display:table-cell}
-.w3-cell-top{vertical-align:top}.w3-cell-middle{vertical-align:middle}.w3-cell-bottom{vertical-align:bottom}
-.w3-hide{display:none!important}.w3-show-block,.w3-show{display:block!important}.w3-show-inline-block{display:inline-block!important}
-@media (max-width:1205px){.w3-auto{max-width:95%}}
-@media (max-width:600px){.w3-modal-content{margin:0 10px;width:auto!important}.w3-modal{padding-top:30px}
-.w3-dropdown-hover.w3-mobile .w3-dropdown-content,.w3-dropdown-click.w3-mobile .w3-dropdown-content{position:relative}	
-.w3-hide-small{display:none!important}.w3-mobile{display:block;width:100%!important}.w3-bar-item.w3-mobile,.w3-dropdown-hover.w3-mobile,.w3-dropdown-click.w3-mobile{text-align:center}
-.w3-dropdown-hover.w3-mobile,.w3-dropdown-hover.w3-mobile .w3-btn,.w3-dropdown-hover.w3-mobile .w3-button,.w3-dropdown-click.w3-mobile,.w3-dropdown-click.w3-mobile .w3-btn,.w3-dropdown-click.w3-mobile .w3-button{width:100%}}
-@media (max-width:768px){.w3-modal-content{width:500px}.w3-modal{padding-top:50px}}
-@media (min-width:993px){.w3-modal-content{width:900px}.w3-hide-large{display:none!important}.w3-sidebar.w3-collapse{display:block!important}}
-@media (max-width:992px) and (min-width:601px){.w3-hide-medium{display:none!important}}
-@media (max-width:992px){.w3-sidebar.w3-collapse{display:none}.w3-main{margin-left:0!important;margin-right:0!important}.w3-auto{max-width:100%}}
-.w3-top,.w3-bottom{position:fixed;width:100%;z-index:1}.w3-top{top:0}.w3-bottom{bottom:0}
-.w3-overlay{position:fixed;display:none;width:100%;height:100%;top:0;left:0;right:0;bottom:0;background-color:rgba(0,0,0,0.5);z-index:2}
-.w3-display-topleft{position:absolute;left:0;top:0}.w3-display-topright{position:absolute;right:0;top:0}
-.w3-display-bottomleft{position:absolute;left:0;bottom:0}.w3-display-bottomright{position:absolute;right:0;bottom:0}
-.w3-display-middle{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);-ms-transform:translate(-50%,-50%)}
-.w3-display-left{position:absolute;top:50%;left:0%;transform:translate(0%,-50%);-ms-transform:translate(-0%,-50%)}
-.w3-display-right{position:absolute;top:50%;right:0%;transform:translate(0%,-50%);-ms-transform:translate(0%,-50%)}
-.w3-display-topmiddle{position:absolute;left:50%;top:0;transform:translate(-50%,0%);-ms-transform:translate(-50%,0%)}
-.w3-display-bottommiddle{position:absolute;left:50%;bottom:0;transform:translate(-50%,0%);-ms-transform:translate(-50%,0%)}
-.w3-display-container:hover .w3-display-hover{display:block}.w3-display-container:hover span.w3-display-hover{display:inline-block}.w3-display-hover{display:none}
-.w3-display-position{position:absolute}
-.w3-circle{border-radius:50%}
-.w3-round-small{border-radius:2px}.w3-round,.w3-round-medium{border-radius:4px}.w3-round-large{border-radius:8px}.w3-round-xlarge{border-radius:16px}.w3-round-xxlarge{border-radius:32px}
-.w3-row-padding,.w3-row-padding>.w3-half,.w3-row-padding>.w3-third,.w3-row-padding>.w3-twothird,.w3-row-padding>.w3-threequarter,.w3-row-padding>.w3-quarter,.w3-row-padding>.w3-col{padding:0 8px}
-.w3-container,.w3-panel{padding:0.01em 16px}.w3-panel{margin-top:16px;margin-bottom:16px}
-.w3-code,.w3-codespan{font-family:Consolas,"courier new";font-size:16px}
-.w3-code{width:auto;background-color:#fff;padding:8px 12px;border-left:4px solid #4CAF50;word-wrap:break-word}
-.w3-codespan{color:crimson;background-color:#f1f1f1;padding-left:4px;padding-right:4px;font-size:110%}
-.w3-card,.w3-card-2{box-shadow:0 2px 5px 0 rgba(0,0,0,0.16),0 2px 10px 0 rgba(0,0,0,0.12)}
-.w3-card-4,.w3-hover-shadow:hover{box-shadow:0 4px 10px 0 rgba(0,0,0,0.2),0 4px 20px 0 rgba(0,0,0,0.19)}
-.w3-spin{animation:w3-spin 2s infinite linear}@keyframes w3-spin{0%{transform:rotate(0deg)}100%{transform:rotate(359deg)}}
-.w3-animate-fading{animation:fading 10s infinite}@keyframes fading{0%{opacity:0}50%{opacity:1}100%{opacity:0}}
-.w3-animate-opacity{animation:opac 0.8s}@keyframes opac{from{opacity:0} to{opacity:1}}
-.w3-animate-top{position:relative;animation:animatetop 0.4s}@keyframes animatetop{from{top:-300px;opacity:0} to{top:0;opacity:1}}
-.w3-animate-left{position:relative;animation:animateleft 0.4s}@keyframes animateleft{from{left:-300px;opacity:0} to{left:0;opacity:1}}
-.w3-animate-right{position:relative;animation:animateright 0.4s}@keyframes animateright{from{right:-300px;opacity:0} to{right:0;opacity:1}}
-.w3-animate-bottom{position:relative;animation:animatebottom 0.4s}@keyframes animatebottom{from{bottom:-300px;opacity:0} to{bottom:0;opacity:1}}
-.w3-animate-zoom {animation:animatezoom 0.6s}@keyframes animatezoom{from{transform:scale(0)} to{transform:scale(1)}}
-.w3-animate-input{transition:width 0.4s ease-in-out}.w3-animate-input:focus{width:100%!important}
-.w3-opacity,.w3-hover-opacity:hover{opacity:0.60}.w3-opacity-off,.w3-hover-opacity-off:hover{opacity:1}
-.w3-opacity-max{opacity:0.25}.w3-opacity-min{opacity:0.75}
-.w3-greyscale-max,.w3-grayscale-max,.w3-hover-greyscale:hover,.w3-hover-grayscale:hover{filter:grayscale(100%)}
-.w3-greyscale,.w3-grayscale{filter:grayscale(75%)}.w3-greyscale-min,.w3-grayscale-min{filter:grayscale(50%)}
-.w3-sepia{filter:sepia(75%)}.w3-sepia-max,.w3-hover-sepia:hover{filter:sepia(100%)}.w3-sepia-min{filter:sepia(50%)}
-.w3-tiny{font-size:10px!important}.w3-small{font-size:12px!important}.w3-medium{font-size:15px!important}.w3-large{font-size:18px!important}
-.w3-xlarge{font-size:24px!important}.w3-xxlarge{font-size:36px!important}.w3-xxxlarge{font-size:48px!important}.w3-jumbo{font-size:64px!important}
-.w3-left-align{text-align:left!important}.w3-right-align{text-align:right!important}.w3-justify{text-align:justify!important}.w3-center{text-align:center!important}
-.w3-border-0{border:0!important}.w3-border{border:1px solid #ccc!important}
-.w3-border-top{border-top:1px solid #ccc!important}.w3-border-bottom{border-bottom:1px solid #ccc!important}
-.w3-border-left{border-left:1px solid #ccc!important}.w3-border-right{border-right:1px solid #ccc!important}
-.w3-topbar{border-top:6px solid #ccc!important}.w3-bottombar{border-bottom:6px solid #ccc!important}
-.w3-leftbar{border-left:6px solid #ccc!important}.w3-rightbar{border-right:6px solid #ccc!important}
-.w3-section,.w3-code{margin-top:16px!important;margin-bottom:16px!important}
-.w3-margin{margin:16px!important}.w3-margin-top{margin-top:16px!important}.w3-margin-bottom{margin-bottom:16px!important}
-.w3-margin-left{margin-left:16px!important}.w3-margin-right{margin-right:16px!important}
-.w3-padding-small{padding:4px 8px!important}.w3-padding{padding:8px 16px!important}.w3-padding-large{padding:12px 24px!important}
-.w3-padding-16{padding-top:16px!important;padding-bottom:16px!important}.w3-padding-24{padding-top:24px!important;padding-bottom:24px!important}
-.w3-padding-32{padding-top:32px!important;padding-bottom:32px!important}.w3-padding-48{padding-top:48px!important;padding-bottom:48px!important}
-.w3-padding-64{padding-top:64px!important;padding-bottom:64px!important}
-.w3-padding-top-64{padding-top:64px!important}.w3-padding-top-48{padding-top:48px!important}
-.w3-padding-top-32{padding-top:32px!important}.w3-padding-top-24{padding-top:24px!important}
-.w3-left{float:left!important}.w3-right{float:right!important}
-.w3-button:hover{color:#000!important;background-color:#ccc!important}
-.w3-transparent,.w3-hover-none:hover{background-color:transparent!important}
-.w3-hover-none:hover{box-shadow:none!important}
-/* Colors */
-.w3-amber,.w3-hover-amber:hover{color:#000!important;background-color:#ffc107!important}
-.w3-aqua,.w3-hover-aqua:hover{color:#000!important;background-color:#00ffff!important}
-.w3-blue,.w3-hover-blue:hover{color:#fff!important;background-color:#2196F3!important}
-.w3-light-blue,.w3-hover-light-blue:hover{color:#000!important;background-color:#87CEEB!important}
-.w3-brown,.w3-hover-brown:hover{color:#fff!important;background-color:#795548!important}
-.w3-cyan,.w3-hover-cyan:hover{color:#000!important;background-color:#00bcd4!important}
-.w3-blue-grey,.w3-hover-blue-grey:hover,.w3-blue-gray,.w3-hover-blue-gray:hover{color:#fff!important;background-color:#607d8b!important}
-.w3-green,.w3-hover-green:hover{color:#fff!important;background-color:#4CAF50!important}
-.w3-light-green,.w3-hover-light-green:hover{color:#000!important;background-color:#8bc34a!important}
-.w3-indigo,.w3-hover-indigo:hover{color:#fff!important;background-color:#3f51b5!important}
-.w3-khaki,.w3-hover-khaki:hover{color:#000!important;background-color:#f0e68c!important}
-.w3-lime,.w3-hover-lime:hover{color:#000!important;background-color:#cddc39!important}
-.w3-orange,.w3-hover-orange:hover{color:#000!important;background-color:#ff9800!important}
-.w3-deep-orange,.w3-hover-deep-orange:hover{color:#fff!important;background-color:#ff5722!important}
-.w3-pink,.w3-hover-pink:hover{color:#fff!important;background-color:#e91e63!important}
-.w3-purple,.w3-hover-purple:hover{color:#fff!important;background-color:#9c27b0!important}
-.w3-deep-purple,.w3-hover-deep-purple:hover{color:#fff!important;background-color:#673ab7!important}
-.w3-red,.w3-hover-red:hover{color:#fff!important;background-color:#f44336!important}
-.w3-sand,.w3-hover-sand:hover{color:#000!important;background-color:#fdf5e6!important}
-.w3-teal,.w3-hover-teal:hover{color:#fff!important;background-color:#009688!important}
-.w3-yellow,.w3-hover-yellow:hover{color:#000!important;background-color:#ffeb3b!important}
-.w3-white,.w3-hover-white:hover{color:#000!important;background-color:#fff!important}
-.w3-black,.w3-hover-black:hover{color:#fff!important;background-color:#000!important}
-.w3-grey,.w3-hover-grey:hover,.w3-gray,.w3-hover-gray:hover{color:#000!important;background-color:#9e9e9e!important}
-.w3-light-grey,.w3-hover-light-grey:hover,.w3-light-gray,.w3-hover-light-gray:hover{color:#000!important;background-color:#f1f1f1!important}
-.w3-dark-grey,.w3-hover-dark-grey:hover,.w3-dark-gray,.w3-hover-dark-gray:hover{color:#fff!important;background-color:#616161!important}
-.w3-pale-red,.w3-hover-pale-red:hover{color:#000!important;background-color:#ffdddd!important}
-.w3-pale-green,.w3-hover-pale-green:hover{color:#000!important;background-color:#ddffdd!important}
-.w3-pale-yellow,.w3-hover-pale-yellow:hover{color:#000!important;background-color:#ffffcc!important}
-.w3-pale-blue,.w3-hover-pale-blue:hover{color:#000!important;background-color:#ddffff!important}
-.w3-text-amber,.w3-hover-text-amber:hover{color:#ffc107!important}
-.w3-text-aqua,.w3-hover-text-aqua:hover{color:#00ffff!important}
-.w3-text-blue,.w3-hover-text-blue:hover{color:#2196F3!important}
-.w3-text-light-blue,.w3-hover-text-light-blue:hover{color:#87CEEB!important}
-.w3-text-brown,.w3-hover-text-brown:hover{color:#795548!important}
-.w3-text-cyan,.w3-hover-text-cyan:hover{color:#00bcd4!important}
-.w3-text-blue-grey,.w3-hover-text-blue-grey:hover,.w3-text-blue-gray,.w3-hover-text-blue-gray:hover{color:#607d8b!important}
-.w3-text-green,.w3-hover-text-green:hover{color:#4CAF50!important}
-.w3-text-light-green,.w3-hover-text-light-green:hover{color:#8bc34a!important}
-.w3-text-indigo,.w3-hover-text-indigo:hover{color:#3f51b5!important}
-.w3-text-khaki,.w3-hover-text-khaki:hover{color:#b4aa50!important}
-.w3-text-lime,.w3-hover-text-lime:hover{color:#cddc39!important}
-.w3-text-orange,.w3-hover-text-orange:hover{color:#ff9800!important}
-.w3-text-deep-orange,.w3-hover-text-deep-orange:hover{color:#ff5722!important}
-.w3-text-pink,.w3-hover-text-pink:hover{color:#e91e63!important}
-.w3-text-purple,.w3-hover-text-purple:hover{color:#9c27b0!important}
-.w3-text-deep-purple,.w3-hover-text-deep-purple:hover{color:#673ab7!important}
-.w3-text-red,.w3-hover-text-red:hover{color:#f44336!important}
-.w3-text-sand,.w3-hover-text-sand:hover{color:#fdf5e6!important}
-.w3-text-teal,.w3-hover-text-teal:hover{color:#009688!important}
-.w3-text-yellow,.w3-hover-text-yellow:hover{color:#d2be0e!important}
-.w3-text-white,.w3-hover-text-white:hover{color:#fff!important}
-.w3-text-black,.w3-hover-text-black:hover{color:#000!important}
-.w3-text-grey,.w3-hover-text-grey:hover,.w3-text-gray,.w3-hover-text-gray:hover{color:#757575!important}
-.w3-text-light-grey,.w3-hover-text-light-grey:hover,.w3-text-light-gray,.w3-hover-text-light-gray:hover{color:#f1f1f1!important}
-.w3-text-dark-grey,.w3-hover-text-dark-grey:hover,.w3-text-dark-gray,.w3-hover-text-dark-gray:hover{color:#3a3a3a!important}
-.w3-border-amber,.w3-hover-border-amber:hover{border-color:#ffc107!important}
-.w3-border-aqua,.w3-hover-border-aqua:hover{border-color:#00ffff!important}
-.w3-border-blue,.w3-hover-border-blue:hover{border-color:#2196F3!important}
-.w3-border-light-blue,.w3-hover-border-light-blue:hover{border-color:#87CEEB!important}
-.w3-border-brown,.w3-hover-border-brown:hover{border-color:#795548!important}
-.w3-border-cyan,.w3-hover-border-cyan:hover{border-color:#00bcd4!important}
-.w3-border-blue-grey,.w3-hover-border-blue-grey:hover,.w3-border-blue-gray,.w3-hover-border-blue-gray:hover{border-color:#607d8b!important}
-.w3-border-green,.w3-hover-border-green:hover{border-color:#4CAF50!important}
-.w3-border-light-green,.w3-hover-border-light-green:hover{border-color:#8bc34a!important}
-.w3-border-indigo,.w3-hover-border-indigo:hover{border-color:#3f51b5!important}
-.w3-border-khaki,.w3-hover-border-khaki:hover{border-color:#f0e68c!important}
-.w3-border-lime,.w3-hover-border-lime:hover{border-color:#cddc39!important}
-.w3-border-orange,.w3-hover-border-orange:hover{border-color:#ff9800!important}
-.w3-border-deep-orange,.w3-hover-border-deep-orange:hover{border-color:#ff5722!important}
-.w3-border-pink,.w3-hover-border-pink:hover{border-color:#e91e63!important}
-.w3-border-purple,.w3-hover-border-purple:hover{border-color:#9c27b0!important}
-.w3-border-deep-purple,.w3-hover-border-deep-purple:hover{border-color:#673ab7!important}
-.w3-border-red,.w3-hover-border-red:hover{border-color:#f44336!important}
-.w3-border-sand,.w3-hover-border-sand:hover{border-color:#fdf5e6!important}
-.w3-border-teal,.w3-hover-border-teal:hover{border-color:#009688!important}
-.w3-border-yellow,.w3-hover-border-yellow:hover{border-color:#ffeb3b!important}
-.w3-border-white,.w3-hover-border-white:hover{border-color:#fff!important}
-.w3-border-black,.w3-hover-border-black:hover{border-color:#000!important}
-.w3-border-grey,.w3-hover-border-grey:hover,.w3-border-gray,.w3-hover-border-gray:hover{border-color:#9e9e9e!important}
-.w3-border-light-grey,.w3-hover-border-light-grey:hover,.w3-border-light-gray,.w3-hover-border-light-gray:hover{border-color:#f1f1f1!important}
-.w3-border-dark-grey,.w3-hover-border-dark-grey:hover,.w3-border-dark-gray,.w3-hover-border-dark-gray:hover{border-color:#616161!important}
-.w3-border-pale-red,.w3-hover-border-pale-red:hover{border-color:#ffe7e7!important}.w3-border-pale-green,.w3-hover-border-pale-green:hover{border-color:#e7ffe7!important}
-.w3-border-pale-yellow,.w3-hover-border-pale-yellow:hover{border-color:#ffffcc!important}.w3-border-pale-blue,.w3-hover-border-pale-blue:hover{border-color:#e7ffff!important}
-

BIN
contrib/PingPanel/opt/PingPanel/yellow_on.gif


BIN
contrib/pingpanel_0.9.8.tar.gz


BIN
contrib/pingpanel_0.9.8_all.deb


BIN
contrib/pingpanel_0.9.9.tar.gz


BIN
contrib/pingpanel_0.9.9_all.deb


+ 0 - 5
contrib/si_README.txt

@@ -1,5 +0,0 @@
-- Debian Paket erstellt in diesem Verzeichnis mit: "dpkg-deb --build PingPanel ."
-- tar-Archiv erstellt in diesem Verzeichnis mit: "tar cvfz pingpanel_0.9.9.tar.gz -C PingPanel/opt PingPanel"
-- Versionsnummer wird aus control-File PingPanel/DEBIAN/control geholt.
-
-