Richard Cornwell (K9RCP) authored on 11/17/2022 13:32:27
Showing 1 changed files
1 1
new file mode 100644
... ...
@@ -0,0 +1,483 @@
1
+<?php
2
+date_default_timezone_set('America/Los_Angeles'); ?><!DOCTYPE html>
3
+<html>
4
+  <head>
5
+    <meta charset="utf-8">
6
+    <title>Mesh Network Topo Map</title>
7
+
8
+<!--
9
+                                                                                
10
+                                                                                
11
+                            &, /@              #@  @                            
12
+                              /@@/@*         @%@@@                              
13
+                                     #    ,                                     
14
+                                        @                                       
15
+                                @   #   %  ,/  ./                               
16
+                             .@@@@&    /&     @@@@@                             
17
+                           *.   ,      &&/      #   *.                          
18
+                                       #@@                                      
19
+                                      @#%#.                                     
20
+                                      @(@#@                                     
21
+                                     @*.@#.,                                    
22
+                                    ,/.#@#%@                                    
23
+                                    @@#@@#&@#                                   
24
+                                   #.@&.@ %/&.           CQ CQ de K9RCP         
25
+                                  ,%.,(*@ @@ @                                  
26
+                                  @(   %@@  (*%                                 
27
+                                 @@(@&*@@#(@&(@/                                
28
+                                &/#. @ %@ /* # @                                
29
+                               *@  %(  %@   @,  @                               
30
+                              .@ #* .& %@. @  % .@                              
31
+                              @*(     @%@*@     @#&                             
32
+                             @(#/%@@&%(@@%%&@@@#/@&#                            
33
+                            @( .&    @.&@/(%    @  @/                           
34
+                           @@    @@.   @@/   ##@    @.                          
35
+                          #@   @. @    @@%   ,% (%  .@                          
36
+                         /@ @.     &.  @@%  #/     (%*@                         
37
+                         &          #* @@% @.         /*                        
38
+                                     *%@@&@                                     
39
+                                      .@@@.//                                   
40
+                                                                                
41
+-->
42
+
43
+    <style>
44
+
45
+    #app {
46
+      display: flex;
47
+      display: -webkit-flex;
48
+      flex-direction: column;
49
+      -webkit-flex-direction: column;
50
+      position: absolute;
51
+      top: 0;
52
+      left: 0;
53
+      width: 100%;
54
+      height: 100%;
55
+    }
56
+
57
+    #header {
58
+      flex: 0 0 auto;
59
+      -webkit-flex: 0 0 auto;
60
+      line-height: 1.3;
61
+    }
62
+
63
+    #panes {
64
+      display: flex;
65
+      display: -webkit-flex;
66
+      flex: 1 1 auto;
67
+      -webkit-flex: 1 1 auto;
68
+    }
69
+
70
+    #graph {
71
+      display: flex;
72
+      display: -webkit-flex;
73
+      flex-direction: column;
74
+      -webkit-flex-direction: column;
75
+    }
76
+    
77
+    #options {
78
+      flex: 0 0 auto;
79
+      -webkit-flex: 0 0 auto;
80
+    }
81
+    
82
+    #output {
83
+      flex: 1 1 auto;
84
+      -webkit-flex: 1 1 auto;
85
+      position: relative;
86
+      overflow: auto;
87
+    }
88
+    
89
+    
90
+    #editor {
91
+      border-right: 1px solid #ccc;
92
+    }
93
+
94
+    #header {
95
+      background: #eee;
96
+      border-bottom: 1px solid #ccc;
97
+      padding: 8px;
98
+      text-align: center;
99
+    }
100
+    
101
+    #header b {
102
+      font-size: 18px;
103
+    }
104
+    
105
+    #options {
106
+      background: #eee;
107
+      border-bottom: 1px solid #ccc;
108
+      padding: 8px;
109
+    }
110
+    
111
+    #options label {
112
+      margin-right: 8px;
113
+    }
114
+    
115
+    #options #raw.disabled {
116
+      opacity: 0.5;
117
+    }
118
+    
119
+    #output svg {
120
+      position: absolute;
121
+      top: 0;
122
+      left: 0;
123
+      width: 100%;
124
+      height: 100%;
125
+    }
126
+    
127
+    #output #text {
128
+      font-size: 12px;
129
+      font-family: monaco, courier, monospace;
130
+      white-space: pre;
131
+      position: absolute;
132
+      top: 0;
133
+      left: 0;
134
+      width: 100%;
135
+      height: 100%;
136
+      overflow: auto;
137
+    }
138
+    
139
+    #output img {
140
+      display: block;
141
+      margin: 0 auto;
142
+    }
143
+    
144
+    #output.working svg, #output.error svg,
145
+    #output.working #text, #output.error #text,
146
+    #output.working img, #output.error img {
147
+      opacity: 0.4;
148
+    }
149
+    
150
+    #output.error #error {
151
+      display: inherit;
152
+    }
153
+    
154
+    #output #error {
155
+      display: none;
156
+      position: absolute;
157
+      top: 20px;
158
+      left: 20px;
159
+      margin-right: 20px;
160
+      background: red;
161
+      color: white;
162
+      z-index: 1;
163
+    }
164
+
165
+    .gutter {
166
+      background-color: #eee;
167
+      background-repeat: no-repeat;
168
+      background-position: 50%;
169
+    }
170
+
171
+    .gutter.gutter-horizontal {
172
+      background-image: url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAeCAYAAADkftS9AAAAIklEQVQoU2M4c+bMfxAGAgYYmwGrIIiDjrELjpo5aiZeMwF+yNnOs5KSvgAAAABJRU5ErkJggg==');
173
+      cursor: ew-resize;
174
+    }
175
+
176
+    .split {
177
+      -webkit-box-sizing: border-box;
178
+      -moz-box-sizing: border-box;
179
+      box-sizing: border-box;
180
+
181
+      overflow-y: auto;
182
+      overflow-x: hidden;
183
+    }
184
+
185
+    .split.split-horizontal, .gutter.gutter-horizontal {
186
+      height: 100%;
187
+      float: left;
188
+    }
189
+    
190
+    </style>
191
+  </head>
192
+  <body>
193
+    
194
+    <div id="app">
195
+      <div id="header">
196
+	<b>WVMN Topology - <?php echo date("F j, Y, g:i a"); ?></b>
197
+      </div>
198
+      <div id="panes">
199
+        <div id="editor"  hidden>
200
+	<?php
201
+$fp = fsockopen("10.204.114.225", 2004, $errno, $errstr, 30);
202
+$data = "";
203
+if (!$fp) {
204
+    echo "$errstr ($errno)<br />\n";
205
+} else {
206
+    while (!feof($fp)) {
207
+        $data .= fgets($fp, 128);
208
+    }
209
+    fclose($fp);
210
+}
211
+
212
+
213
+if (!function_exists('str_contains')) {
214
+    function str_contains($haystack, $needle): bool {
215
+        if ( is_string($haystack) && is_string($needle) ) {
216
+            return '' === $needle || false !== strpos($haystack, $needle);
217
+        } else {
218
+            return false;
219
+        }
220
+    }
221
+}
222
+
223
+
224
+
225
+$ips = json_decode(file_get_contents("./ips.host"), TRUE);
226
+$ar = explode("\n", $data);
227
+
228
+$checkNodes = array();
229
+
230
+$data = "";
231
+
232
+foreach ($ar as &$value) {
233
+        $ip = explode('"', $value)[1];
234
+
235
+if (filter_var($ip, FILTER_VALIDATE_IP && !isset($ips[$ip]))) {
236
+        $ips[$ip] = "NULL";
237
+
238
+}
239
+        if (!str_contains($value, 'HNA') && !str_contains($value, 'diamond')) {
240
+	        if (str_contains($value, 'label')) {
241
+			$dr = explode('];', $value);
242
+			$val = explode('"', explode('label="', $value)[1])[0];
243
+			if ($val < 0.98) { $color = "blue"; $pwidth = 1; }
244
+			if ($val > 0.99) { $color = "green"; $pwidth = 2.5; }
245
+			if ($val > 3.00) { $color = "yellow";$pwidth = 2.5; }
246
+			if ($val > 4.00) { $color = "orange"; $pwidth = 3.5; }
247
+			if ($val > 6.00) { $color = "red"; $pwidth = 5; }
248
+			if ($val == "INFINITE") { $color = "red"; $pwidth = 8; }
249
+
250
+//$dr[0] = "10.166.72.127" -> "10.138.41.208"[label="0.100"];
251
+
252
+			$da = explode('"', $dr[0]);
253
+			if (!isset($checkNodes[$da[3]."-".$da[1]])) {
254
+				$data .= $dr[0].', penwidth='.$pwidth.' color="'.$color.'"];'."\n";
255
+				$checkNodes[$da[1]."-".$da[3]] = "TRUE";
256
+			} else {
257
+				$data .= $dr[0].', penwidth='.$pwidth.' color="'.$color.'"];'."\n";
258
+				
259
+			}
260
+		} else {
261
+                	$data .= $value."\n";
262
+		}
263
+        }
264
+}
265
+foreach ($ips as $key => $value) {
266
+	if(filter_var($ips[$key], FILTER_VALIDATE_IP) || $ips[$key] == "NULL") {
267
+	        $ips[$key] = gethostbyaddr($key);
268
+	}
269
+        $data = str_replace($key, $ips[$key], $data);
270
+}
271
+file_put_contents("./ips.host", json_encode($ips));
272
+
273
+//print_r($checkNodes);
274
+
275
+echo $data;
276
+
277
+?>
278
+	</div>
279
+        <div id="graph">
280
+          <div id="options" hidden>
281
+            <label id="engine">
282
+              Engine:
283
+              <select>
284
+                <option>circo</option>
285
+                <option selected>dot</option>
286
+                <option>fdp</option>
287
+                <option>neato</option>
288
+                <option>osage</option>
289
+                <option>twopi</option>
290
+              </select>
291
+            </label>
292
+            
293
+            <label id="format">
294
+              Format:
295
+              <select>
296
+                <option selected>svg</option>
297
+                <option>png-image-element</option>
298
+                <option>json</option>
299
+                <option>xdot</option>
300
+                <option>plain</option>
301
+                <option>ps</option>
302
+              </select>
303
+            </label>
304
+            
305
+            <label id="raw">
306
+              <input type="checkbox"> Show raw output
307
+            </label>
308
+          </div>
309
+          <div id="output">
310
+            <div id="error"></div>
311
+          </div>
312
+        </div>
313
+      </div>
314
+    </div>
315
+    
316
+    <script src="./js/ace.js"></script>
317
+    <script src="./js/viz.js"></script>
318
+    <script src="./js/fabric.min.js"></script>
319
+    <script src="./js/split.min.js"></script>
320
+    <script src="./js/svg-pan-zoom.min.js"></script>
321
+    <script>
322
+
323
+    var beforeUnloadMessage = null;
324
+
325
+    var resizeEvent = new Event("paneresize");
326
+    Split(['#editor', '#graph'], {
327
+      sizes: [0, 100],
328
+      onDragEnd: function() { 
329
+        var svgOutput = document.getElementById("svg_output");
330
+        if (svgOutput != null) {
331
+          svgOutput.dispatchEvent(resizeEvent);
332
+        }
333
+      }
334
+    });
335
+    
336
+    var editor = ace.edit("editor");
337
+    editor.getSession().setMode("ace/mode/dot");
338
+
339
+    var parser = new DOMParser();
340
+    var worker;
341
+    var result;
342
+
343
+    function updateGraph() {
344
+      if (worker) {
345
+        worker.terminate();
346
+      }
347
+
348
+      document.querySelector("#output").classList.add("working");
349
+      document.querySelector("#output").classList.remove("error");
350
+
351
+      worker = new Worker("./worker.js");
352
+
353
+      worker.onmessage = function(e) {
354
+        document.querySelector("#output").classList.remove("working");
355
+        document.querySelector("#output").classList.remove("error");
356
+        
357
+        result = e.data;
358
+        
359
+        updateOutput();
360
+      }
361
+
362
+      worker.onerror = function(e) {
363
+        document.querySelector("#output").classList.remove("working");
364
+        document.querySelector("#output").classList.add("error");
365
+        
366
+        var message = e.message === undefined ? "An error occurred while processing the graph input." : e.message;
367
+        
368
+        var error = document.querySelector("#error");
369
+        while (error.firstChild) {
370
+          error.removeChild(error.firstChild);
371
+        }
372
+        
373
+        document.querySelector("#error").appendChild(document.createTextNode(message));
374
+        
375
+        console.error(e);
376
+        e.preventDefault();
377
+      }
378
+      
379
+      var params = {
380
+        src: editor.getSession().getDocument().getValue(),
381
+        options: {
382
+          engine: document.querySelector("#engine select").value,
383
+          format: document.querySelector("#format select").value
384
+        }
385
+      };
386
+      
387
+      // Instead of asking for png-image-element directly, which we can't do in a worker,
388
+      // ask for SVG and convert when updating the output.
389
+      
390
+      if (params.options.format == "png-image-element") {
391
+        params.options.format = "svg";
392
+      }
393
+      
394
+      worker.postMessage(params);
395
+    }
396
+    
397
+    function updateOutput() {
398
+      var graph = document.querySelector("#output");
399
+
400
+      var svg = graph.querySelector("svg");
401
+      if (svg) {
402
+        graph.removeChild(svg);
403
+      }
404
+
405
+      var text = graph.querySelector("#text");
406
+      if (text) {
407
+        graph.removeChild(text);
408
+      }
409
+
410
+      var img = graph.querySelector("img");
411
+      if (img) {
412
+        graph.removeChild(img);
413
+      }
414
+      
415
+      if (!result) {
416
+        return;
417
+      }
418
+      
419
+      if (document.querySelector("#format select").value == "svg" && !document.querySelector("#raw input").checked) {
420
+        var svg = parser.parseFromString(result, "image/svg+xml").documentElement;
421
+        svg.id = "svg_output";
422
+        graph.appendChild(svg);
423
+
424
+        panZoom = svgPanZoom(svg, {
425
+          zoomEnabled: true,
426
+          controlIconsEnabled: true,
427
+          fit: true,
428
+          center: true,
429
+          minZoom: 0.1
430
+        });
431
+
432
+        svg.addEventListener('paneresize', function(e) {
433
+          panZoom.resize();
434
+        }, false);
435
+        window.addEventListener('resize', function(e) {
436
+          panZoom.resize();
437
+        });
438
+      } else if (document.querySelector("#format select").value == "png-image-element") {
439
+        var image = Viz.svgXmlToPngImageElement(result);
440
+        graph.appendChild(image);
441
+      } else {
442
+        var text = document.createElement("div");
443
+        text.id = "text";
444
+        text.appendChild(document.createTextNode(result));
445
+        graph.appendChild(text);
446
+      }
447
+    }
448
+
449
+    editor.on("change", function() {
450
+      updateGraph();
451
+      beforeUnloadMessage = "Your changes will not be saved.";
452
+    });
453
+    
454
+    window.addEventListener("beforeunload", function(e) {
455
+      return beforeUnloadMessage;
456
+    });
457
+    
458
+    document.querySelector("#engine select").addEventListener("change", function() {
459
+      updateGraph();
460
+    });
461
+
462
+    document.querySelector("#format select").addEventListener("change", function() {
463
+      if (document.querySelector("#format select").value === "svg") {
464
+        document.querySelector("#raw").classList.remove("disabled");
465
+        document.querySelector("#raw input").disabled = false;
466
+      } else {
467
+        document.querySelector("#raw").classList.add("disabled");
468
+        document.querySelector("#raw input").disabled = true;
469
+      }
470
+      
471
+      updateGraph();
472
+    });
473
+
474
+    document.querySelector("#raw input").addEventListener("change", function() {
475
+      updateOutput();
476
+    });
477
+    
478
+    updateGraph();
479
+    
480
+    </script>
481
+    
482
+  </body>
483
+</html>