index.php
df7bf5db
 <?php
 date_default_timezone_set('America/Los_Angeles'); ?><!DOCTYPE html>
 <html>
   <head>
     <meta charset="utf-8">
     <title>Mesh Network Topo Map</title>
 
 <!--
                                                                                 
                                                                                 
                             &, /@              #@  @                            
                               /@@/@*         @%@@@                              
                                      #    ,                                     
                                         @                                       
                                 @   #   %  ,/  ./                               
                              .@@@@&    /&     @@@@@                             
                            *.   ,      &&/      #   *.                          
                                        #@@                                      
                                       @#%#.                                     
                                       @(@#@                                     
                                      @*.@#.,                                    
                                     ,/.#@#%@                                    
                                     @@#@@#&@#                                   
                                    #.@&.@ %/&.           CQ CQ de K9RCP         
                                   ,%.,(*@ @@ @                                  
                                   @(   %@@  (*%                                 
                                  @@(@&*@@#(@&(@/                                
                                 &/#. @ %@ /* # @                                
                                *@  %(  %@   @,  @                               
                               .@ #* .& %@. @  % .@                              
                               @*(     @%@*@     @#&                             
                              @(#/%@@&%(@@%%&@@@#/@&#                            
                             @( .&    @.&@/(%    @  @/                           
                            @@    @@.   @@/   ##@    @.                          
                           #@   @. @    @@%   ,% (%  .@                          
                          /@ @.     &.  @@%  #/     (%*@                         
                          &          #* @@% @.         /*                        
                                      *%@@&@                                     
                                       .@@@.//                                   
                                                                                 
 -->
 
     <style>
 
     #app {
       display: flex;
       display: -webkit-flex;
       flex-direction: column;
       -webkit-flex-direction: column;
       position: absolute;
       top: 0;
       left: 0;
       width: 100%;
       height: 100%;
     }
 
     #header {
       flex: 0 0 auto;
       -webkit-flex: 0 0 auto;
       line-height: 1.3;
     }
 
     #panes {
       display: flex;
       display: -webkit-flex;
       flex: 1 1 auto;
       -webkit-flex: 1 1 auto;
     }
 
     #graph {
       display: flex;
       display: -webkit-flex;
       flex-direction: column;
       -webkit-flex-direction: column;
     }
     
     #options {
       flex: 0 0 auto;
       -webkit-flex: 0 0 auto;
     }
     
     #output {
       flex: 1 1 auto;
       -webkit-flex: 1 1 auto;
       position: relative;
       overflow: auto;
     }
     
     
     #editor {
       border-right: 1px solid #ccc;
     }
 
     #header {
       background: #eee;
       border-bottom: 1px solid #ccc;
       padding: 8px;
       text-align: center;
     }
     
     #header b {
       font-size: 18px;
     }
     
     #options {
       background: #eee;
       border-bottom: 1px solid #ccc;
       padding: 8px;
     }
     
     #options label {
       margin-right: 8px;
     }
     
     #options #raw.disabled {
       opacity: 0.5;
     }
     
     #output svg {
       position: absolute;
       top: 0;
       left: 0;
       width: 100%;
       height: 100%;
     }
     
     #output #text {
       font-size: 12px;
       font-family: monaco, courier, monospace;
       white-space: pre;
       position: absolute;
       top: 0;
       left: 0;
       width: 100%;
       height: 100%;
       overflow: auto;
     }
     
     #output img {
       display: block;
       margin: 0 auto;
     }
     
     #output.working svg, #output.error svg,
     #output.working #text, #output.error #text,
     #output.working img, #output.error img {
       opacity: 0.4;
     }
     
     #output.error #error {
       display: inherit;
     }
     
     #output #error {
       display: none;
       position: absolute;
       top: 20px;
       left: 20px;
       margin-right: 20px;
       background: red;
       color: white;
       z-index: 1;
     }
 
     .gutter {
       background-color: #eee;
       background-repeat: no-repeat;
       background-position: 50%;
     }
 
     .gutter.gutter-horizontal {
       background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAeCAYAAADkftS9AAAAIklEQVQoU2M4c+bMfxAGAgYYmwGrIIiDjrELjpo5aiZeMwF+yNnOs5KSvgAAAABJRU5ErkJggg==');
       cursor: ew-resize;
     }
 
     .split {
       -webkit-box-sizing: border-box;
       -moz-box-sizing: border-box;
       box-sizing: border-box;
 
       overflow-y: auto;
       overflow-x: hidden;
     }
 
     .split.split-horizontal, .gutter.gutter-horizontal {
       height: 100%;
       float: left;
     }
     
     </style>
   </head>
   <body>
     
     <div id="app">
       <div id="header">
 	<b>WVMN Topology - <?php echo date("F j, Y, g:i a"); ?></b>
       </div>
       <div id="panes">
         <div id="editor"  hidden>
 	<?php
 $fp = fsockopen("10.204.114.225", 2004, $errno, $errstr, 30);
 $data = "";
 if (!$fp) {
     echo "$errstr ($errno)<br />\n";
 } else {
     while (!feof($fp)) {
         $data .= fgets($fp, 128);
     }
     fclose($fp);
 }
 
 
 if (!function_exists('str_contains')) {
     function str_contains($haystack, $needle): bool {
         if ( is_string($haystack) && is_string($needle) ) {
             return '' === $needle || false !== strpos($haystack, $needle);
         } else {
             return false;
         }
     }
 }
 
 
 
 $ips = json_decode(file_get_contents("./ips.host"), TRUE);
 $ar = explode("\n", $data);
 
 $checkNodes = array();
 
 $data = "";
 
 foreach ($ar as &$value) {
         $ip = explode('"', $value)[1];
 
 if (filter_var($ip, FILTER_VALIDATE_IP && !isset($ips[$ip]))) {
         $ips[$ip] = "NULL";
 
 }
         if (!str_contains($value, 'HNA') && !str_contains($value, 'diamond')) {
 	        if (str_contains($value, 'label')) {
 			$dr = explode('];', $value);
 			$val = explode('"', explode('label="', $value)[1])[0];
 			if ($val < 0.98) { $color = "blue"; $pwidth = 1; }
 			if ($val > 0.99) { $color = "green"; $pwidth = 2.5; }
 			if ($val > 3.00) { $color = "yellow";$pwidth = 2.5; }
 			if ($val > 4.00) { $color = "orange"; $pwidth = 3.5; }
 			if ($val > 6.00) { $color = "red"; $pwidth = 5; }
 			if ($val == "INFINITE") { $color = "red"; $pwidth = 8; }
 
 //$dr[0] = "10.166.72.127" -> "10.138.41.208"[label="0.100"];
 
 			$da = explode('"', $dr[0]);
 			if (!isset($checkNodes[$da[3]."-".$da[1]])) {
 				$data .= $dr[0].', penwidth='.$pwidth.' color="'.$color.'"];'."\n";
 				$checkNodes[$da[1]."-".$da[3]] = "TRUE";
 			} else {
 				$data .= $dr[0].', penwidth='.$pwidth.' color="'.$color.'"];'."\n";
 				
 			}
 		} else {
                 	$data .= $value."\n";
 		}
         }
 }
 foreach ($ips as $key => $value) {
 	if(filter_var($ips[$key], FILTER_VALIDATE_IP) || $ips[$key] == "NULL") {
 	        $ips[$key] = gethostbyaddr($key);
 	}
         $data = str_replace($key, $ips[$key], $data);
 }
 file_put_contents("./ips.host", json_encode($ips));
 
 //print_r($checkNodes);
 
 echo $data;
 
 ?>
 	</div>
         <div id="graph">
           <div id="options" hidden>
             <label id="engine">
               Engine:
               <select>
                 <option>circo</option>
                 <option selected>dot</option>
                 <option>fdp</option>
                 <option>neato</option>
                 <option>osage</option>
                 <option>twopi</option>
               </select>
             </label>
             
             <label id="format">
               Format:
               <select>
                 <option selected>svg</option>
                 <option>png-image-element</option>
                 <option>json</option>
                 <option>xdot</option>
                 <option>plain</option>
                 <option>ps</option>
               </select>
             </label>
             
             <label id="raw">
               <input type="checkbox"> Show raw output
             </label>
           </div>
           <div id="output">
             <div id="error"></div>
           </div>
         </div>
       </div>
     </div>
     
     <script src="./js/ace.js"></script>
     <script src="./js/viz.js"></script>
     <script src="./js/fabric.min.js"></script>
     <script src="./js/split.min.js"></script>
     <script src="./js/svg-pan-zoom.min.js"></script>
     <script>
 
     var beforeUnloadMessage = null;
 
     var resizeEvent = new Event("paneresize");
     Split(['#editor', '#graph'], {
       sizes: [0, 100],
       onDragEnd: function() { 
         var svgOutput = document.getElementById("svg_output");
         if (svgOutput != null) {
           svgOutput.dispatchEvent(resizeEvent);
         }
       }
     });
     
     var editor = ace.edit("editor");
     editor.getSession().setMode("ace/mode/dot");
 
     var parser = new DOMParser();
     var worker;
     var result;
 
     function updateGraph() {
       if (worker) {
         worker.terminate();
       }
 
       document.querySelector("#output").classList.add("working");
       document.querySelector("#output").classList.remove("error");
 
       worker = new Worker("./worker.js");
 
       worker.onmessage = function(e) {
         document.querySelector("#output").classList.remove("working");
         document.querySelector("#output").classList.remove("error");
         
         result = e.data;
         
         updateOutput();
       }
 
       worker.onerror = function(e) {
         document.querySelector("#output").classList.remove("working");
         document.querySelector("#output").classList.add("error");
         
         var message = e.message === undefined ? "An error occurred while processing the graph input." : e.message;
         
         var error = document.querySelector("#error");
         while (error.firstChild) {
           error.removeChild(error.firstChild);
         }
         
         document.querySelector("#error").appendChild(document.createTextNode(message));
         
         console.error(e);
         e.preventDefault();
       }
       
       var params = {
         src: editor.getSession().getDocument().getValue(),
         options: {
           engine: document.querySelector("#engine select").value,
           format: document.querySelector("#format select").value
         }
       };
       
       // Instead of asking for png-image-element directly, which we can't do in a worker,
       // ask for SVG and convert when updating the output.
       
       if (params.options.format == "png-image-element") {
         params.options.format = "svg";
       }
       
       worker.postMessage(params);
     }
     
     function updateOutput() {
       var graph = document.querySelector("#output");
 
       var svg = graph.querySelector("svg");
       if (svg) {
         graph.removeChild(svg);
       }
 
       var text = graph.querySelector("#text");
       if (text) {
         graph.removeChild(text);
       }
 
       var img = graph.querySelector("img");
       if (img) {
         graph.removeChild(img);
       }
       
       if (!result) {
         return;
       }
       
       if (document.querySelector("#format select").value == "svg" && !document.querySelector("#raw input").checked) {
         var svg = parser.parseFromString(result, "image/svg+xml").documentElement;
         svg.id = "svg_output";
         graph.appendChild(svg);
 
         panZoom = svgPanZoom(svg, {
           zoomEnabled: true,
           controlIconsEnabled: true,
           fit: true,
           center: true,
           minZoom: 0.1
         });
 
         svg.addEventListener('paneresize', function(e) {
           panZoom.resize();
         }, false);
         window.addEventListener('resize', function(e) {
           panZoom.resize();
         });
       } else if (document.querySelector("#format select").value == "png-image-element") {
         var image = Viz.svgXmlToPngImageElement(result);
         graph.appendChild(image);
       } else {
         var text = document.createElement("div");
         text.id = "text";
         text.appendChild(document.createTextNode(result));
         graph.appendChild(text);
       }
     }
 
     editor.on("change", function() {
       updateGraph();
       beforeUnloadMessage = "Your changes will not be saved.";
     });
     
     window.addEventListener("beforeunload", function(e) {
       return beforeUnloadMessage;
     });
     
     document.querySelector("#engine select").addEventListener("change", function() {
       updateGraph();
     });
 
     document.querySelector("#format select").addEventListener("change", function() {
       if (document.querySelector("#format select").value === "svg") {
         document.querySelector("#raw").classList.remove("disabled");
         document.querySelector("#raw input").disabled = false;
       } else {
         document.querySelector("#raw").classList.add("disabled");
         document.querySelector("#raw input").disabled = true;
       }
       
       updateGraph();
     });
 
     document.querySelector("#raw input").addEventListener("change", function() {
       updateOutput();
     });
     
     updateGraph();
     
     </script>
     
   </body>
 </html>