query('SELECT `Id` FROM `NetworkMark` WHERE `Comment`="'.$Comment.'"'); if ($DbResult->num_rows > 0) { $DbRow = $DbResult->fetch_assoc(); return $DbRow['Id']; } else { $DbResult = $Database->query('INSERT INTO `NetworkMark` (`Comment`) VALUES ("'.$Comment.'")'); return $Database->insert_id; } } function GetSubgroupByRange(string $AddressRange): int { global $Database; $DbResult = $Database->query('SELECT `Id` FROM `NetworkMangleSubgroup` WHERE `AddressRange`="'.$AddressRange.'"'); if ($DbResult->num_rows > 0) { $DbRow = $DbResult->fetch_assoc(); return $DbRow['Id']; } else { $DbResult = $Database->query('INSERT INTO `NetworkMangleSubgroup` (`AddressRange`) VALUES ("'.$AddressRange.'")'); return $Database->insert_id; } } function InsertToAddressTreeIPv4(array &$Tree, NetworkAddressIPv4 $Address, string $Name, bool $InterSubnets = false, bool $ForceMark = false) { global $Config; $Found = false; foreach ($Tree['Items'] as $Index => $Node) { if ($Node['Address']->Contain($Address)) { InsertToAddressTreeIPv4($Tree['Items'][$Index], $Address, $Name, true); $Found = true; } } if ($Found == false) { if ($InterSubnets and ($Tree['Address']->Prefix < $Config['MainRouter']['MangleRuleSubgroupMinPrefix']) and ($Address->Prefix > ($Tree['Address']->Prefix + 1))) { $NewAddress = new NetworkAddressIPv4(); $NewAddress->Address = $Address->Address; $NewAddress->ChangePrefix($Tree['Address']->Prefix + 1); $Tree['Items'][] = array('Address' => $NewAddress, 'Name' => $Name, 'Items' => array(), 'ForceMark' => false); InsertToAddressTreeIPv4($Tree['Items'][count($Tree['Items']) - 1], $Address, $Name, true); } else { $NewNode = array('Address' => $Address, 'Name' => $Name, 'Items' => array(), 'ForceMark' => $ForceMark); // Should be existed items placed under new node? $Found = false; foreach ($Tree['Items'] as $Index => $Node) { if (($Node['Address']->Address == $NewNode['Address']->Address) and ($Node['Address']->Prefix == $NewNode['Address']->Prefix)) $Found = true; if ($Address->Contain($Node['Address'])) { $NewNode['Items'][] = $Node; unset($Tree['Items'][$Index]); } } if ($Found == false) $Tree['Items'][] = $NewNode; } } } function InsertToAddressTreeIPv6(array &$Tree, NetworkAddressIPv6 $Address, string $Name, bool $InterSubnets = false, bool $ForceMark = false) { global $Config; $Found = false; foreach ($Tree['Items'] as $Index => $Node) { if ($Node['Address']->Contain($Address)) { InsertToAddressTreeIPv6($Tree['Items'][$Index], $Address, $Name, true); $Found = true; } } if ($Found == false) { if ($InterSubnets and ($Tree['Address']->Prefix < $Config['MainRouter']['MangleRuleSubgroupMinPrefix']) and ($Address->Prefix > ($Tree['Address']->Prefix + 1))) { $NewAddress = new NetworkAddressIPv6(); $NewAddress->Address = $Address->Address; $NewAddress->ChangePrefix($Tree['Address']->Prefix + 1); $Tree['Items'][] = array('Address' => $NewAddress, 'Name' => $Name, 'Items' => array(), 'ForceMark' => false); InsertToAddressTreeIPv6($Tree['Items'][count($Tree['Items']) - 1], $Address, $Name, true); } else { $NewNode = array('Address' => $Address, 'Name' => $Name, 'Items' => array(), 'ForceMark' => $ForceMark); // Should be existed items placed under new node? $Found = false; foreach ($Tree['Items'] as $Index => $Node) { if (($Node['Address']->Address == $NewNode['Address']->Address) and ($Node['Address']->Prefix == $NewNode['Address']->Prefix)) $Found = true; if ($Address->Contain($Node['Address'])) { $NewNode['Items'][] = $Node; unset($Tree['Items'][$Index]); } } if ($Found == false) $Tree['Items'][] = $NewNode; } } } function ShowSubnetNode(array $Node, int $Indent = 0): void { echo(str_repeat(' ', $Indent).$Node['Address']->AddressToString().'/'.$Node['Address']->Prefix.' '.$Node['Name']."\n"); foreach ($Node['Items'] as $Index => $Item) { ShowSubnetNode($Item, $Indent + 1); } }