Compare commits
39 Commits
b4daa46e1b
...
master
Author | SHA1 | Date | |
---|---|---|---|
d5fc01f78f | |||
1bcb980fd6 | |||
6193ae3edb | |||
0a4921646e | |||
abc3d30473 | |||
8c4ae9626f | |||
a6189199ee | |||
35f9760b24 | |||
f1dad26944 | |||
266ed7e24e | |||
267303d4ce | |||
5f087b1689 | |||
30b47dedde | |||
341b017c01 | |||
d9415c7fa6 | |||
5a63ac033e | |||
25db944ae5 | |||
2efdbb339a | |||
e988e09b7f | |||
a36abb0ddf | |||
3886890c06 | |||
ea88991a9d | |||
6258874114 | |||
c8c376f1dd | |||
5c625b0ec2 | |||
93b7498b75 | |||
c5c2dc5a10 | |||
74c0812128 | |||
98f38c51d8 | |||
b54b4f6bfc | |||
832a0c1232 | |||
8dbc082b37 | |||
e74d49e34c | |||
88228aedae | |||
68fcc088c6 | |||
75d16a5e41 | |||
70b3644b8d | |||
c628ee81d7 | |||
dd419bd0fa |
4
config.php
Normal file
4
config.php
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
$basedir = __DIR__ . "/confs";
|
||||||
|
$locale = "fr_FR.UTF-8";
|
0
custom.css
Normal file
0
custom.css
Normal file
1
favicon.svg
Normal file
1
favicon.svg
Normal file
@ -0,0 +1 @@
|
|||||||
|
<svg role="img" focusable="false" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 14 14"><path fill="#cfd8dc" d="M12.99999994 11.66666662c0 .73633333-.597 1.33333332-1.33333332 1.33333332H2.33333338c-.73633333 0-1.33333332-.597-1.33333332-1.33333332V2.33333338c0-.73633333.597-1.33333332 1.33333332-1.33333332h9.33333324c.73633333 0 1.33333332.597 1.33333332 1.33333332v9.33333324z"/><g fill="#455a64"><path d="M2.66666671 3.33333337h8.66666658v5.33333328H2.66666671z"/><path d="M4.00000003 7.33333333h5.99999994v2.33333331H4.00000003z"/><path d="M5.33333335 8.66666665h3.3333333v1.99999998h-3.3333333z"/></g><path fill="#fdd835" d="M3.6666667 4.00000003h.66666666v2.33333331H3.6666667zm.99999999 0h.66666666v2.33333331h-.66666666zm.99999999 0h.66666666v2.33333331h-.66666666zm.99999999 0h.66666666v2.33333331h-.66666666zm.99999999 0h.66666666v2.33333331h-.66666666zm.99999999 0h.66666666v2.33333331h-.66666666zm.99999999 0h.66666666v2.33333331h-.66666666z"/></svg>
|
After Width: | Height: | Size: 984 B |
87
index.php
87
index.php
@ -1,51 +1,62 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
require_once "config.php";
|
||||||
|
|
||||||
|
setlocale(LC_CTYPE, $locale);
|
||||||
|
|
||||||
|
if ($_SERVER["QUERY_STRING"] != "") {
|
||||||
|
include "switch.php";
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
?>
|
||||||
<!DOCTYPE HTML>
|
<!DOCTYPE HTML>
|
||||||
<html lang='fr'>
|
<html lang='fr'>
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<title>Schémas des VLANs</title>
|
<title>Schémas des VLANs</title>
|
||||||
<link rel="stylesheet" type="text/css" href="style.css">
|
<link rel="stylesheet" type="text/css" href="style.css">
|
||||||
|
<link rel="icon" type="image/svg" href="favicon.svg">
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<div class="container">
|
<h1>Schémas des VLANs</h1>
|
||||||
<h1>Schémas des VLANs</h1>
|
<div class="file-list">
|
||||||
<div class="file-list">
|
<ul>
|
||||||
<ul>
|
|
||||||
<?php
|
<?php
|
||||||
$basedir = __DIR__ . "/confs";
|
function recursive_ls($path) {
|
||||||
|
global $basedir;
|
||||||
function recursive_ls($path) {
|
|
||||||
global $basedir;
|
|
||||||
|
|
||||||
if (substr(basename($path), 0, 1) == '.') {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
if (is_dir($path)) {
|
|
||||||
$str = "";
|
|
||||||
foreach (scandir($path) as $filename) {
|
|
||||||
$str .= recursive_ls("$path/$filename");
|
|
||||||
}
|
|
||||||
if ($str == "") {
|
|
||||||
return "";
|
|
||||||
} else {
|
|
||||||
if ($path == $basedir) {
|
|
||||||
return "<ul>\n$str\n</ul>\n";
|
|
||||||
} else {
|
|
||||||
return "<li>\n<details>\n<summary>" . basename($path) . "</summary>\n<ul>\n" . $str . "</ul>\n</details>\n</li>\n";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (substr($path, -4) == ".cfg") {
|
|
||||||
return "<li><a href='show.php?switch=".str_replace("$basedir/", "", $path)."' target='_blank'>" . basename($path) . "</a></li>\n";
|
|
||||||
}
|
|
||||||
|
|
||||||
|
if (substr(basename($path), 0, 1) == '.') {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|
||||||
echo recursive_ls($basedir);
|
if (is_dir($path)) {
|
||||||
|
$str = "";
|
||||||
|
foreach (scandir($path) as $filename) {
|
||||||
|
$str .= recursive_ls("$path/$filename");
|
||||||
|
}
|
||||||
|
if ($str == "") {
|
||||||
|
return "";
|
||||||
|
} else {
|
||||||
|
if ($path == $basedir) {
|
||||||
|
return "<ul>\n$str\n</ul>\n";
|
||||||
|
} else {
|
||||||
|
return "<li>\n<details>\n<summary>" . basename($path) . "</summary>\n<ul>\n" . $str . "</ul>\n</details>\n</li>\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (substr($path, -4) == ".cfg") {
|
||||||
|
return "<li><a href='?" . str_replace("$basedir/", "", $path) . "' target='_blank'>" . basename($path) . "</a></li>\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
echo recursive_ls($basedir);
|
||||||
?>
|
?>
|
||||||
</ul>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
|
118
show.php
118
show.php
@ -1,118 +0,0 @@
|
|||||||
<?php
|
|
||||||
$basedir = __DIR__ . "/confs/";
|
|
||||||
$path = realpath($basedir . filter_input(INPUT_GET, "switch", FILTER_SANITIZE_STRING));
|
|
||||||
if (strpos($path, $basedir) !== 0 || substr($path, -4) != ".cfg") {
|
|
||||||
header('HTTP/1.1 404 Not Found');
|
|
||||||
die();
|
|
||||||
}
|
|
||||||
|
|
||||||
$conf = file_get_contents($path);
|
|
||||||
|
|
||||||
preg_match("/ sysname ([\w-]+)/", $conf, $sysname);
|
|
||||||
preg_match("/ip address ([\d.]+)/", $conf, $address);
|
|
||||||
preg_match_all("/(?<=\n)vlan (?P<pvid>\d+)[\r\n]+(?: name (?P<name>.+)[\r\n]+| description (?P<description>.+)[\r\n]+| .*[\r\n]+)*/", $conf, $vlans, PREG_SET_ORDER);
|
|
||||||
preg_match_all("/(?<=\n)interface [\w-]+(?P<member>\d+)\/0\/(?P<port>\d+)[\r\n]+(?: port hybrid (?:pvid )?vlan (?:(?P<tagged>\d+)(?: [0-9a-z ]*) tagged|(?P<untagged>\d+)(?: \d+)* untagged)[\r\n]+| port (?:access |trunk |hybrid |pvid |vlan )*(?P<pvid>\d+)[\r\n]+| voice-vlan (?P<voice_vlan>\d+) enable[\r\n]+| .*[\r\n]+)*(?<!#)/", $conf, $interfaces, PREG_SET_ORDER);
|
|
||||||
$stack = array();
|
|
||||||
foreach ($interfaces as $interface) {
|
|
||||||
if (!isset($stack[$interface["member"]])) $stack[$interface["member"]] = [[], []];
|
|
||||||
$interface["style"] = "";
|
|
||||||
if (!empty($interface["pvid"])) $interface["style"] .= "--pvid: {$interface["pvid"]}; ";
|
|
||||||
if (!empty($interface["tagged"])) $interface["style"] .= "--tagged: {$interface["tagged"]}; ";
|
|
||||||
if (!empty($interface["untagged"])) $interface["style"] .= "--untagged: {$interface["untagged"]}; ";
|
|
||||||
$stack[$interface["member"]][1 - $interface["port"] % 2][$interface["port"]] = $interface;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*echo ("<!--");
|
|
||||||
var_dump($stack);
|
|
||||||
echo ("-->");*/
|
|
||||||
|
|
||||||
?>
|
|
||||||
<!DOCTYPE HTML>
|
|
||||||
<html lang='fr'>
|
|
||||||
|
|
||||||
<head>
|
|
||||||
<title><?= $sysname[1] ?? "Switch sans nom" ?> - Tableau des VLANs</title>
|
|
||||||
<link href="style.css" rel="stylesheet" />
|
|
||||||
</head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<div class="container">
|
|
||||||
<header>
|
|
||||||
<h1>
|
|
||||||
<div><?= $sysname[1] ?? "Switch sans nom" ?></div>
|
|
||||||
<small><a href="https://<?= $address[1] ?>" target="_blank" class="link"><?= $address[1] ?></a></small>
|
|
||||||
</h1>
|
|
||||||
</header>
|
|
||||||
|
|
||||||
<main>
|
|
||||||
<div class="stack">
|
|
||||||
<h2>Interfaces</h2>
|
|
||||||
<?php
|
|
||||||
foreach ($stack as $member_id => $lines) {
|
|
||||||
echo "<div class='member'>\n<span class='member-id'>$member_id</span>\n<table class='interfaces'>\n<tbody>\n";
|
|
||||||
foreach ($lines as $interfaces) {
|
|
||||||
echo "<tr>\n";
|
|
||||||
foreach ($interfaces as $interface) {
|
|
||||||
echo "<td class='{$interface[0]}" . (isset($interface["voice_vlan"]) ? " voice_vlan" : "") . "' title='{$interface[0]}' style='{$interface["style"]}'>{$interface["port"]}</td>\n";
|
|
||||||
};
|
|
||||||
echo "</tr>\n";
|
|
||||||
}
|
|
||||||
echo "</tr>\n</tbody>\n</table>\n</div>\n";
|
|
||||||
}
|
|
||||||
?>
|
|
||||||
</div>
|
|
||||||
<table class='legend'>
|
|
||||||
<caption>
|
|
||||||
<h2>Légende</h2>
|
|
||||||
</caption>
|
|
||||||
<thead>
|
|
||||||
<tr>
|
|
||||||
<th>PVID</th>
|
|
||||||
<th>Nom</th>
|
|
||||||
<th>Description</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
<?php
|
|
||||||
foreach ($vlans as $vlan) {
|
|
||||||
if (isset($vlan["pvid"]) and $vlan["pvid"] != 1) {
|
|
||||||
$name = $vlan["name"] ?? "";
|
|
||||||
$description = $vlan["description"] ?? "";
|
|
||||||
echo "<tr title='{$vlan[0]}'><td class='interface vlan' style='--pvid: {$vlan["pvid"]}'>{$vlan["pvid"]}</td><td>$name</td><td>$description</td></tr>";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
?>
|
|
||||||
<tr>
|
|
||||||
<td class='interface trunk'></td>
|
|
||||||
<td colspan='2'>Trunk</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class='interface hybrid' style='--tagged:60; --untagged:0'></td>
|
|
||||||
<td colspan='2'>Hybride (tagged/untagged)</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class='interface poe'></td>
|
|
||||||
<td colspan='2'>Power on Ethernet</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class='interface voice_vlan'></td>
|
|
||||||
<td colspan='2'>ToIP (voice-vlan)</td>
|
|
||||||
</tr>
|
|
||||||
<tr>
|
|
||||||
<td class='interface shutdown'></td>
|
|
||||||
<td colspan='2'>Interface désactivée</td>
|
|
||||||
</tr>
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</main>
|
|
||||||
<footer>
|
|
||||||
<label id="colorSliderLabel" for="colorSlider" class="no-print">Changer les couleurs</label>
|
|
||||||
<input id="colorSlider" type="range" min="0" max="2000000" step="0.000000001" value="1353651.53435435"
|
|
||||||
oninput="document.documentElement.style.setProperty('--hue', this.value);" class="no-print" />
|
|
||||||
<a href="<?= str_replace(__DIR__ . "/", "", $path) ?>" target="_blank" class="link no-print">Télécharger la configuration</a>
|
|
||||||
<a href="index.php" class="link no-print">← Retour à la liste</a>
|
|
||||||
</footer>
|
|
||||||
</div>
|
|
||||||
</body>
|
|
||||||
|
|
||||||
</html>
|
|
131
style.css
131
style.css
@ -1,6 +1,6 @@
|
|||||||
:root {
|
:root {
|
||||||
--hue: 1353651.53435435;
|
--hue: 58.3;
|
||||||
--saturation: 97%;
|
--saturation: 90%;
|
||||||
--lightness: 65%;
|
--lightness: 65%;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -8,19 +8,19 @@
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
overflow: visible !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
body {
|
body {
|
||||||
|
margin: 0;
|
||||||
|
padding: 2rem 1rem;
|
||||||
font-family: Arial, sans-serif;
|
font-family: Arial, sans-serif;
|
||||||
line-height: 1.6;
|
line-height: 1.6;
|
||||||
background-color: #f5f5f5;
|
background-color: #f5f5f5;
|
||||||
color: #333;
|
color: #333;
|
||||||
}
|
display: flex;
|
||||||
|
flex-direction: column;
|
||||||
.container {
|
height: 100vh;
|
||||||
max-width: 1200px;
|
|
||||||
margin: 2rem auto;
|
|
||||||
padding: 0 1rem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
h1 {
|
h1 {
|
||||||
@ -31,6 +31,7 @@ h1 {
|
|||||||
|
|
||||||
h2 {
|
h2 {
|
||||||
color: #34495e;
|
color: #34495e;
|
||||||
|
text-align: center;
|
||||||
margin-bottom: 0.5rem;
|
margin-bottom: 0.5rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -42,6 +43,7 @@ h2 {
|
|||||||
transition: background-color 0.3s;
|
transition: background-color 0.3s;
|
||||||
margin-bottom: 0.5em;
|
margin-bottom: 0.5em;
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.file-list summary:hover {
|
.file-list summary:hover {
|
||||||
@ -61,7 +63,7 @@ h2 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
.file-list li {
|
.file-list li {
|
||||||
margin-left: 0.5rem;
|
margin-left: 1.2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
.file-list a::before {
|
.file-list a::before {
|
||||||
@ -95,40 +97,27 @@ h2 {
|
|||||||
}
|
}
|
||||||
|
|
||||||
main {
|
main {
|
||||||
|
flex-grow: 2;
|
||||||
display: flex;
|
display: flex;
|
||||||
flex-flow: wrap;
|
flex-flow: wrap;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-around;
|
||||||
gap: 1rem;
|
gap: 1rem;
|
||||||
margin-bottom: 2rem;
|
margin-bottom: 2rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
ul {
|
|
||||||
list-style: none;
|
|
||||||
}
|
|
||||||
|
|
||||||
details {
|
|
||||||
cursor: pointer;
|
|
||||||
}
|
|
||||||
|
|
||||||
main > table {
|
|
||||||
margin: auto;
|
|
||||||
}
|
|
||||||
|
|
||||||
td {
|
|
||||||
text-align: left;
|
|
||||||
}
|
|
||||||
|
|
||||||
.member {
|
.member {
|
||||||
display: flex;
|
display: flex;
|
||||||
align-items: center;
|
align-items: center;
|
||||||
border: 8px outset #476079;
|
border: 6px outset #476079;
|
||||||
border-radius: 6px;
|
border-radius: 4px;
|
||||||
background-color: #34495e;
|
background-color: #34495e;
|
||||||
margin-bottom: 0.5rem;
|
margin-bottom: 0.5rem;
|
||||||
print-color-adjust: exact;
|
print-color-adjust: exact;
|
||||||
}
|
}
|
||||||
|
|
||||||
.member-id {
|
.member-id {
|
||||||
background: #777;
|
background: #888;
|
||||||
align-content: center;
|
align-content: center;
|
||||||
color: lightgreen;
|
color: lightgreen;
|
||||||
text-shadow: 0 1px 3px #fffb;
|
text-shadow: 0 1px 3px #fffb;
|
||||||
@ -151,16 +140,21 @@ td {
|
|||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
min-width: 2em;
|
min-width: 2em;
|
||||||
height: 2em;
|
height: 2em;
|
||||||
mix-blend-mode: darken;
|
|
||||||
cursor: help;
|
|
||||||
transition: 0.2s background-color;
|
transition: 0.2s background-color;
|
||||||
border: 2px inset #476079;
|
border: 3px inset #476079;
|
||||||
border-image-width: 4px;
|
border-image-width: 5px;
|
||||||
border-image-slice: 3;
|
border-image-slice: 3;
|
||||||
border-image-source: url(rj45.svg);
|
border-image-source: url(rj45.svg);
|
||||||
border-image-repeat: stretch;
|
border-image-repeat: stretch;
|
||||||
background-color: white;
|
background-color: white;
|
||||||
print-color-adjust: exact;
|
print-color-adjust: exact;
|
||||||
|
background-size: cover;
|
||||||
|
background-position: center;
|
||||||
|
background-origin: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
|
[title] {
|
||||||
|
cursor: help;
|
||||||
}
|
}
|
||||||
|
|
||||||
.member tr:nth-child(even) .interface {
|
.member tr:nth-child(even) .interface {
|
||||||
@ -173,11 +167,12 @@ td {
|
|||||||
|
|
||||||
.vlan {
|
.vlan {
|
||||||
--pvid: 0;
|
--pvid: 0;
|
||||||
color: #ecf0f1;
|
--pvid-color: hsl(
|
||||||
text-shadow: 0 1px 3px black;
|
|
||||||
background-color: hsl(
|
|
||||||
calc(var(--hue) * var(--pvid)) var(--saturation) var(--lightness)
|
calc(var(--hue) * var(--pvid)) var(--saturation) var(--lightness)
|
||||||
);
|
);
|
||||||
|
color: #ecf0f1;
|
||||||
|
text-shadow: 1px 2px 2px black;
|
||||||
|
background-color: var(--pvid-color);
|
||||||
}
|
}
|
||||||
|
|
||||||
.vlan:hover {
|
.vlan:hover {
|
||||||
@ -187,60 +182,55 @@ td {
|
|||||||
|
|
||||||
.trunk:not(.shutdown) {
|
.trunk:not(.shutdown) {
|
||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
border: 3px solid;
|
background-image: linear-gradient(
|
||||||
border-image-slice: 1 !important;
|
140deg,
|
||||||
border-image-source: linear-gradient(
|
red 18%,
|
||||||
127deg,
|
|
||||||
red,
|
|
||||||
orange,
|
orange,
|
||||||
yellow,
|
yellow,
|
||||||
green,
|
green,
|
||||||
blue,
|
blue,
|
||||||
violet
|
magenta,
|
||||||
) !important;
|
violet 82%
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
.hybrid {
|
/*.hybrid {
|
||||||
--tagged: 0;
|
--tagged: 0;
|
||||||
|
--tagged-color: hsl(calc(var(--hue) * var(--tagged)) var(--saturation) var(--lightness));
|
||||||
--untagged: var(--pvid);
|
--untagged: var(--pvid);
|
||||||
background-image: linear-gradient(
|
--untagged-color: hsl(calc(var(--hue) * var(--untagged)) var(--saturation) var(--lightness));
|
||||||
135deg,
|
background-image: linear-gradient(145deg, transparent 65%, var(--tagged-color) 65%);
|
||||||
hsl(calc(var(--hue) * var(--tagged)) var(--saturation) var(--lightness)) 50%,
|
}*/
|
||||||
hsl(calc(var(--hue) * var(--untagged)) var(--saturation) var(--lightness))
|
|
||||||
50%
|
|
||||||
);
|
|
||||||
background-size: cover;
|
|
||||||
background-position: center;
|
|
||||||
background-origin: border-box;
|
|
||||||
}
|
|
||||||
|
|
||||||
.shutdown:not([class*="loopback-detection action shutdown"]) {
|
.shutdown:not([class*="loopback-detection action shutdown"]) {
|
||||||
background-color: lightgray;
|
background-color: lightgray;
|
||||||
color: gray !important;
|
color: gray !important;
|
||||||
|
font-weight: normal;
|
||||||
|
text-shadow: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
.poe::before {
|
.voice_vlan::before {
|
||||||
|
content: "📞";
|
||||||
|
position: absolute;
|
||||||
|
bottom: -0.4em;
|
||||||
|
left: -0.4em;
|
||||||
|
}
|
||||||
|
|
||||||
|
.poe::after {
|
||||||
content: "⚡";
|
content: "⚡";
|
||||||
font-size: 0.7em;
|
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: -0.5em;
|
top: -0.5em;
|
||||||
right: -0.5em;
|
right: -0.5em;
|
||||||
}
|
}
|
||||||
|
|
||||||
.voice_vlan::after {
|
|
||||||
content: "📞";
|
|
||||||
font-size: 0.7em;
|
|
||||||
position: absolute;
|
|
||||||
bottom: -0.5em;
|
|
||||||
left: -0.5em;
|
|
||||||
}
|
|
||||||
|
|
||||||
.legend {
|
.legend {
|
||||||
border-spacing: 0;
|
border-spacing: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
.legend td:not(.interface) {
|
.legend td:not(.interface) {
|
||||||
border: 1px solid #2c3e50;
|
border: 1px solid #2c3e50;
|
||||||
|
text-align: left;
|
||||||
|
padding: 0 0.3em;
|
||||||
}
|
}
|
||||||
|
|
||||||
footer {
|
footer {
|
||||||
@ -253,9 +243,20 @@ footer {
|
|||||||
width: 33%;
|
width: 33%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
input[type="color"] {
|
||||||
|
opacity: 0%;
|
||||||
|
position: absolute;
|
||||||
|
top: 0;
|
||||||
|
left: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 100%;
|
||||||
|
cursor: pointer;
|
||||||
|
}
|
||||||
|
|
||||||
@media print {
|
@media print {
|
||||||
* {
|
body {
|
||||||
overflow: visible !important;
|
margin: auto;
|
||||||
|
background-color: unset;
|
||||||
}
|
}
|
||||||
|
|
||||||
.no-print {
|
.no-print {
|
||||||
|
155
switch.php
Normal file
155
switch.php
Normal file
@ -0,0 +1,155 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
$path = realpath($basedir . DIRECTORY_SEPARATOR . ltrim(urldecode($_SERVER["QUERY_STRING"]), '/'));
|
||||||
|
|
||||||
|
if (
|
||||||
|
strpos($path, $basedir) !== 0
|
||||||
|
|| substr($path, -4) != ".cfg"
|
||||||
|
|| !file_exists($path)
|
||||||
|
) {
|
||||||
|
http_response_code(404);
|
||||||
|
die("Fichier non trouvé");
|
||||||
|
}
|
||||||
|
|
||||||
|
$conf = file_get_contents($path);
|
||||||
|
|
||||||
|
if ($conf === false) {
|
||||||
|
http_response_code(404);
|
||||||
|
die("Fichier non trouvé");
|
||||||
|
}
|
||||||
|
|
||||||
|
preg_match("/ sysname ([\w-]+)/", $conf, $sysname);
|
||||||
|
preg_match("/ip address ([\d.]+)/", $conf, $address);
|
||||||
|
$startPtn = "(?<=[\r\n])";
|
||||||
|
$NL = "(?:[\r\n]+)";
|
||||||
|
$vlanPvidPtn = "vlan (?P<pvid>\d+)$NL";
|
||||||
|
$vlanNamePtn = "$startPtn name (?P<name>.+)$NL";
|
||||||
|
$vlanDescriptionPtn = "$startPtn description (?P<description>.+)$NL";
|
||||||
|
$otherPtn = "$startPtn .*$NL";
|
||||||
|
$endPtn = "(?<!#)";
|
||||||
|
preg_match_all("/$startPtn$vlanPvidPtn(?:$vlanNamePtn|$vlanDescriptionPtn|$otherPtn)*$endPtn/", $conf, $vlans, PREG_SET_ORDER);
|
||||||
|
$interfaceAddressPtn = "interface [\w-]+(?P<member>\d+)\/0\/(?P<port>\d+)$NL";
|
||||||
|
$pvidPtn = "$startPtn port (?:access|trunk pvid|hybrid pvid) vlan (?P<pvid>\d+)$NL";
|
||||||
|
$portHybridPtn = "$startPtn port hybrid vlan (?:(?P<tagged>\d+)(?: (?:to|\d+))* tagged|(?P<untagged>\d+)(?: \d+)* untagged)$NL";
|
||||||
|
$voiceVlanPtn = "$startPtn voice-vlan (?P<voice_vlan>\d+) enable$NL";
|
||||||
|
preg_match_all("/$startPtn$interfaceAddressPtn(?:$pvidPtn|$portHybridPtn|$voiceVlanPtn|$otherPtn)*$endPtn/", $conf, $interfaces, PREG_SET_ORDER);
|
||||||
|
|
||||||
|
$stack = array();
|
||||||
|
foreach ($interfaces as $interface) {
|
||||||
|
if ($interface["member"] == 0) continue;
|
||||||
|
if (!isset($stack[$interface["member"]])) $stack[$interface["member"]] = [[], []];
|
||||||
|
$interface["style"] = "";
|
||||||
|
if (!empty($interface["pvid"])) $interface["style"] .= "--pvid: {$interface["pvid"]};";
|
||||||
|
if (!empty($interface["tagged"])) $interface["style"] .= " --tagged: {$interface["tagged"]};";
|
||||||
|
if (!empty($interface["untagged"])) $interface["style"] .= " --untagged: {$interface["untagged"]};";
|
||||||
|
if (!empty($interface["voice_vlan"])) $interface["style"] .= " --voice-vlan: {$interface["voice_vlan"]};";
|
||||||
|
$stack[$interface["member"]][1 - $interface["port"] % 2][$interface["port"]] = $interface;
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
<!DOCTYPE HTML>
|
||||||
|
<html lang='fr'>
|
||||||
|
|
||||||
|
<head>
|
||||||
|
<title><?= $sysname[1] ?? "Switch sans nom" ?> - Schéma des VLANs</title>
|
||||||
|
<link rel="icon" type="image/svg" href="favicon.svg">
|
||||||
|
<link href="style.css" rel="stylesheet" />
|
||||||
|
<link href="custom.css" rel="stylesheet" />
|
||||||
|
<style id="customColors"></style>
|
||||||
|
</head>
|
||||||
|
|
||||||
|
<body>
|
||||||
|
<header>
|
||||||
|
<h1>
|
||||||
|
<div><?= $sysname[1] ?? "Switch sans nom" ?></div>
|
||||||
|
<small><a href="https://<?= $address[1] ?>" target="_blank" class="link"><?= $address[1] ?></a></small>
|
||||||
|
</h1>
|
||||||
|
</header>
|
||||||
|
|
||||||
|
<main>
|
||||||
|
<div class="stack">
|
||||||
|
<h2>Interfaces</h2>
|
||||||
|
<?php
|
||||||
|
foreach ($stack as $member_id => $lines) {
|
||||||
|
echo "<div class='member'>\n<span class='member-id'>$member_id</span>\n<table class='interfaces'>\n<tbody>\n";
|
||||||
|
foreach ($lines as $interfaces) {
|
||||||
|
ksort($interfaces);
|
||||||
|
echo "<tr>\n";
|
||||||
|
foreach ($interfaces as $interface) {
|
||||||
|
echo "<td class='{$interface[0]}" . (isset($interface["voice_vlan"]) ? " voice_vlan" : "") . "' title='{$interface[0]}' style='{$interface["style"]}'>{$interface["port"]}</td>\n";
|
||||||
|
};
|
||||||
|
echo "</tr>\n";
|
||||||
|
}
|
||||||
|
echo "</tr>\n</tbody>\n</table>\n</div>\n";
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
</div>
|
||||||
|
<table class='legend'>
|
||||||
|
<caption>
|
||||||
|
<h2>Légende</h2>
|
||||||
|
</caption>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th>PVID</th>
|
||||||
|
<th>Nom</th>
|
||||||
|
<th>Description</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
<?php
|
||||||
|
foreach ($vlans as $vlan) {
|
||||||
|
if (isset($vlan["pvid"]) and $vlan["pvid"] != 1) {
|
||||||
|
$name = $vlan["name"] ?? "";
|
||||||
|
$description = $vlan["description"] ?? "";
|
||||||
|
echo "<tr title='{$vlan[0]}'><td class='interface vlan {$vlan["pvid"]}' style='--pvid: {$vlan["pvid"]};'>{$vlan["pvid"]}<input type='color' oninput='changeColor({$vlan["pvid"]}, this.value)' title='Changer la couleur' /></td><td>$name</td><td>$description</td></tr>";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
?>
|
||||||
|
<tr>
|
||||||
|
<td class='interface trunk'></td>
|
||||||
|
<td colspan='2'>Trunk</td>
|
||||||
|
</tr>
|
||||||
|
<!--<tr>
|
||||||
|
<td class='interface hybrid' style='--tagged:60; --untagged:0'></td>
|
||||||
|
<td colspan='2'>Hybride (PVID / tagged)</td>
|
||||||
|
</tr>-->
|
||||||
|
<tr>
|
||||||
|
<td class='interface poe'></td>
|
||||||
|
<td colspan='2'>Power on Ethernet</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class='interface voice_vlan'></td>
|
||||||
|
<td colspan='2'>ToIP (voice-vlan)</td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td class='interface shutdown'></td>
|
||||||
|
<td colspan='2'>Interface désactivée</td>
|
||||||
|
</tr>
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</main>
|
||||||
|
<footer>
|
||||||
|
<label for="colorSlider" class="no-print">Changer les couleurs (ou cliquez dans la légende)</label>
|
||||||
|
<input id="colorSlider" type="range" min="0" max="360" step="0.000000001" value="58.3"
|
||||||
|
oninput="document.documentElement.style.setProperty('--hue', this.value);" class="no-print" />
|
||||||
|
<a href="<?= str_replace(__DIR__ . "/", "", $path) ?>" target="_blank" class="link no-print">Télécharger la configuration</a>
|
||||||
|
<a href="." class="link no-print">← Retour à la liste</a>
|
||||||
|
</footer>
|
||||||
|
<script>
|
||||||
|
function changeColor(pvid, color) {
|
||||||
|
for (let i = customColors.sheet.cssRules.length - 1; i >= 0; i--) {
|
||||||
|
if (
|
||||||
|
(customColors.sheet.cssRules[i].selectorText == `[style*="--pvid: ${pvid};"]`) ||
|
||||||
|
(customColors.sheet.cssRules[i].selectorText == `[style*="--tagged: ${pvid};"]`) ||
|
||||||
|
(customColors.sheet.cssRules[i].selectorText == `[style*="--untagged: ${pvid};"]`)
|
||||||
|
) {
|
||||||
|
customColors.sheet.deleteRule(i)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
customColors.sheet.insertRule(`[style*="--pvid: ${pvid};"] { --pvid-color: ${color} }`)
|
||||||
|
customColors.sheet.insertRule(`[style*="--tagged: ${pvid};"] { --tagged-color: ${color} }`)
|
||||||
|
customColors.sheet.insertRule(`[style*="--untagged: ${pvid};"] { --untagged-color: ${color} }`)
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</body>
|
||||||
|
|
||||||
|
</html>
|
Reference in New Issue
Block a user