.*?)(\1)$/s'; while (preg_match($pattern, $string, $matches)) { $string = $matches['value']; } } } return $string; } /** * Humanize User * * Process an array containing user info to add/modify elements. * * @param array $user */ // TESTME needs unit testing function humanize_user(&$user) { $level_permissions = auth_user_level_permissions($user['level']); $level_real = $level_permissions['level']; if (isset($GLOBALS['config']['user_level'][$level_real])) { $def = $GLOBALS['config']['user_level'][$level_real]; $user['level_label'] = $def['name']; $user['level_name'] = $def['name']; $user['level_real'] = $level_real; unset($def['name'], $level_permissions['level']); $user = array_merge($user, $def, $level_permissions); // Add label class $user['label_class'] = ($user['row_class'] == 'disabled' ? 'inverse' : $user['row_class']); } //r($user); } /** * Humanize Scheduled Maintanance * * Process an array containing a row from `alert_maintenance` and in-place add/modify elements for use in the UI * * */ function humanize_maintenance(&$maint) { $maint['duration'] = $maint['maint_end'] - $maint['maint_start']; if ($maint['maint_global'] == 1) { $maint['entities_text'] = 'Global Maintenance'; } else { $entities = dbFetchRows("SELECT * FROM `alerts_maint_assoc` WHERE `maint_id` = ?", array($maint['maint_id'])); if (is_array($entities) && count($entities)) { foreach ($entities as $entity) { // FIXME, what here should be? } } else { $maint['entities_text'] = 'Maintenance is not associated with any entities.'; } } $maint['row_class'] = ''; if ($maint['maint_start'] > $GLOBALS['config']['time']['now']) { $maint['start_text'] = "+".format_uptime($maint['maint_start'] - $GLOBALS['config']['time']['now']); } else { $maint['start_text'] = "-".format_uptime($GLOBALS['config']['time']['now'] - $maint['maint_start']); $maint['row_class'] = "warning"; $maint['active_text'] = 'active'; } if ($maint['maint_end'] > $GLOBALS['config']['time']['now']) { $maint['end_text'] = "+".format_uptime($maint['maint_end'] - $GLOBALS['config']['time']['now']); } else { $maint['end_text'] = "-".format_uptime($GLOBALS['config']['time']['now'] - $maint['maint_end']); $maint['row_class'] = "disabled"; $maint['active_text'] = 'ended'; } } /** * Humanize Alert Check * * Process an array containing a row from `alert_checks` and in place to add/modify elements. * * @param array $check */ // TESTME needs unit testing function humanize_alert_check(&$check) { // Fetch the queries to build the alert table. list($query, $param, $query_count) = build_alert_table_query(array('alert_test_id' => $check['alert_test_id'])); // Fetch a quick set of alert_status values to build the alert check status text $query = str_replace(" * ", " `alert_status` ", $query); $check['entities'] = dbFetchRows($query, $param); $check['entity_status'] = array('up' => 0, 'down' => 0, 'unknown' => 0, 'delay' => 0, 'suppress' => 0); foreach ($check['entities'] as $alert_table_id => $alert_table_entry) { if ($alert_table_entry['alert_status'] == '1') { ++$check['entity_status']['up']; } elseif ($alert_table_entry['alert_status'] == '0') { ++$check['entity_status']['down']; } elseif ($alert_table_entry['alert_status'] == '2') { ++$check['entity_status']['delay']; } elseif ($alert_table_entry['alert_status'] == '3') { ++$check['entity_status']['suppress']; } else { ++$check['entity_status']['unknown']; } } $check['num_entities'] = count($check['entities']); if ($check['entity_status']['up'] == $check['num_entities']) { $check['class'] = "green"; $check['html_row_class'] = "up"; } elseif ($check['entity_status']['down'] > 0) { if ($check['severity'] === 'warn') { $check['class'] = "olive"; $check['html_row_class'] = "warning"; } else { $check['class'] = "red"; $check['html_row_class'] = "error"; } } elseif ($check['entity_status']['delay'] > 0) { $check['class'] = "orange"; $check['html_row_class'] = "warning"; } elseif ($check['entity_status']['suppress'] > 0) { $check['class'] = "purple"; $check['html_row_class'] = "suppressed"; } elseif ($check['entity_status']['up'] > 0) { $check['class'] = "green"; $check['html_row_class'] = "success"; } else { $check['entity_status']['class'] = "gray"; $check['table_tab_colour'] = "#555555"; $check['html_row_class'] = "disabled"; } $check['status_numbers'] = ''. $check['entity_status']['up']. ''. $check['entity_status']['suppress']. ''. $check['entity_status']['down']. ''. $check['entity_status']['delay']. ''. $check['entity_status']['unknown']. ''; // We return nothing, $check is modified in place. } /** * Humanize Alert * * Process an array containing a row from `alert_entry` and `alert_entry-state` in place to add/modify elements. * * @param array $entry */ // TESTME needs unit testing function humanize_alert_entry(&$entry) { // Exit if already humanized if (isset($entry['humanized']) && $entry['humanized']) { return; } // Set colours and classes based on the status of the alert if ($entry['alert_status'] == '1') { // 1 means ok. Set blue text and disable row class $entry['class'] = "green"; $entry['html_row_class'] = "up"; $entry['status'] = "OK"; } elseif ($entry['alert_status'] == '0') { // 0 means down. Set red text and error class //r($entry); if ($entry['severity'] === 'warn') { $entry['class'] = "olive"; $entry['html_row_class'] = "warning"; $entry['status'] = "WARNING"; } else { $entry['class'] = "red"; $entry['html_row_class'] = "error"; $entry['status'] = "FAILED"; } } elseif ($entry['alert_status'] == '2') { // 2 means the checks failed but we're waiting for x repetitions. set colour to orange and class to warning $entry['class'] = "orange"; $entry['html_row_class'] = "warning"; $entry['status'] = "DELAYED"; } elseif ($entry['alert_status'] == '3') { // 3 means the checks failed but the alert is suppressed. set the colour to purple and the row class to suppressed $entry['class'] = "purple"; $entry['html_row_class'] = "suppressed"; $entry['status'] = "SUPPRESSED"; } else { // Anything else set the colour to grey and the class to disabled. $entry['class'] = "gray"; $entry['html_row_class'] = "disabled"; $entry['status'] = "Unknown"; } // Set the checked/changed/alerted entries to formatted date strings if they exist, else set them to never if (!isset($entry['last_checked']) || $entry['last_checked'] == '0') { $entry['checked'] = "Never"; } else { $entry['checked'] = format_uptime(time()-$entry['last_checked'], 'short-3'); } if (!isset($entry['last_changed']) || $entry['last_changed'] == '0') { $entry['changed'] = "Never"; } else { $entry['changed'] = format_uptime(time()-$entry['last_changed'], 'short-3'); } if (!isset($entry['last_alerted']) || $entry['last_alerted'] == '0') { $entry['alerted'] = "Never"; } else { $entry['alerted'] = format_uptime(time()-$entry['last_alerted'], 'short-3'); } if (!isset($entry['last_recovered']) || $entry['last_recovered'] == '0') { $entry['recovered'] = "Never"; } else { $entry['recovered'] = format_uptime(time()-$entry['last_recovered'], 'short-3'); } if (!isset($entry['ignore_until']) || $entry['ignore_until'] == '0') { $entry['ignore_until_text'] = "Disabled"; } else { $entry['ignore_until_text'] = format_timestamp($entry['ignore_until']); } if (!isset($entry['ignore_until_ok']) || $entry['ignore_until_ok'] == '0') { $entry['ignore_until_ok_text'] = "Disabled"; } else { $entry['ignore_until_ok_text'] = 'Yes'; } // Set humanized so we can check for it later. $entry['humanized'] = TRUE; // We return nothing as we're working on a reference. } /** * Humanize Device * * Process an array containing a row from `devices` to add/modify elements. * * @param array $device * @return none */ // TESTME needs unit testing function humanize_device(&$device) { global $config; // Exit if already humanized if (isset($device['humanized']) && $device['humanized']) { return; } // Expand the device state array from the php serialized string $device['state'] = safe_unserialize($device['device_state']); // Set the HTML class and Tab color for the device based on status if ($device['status'] == '0') { $device['row_class'] = "danger"; $device['html_row_class'] = "error"; } else { $device['row_class'] = ""; $device['html_row_class'] = "up"; } if ($device['ignore'] == '1' || (!is_null($device['ignore_until']) && strtotime($device['ignore_until']) > time()) ) { $device['html_row_class'] = "suppressed"; if ($device['status'] == '1') { $device['html_row_class'] = "success"; // Why green for ignore? Confusing! // I chose this purely because using green for up and blue for up/ignore was uglier. } else { $device['row_class'] = "suppressed"; } } if ($device['disabled'] == '1') { $device['row_class'] = "disabled"; $device['html_row_class'] = "disabled"; } // Set country code always lowercase if (isset($device['location_country'])) { $device['location_country'] = strtolower($device['location_country']); } // Set the name we print for the OS $device['os_text'] = $config['os'][$device['os']]['text']; // Format ASN as asdot if configured $device['human_local_as'] = $config['web_show_bgp_asdot'] ? bgp_asplain_to_asdot($device['bgpLocalAs']) : $device['bgpLocalAs']; // Mark this device as being humanized $device['humanized'] = TRUE; } /** * Humanize BGP Peer * * Returns a the $peer array with processed information: * row_class, table_tab_colour, state_class, admin_class * * @param array $peer * @return array|void $peer * */ // TESTME needs unit testing function humanize_bgp(&$peer) { global $config; // Exit if already humanized if (isset($peer['humanized']) && $peer['humanized']) { return; } // Set colours and classes based on the status of the peer if ($peer['bgpPeerAdminStatus'] === 'stop' || $peer['bgpPeerAdminStatus'] === 'halted') { // Peer is disabled, set row to warning and text classes to muted. $peer['html_row_class'] = "warning"; $peer['state_class'] = "muted"; $peer['admin_class'] = "muted"; $peer['alert'] = 0; $peer['disabled'] = 1; } elseif ($peer['bgpPeerAdminStatus'] === "start" || $peer['bgpPeerAdminStatus'] === "running" ) { // Peer is enabled, set state green and check other things $peer['admin_class'] = "success"; if ($peer['bgpPeerState'] === "established") { // Peer is up, set colour to blue and disable row class $peer['state_class'] = "success"; $peer['html_row_class'] = "up"; } else { // Peer is down, set colour to red and row class to error. $peer['state_class'] = "danger"; $peer['html_row_class'] = "error"; } } // Set text and colour if peer is same AS, private AS or external. if ($peer['bgpPeerRemoteAs'] == $peer['local_as']) { $peer['peer_type_class'] = "info"; $peer['peer_type'] = "iBGP"; } else { $peer['peer_type_class'] = "primary"; $peer['peer_type'] = "eBGP"; } // Private AS numbers, see: https://tools.ietf.org/html/rfc6996 if (is_bgp_as_private($peer['bgpPeerRemoteAs'])) { $peer['peer_type_class'] = "warning"; $peer['peer_type'] = "Priv ".$peer['peer_type']; } if (is_bgp_as_private($peer['local_as'])) { $peer['peer_local_class'] = "warning"; $peer['peer_local_type'] = "private"; } else { $peer['peer_local_class'] = ""; $peer['peer_local_type'] = "public"; } // Format (compress) the local/remote IPs if they're IPv6 $peer['human_localip'] = ip_compress($peer['bgpPeerLocalAddr']); $peer['human_remoteip'] = ip_compress($peer['bgpPeerRemoteAddr']); // Format ASN as asdot if configured $peer['human_local_as'] = $config['web_show_bgp_asdot'] ? bgp_asplain_to_asdot($peer['local_as']) : $peer['local_as']; $peer['human_remote_as'] = $config['web_show_bgp_asdot'] ? bgp_asplain_to_asdot($peer['bgpPeerRemoteAs']) : $peer['bgpPeerRemoteAs']; // Set humanized entry in the array so we can tell later $peer['humanized'] = TRUE; } function process_port_label(&$this_port, $device) { global $config; //file_put_contents('/tmp/process_port_label_'.$device['hostname'].'_'.$this_port['ifIndex'].'.port', var_export($this_port, TRUE)); ///DEBUG // OS Specific rewrites (get your shit together, vendors) if ($device['os'] === 'zxr10') { $this_port['ifAlias'] = preg_replace("/^" . str_replace("/", "\\/", $this_port['ifName']) . "\s*/", '', $this_port['ifDescr']); } elseif ($device['os'] === 'ciscosb' && $this_port['ifType'] === 'propVirtual' && is_numeric($this_port['ifDescr'])) { $this_port['ifName'] = 'Vlan'.$this_port['ifDescr']; } // Will copy ifDescr -> ifAlias if ifDescr != ifName (Actually for Brocade NOS and Allied Telesys devices) if (isset($config['os'][$device['os']]['ifDescr_ifAlias']) && $config['os'][$device['os']]['ifDescr_ifAlias'] && $this_port['ifDescr'] !== $this_port['ifName'] && $this_port['ifDescr'] !== '-' && in_array($this_port['ifType'], [ 'ethernetCsmacd', 'opticalTransport', 'opticalChannel', 'ip' ], TRUE) && !str_starts($this_port['ifDescr'], [ 'Allied Teles', 'No description configured' ])) { if (safe_empty($this_port['ifAlias']) || $this_port['ifName'] === $this_port['ifAlias']) { $this_port['ifAlias'] = $this_port['ifDescr']; } } // Write port_label, port_label_base and port_label_num // Here definition override for ifDescr, because Calix switch ifDescr <> ifName since fw 2.2 // Note, only for 'calix' os now if ($device['os'] === 'calix') { unset($config['os'][$device['os']]['ifname']); $version_parts = explode('.', $device['version']); if ($version_parts[0] > 2 || ($version_parts[0] == 2 && $version_parts[1] > 1)) { if (safe_empty($this_port['ifName'])) { $this_port['port_label'] = $this_port['ifDescr']; } else { $this_port['port_label'] = $this_port['ifName']; } } } // This happen on some liebert UPS devices or when device have memory leak (ie Eaton Powerware) if (isset($config['os'][$device['os']]['ifType_ifDescr']) && $config['os'][$device['os']]['ifType_ifDescr'] && $this_port['ifIndex']) { $len = strlen($this_port['ifDescr']); $type = rewrite_iftype($this_port['ifType']); if ($type && ($len === 0 || $len > 255 || isHexString($this_port['ifDescr']) || preg_match('/(.)\1{4,}/', $this_port['ifDescr']))) { $this_port['ifDescr'] = $type . ' ' . $this_port['ifIndex']; print_debug("Port 'ifDescr' rewritten: '' -> '" . $this_port['ifDescr'] . "'"); } } if (isset($config['os'][$device['os']]['ifname'])) { if (safe_empty($this_port['ifName'])) { $this_port['port_label'] = $this_port['ifDescr']; } else { $this_port['port_label'] = $this_port['ifName']; } } elseif (isset($config['os'][$device['os']]['ifalias'])) { $this_port['port_label'] = $this_port['ifAlias']; } else { if ($this_port['ifDescr'] === '' && $this_port['ifName'] !== '') { // Some new NX-OS have empty ifDescr $this_port['port_label'] = $this_port['ifName']; } else { $this_port['port_label'] = $this_port['ifDescr']; } if (isset($config['os'][$device['os']]['ifindex'])) { $this_port['port_label'] .= ' ' . $this_port['ifIndex']; } } // Process label by os definition rewrites $oid = 'port_label'; if (isset($config['os'][$device['os']][$oid])) { $this_port['port_label'] = preg_replace('/\ {2,}/', ' ', $this_port['port_label']); // clear 2 and more spaces $oid_base = $oid.'_base'; $oid_num = $oid.'_num'; $oid_short = $oid.'_short'; foreach ($config['os'][$device['os']][$oid] as $pattern) { if (preg_match($pattern, $this_port[$oid], $matches)) { //print_debug_vars($matches); if (isset($matches[$oid])) { // if exist 'port_label' match reference $this_port[$oid] = $matches[$oid]; } else { // or just first reference $this_port[$oid] = $matches[1]; } print_debug("Port '$oid' rewritten: '" . $this_port[$oid] . "' -> '" . $this_port[$oid] . "'"); if (isset($matches[$oid_base])) { $this_port[$oid_base] = $matches[$oid_base]; } if (isset($matches[$oid_num])) { if ($device['os'] === 'cisco-altiga' && $matches[$oid_num] === '') { // This derp only for altiga (I hope so) // See cisco-altiga os definition // If port_label_num match set, but it empty, use ifIndex as num $this_port[$oid_num] = $this_port['ifIndex']; $this_port[$oid] .= $this_port['ifIndex']; } else { $this_port[$oid_num] = $matches[$oid_num]; } } // Additionally, possible to parse port_label_short if (isset($matches[$oid_short])) { $this_port[$oid_short] = $matches[$oid_short]; } // Additionally, possible to parse ifAlias from ifDescr (ie timos) if (isset($matches['ifAlias'])) { $this_port['ifAlias'] = $matches['ifAlias']; } break; } } } else { // Common port name rewrites (do not escape) $this_port['port_label'] = rewrite_ifname($this_port['port_label'], FALSE); } if (!isset($this_port['port_label_base'])) { // skip when already set by previous processing, ie os definitions // Extract bracket part from port label and remove it $label_bracket = ''; if (preg_match('/\s*(\([^\)]+\))$/', $this_port['port_label'], $matches)) { // GigaVUE-212 Port 8/48 (Network Port) // rtif(172.20.30.46/28) print_debug('Port label ('.$this_port['port_label'].') matched #1'); // Just for find issues $label_bracket = $this_port['port_label']; // fallback list($this_port['port_label']) = explode($matches[0], $this_port['port_label'], 2); } elseif (preg_match('!^10*(?:/10*)*\s*[MGT]Bit\s+(.*)!i', $this_port['port_label'], $matches)) { // remove 10/100 Mbit part from beginning, this broke detect label_base/label_num (see hirschmann-switch os) // 10/100 MBit Ethernet Switch Interface 6 // 1 MBit Ethernet Switch Interface 6 print_debug('Port label ('.$this_port['port_label'].') matched #2'); // Just for find issues $label_bracket = $this_port['port_label']; // fallback $this_port['port_label'] = $matches[1]; } elseif (preg_match('/^(.+)\s*:\s+(.+)/', $this_port['port_label'], $matches)) { // Another case with colon // gigabitEthernet 1/0/24 : copper // port 3: Gigabit Fiber print_debug('Port label ('.$this_port['port_label'].') matched #3'); // Just for find issues $label_bracket = $this_port['port_label']; // fallback $this_port['port_label'] = $matches[1]; } // Detect port_label_base and port_label_num //if (preg_match('/\d+(?:(?:[\/:](?:[a-z])?[\d\.:]+)+[a-z\d\.\:]*(?:[\-\_][\w\.\:]+)*|\/\w+$)/i', $this_port['port_label'], $matches)) if (preg_match('/\d+((?(?:[\/:]([a-z]*\d+|[a-z]+[a-z0-9\-\_]*)(?:\.\d+)?)+)(?[\-\_\.][\w\.\:]+)*|\/\w+$)/i', $this_port['port_label'], $matches)) { // Multipart numeric /* 1/1/1 e1-0/0/1.0 e1-0/2/0:13.0 dwdm0/1/0/6 DTI1/1/0 Cable8/1/4-upstream2 Cable8/1/4 16GigabitEthernet1/2/1 cau4-0/2/0 dot11radio0/0 Dialer0/0.1 Downstream 0/2/0 ControlEthernet0/RSP0/CPU0/S0/10 1000BaseTX Port 8/48 Name Backplane-GigabitEthernet0/3 Ethernet1/10 FC port 0/19 GigabitEthernet0/0/0/1 GigabitEthernet0/1.ServiceInstance.206 Integrated-Cable7/0/0:0 Logical Upstream Channel 1/0.0/0 Slot0/1 sonet_12/1 GigaVUE-212 Port 8/48 (Network Port) Stacking Port 1/StackA gigabitEthernet 1/0/24 : copper 1:38 1/4/x24, mx480-xe-0-0-0 1/4/x24 5/1/lns-net */ $this_port['port_label_num'] = $matches[0]; list($this_port['port_label_base']) = explode($matches[0], $this_port['port_label'], 2); $this_port['port_label'] = $this_port['port_label_base'] . $this_port['port_label_num']; // Remove additional part (after port number) } elseif (preg_match('/(?(?:\d+[a-z])?\d[\d\.\:]*(?:[\-\_]\w+)?)(?: [a-z()\[\] ]+)?$/i', $this_port['port_label'], $matches)) { // Simple numeric /* GigaVUE-212 Port 1 (Network Port) MMC-A s3 SW Port Atm0_Physical_Interface wan1_phys fwbr101i0 Nortel Ethernet Switch 325-24G Module - Port 1 lo0.32768 vlan.818 jsrv.1 Bundle-Ether1.1701 Ethernet1 ethernet_13 eth0 eth0.101 BVI900 A/1 e1 CATV-MAC 1 16 */ $this_port['port_label_num'] = $matches['port_label_num']; $this_port['port_label_base'] = substr($this_port['port_label'], 0, 0 - strlen($matches[0])); $this_port['port_label'] = $this_port['port_label_base'] . $this_port['port_label_num']; // Remove additional part (after port number) } else { // All other (non-numeric) /* UniPing Server Solution v3/SMS Enet Port MMC-A s2 SW Port Control Plane */ $this_port['port_label_base'] = $this_port['port_label']; } // When not empty label brackets and empty numeric part, re-add brackets to label if (!empty($label_bracket) && safe_empty($this_port['port_label_num'])) { // rtif(172.20.30.46/28) $this_port['port_label'] = $label_bracket; $this_port['port_label_base'] = $this_port['port_label']; $this_port['port_label_num'] = ''; } } // Make short version (do not escape) if (isset($this_port['port_label_short'])) { // Short already parsed from definitions (not sure if need additional shorting) $this_port['port_label_short'] = short_ifname($this_port['port_label_short'], NULL, FALSE); } else { $this_port['port_label_short'] = short_ifname($this_port['port_label'], NULL, FALSE); } // Set entity variables for use by code which uses entities // Base label part: TenGigabitEthernet3/3 -> TenGigabitEthernet, GigabitEthernet4/8.722 -> GigabitEthernet, Vlan2603 -> Vlan //$port['port_label_base'] = preg_replace('/^([A-Za-z ]*).*/', '$1', $port['port_label']); //$port['port_label_num'] = substr($port['port_label'], strlen($port['port_label_base'])); // Second label part // // // Index example for TenGigabitEthernet3/10.324: // // $ports_links['Ethernet'][] = array('label_base' => 'TenGigabitEthernet', 'label_num0' => '3', 'label_num1' => '10', 'label_num2' => '324') // $label_num = preg_replace('![^\d\.\/]!', '', substr($data['port_label'], strlen($data['port_label_base']))); // Remove base part and all not-numeric chars // preg_match('!^(\d+)(?:\/(\d+)(?:\.(\d+))*)*!', $label_num, $label_nums); // Split by slash and point (1/1.324) // $ports_links[$data['human_type']][$data['ifIndex']] = array( // 'label' => $data['port_label'], // 'label_base' => $data['port_label_base'], // 'label_num0' => $label_nums[0], // 'label_num1' => $label_nums[1], // 'label_num2' => $label_nums[2], // 'link' => generate_port_link($data, $data['port_label_short']) // ); return TRUE; } /** * Humanize port. * * Returns a $port array with processed information: * label, humans_speed, human_type, html_class and human_mac * row_class, table_tab_colour * * Escaping should not be done here, since these values are used in the API too. * * @param array $port * @return void * */ // TESTME needs unit testing function humanize_port(&$port) { global $config, $cache; // Exit if already humanized if (isset($port['humanized']) && $port['humanized']) { return; } // Pre-check if port attribs for device exist if (!isset($GLOBALS['cache']['devices_attribs'][$port['device_id']])) { cache_device_attribs_exist($port); } // if (!isset($GLOBALS['cache']['devices_attribs'][$port['device_id']]['port'])) { // $GLOBALS['cache']['devices_attribs'][$port['device_id']]['port'] = dbExist('entity_attribs', '`entity_type` = ? AND `device_id` = ?', [ 'port', $port['device_id'] ]); // } // Speedup queries, when not exist attribs if (isset($GLOBALS['cache']['devices_attribs'][$port['device_id']]['port']) && $GLOBALS['cache']['devices_attribs'][$port['device_id']]['port']) { $port['attribs'] = get_entity_attribs('port', $port['port_id']); } else { $port['attribs'] = []; } // If we can get the device data from the global cache, do it, else pull it from the db (mostly for external scripts) if (is_array($GLOBALS['cache']['devices']['id'][$port['device_id']])) { $device = &$GLOBALS['cache']['devices']['id'][$port['device_id']]; } else { $device = device_by_id_cache($port['device_id']); } // Workaround for devices/ports who long time not updated and have empty port_label if (safe_empty($port['port_label']) || safe_empty($port['port_label_base'].$port['port_label_num'])) { process_port_label($port, $device); } // Set humanised values for use in UI $port['human_speed'] = humanspeed($port['ifSpeed']); $port['human_type'] = rewrite_iftype($port['ifType']); $port['html_class'] = port_html_class($port['ifOperStatus'], $port['ifAdminStatus'], $port['encrypted']); $port['human_mac'] = format_mac($port['ifPhysAddress']); // Set entity_* values for code which expects them. $port['entity_name'] = $port['port_label']; $port['entity_shortname'] = $port['port_label_short']; $port['entity_descr'] = $port['ifAlias']; $port['table_tab_colour'] = "#aaaaaa"; $port['row_class'] = ""; $port['icon'] = 'port-ignored'; // Default $port['admin_status'] = $port['ifAdminStatus']; if ($port['ifAdminStatus'] === "down") { $port['admin_status'] = 'disabled'; $port['row_class'] = "disabled"; $port['icon'] = 'port-disabled'; $port['admin_class'] = "disabled"; } elseif ($port['ifAdminStatus'] === "up") { $port['admin_status'] = 'enabled'; $port['admin_class'] = 'primary'; switch ($port['ifOperStatus']) { case 'up': $port['table_tab_colour'] = "#194B7F"; $port['row_class'] = "ok"; $port['icon'] = 'port-up'; $port['oper_class'] = "primary"; break; case 'monitoring': // This is monitoring ([e|r]span) ports $port['table_tab_colour'] = "#008C00"; $port['row_class'] = "success"; $port['icon'] = 'port-up'; $port['oper_class'] = "success"; break; case 'down': $port['table_tab_colour'] = "#cc0000"; $port['row_class'] = "error"; $port['icon'] = 'port-down'; $port['oper_class'] = "error"; break; case 'lowerLayerDown': $port['table_tab_colour'] = "#ff6600"; $port['row_class'] = "warning"; $port['icon'] = 'port-down'; $port['oper_class'] = "warning"; break; case 'testing': case 'unknown': case 'dormant': case 'notPresent': $port['table_tab_colour'] = "#85004b"; $port['row_class'] = "info"; $port['icon'] = 'port-ignored'; $port['oper_class'] = "info"; break; } } // If the device is down, colour the row/tab as 'warning' meaning that the entity is down because of something below it. if ($device['status'] == '0') { $port['table_tab_colour'] = "#ff6600"; $port['row_class'] = "warning"; $port['icon'] = 'port-ignored'; } if ($port['ignore'] == '1' && $port['row_class'] !== 'ok') { $port['row_class'] = "suppressed"; } if ($port['disabled'] == '1') { $port['row_class'] = "disabled"; } $port['in_rate'] = $port['ifInOctets_rate'] * 8; $port['out_rate'] = $port['ifOutOctets_rate'] * 8; // Colour in bps based on speed if > 50, else by UI convention. if ($port['ifSpeed'] > 0) { $in_perc = round($port['in_rate']/$port['ifSpeed']*100); $out_perc = round($port['out_rate']/$port['ifSpeed']*100); } else { // exclude division by zero error $in_perc = 0; $out_perc = 0; } if ($port['in_rate'] == 0) { $port['bps_in_style'] = ''; } elseif ($in_perc < '50') { $port['bps_in_style'] = 'color: #008C00;'; } else { $port['bps_in_style'] = 'color: ' . percent_colour($in_perc) . '; '; } // Colour out bps based on speed if > 50, else by UI convention. if ($port['out_rate'] == 0) { $port['bps_out_style'] = ''; } elseif ($out_perc < '50') { $port['bps_out_style'] = 'color: #394182;'; } else { $port['bps_out_style'] = 'color: ' . percent_colour($out_perc) . '; '; } // Colour in and out pps based on UI convention $port['pps_in_style'] = ($port['ifInUcastPkts_rate'] == 0) ? '' : 'color: #740074;'; $port['pps_out_style'] = ($port['ifOutUcastPkts_rate'] == 0) ? '' : 'color: #FF7400;'; $port['humanized'] = TRUE; /// Set this so we can check it later. } // Rewrite arrays /// FIXME. Clean, rename GLOBAL $rewrite_* variables into $config['rewrite'] definition $rewrite_liebert_hardware = array( // UpsProducts - Liebert UPS Registrations 'lgpSeries7200' => array('name' => 'Series 7200 UPS', 'type' => 'ups'), 'lgpUPStationGXT' => array('name' => 'UPStationGXT UPS', 'type' => 'ups'), 'lgpPowerSureInteractive' => array('name' => 'PowerSure Interactive UPS', 'type' => 'ups'), 'lgpNfinity' => array('name' => 'Nfinity UPS', 'type' => 'ups'), 'lgpNpower' => array('name' => 'Npower UPS', 'type' => 'ups'), 'lgpGXT2Dual' => array('name' => 'GXT2 Dual Inverter', 'type' => 'ups'), 'lgpPowerSureInteractive2' => array('name' => 'PowerSure Interactive 2 UPS', 'type' => 'ups'), 'lgpNX' => array('name' => 'ENPC Nx UPS', 'type' => 'ups'), 'lgpHiNet' => array('name' => 'Hiross HiNet UPS', 'type' => 'ups'), 'lgpNXL' => array('name' => 'NXL UPS', 'type' => 'ups'), 'lgpSuper400' => array('name' => 'Super 400 UPS', 'type' => 'ups'), 'lgpSeries600or610' => array('name' => 'Series 600/610 UPS', 'type' => 'ups'), 'lgpSeries300' => array('name' => 'Series 300 UPS', 'type' => 'ups'), 'lgpSeries610SMS' => array('name' => 'Series 610 Single Module System (SMS) UPS', 'type' => 'ups'), 'lgpSeries610MMU' => array('name' => 'Series 610 Multi Module Unit (MMU) UPS', 'type' => 'ups'), 'lgpSeries610SCC' => array('name' => 'Series 610 System Control Cabinet (SCC) UPS', 'type' => 'ups'), 'lgpNXr' => array('name' => 'APM UPS', 'type' => 'ups'), // AcProducts - Liebert Environmental Air Conditioning Registrations 'lgpAdvancedMicroprocessor' => array('name' => 'Environmental Advanced Microprocessor control', 'type' => 'environment'), 'lgpStandardMicroprocessor' => array('name' => 'Environmental Standard Microprocessor control', 'type' => 'environment'), 'lgpMiniMate2' => array('name' => 'Environmental Mini-Mate 2', 'type' => 'environment'), 'lgpHimod' => array('name' => 'Environmental Himod', 'type' => 'environment'), 'lgpCEMS100orLECS15' => array('name' => 'Australia Environmental CEMS100 and LECS15 control', 'type' => 'environment'), 'lgpIcom' => array('name' => 'Environmental iCOM control', 'type' => 'environment'), 'lgpIcomPA' => array('name' => 'iCOM PA (Floor mount) Environmental', 'type' => 'environment'), 'lgpIcomXD' => array('name' => 'iCOM XD (Rack cooling with compressor) Environmental', 'type' => 'environment'), 'lgpIcomXP' => array('name' => 'iCOM XP (Pumped refrigerant) Environmental', 'type' => 'environment'), 'lgpIcomSC' => array('name' => 'iCOM SC (Chiller) Environmental', 'type' => 'environment'), 'lgpIcomCR' => array('name' => 'iCOM CR (Computer Row) Environmental', 'type' => 'environment'), // iCOM PA Family - Liebert PA (Floor mount) Environmental Registrations 'lgpIcomPAtypeDS' => array('name' => 'DS Environmental', 'type' => 'environment'), 'lgpIcomPAtypeHPM' => array('name' => 'HPM Environmental', 'type' => 'environment'), 'lgpIcomPAtypeChallenger' => array('name' => 'Challenger Environmental', 'type' => 'environment'), 'lgpIcomPAtypePeX' => array('name' => 'PeX Environmental', 'type' => 'environment'), 'lgpIcomPAtypeDeluxeSys3' => array('name' => 'Deluxe System 3 Environmental', 'type' => 'environment'), 'lgpIcomPAtypeJumboCW' => array('name' => 'Jumbo CW Environmental', 'type' => 'environment'), 'lgpIcomPAtypeDSE' => array('name' => 'DSE Environmental', 'type' => 'environment'), 'lgpIcomPAtypePEXS' => array('name' => 'PEX-S Environmental', 'type' => 'environment'), 'lgpIcomPAtypePDX' => array('name' => 'PDX - PCW Environmental', 'type' => 'environment'), // iCOM XD Family - Liebert XD Environmental Registrations 'lgpIcomXDtypeXDF' => array('name' => 'XDF Environmental', 'type' => 'environment'), 'lgpIcomXDtypeXDFN' => array('name' => 'XDFN Environmental', 'type' => 'environment'), 'lgpIcomXPtypeXDP' => array('name' => 'XDP Environmental', 'type' => 'environment'), 'lgpIcomXPtypeXDPCray' => array('name' => 'XDP Environmental products for Cray', 'type' => 'environment'), 'lgpIcomXPtypeXDC' => array('name' => 'XDC Environmental', 'type' => 'environment'), 'lgpIcomXPtypeXDPW' => array('name' => 'XDP-W Environmental', 'type' => 'environment'), // iCOM SC Family - Liebert SC (Chillers) Environmental Registrations 'lgpIcomSCtypeHPC' => array('name' => 'HPC Environmental', 'type' => 'environment'), 'lgpIcomSCtypeHPCSSmall' => array('name' => 'HPC-S Small', 'type' => 'environment'), 'lgpIcomSCtypeHPCSLarge' => array('name' => 'HPC-S Large', 'type' => 'environment'), 'lgpIcomSCtypeHPCR' => array('name' => 'HPC-R', 'type' => 'environment'), 'lgpIcomSCtypeHPCM' => array('name' => 'HPC-M', 'type' => 'environment'), 'lgpIcomSCtypeHPCL' => array('name' => 'HPC-L', 'type' => 'environment'), 'lgpIcomSCtypeHPCW' => array('name' => 'HPC-W', 'type' => 'environment'), // iCOM CR Family - Liebert CR (Computer Row) Environmental Registrations 'lgpIcomCRtypeCRV' => array('name' => 'CRV Environmental', 'type' => 'environment'), // PowerConditioningProducts - Liebert Power Conditioning Registrations 'lgpPMP' => array('name' => 'PMP (Power Monitoring Panel)', 'type' => 'power'), 'lgpEPMP' => array('name' => 'EPMP (Extended Power Monitoring Panel)', 'type' => 'power'), // Transfer Switch Products - Liebert Transfer Switch Registrations 'lgpStaticTransferSwitchEDS' => array('name' => 'EDS Static Transfer Switch', 'type' => 'network'), 'lgpStaticTransferSwitch1' => array('name' => 'Static Transfer Switch 1', 'type' => 'network'), 'lgpStaticTransferSwitch2' => array('name' => 'Static Transfer Switch 2', 'type' => 'network'), 'lgpStaticTransferSwitch2FourPole' => array('name' => 'Static Transfer Switch 2 - 4Pole', 'type' => 'network'), // MultiLink Products - Liebert MultiLink Registrations 'lgpMultiLinkBasicNotification' => array('name' => 'MultiLink MLBN device proxy', 'type' => 'power'), // Power Distribution Products - Liebert Power Conditioning Distribution 'lgpRackPDU' => array('name' => 'Rack Power Distribution Products (RPDU)', 'type' => 'pdu'), 'lgpMPX' => array('name' => 'MPX product distribution (PDU)', 'type' => 'pdu'), 'lgpMPH' => array('name' => 'MPH product distribution (PDU)', 'type' => 'pdu'), 'lgpRackPDU2' => array('name' => 'Rack Power Distribution Products 2 (RPDU2)', 'type' => 'pdu'), 'lgpRPC2kMPX' => array('name' => 'MPX product distribution 2 (PDU2)', 'type' => 'pdu'), 'lgpRPC2kMPH' => array('name' => 'MPH product distribution 2 (PDU2)', 'type' => 'pdu'), // Combined System Product Registrations 'lgpPMPandLDMF' => array('name' => 'PMP version 4/LDMF', 'type' => 'power'), 'lgpPMPgeneric' => array('name' => 'PMP version 4', 'type' => 'power'), 'lgpPMPonFPC' => array('name' => 'PMP version 4 for FPC', 'type' => 'power'), 'lgpPMPonPPC' => array('name' => 'PMP version 4 for PPC', 'type' => 'power'), 'lgpPMPonFDC' => array('name' => 'PMP version 4 for FDC', 'type' => 'power'), 'lgpPMPonRDC' => array('name' => 'PMP version 4 for RDC', 'type' => 'power'), 'lgpPMPonEXC' => array('name' => 'PMP version 4 for EXC', 'type' => 'power'), 'lgpPMPonSTS2' => array('name' => 'PMP version 4 for STS2', 'type' => 'power'), 'lgpPMPonSTS2PDU' => array('name' => 'PMP version 4 for STS2/PDU', 'type' => 'power'), ); // Rewrite functions /** * Rewrites device hardware based on device os/sysObjectID and hw definitions * * @param array $device Device array required keys -> os, sysObjectID * @param string $sysObjectID_new If passed, than use "new" sysObjectID instead from device array * @return string Device hw name or empty string */ function rewrite_definition_hardware($device, $sysObjectID_new = NULL) { $model_array = get_model_array($device, $sysObjectID_new); if (is_array($model_array) && isset($model_array['name'])) { return $model_array['name']; } } /** * Rewrites device type based on device os/sysObjectID and hw definitions * * @param array $device Device array required keys -> os, sysObjectID * @param string $sysObjectID_new If passed, than use "new" sysObjectID instead from device array * @return string Device type or empty string */ function rewrite_definition_type($device, $sysObjectID_new = NULL) { $model_array = get_model_array($device, $sysObjectID_new); if (is_array($model_array) && isset($model_array['type'])) { return $model_array['type']; } } // DOCME needs phpdoc block // TESTME needs unit testing function rewrite_extreme_hardware($hardware) { $hardware = str_replace('EXTREME-BASE-MIB::', '', $hardware); // Common replaces $from = array(); $to = array(); $from[] = '/^summit/'; $to[] = 'Summit '; // summitX440G2-48t-10G4-DC $from[] = '/^x/'; $to[] = 'Summit X'; // x690-48x-4q-2c $from[] = '/^isw/'; $to[] = 'Industrial Switch isw'; // isw-8GP-G4 $from[] = '/^one/'; $to[] = 'One'; // oneC-A-600 $from[] = '/^aviatCtr/'; $to[] = 'CTR'; // aviatCtr-8440 $from[] = '/^e4g/'; $to[] = 'E4G'; // e4g-200-12x $from[] = '/^bdx8/'; $to[] = 'BlackDiamond X'; // bdx8 $from[] = '/^bd/'; $to[] = 'BlackDiamond '; // bd20804 $from[] = '/^blackDiamond/'; $to[] = 'BlackDiamond '; // blackDiamond6816 $from[] = '/^ags/'; $to[] = 'AGS'; // ags150-24p $from[] = '/^altitude/'; $to[] = 'Altitude '; // altitude4700 $from[] = '/^sentriant/'; $to[] = 'Sentriant '; // sentriantPS200v1 $from[] = '/^nwi/'; $to[] = 'NWI'; // nwi-e450a $from[] = '/^enetSwitch/'; $to[] = 'EnetSwitch '; // enetSwitch24Port $hardware = preg_replace($from, $to, $hardware); return $hardware; } // DOCME needs phpdoc block // TESTME needs unit testing function rewrite_cpqida_hardware($hardware) { return array_str_replace($GLOBALS['config']['rewrites']['cpqida_hardware'], $hardware); } // DOCME needs phpdoc block // TESTME needs unit testing function rewrite_liebert_hardware($hardware) { global $rewrite_liebert_hardware; if (isset($rewrite_liebert_hardware[$hardware])) { $hardware = $rewrite_liebert_hardware[$hardware]['name']; } return ($hardware); } // DOCME needs phpdoc block // TESTME needs unit testing function rewrite_breeze_type($type) { $type = strtolower($type); return isset($GLOBALS['config']['rewrites']['breeze_type'][$type]) ? $GLOBALS['config']['rewrites']['breeze_type'][$type] : strtoupper($type); } // DOCME needs phpdoc block // TESTME needs unit testing function rewrite_unix_hardware($descr, $hw = NULL) { $hardware = !empty($hw) ? trim($hw): 'Generic'; if (preg_match('/i[3456]86/i', $descr)) { $hardware .= ' x86 [32bit]'; } elseif (preg_match('/x86_64|amd64/i', $descr)) { $hardware .= ' x86 [64bit]'; } elseif (stripos($descr, 'ia64') !== FALSE) { $hardware .= ' IA [64bit]'; } elseif (stripos($descr, 'ppc') !== FALSE) { $hardware .= ' PPC [32bit]'; } elseif (stripos($descr, 'sparc32') !== FALSE) { $hardware .= ' SPARC [32bit]'; } elseif (stripos($descr, 'sparc64') !== FALSE) { $hardware .= ' SPARC [64bit]'; } elseif (stripos($descr, 'mips64') !== FALSE) { $hardware .= ' MIPS [64bit]'; } elseif (stripos($descr, 'mips') !== FALSE) { $hardware .= ' MIPS [32bit]'; } elseif (preg_match('/armv(\d+)/i', $descr, $matches)) { $hardware .= ' ARMv' . $matches[1]; } elseif (stripos($descr, 'armv') !== FALSE) { $hardware .= ' ARM'; } return $hardware; } // DOCME needs phpdoc block // TESTME needs unit testing function rewrite_ftos_vlanid($device, $ifindex) { // damn DELL use them one known indexes //dot1qVlanStaticName.1107787777 = Vlan 1 //dot1qVlanStaticName.1107787998 = mgmt $ftos_vlan = dbFetchCell('SELECT `ifName` FROM `ports` WHERE `device_id` = ? AND `ifIndex` = ?', [ $device['device_id'], $ifindex ]); list(,$vlanid) = explode(' ', $ftos_vlan); return $vlanid; } // DOCME needs phpdoc block // TESTME needs unit testing function rewrite_iftype($type) { return array_key_replace($GLOBALS['config']['rewrites']['iftype'], $type); } // NOTE. For graphs use $escape = FALSE // TESTME needs unit testing function rewrite_ifname($inf, $escape = TRUE) { $inf = array_str_replace($GLOBALS['config']['rewrites']['ifname'], $inf); //$inf = array_preg_replace($GLOBALS['rewrite_ifname_regexp'], $inf); // use os definitions instead $inf = preg_replace('/\ {2,}/', ' ', $inf); // Clean multiple spaces if ($escape) { $inf = escape_html($inf); } // By default use htmlentities return trim($inf); } // DOCME needs phpdoc block // TESTME needs unit testing function rewrite_adslLineType($adslLineType) { $rewrite_adslLineType = $GLOBALS['config']['rewrites']['adslLineType']; if (isset($rewrite_adslLineType[$adslLineType])) { $adslLineType = $rewrite_adslLineType[$adslLineType]; } return $adslLineType; } // DOCME needs phpdoc block // TESTME needs unit testing function short_hostname($hostname, $len = NULL, $escape = TRUE) { $len = (is_numeric($len) ? (int)$len : (int)$GLOBALS['config']['short_hostname']['length']); if (function_exists('custom_shorthost')) { $short_hostname = custom_shorthost($hostname, $len); } elseif (function_exists('custom_short_hostname')) { $short_hostname = custom_short_hostname($hostname, $len); } else { if (get_ip_version($hostname)) { return $hostname; } // If hostname is IP address, always return full hostname $parts = explode('.', $hostname); $short_hostname = $parts[0]; $i = 1; while ($i < count($parts) && strlen($short_hostname.'.'.$parts[$i]) < $len) { $short_hostname .= '.' . $parts[$i]; $i++; } } if ($escape) { $short_hostname = escape_html($short_hostname); } return $short_hostname; } // DOCME needs phpdoc block // TESTME needs unit testing // NOTE, this is shorting for ifAlias! Can be rename to short_ifalias() ? function short_port_descr($descr, $len = NULL, $escape = TRUE) { $len = (is_numeric($len) ? (int)$len : (int)$GLOBALS['config']['short_port_descr']['length']); if (function_exists('custom_short_port_descr')) { $descr = custom_short_port_descr($descr, $len); } else { list($descr) = explode("(", $descr); list($descr) = explode("[", $descr); list($descr) = explode("{", $descr); list($descr) = explode("|", $descr); list($descr) = explode("<", $descr); $descr = truncate(trim($descr), $len, ''); } if ($escape) { $descr = escape_html($descr); } return $descr; } // NOTE. For graphs use $escape = FALSE // NOTE. short_ifname() differs from short_port_descr() // short_ifname('FastEternet0/10') == 'Fa0/10' // DOCME needs phpdoc block // TESTME needs unit testing function short_ifname($if, $len = NULL, $escape = TRUE) { $len = (is_numeric($len) ? (int)$len : FALSE); $if = rewrite_ifname($if, $escape); $if = array_str_replace($GLOBALS['config']['rewrites']['shortif'], $if); $if = array_preg_replace($GLOBALS['config']['rewrites']['shortif_regexp'], $if); if ($len) { $if = truncate($if, $len, ''); } return $if; } /** * Rewrite name or description of an entity. * Note, not same as entity_rewrite(), since this function impersonally of entity db entry. * * @param string $string Entity name or description * @param null|string $entity_type Entity type, by default use common rewrites * @param bool $escape Escape return string * * @return string */ function rewrite_entity_name($string, $entity_type = NULL, $escape = TRUE) { $string = array_str_replace($GLOBALS['config']['rewrites']['entity_name'], $string, TRUE); // case-sensitive $string = array_preg_replace($GLOBALS['config']['rewrites']['entity_name_regexp'], $string); $string = preg_replace('/\s{2,}/', ' ', $string); // multiple spaces to single space $string = preg_replace('/([a-z])([A-Z]{2,})/', '$1 $2', $string); // turn "fixedAC" into "fixed AC" // Entity specific rewrites (additionally to common) switch ($entity_type) { case 'port': return rewrite_ifname($string, $escape); break; case 'processor': $string = str_replace([ "Routing Processor", "Route Processor", "Switching Processor" ], [ "RP", "RP", "SP" ], $string); break; case 'storage': $string = rewrite_storage($string); break; } if ($escape) { $string = escape_html($string); } return trim($string); } // DOCME needs phpdoc block // TESTME needs unit testing function rewrite_storage($string) { $string = preg_replace('/.*mounted on: (.*)/', "\\1", $string); // JunOS $string = preg_replace("/(.*), type: (.*), dev: (.*)/", "\\1", $string); // FreeBSD: '/mnt/Media, type: zfs, dev: Media' $string = preg_replace("/(.*) Label:(.*) Serial Number (.*)/", "\\1", $string); // Windows: E:\ Label:Large Space Serial Number 26ad0d98 return trim($string); } // DOCME needs phpdoc block // TESTME needs unit testing function rewrite_location($location) { global $config, $attribs; $location = str_replace(array('\"', '"'), '', $location); // Allow override sysLocation from DB. if ($attribs['override_sysLocation_bool']) { $new_location = $attribs['override_sysLocation_string']; $by = 'DB override'; } // This will call a user-defineable function to rewrite the location however the user wants. if (!isset($new_location) && function_exists('custom_rewrite_location')) { $new_location = custom_rewrite_location($location); $by = 'function custom_rewrite_location()'; } // This uses a statically defined array to map locations. if (!isset($new_location)) { if (isset($config['location']['map'][$location])) { $new_location = $config['location']['map'][$location]; $by = '$config[\'location\'][\'map\']'; } else if (isset($config['location']['map_regexp'])) { foreach ($config['location']['map_regexp'] as $pattern => $entry) { if (preg_match($pattern, $location)) { $new_location = $entry; $by = '$config[\'location\'][\'map_regexp\']'; break; // stop foreach } } } } if (isset($new_location)) { print_debug("sysLocation rewritten from '$location' to '$new_location' by $by."); $location = $new_location; } return $location; } /** * This function cleanup vendor/manufacturer name and * unification multiple same names to single common vendor name. */ function rewrite_vendor($string) { global $config; $clean_name = $string; // By first, clean all additional abbreviations in vendor name $clean_array = array( '/(?:\s+|,\s*)(?:inc|corp|comm|co|elec|tech|llc)(?![a-z])/i' => '', // abbreviations '/(?:\s+|,\s*)(?:Systems|Computer|Corporation|Company|Communications|Networks|Electronics)(?![a-z])/i' => '', ); foreach ($clean_array as $pattern => $replace) { if (preg_match_all($pattern, $string, $matches)) { foreach($matches[0] as $match) { $clean_name = str_replace($match, $replace, $clean_name); } } } $clean_name = trim($clean_name, " \t\n\r\0\x0B.,;'\"()"); // Clean punctuations after rewrites // Remove string duplicates $clean_name_array = array_unique(explode(' ', $clean_name)); $clean_name = implode(' ', $clean_name_array); // Now try to find exist vendor definition $clean_key = safename(strtolower($clean_name)); if (isset($config['vendors'][$clean_key])) { // Founded definition by original string return $config['vendors'][$clean_key]['name']; } $key = safename(strtolower($string)); if (isset($config['vendors'][$key])) { // Founded definition by clean string return $config['vendors'][$key]['name']; } // Now try to find definition by full search in definitions foreach ($config['vendors'] as $vendor_key => $entry) { if (strlen($entry['name']) <= 3) { // In case, when vendor name too short, that seems as abbr, ie GE if (strcasecmp($clean_name, $entry['name']) == 0 || // Cleaned string strcasecmp($string, $entry['name']) == 0) // Original string { // Founded in definitions return $entry['name']; } $search_array = array(); } else { $search_array = array($entry['name']); } if (isset($entry['full_name'])) { $search_array[] = $entry['full_name']; } // Full name of vendor if (isset($entry['alternatives'])) { $search_array = array_merge($search_array, $entry['alternatives']); } // Alternative (possible) names of vendor if (str_istarts($clean_name, $search_array) || // Cleaned string str_istarts($string, $search_array)) // Original string { // Founded in definitions return $entry['name']; } } if (strlen($clean_name) < 5 || preg_match('/^([A-Z0-9][a-z]+[\ \-]?[A-Z]+[a-z]*|[A-Z0-9]+[\ \-][A-Za-z]+|[A-Z]{2,}[a-z]+)/', $clean_name)) { // This is MultiCase name or small name, keeps as is //echo("\n"); print_error($clean_name . ': MULTICASE '); return $clean_name; } else { // Last, just return cleaned name //echo("\n"); print_error($clean_name . ': UCWORDS'); return ucwords(strtolower($clean_name)); } } // Underlying rewrite functions /** * Replace strings equals to key string with appropriate value from array: key -> replace * * @param array $array Array with string and replace string (key -> replace) * @param string $string String subject where replace * @return string Result string with replaced strings */ function array_key_replace($array, $string) { if (array_key_exists($string, $array)) { $string = $array[$string]; } return $string; } /** * Replace strings matched by key string with appropriate value from array: string -> replace * Note, by default CASE INSENSITIVE * * @param array $array Array with string and replace string (string -> replace) * @param string $string String subject where replace * @param bool $case_sensitive Case sensitive (default FALSE) * * @return string Result string with replaced strings */ function array_str_replace($array, $string, $case_sensitive = FALSE) { $search = array(); $replace = array(); foreach ($array as $key => $entry) { $search[] = $key; $replace[] = $entry; } if ($case_sensitive) { $string = str_replace($search, $replace, $string); } else { $string = str_ireplace($search, $replace, $string); } return $string; } /** * Replace strings matched by pattern key with appropriate value from array: pattern -> replace * * @param array $array Array with pattern and replace string (pattern -> replace) * @param string $string String subject where replace * @return string Result string with replaced patterns */ function array_preg_replace($array, $string) { foreach ($array as $search => $replace) { $string = preg_replace($search, $replace, $string); } return $string; } /** * Replace tag(s) inside string with appropriate key from array: %tag% -> $array['tag'] * Note, not exist tags in array will cleaned from string! * * @param array $array Array with keys appropriate for tags, wich used for replace * @param string|array $string String with tag(s) for replace (between percent sign, ie: %key%) * @param string $tag_scope Scope string for detect tag(s), default: % * @return string|array Result string with replaced tags */ function array_tag_replace($array, $string, $tag_scope = '%') { // If passed array, do tag replace recursive (for values only) if (is_array($string)) { foreach ($string as $key => $value) { $string[$key] = array_tag_replace($array, $value, $tag_scope); } return $string; } // Keep non string values as is if (!is_string($string)) { return $string; } $new_array = []; // Generate new array of tags including delimiter foreach($array as $key => $value) { $new_array[$tag_scope.$key.$tag_scope] = $value; } // Replace tags $string = array_str_replace($new_array, $string, TRUE); //$string = strtr($string, $new_array); // never use this slowest function in the world // Remove unused tags if ($tag_scope !== '/') { $pattern_clean = '/'.$tag_scope.'\S+?'.$tag_scope.'/'; } else { $pattern_clean = '%/\S+?/%'; } $string = preg_replace($pattern_clean, '', $string); return $string; } // DOCME needs phpdoc block // TESTME needs unit testing function country_from_code($code) { global $config; $countries = $config['rewrites']['countries']; $code = strtoupper(trim($code)); switch (strlen($code)) { case 0: case 1: return "Unknown"; case 2: // ISO 2 case 3: // ISO 3 // Return country by code if (array_key_exists($code, $countries)) { return $countries[$code]; } return "Unknown"; default: // Try to search by country name $names = array_unique(array_values($countries)); foreach ($names as $country) { if (str_istarts($country, $code) || str_istarts($code, $country)) { return $country; } } return "Unknown"; } } // EOF