瀏覽代碼

Fixed the handling of possible looping in the switch connection scheme

root 5 月之前
父節點
當前提交
7375894a19

+ 1 - 0
docs/mysql/2-9-0/mysql.sql

@@ -712,6 +712,7 @@ CREATE TABLE `mac_vendors` (
 
 CREATE TABLE `OU` (
   `id` int(11) NOT NULL,
+  `parent_id` INT(11) NULL DEFAULT NULL,
   `ou_name` varchar(40) DEFAULT NULL,
   `comment` varchar(250) DEFAULT NULL,
   `default_users` tinyint(1) NOT NULL DEFAULT 0,

+ 3 - 2
html/admin/devices/editport.php

@@ -71,6 +71,7 @@ print_editdevice_submenu($page_url, $device_id, $device['device_type'], $user_in
             </div>
         </div>
     </form>
-    <?php
+
+<?php
     require_once($_SERVER['DOCUMENT_ROOT'] . "/inc/footer.php");
-    ?>
+?>

+ 48 - 27
html/admin/devices/index-tree-simple.php

@@ -5,49 +5,70 @@ unset($_POST);
 require_once ($_SERVER['DOCUMENT_ROOT']."/inc/header.php");
 print_device_submenu($page_url);
 ?>
+
 <div id="cont">
 <br>
 <?php
 
-function print_child($device_id,$hash) 
+function print_child($device_id, $hash, $processed_ids = array()) 
 {
-foreach ($hash as $device) {
-    if (!isset($device['parent_id'])) { continue; }
-    if ($device['parent_id'] !== $device_id) { continue; }
-    print '<ul><li>';
-    print_url($device['parent_port'].'->'.$device['uplink'].'&nbsp'.$device['name'].'&nbsp::&nbsp<small><i>['.$device['model_name'].']</i></small>','/admin/devices/editdevice.php?id='.$device['id']);
-    print_child($device['id'],$hash);
-    print '</li></ul>';
+    // Защита от циклических ссылок - проверяем, не обрабатывали ли уже это устройство
+    if (in_array($device_id, $processed_ids)) {
+        return '';
+    }
+    // Добавляем текущее устройство в список обработанных
+    $processed_ids[] = $device_id;
+    foreach ($hash as $device) {
+        if (!isset($device['parent_id'])) { continue; }
+        if ($device['parent_id'] !== $device_id) { continue; }
+        print '<ul><li>';
+        print_url($device['parent_port'].'->'.$device['uplink'].'&nbsp'.$device['name'].'&nbsp::&nbsp<small><i>['.$device['model_name'].']</i></small>','/admin/devices/editdevice.php?id='.$device['id']);
+        print_child($device['id'],$hash);
+        print '</li></ul>';
     }
 }
 
 $dSQL = 'SELECT D.*,DM.model_name FROM devices as D,device_models as DM WHERE D.device_model_id=DM.id AND (deleted=0 and device_type<=2)';
 $switches = get_records_sql($db_link,$dSQL);
 $dev_hash = NULL;
+
+// Сначала соберем все устройства
 foreach ($switches as $row) {
-$dev_id=$row['id'];
-$dev_hash[$dev_id]['id']=$dev_id;
-$dev_hash[$dev_id]['name']=$row['device_name'];
-$dev_hash[$dev_id]['model_name']=$row['model_name'];
-$pSQL = 'SELECT * FROM device_ports WHERE uplink = 1 and device_id='.$dev_id;
-$uplink = get_record_sql($db_link,$pSQL);
-if (empty($uplink)) { continue; }
-if (empty($uplink['target_port_id'])) { continue; }
-$dev_hash[$dev_id]['uplink']=$uplink['port_name'];
-$parentSQL='SELECT * FROM device_ports WHERE device_ports.id='.$uplink['target_port_id'];
-$parent=get_record_sql($db_link,$parentSQL);
-$dev_hash[$dev_id]['parent_id']=$parent['device_id'];
-$dev_hash[$dev_id]['parent_port']=$parent['port_name'];
+    $dev_id = $row['id'];
+    $dev_hash[$dev_id]['id'] = $dev_id;
+    $dev_hash[$dev_id]['name'] = $row['device_name'];
+    $dev_hash[$dev_id]['type'] = $row['device_type'];
+    $dev_hash[$dev_id]['model_name'] = $row['model_name'];
+    $dev_hash[$dev_id]['parent_id'] = null; // инициализируем
+    $pSQL = 'SELECT * FROM device_ports WHERE uplink = 1 and device_id='.$dev_id;
+    $uplink = get_record_sql($db_link,$pSQL);
+    if (empty($uplink)) { continue; }
+    if (empty($uplink['target_port_id'])) { continue; }
+    $dev_hash[$dev_id]['uplink'] = $uplink['port_name'];
+    $parentSQL = 'SELECT * FROM device_ports WHERE device_ports.id='.$uplink['target_port_id'];
+    $parent = get_record_sql($db_link,$parentSQL);
+    // Защита от ссылки на самого себя
+    if ($parent['device_id'] == $dev_id) {
+        // Устройство ссылается само на себя - пропускаем эту связь
+        $dev_hash[$dev_id]['parent_id'] = null;
+        continue;
+    }
+    $dev_hash[$dev_id]['parent_id'] = $parent['device_id'];
+    $dev_hash[$dev_id]['parent_port'] = $parent['port_name'];
 }
 
 print '<div id="html">';
+
 foreach ($dev_hash as $device) {
-if (isset($device['parent_id'])) { continue; }
-print '<ul><li>';
-print_url($device['name'],'/admin/devices/editdevice.php?id='.$device['id']);
-print_child($device['id'],$dev_hash);
-print '</li>';
-print '</ul>';
+    // Пропускаем устройства, которые имеют родителя (они будут отображены как дети)
+    if (isset($device['parent_id']) && $device['parent_id'] !== null) { 
+        continue; 
+    }
+    print '<ul><li>';
+    print_url($device['name'],'/admin/devices/editdevice.php?id='.$device['id']); 
+    print print_child($device['id'], $dev_hash, array()); 
+    print '</li>';
+    print '</ul>';
 }
 print '</div>';
 

+ 75 - 40
html/admin/devices/index-tree.php

@@ -17,43 +17,67 @@ $.getScript("/js/jstree/jstree.min.js")
 <br>
 <?php
 
-function print_child($device_id,$hash) 
+function print_child($device_id, $hash, $processed_ids = array()) 
 {
-foreach ($hash as $device) {
-    if (!isset($device['parent_id'])) { continue; }
-    if ($device['parent_id'] !== $device_id) { continue; }
-    $dev_icon = '/img/server.png';
-    if ($device['type'] == 0) { $dev_icon = '/img/router.png'; }
-    if ($device['type'] == 1) { $dev_icon = '/img/switch16.png'; }
-    if ($device['type'] == 2) { $dev_icon = '/img/gateway.png'; }
-    if ($device['type'] == 3) { $dev_icon = '/img/server.png'; }
-    if ($device['type'] == 4) { $dev_icon = '/img/ap.png'; }
-    print '{ "text" : "'; print $device['parent_port'].'->'.$device['uplink'].'&nbsp'.$device['name'].'&nbsp::&nbsp<small><i>['.$device['model_name'].']</i></small>'; print '", "icon" : "'.$dev_icon.'", "id" : "'.$device['id'].'","state" : { "opened" : true },';
-    print '"a_attr" : { "href": "'.reencodeurl('/admin/devices/editdevice.php?id='.$device['id']).'"},';
-    print '"children" : ['; print_child($device['id'],$hash); print ']';print "},\n";
+    // Защита от циклических ссылок - проверяем, не обрабатывали ли уже это устройство
+    if (in_array($device_id, $processed_ids)) {
+        return '';
+    }
+    
+    // Добавляем текущее устройство в список обработанных
+    $processed_ids[] = $device_id;
+    
+    $output = '';
+    foreach ($hash as $device) {
+        if (!isset($device['parent_id'])) { continue; }
+        if ($device['parent_id'] !== $device_id) { continue; }
+        
+        $dev_icon = '/img/server.png';
+        if ($device['type'] == 0) { $dev_icon = '/img/router.png'; }
+        if ($device['type'] == 1) { $dev_icon = '/img/switch16.png'; }
+        if ($device['type'] == 2) { $dev_icon = '/img/gateway.png'; }
+        if ($device['type'] == 3) { $dev_icon = '/img/server.png'; }
+        if ($device['type'] == 4) { $dev_icon = '/img/ap.png'; }
+        
+        $output .= '{ "text" : "' . $device['parent_port'].'->'.$device['uplink'].'&nbsp'.$device['name'].'&nbsp::&nbsp<small><i>['.$device['model_name'].']</i></small>' . '", "icon" : "'.$dev_icon.'", "id" : "'.$device['id'].'","state" : { "opened" : true },';
+        $output .= '"a_attr" : { "href": "'.reencodeurl('/admin/devices/editdevice.php?id='.$device['id']).'"},';
+        $output .= '"children" : [' . print_child($device['id'], $hash, $processed_ids) . ']';
+        $output .= "},\n";
     }
+    return $output;
 }
 
 $dSQL = 'SELECT D.*,DM.model_name FROM devices as D,device_models as DM WHERE D.device_model_id=DM.id AND (deleted=0 and device_type<=2)';
 $switches = get_records_sql($db_link,$dSQL);
 $dev_hash = NULL;
+
+// Сначала соберем все устройства
 foreach ($switches as $row) {
-$dev_id=$row['id'];
-$dev_hash[$dev_id]['id']=$dev_id;
-$dev_hash[$dev_id]['name']=$row['device_name'];
-$dev_hash[$dev_id]['type']=$row['device_type'];
-$dev_hash[$dev_id]['model_name']=$row['model_name'];
-$pSQL = 'SELECT * FROM device_ports WHERE uplink = 1 and device_id='.$dev_id;
-$uplink = get_record_sql($db_link,$pSQL);
-if (empty($uplink)) { continue; }
-if (empty($uplink['target_port_id'])) { continue; }
-//$dev_hash[$dev_id]['uplink']=$uplink['ifName'];
-$dev_hash[$dev_id]['uplink']=$uplink['port_name'];
-$parentSQL='SELECT * FROM device_ports WHERE device_ports.id='.$uplink['target_port_id'];
-$parent=get_record_sql($db_link,$parentSQL);
-$dev_hash[$dev_id]['parent_id']=$parent['device_id'];
-//$dev_hash[$dev_id]['parent_port']=$parent['ifName'];
-$dev_hash[$dev_id]['parent_port']=$parent['port_name'];
+    $dev_id = $row['id'];
+    $dev_hash[$dev_id]['id'] = $dev_id;
+    $dev_hash[$dev_id]['name'] = $row['device_name'];
+    $dev_hash[$dev_id]['type'] = $row['device_type'];
+    $dev_hash[$dev_id]['model_name'] = $row['model_name'];
+    $dev_hash[$dev_id]['parent_id'] = null; // инициализируем
+    
+    $pSQL = 'SELECT * FROM device_ports WHERE uplink = 1 and device_id='.$dev_id;
+    $uplink = get_record_sql($db_link,$pSQL);
+    if (empty($uplink)) { continue; }
+    if (empty($uplink['target_port_id'])) { continue; }
+    
+    $dev_hash[$dev_id]['uplink'] = $uplink['port_name'];
+    $parentSQL = 'SELECT * FROM device_ports WHERE device_ports.id='.$uplink['target_port_id'];
+    $parent = get_record_sql($db_link,$parentSQL);
+    
+    // Защита от ссылки на самого себя
+    if ($parent['device_id'] == $dev_id) {
+        // Устройство ссылается само на себя - пропускаем эту связь
+        $dev_hash[$dev_id]['parent_id'] = null;
+        continue;
+    }
+    
+    $dev_hash[$dev_id]['parent_id'] = $parent['device_id'];
+    $dev_hash[$dev_id]['parent_port'] = $parent['port_name'];
 }
 
 print '<div id="frmt" class="tree"></div>';
@@ -63,18 +87,28 @@ print "$('#frmt').jstree({";
 print '"themes" : { "theme" : "default", "dots" : false, "icons" : false }, "plugins" : [ "themes", "html_data", "ui", "sort" ],';
 print "'core' : { 'data' : [";
 print "\n";
+
 foreach ($dev_hash as $device) {
-if (isset($device['parent_id'])) { continue; }
-$dev_icon = '/img/server.png';
-if ($device['type'] == 0) { $dev_icon = '/img/router.png'; }
-if ($device['type'] == 1) { $dev_icon = '/img/switch16.png'; }
-if ($device['type'] == 2) { $dev_icon = '/img/gateway.png'; }
-if ($device['type'] == 3) { $dev_icon = '/img/server.png'; }
-if ($device['type'] == 4) { $dev_icon = '/img/ap.png'; }
-print '{ "text" : "'; print_url($device['name'],'/admin/devices/editdevice.php?id='.$device['id']); print '","icon" : "'.$dev_icon.'", "id" : "'.$device['id'].'" ,"state" : { "opened" : true },';
-print '"a_attr" : { "href": "'.reencodeurl('/admin/devices/editdevice.php?id='.$device['id']).'"},';
-print '"children" : ['; print_child($device['id'],$dev_hash); print "]";
-print "},\n";
+    // Пропускаем устройства, которые имеют родителя (они будут отображены как дети)
+    if (isset($device['parent_id']) && $device['parent_id'] !== null) { 
+        continue; 
+    }
+    
+    $dev_icon = '/img/server.png';
+    if ($device['type'] == 0) { $dev_icon = '/img/router.png'; }
+    if ($device['type'] == 1) { $dev_icon = '/img/switch16.png'; }
+    if ($device['type'] == 2) { $dev_icon = '/img/gateway.png'; }
+    if ($device['type'] == 3) { $dev_icon = '/img/server.png'; }
+    if ($device['type'] == 4) { $dev_icon = '/img/ap.png'; }
+    
+    print '{ "text" : "'; 
+    print_url($device['name'],'/admin/devices/editdevice.php?id='.$device['id']); 
+    print '","icon" : "'.$dev_icon.'", "id" : "'.$device['id'].'" ,"state" : { "opened" : true },';
+    print '"a_attr" : { "href": "'.reencodeurl('/admin/devices/editdevice.php?id='.$device['id']).'"},';
+    print '"children" : ['; 
+    print print_child($device['id'], $dev_hash, array()); 
+    print "]";
+    print "},\n";
 }
 ?>
 ]}
@@ -91,3 +125,4 @@ print "},\n";
 <?php
 require_once ($_SERVER['DOCUMENT_ROOT']."/inc/footer.php");
 ?>
+

+ 1 - 1
html/admin/devices/mactable.php

@@ -66,5 +66,5 @@ if ($snmp_ok) {
 	}
 
 unset_lock_discovery($db_link,$id);
-require_once($_SERVER['DOCUMENT_ROOT'] . "/inc/footer.small.php");
+require_once($_SERVER['DOCUMENT_ROOT'] . "/inc/footer.simple.php");
 ?>

+ 1 - 1
html/admin/devices/portmactable.php

@@ -107,5 +107,5 @@ while (list ($fmac, $f_last) = mysqli_fetch_array($maclist)) {
 
 print "</table>\n";
 
-require_once($_SERVER['DOCUMENT_ROOT'] . "/inc/footer.small.php");
+require_once($_SERVER['DOCUMENT_ROOT'] . "/inc/footer.simple.php");
 ?>

+ 1 - 1
html/admin/devices/switchport-conn.php

@@ -60,5 +60,5 @@ print "</table>\n";
 </form>
 
 <?php
-require_once ($_SERVER['DOCUMENT_ROOT']."/inc/footer.small.php");
+require_once ($_SERVER['DOCUMENT_ROOT']."/inc/footer.simple.php");
 ?>

+ 1 - 1
html/admin/devices/switchport.php

@@ -155,5 +155,5 @@ print "</table>\n";
 </div>
 </form>
 <?php
-require_once ($_SERVER['DOCUMENT_ROOT']."/inc/footer.small.php");
+require_once ($_SERVER['DOCUMENT_ROOT']."/inc/footer.simple.php");
 ?>

+ 1 - 1
html/admin/devices/switchstatus.php

@@ -422,5 +422,5 @@ print_editdevice_submenu($page_url, $id, $device['device_type'], $user_info['log
         print "</table>\n";
         print "</form>";
         unset_lock_discovery($db_link, $id);
-        require_once($_SERVER['DOCUMENT_ROOT'] . "/inc/footer.small.php");
+        require_once($_SERVER['DOCUMENT_ROOT'] . "/inc/footer.simple.php");
         ?>

+ 16 - 0
html/css/white.css

@@ -76,3 +76,19 @@ input[type="datetime-local"]:focus {
             border-color: #3498db;
             outline: none;
 }
+
+.performance-info {
+//    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+//    color: white;
+    padding: 12px 20px;
+    border-radius: 10px;
+    font-size: 14px;
+    text-align: center;
+    margin: 20px 0;
+    box-shadow: 0 4px 15px rgba(0,0,0,0.1);
+    font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
+}
+
+.performance-info strong {
+    color: black;
+}

+ 4 - 1
html/inc/auth.php

@@ -1,11 +1,14 @@
 <?php
+
+$start_memory = memory_get_usage();
+$start_time = microtime();
+
 ob_start();
 
 require_once ($_SERVER['DOCUMENT_ROOT']."/inc/auth.utils.php");
 
 login($db_link);
 
-$start_time = microtime();
 $start_array = explode(" ",$start_time);
 $start_time = $start_array[1] + $start_array[0];
 

+ 33 - 2
html/inc/footer.php

@@ -1,13 +1,44 @@
-<div id="copyright">Copyright &copy; 2008-2025 Eye v<?php print $config["version"]; ?> &nbsp<a href="https://github.com/rajven/Eye">rnd@rajven.ru</a></div>
+<br style="clear: both">
 
+<div id="copyright">Copyright &copy; 2008-2025 Eye v<?php print $config["version"]; ?> &nbsp<a href="https://github.com/rajven/Eye">rnd@rajven.ru</a></div>
+<hr>
+<div>
 <?php
 $end_time = microtime();
 $end_array = explode(" ",$end_time);
 $end_time = $end_array[1] + $end_array[0];
 $time = $end_time - $start_time;
-printf(WEB_page_speed."%f ".WEB_sec,$time);
+$end_memory = memory_get_usage();
+$peak_memory = memory_get_peak_usage();
 ob_end_flush();
 ?>
+</div>
+
+<div class="performance-info">
+    ⚡ Страница сгенерирована за <strong><?php printf("%.4f сек", $time); ?></strong>
+    &nbsp;|&nbsp;
+    🧠 Память: <?php echo fbytes($peak_memory); ?> (пик)
+    &nbsp;|&nbsp;
+    💾 Использовано: <?php echo fbytes($end_memory - $start_memory); ?>
+</div>
+
+<style>
+.performance-info {
+//    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
+//    color: white;
+    padding: 12px 20px;
+    border-radius: 10px;
+    font-size: 14px;
+    text-align: center;
+    margin: 20px 0;
+    box-shadow: 0 4px 15px rgba(0,0,0,0.1);
+    font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
+}
+
+.performance-info strong {
+    color: black;
+}
+</style>
 
 </div>
 

+ 15 - 2
html/inc/footer.simple.php

@@ -1,13 +1,26 @@
-<div id="copyright">Copyright &copy; 2008-2025 Eye v<?php print $config["version"]; ?> &nbsp<a href="https://github.com/rajven/Eye">rnd@rajven.ru</a></div>
+<br style="clear: both">
 
+<div id="copyright">Copyright &copy; 2008-2025 Eye v<?php print $config["version"]; ?> &nbsp<a href="https://github.com/rajven/Eye">rnd@rajven.ru</a></div>
+<hr>
+<div>
 <?php
 $end_time = microtime();
 $end_array = explode(" ",$end_time);
 $end_time = $end_array[1] + $end_array[0];
 $time = $end_time - $start_time;
-printf(WEB_page_speed."%f ".WEB_sec,$time);
+$end_memory = memory_get_usage();
+$peak_memory = memory_get_peak_usage();
 ob_end_flush();
 ?>
+</div>
+
+<div class="performance-info">
+    ⚡ Страница сгенерирована за <strong><?php printf("%.4f сек", $time); ?></strong>
+    &nbsp;|&nbsp;
+    🧠 Память: <?php echo fbytes($peak_memory); ?> (пик)
+    &nbsp;|&nbsp;
+    💾 Использовано: <?php echo fbytes($end_memory - $start_memory); ?>
+</div>
 
 </div>
 

+ 0 - 15
html/inc/footer.small.php

@@ -1,15 +0,0 @@
-<div id="copyright">Copyright &copy; 2008-2025 Eye v<?php print $config["version"]; ?> &nbsp<a href="https://github.com/rajven/Eye">rnd@rajven.ru</a></div>
-<?php
-$end_time = microtime();
-$end_array = explode(" ",$end_time);
-$end_time = $end_array[1] + $end_array[0];
-$time = $end_time - $start_time;
-printf(WEB_page_speed."%f ".WEB_sec,$time);
-ob_end_flush();
-?>
-</div>
-
-<script src="/js/select-auto.js"></script>
-
-</body>
-</html>

+ 1 - 0
html/inc/languages/english.php

@@ -434,6 +434,7 @@ define("WEB_group_filter_order","Rules order");
 define("WEB_group_filter_name","Filter name");
 
 /* edit OU */
+define("WEB_ou_parent","Parent group");
 define("WEB_ou_autoclient_rules","Rules for autoclient clients");
 define("WEB_ou_rules_for_autoassigning","Rules for autoassigning addresses in");
 define("WEB_ou_rules_order","Apply order");

+ 1 - 0
html/inc/languages/russian.php

@@ -434,6 +434,7 @@ define("WEB_group_filter_order","Порядок правил");
 define("WEB_group_filter_name","Название фильтра");
 
 /* edit OU */
+define("WEB_ou_parent","Родительская группа");
 define("WEB_ou_autoclient_rules","Правила для автоназначенных клиентов");
 define("WEB_ou_rules_for_autoassigning","Правила автоназначения адресов в");
 define("WEB_ou_rules_order","Порядок применения");

+ 1 - 0
scripts/updates/2-9-0/ou.sql

@@ -0,0 +1 @@
+ALTER TABLE `OU` ADD COLUMN `parent_id` INT(11) NULL DEFAULT NULL;