1<?php
2
3/**
4 * Observium
5 *
6 *   This file is part of Observium.
7 *
8 *   These functions perform rewrites on strings and numbers.
9 *
10 * @package    observium
11 * @subpackage functions
12 * @author     Adam Armstrong <adama@observium.org>
13 * @copyright  (C) 2006-2013 Adam Armstrong, (C) 2013-2019 Observium Limited
14 *
15 */
16
17/**
18 * Process strings to give them a nicer capitalisation format
19 *
20 * This function does rewrites from the lowercase identifiers we use to the
21 * standard capitalisation. UK English style plurals, please.
22 * This uses $config['nicecase']
23 *
24 * @param string $item
25 * @return string
26*/
27function nicecase($item)
28{
29  $mappings = $GLOBALS['config']['nicecase'];
30  if (isset($mappings[$item])) { return $mappings[$item]; }
31  //$item = preg_replace('/([a-z])([A-Z]{2,})/', '$1 $2', $item); // turn "fixedAC" into "fixed AC"
32
33  return ucfirst($item);
34}
35
36/**
37 * Trim string and remove paired and/or escaped quotes from string
38 *
39 * @param string $string Input string
40 * @return string Cleaned string
41 */
42function trim_quotes($string, $flags = OBS_QUOTES_TRIM)
43{
44  $string = trim($string); // basic string clean
45  if (strpos($string, '"') !== FALSE)
46  {
47    if (is_flag_set(OBS_QUOTES_STRIP, $flags))
48    {
49      // Just remove all (double) quotes from string
50      $string = str_replace(array('\"', '"'), '', $string);
51    }
52    else if (is_flag_set(OBS_QUOTES_TRIM, $flags))
53    {
54      if (strpos($string, '\"') !== FALSE)
55      {
56        $string = str_replace('\"', '"', $string); // replace escaped quotes
57      }
58      $quotes = array('["\']', // remove single quotes
59                      //'\\\"',  // remove escaped quotes
60                      );
61      foreach ($quotes as $quote)
62      {
63        $pattern = '/^(' . $quote . ')(?<value>.*?)(\1)$/s';
64        while (preg_match($pattern, $string, $matches))
65        {
66          $string = $matches['value'];
67        }
68      }
69    }
70  }
71  return $string;
72}
73
74 /**
75  * Humanize User
76  *
77  *   Process an array containing user info to add/modify elements.
78  *
79  * @param array $user
80  */
81// TESTME needs unit testing
82function humanize_user(&$user)
83{
84  $level_permissions = auth_user_level_permissions($user['level']);
85  $level_real        = $level_permissions['level'];
86  if (isset($GLOBALS['config']['user_level'][$level_real]))
87  {
88    $def        = $GLOBALS['config']['user_level'][$level_real];
89    $user['level_label'] = $def['name'];
90    $user['level_name']  = $def['name'];
91    $user['level_real']  = $level_real;
92    unset($def['name'], $level_permissions['level']);
93    $user = array_merge($user, $def, $level_permissions);
94    // Add label class
95    $user['label_class']  = ($user['row_class'] == 'disabled' ? 'inverse' : $user['row_class']);
96  }
97  //r($user);
98}
99
100/**
101 * Humanize Scheduled Maintanance
102 *
103 *   Process an array containing a row from `alert_maintenance` and in-place add/modify elements for use in the UI
104 *
105 *
106 */
107function humanize_maintenance(&$maint)
108{
109
110  $maint['duration'] = $maint['maint_end'] - $maint['maint_start'];
111
112  if ($maint['maint_global'] == 1)
113  {
114    $maint['entities_text'] = '<span class="label label-info">Global Maintenance</span>';
115  } else {
116    $entities = dbFetchRows("SELECT * FROM `alerts_maint_assoc` WHERE `maint_id` = ?", array($maint['maint_id']));
117    if (is_array($entities) && count($entities))
118    {
119      foreach ($entities as $entity)
120      {
121        // FIXME, what here should be?
122      }
123    } else {
124      $maint['entities_text'] = '<span class="label label-error">Maintenance is not associated with any entities.</span>';
125    }
126  }
127
128  $maint['row_class'] = '';
129
130  if ($maint['maint_start'] > $GLOBALS['config']['time']['now'])
131  {
132    $maint['start_text'] = "+".format_uptime($maint['maint_start'] - $GLOBALS['config']['time']['now']);
133  } else {
134    $maint['start_text'] = "-".format_uptime($GLOBALS['config']['time']['now'] - $maint['maint_start']);
135    $maint['row_class']  = "warning";
136    $maint['active_text'] = '<span class="label label-warning pull-right">active</span>';
137  }
138
139  if ($maint['maint_end'] > $GLOBALS['config']['time']['now'])
140  {
141    $maint['end_text'] = "+".format_uptime($maint['maint_end'] - $GLOBALS['config']['time']['now']);
142  } else {
143    $maint['end_text'] = "-".format_uptime($GLOBALS['config']['time']['now'] - $maint['maint_end']);
144    $maint['row_class']  = "disabled";
145    $maint['active_text'] = '<span class="label label-disabled pull-right">ended</span>';
146  }
147
148}
149
150/**
151 * Humanize Alert Check
152 *
153 *   Process an array containing a row from `alert_checks` and in place to add/modify elements.
154 *
155 * @param array $check
156 */
157// TESTME needs unit testing
158function humanize_alert_check(&$check)
159{
160  // Fetch the queries to build the alert table.
161  list($query, $param, $query_count) = build_alert_table_query(array('alert_test_id' => $check['alert_test_id']));
162
163  // Fetch a quick set of alert_status values to build the alert check status text
164  $query = str_replace(" * ", " `alert_status` ", $query);
165  $check['entities'] = dbFetchRows($query, $param);
166
167  $check['entity_status'] = array('up' => 0, 'down' => 0, 'unknown' => 0, 'delay' => 0, 'suppress' => 0);
168  foreach ($check['entities'] as $alert_table_id => $alert_table_entry)
169  {
170    if ($alert_table_entry['alert_status'] == '1')      { ++$check['entity_status']['up'];
171    } elseif($alert_table_entry['alert_status'] == '0') { ++$check['entity_status']['down'];
172    } elseif($alert_table_entry['alert_status'] == '2') { ++$check['entity_status']['delay'];
173    } elseif($alert_table_entry['alert_status'] == '3') { ++$check['entity_status']['suppress'];
174    } else                                              { ++$check['entity_status']['unknown']; }
175  }
176
177  $check['num_entities'] = count($check['entities']);
178
179  if ($check['entity_status']['up'] == $check['num_entities'])
180  {
181    $check['class']  = "green"; $check['html_row_class'] = "up";
182  } elseif($check['entity_status']['down'] > '0') {
183    $check['class']  = "red"; $check['html_row_class'] = "error";
184  } elseif($check['entity_status']['delay'] > '0') {
185    $check['class']  = "orange"; $check['html_row_class'] = "warning";
186  } elseif($check['entity_status']['suppress'] > '0') {
187    $check['class']  = "purple"; $check['html_row_class'] = "suppressed";
188  } elseif($check['entity_status']['up'] > '0') {
189    $check['class']  = "green"; $check['html_row_class'] = "success";
190  } else {
191    $check['entity_status']['class']  = "gray"; $check['table_tab_colour'] = "#555555"; $check['html_row_class'] = "disabled";
192  }
193
194  $check['status_numbers'] = '<span class="label label-success">'. $check['entity_status']['up']. '</span><span class="label label-suppressed">'. $check['entity_status']['suppress'].
195         '</span><span class="label label-error">'. $check['entity_status']['down']. '</span><span class="label label-warning">'. $check['entity_status']['delay'].
196         '</span><span class="label">'. $check['entity_status']['unknown']. '</span>';
197
198  // We return nothing, $check is modified in place.
199}
200
201 /**
202  * Humanize Alert
203  *
204  *   Process an array containing a row from `alert_entry` and `alert_entry-state` in place to add/modify elements.
205  *
206  * @param array $entry
207  */
208// TESTME needs unit testing
209function humanize_alert_entry(&$entry)
210{
211  // Exit if already humanized
212  if ($entry['humanized']) { return; }
213
214  // Set colours and classes based on the status of the alert
215  if ($entry['alert_status'] == '1')
216  {
217    // 1 means ok. Set blue text and disable row class
218    $entry['class']  = "green"; $entry['html_row_class'] = "up"; $entry['status'] = "OK";
219  } elseif($entry['alert_status'] == '0') {
220    // 0 means down. Set red text and error class
221    $entry['class']  = "red"; $entry['html_row_class'] = "error"; $entry['status'] = "FAILED";
222  } elseif($entry['alert_status'] == '2') {
223    // 2 means the checks failed but we're waiting for x repetitions. set colour to orange and class to warning
224    $entry['class']  = "orange"; $entry['html_row_class'] = "warning"; $entry['status'] = "DELAYED";
225  } elseif($entry['alert_status'] == '3') {
226    // 3 means the checks failed but the alert is suppressed. set the colour to purple and the row class to suppressed
227    $entry['class']  = "purple"; $entry['html_row_class'] = "suppressed"; $entry['status'] = "SUPPRESSED";
228  } else {
229    // Anything else set the colour to grey and the class to disabled.
230    $entry['class']  = "gray"; $entry['html_row_class'] = "disabled"; $entry['status'] = "Unknown";
231  }
232
233  // Set the checked/changed/alerted entries to formatted date strings if they exist, else set them to never
234  if (!isset($entry['last_checked']) || $entry['last_checked'] == '0') { $entry['checked'] = "<i>Never</i>"; } else { $entry['checked'] = format_uptime(time()-$entry['last_checked'], 'short-3'); }
235  if (!isset($entry['last_changed']) || $entry['last_changed'] == '0') { $entry['changed'] = "<i>Never</i>"; } else { $entry['changed'] = format_uptime(time()-$entry['last_changed'], 'short-3'); }
236  if (!isset($entry['last_alerted']) || $entry['last_alerted'] == '0') { $entry['alerted'] = "<i>Never</i>"; } else { $entry['alerted'] = format_uptime(time()-$entry['last_alerted'], 'short-3'); }
237  if (!isset($entry['last_recovered']) || $entry['last_recovered'] == '0') { $entry['recovered'] = "<i>Never</i>"; } else { $entry['recovered'] = format_uptime(time()-$entry['last_recovered'], 'short-3'); }
238
239  if (!isset($entry['ignore_until']) || $entry['ignore_until'] == '0') { $entry['ignore_until_text'] = "<i>Disabled</i>"; } else { $entry['ignore_until_text'] = format_timestamp($entry['ignore_until']); }
240  if (!isset($entry['ignore_until_ok']) || $entry['ignore_until_ok'] == '0') { $entry['ignore_until_ok_text'] = "<i>Disabled</i>"; } else { $entry['ignore_until_ok_text'] = '<span class="purple">Yes</span>'; }
241
242  // Set humanized so we can check for it later.
243  $entry['humanized'] = TRUE;
244
245  // We return nothing as we're working on a reference.
246}
247
248/**
249 * Humanize Device
250 *
251 *   Process an array containing a row from `devices` to add/modify elements.
252 *
253 * @param array $device
254 * @return none
255 */
256// TESTME needs unit testing
257function humanize_device(&$device)
258{
259  global $config;
260
261  // Exit if already humanized
262  if ($device['humanized']) { return; }
263
264  // Expand the device state array from the php serialized string
265  $device['state'] = unserialize($device['device_state']);
266
267  // Set the HTML class and Tab color for the device based on status
268  if ($device['status'] == '0')
269  {
270    $device['row_class'] = "danger";
271    $device['html_row_class'] = "error";
272  } else {
273    $device['row_class'] = "";
274    $device['html_row_class'] = "up";  // Fucking dull gay colour, but at least there's a semicolon now - tom
275                                            // Your mum's a semicolon - adama
276                                            // Haha - mike
277  }
278  if ($device['ignore'] == '1')
279  {
280    $device['html_row_class'] = "suppressed";
281    if ($device['status'] == '1')
282    {
283      $device['html_row_class'] = "success";  // Why green for ignore? Confusing!
284                                              // I chose this purely because using green for up and blue for up/ignore was uglier.
285    } else {
286      $device['row_class'] = "suppressed";
287    }
288  }
289  if ($device['disabled'] == '1')
290  {
291    $device['row_class'] = "disabled";
292    $device['html_row_class'] = "disabled";
293  }
294
295  // Set country code always lowercase
296  if (isset($device['location_country']))
297  {
298    $device['location_country'] = strtolower($device['location_country']);
299  }
300
301  // Set the name we print for the OS
302  $device['os_text'] = $config['os'][$device['os']]['text'];
303
304  // Format ASN as asdot if configured
305  $device['human_local_as'] = $config['web_show_bgp_asdot'] ? bgp_asplain_to_asdot($device['bgpLocalAs']) : $device['bgpLocalAs'];
306
307  // Mark this device as being humanized
308  $device['humanized'] = TRUE;
309}
310
311/**
312 * Humanize BGP Peer
313 *
314 * Returns a the $peer array with processed information:
315 * row_class, table_tab_colour, state_class, admin_class
316 *
317 * @param array $peer
318 * @return array $peer
319 *
320 */
321// TESTME needs unit testing
322function humanize_bgp(&$peer)
323{
324  global $config;
325
326  // Exit if already humanized
327  if ($peer['humanized']) { return; }
328
329  // Set colours and classes based on the status of the peer
330  if ($peer['bgpPeerAdminStatus'] == 'stop' || $peer['bgpPeerAdminStatus'] == 'halted')
331  {
332    // Peer is disabled, set row to warning and text classes to muted.
333    $peer['html_row_class'] = "warning";
334    $peer['state_class']    = "muted";
335    $peer['admin_class']    = "muted";
336    $peer['alert']          = 0;
337    $peer['disabled']       = 1;
338  }
339  else if ($peer['bgpPeerAdminStatus'] == "start" || $peer['bgpPeerAdminStatus'] == "running" )
340  {
341    // Peer is enabled, set state green and check other things
342    $peer['admin_class'] = "success";
343    if ($peer['bgpPeerState'] == "established")
344    {
345      // Peer is up, set colour to blue and disable row class
346      $peer['state_class'] = "success"; $peer['html_row_class'] = "up";
347    } else {
348      // Peer is down, set colour to red and row class to error.
349      $peer['state_class'] = "danger"; $peer['html_row_class'] = "error";
350    }
351  }
352
353  // Set text and colour if peer is same AS, private AS or external.
354  if ($peer['bgpPeerRemoteAs'] == $peer['local_as'])                                    { $peer['peer_type_class'] = "info";    $peer['peer_type'] = "iBGP"; }
355  else                                                                                  { $peer['peer_type_class'] = "primary"; $peer['peer_type'] = "eBGP"; }
356
357  // Private AS numbers, see: https://tools.ietf.org/html/rfc6996
358  if (is_bgp_as_private($peer['bgpPeerRemoteAs']))
359  {
360    $peer['peer_type_class'] = "warning";
361    $peer['peer_type'] = "Priv ".$peer['peer_type'];
362  }
363  if (is_bgp_as_private($peer['local_as']))
364  {
365    $peer['peer_local_class'] = "warning";
366    $peer['peer_local_type']  = "private";
367  } else {
368    $peer['peer_local_class'] = "";
369    $peer['peer_local_type']  = "public";
370  }
371
372  // Format (compress) the local/remote IPs if they're IPv6
373  $peer['human_localip']  = (strstr($peer['bgpPeerLocalAddr'],  ':')) ? Net_IPv6::compress($peer['bgpPeerLocalAddr'])  : $peer['bgpPeerLocalAddr'];
374  $peer['human_remoteip'] = (strstr($peer['bgpPeerRemoteAddr'], ':')) ? Net_IPv6::compress($peer['bgpPeerRemoteAddr']) : $peer['bgpPeerRemoteAddr'];
375
376  // Format ASN as asdot if configured
377  $peer['human_local_as']  = $config['web_show_bgp_asdot'] ? bgp_asplain_to_asdot($peer['local_as']) : $peer['local_as'];
378  $peer['human_remote_as'] = $config['web_show_bgp_asdot'] ? bgp_asplain_to_asdot($peer['bgpPeerRemoteAs']) : $peer['bgpPeerRemoteAs'];
379
380  // Set humanized entry in the array so we can tell later
381  $peer['humanized'] = TRUE;
382}
383
384function process_port_label(&$this_port, $device)
385{
386  global $config;
387
388  //file_put_contents('/tmp/process_port_label_'.$device['hostname'].'_'.$this_port['ifIndex'].'.port', var_export($this_port, TRUE)); ///DEBUG
389
390  // OS Specific rewrites (get your shit together, vendors)
391  if ($device['os'] == 'zxr10') { $this_port['ifAlias'] = preg_replace("/^" . str_replace("/", "\\/", $this_port['ifName']) . "\s*/", '', $this_port['ifDescr']); }
392  if ($device['os'] == 'ciscosb' && $this_port['ifType'] == 'propVirtual' && is_numeric($this_port['ifDescr'])) { $this_port['ifName'] = 'Vlan'.$this_port['ifDescr']; }
393
394  // Added for Brocade NOS. Will copy ifDescr -> ifAlias if ifDescr != ifName
395  /* ifAlias passed over SW-MIB
396  if ($config['os'][$device['os']]['ifDescr_ifAlias'] && $this_port['ifAlias'] == '' && $this_port['ifDescr'] != $this_port['ifName'])
397  {
398    $this_port['ifAlias'] = $this_port['ifDescr'];
399  }
400  */
401
402  // Write port_label, port_label_base and port_label_num
403
404  // Here definition override for ifDescr, because Calix switch ifDescr <> ifName since fw 2.2
405  // Note, only for 'calix' os now
406  if ($device['os'] == 'calix')
407  {
408    unset($config['os'][$device['os']]['ifname']);
409    $version_parts = explode('.', $device['version']);
410    if ($version_parts[0] > 2 || ($version_parts[0] == 2 && $version_parts[1] > 1))
411    {
412      if ($this_port['ifName'] == '')
413      {
414        $this_port['port_label'] = $this_port['ifDescr'];
415      } else {
416        $this_port['port_label'] = $this_port['ifName'];
417      }
418    }
419  }
420
421  if ($this_port['ifDescr'] === '' && $config['os'][$device['os']]['ifType_ifDescr'] && $this_port['ifIndex'])
422  {
423    // This happen on some liebert UPS devices
424    $type = rewrite_iftype($this_port['ifType']);
425    if ($type)
426    {
427      $this_port['ifDescr'] = $type . ' ' . $this_port['ifIndex'];
428      print_debug("Port 'ifDescr' rewritten: '' -> '" . $this_port['ifDescr'] . "'");
429    }
430  }
431
432  if (isset($config['os'][$device['os']]['ifname']))
433  {
434    if ($this_port['ifName'] == '')
435    {
436      $this_port['port_label'] = $this_port['ifDescr'];
437    } else {
438      $this_port['port_label'] = $this_port['ifName'];
439    }
440  }
441  elseif (isset($config['os'][$device['os']]['ifalias']))
442  {
443    $this_port['port_label'] = $this_port['ifAlias'];
444  } else {
445    if ($this_port['ifDescr'] === '' && $this_port['ifName'] !== '')
446    {
447      // Some new NX-OS have empty ifDescr
448      $this_port['port_label'] = $this_port['ifName'];
449    } else {
450      $this_port['port_label'] = $this_port['ifDescr'];
451    }
452    if (isset($config['os'][$device['os']]['ifindex']))
453    {
454      $this_port['port_label'] .= ' ' . $this_port['ifIndex'];
455    }
456  }
457
458  // Process label by os definition rewrites
459  $oid = 'port_label';
460  if (isset($config['os'][$device['os']][$oid]))
461  {
462    $this_port['port_label'] = preg_replace('/\ {2,}/', ' ', $this_port['port_label']); // clear 2 and more spaces
463
464    $oid_base  = $oid.'_base';
465    $oid_num   = $oid.'_num';
466    $oid_short = $oid.'_short';
467    foreach ($config['os'][$device['os']][$oid] as $pattern)
468    {
469      if (preg_match($pattern, $this_port[$oid], $matches))
470      {
471        //print_debug_vars($matches);
472        if (isset($matches[$oid]))
473        {
474          // if exist 'port_label' match reference
475          $this_port[$oid] = $matches[$oid];
476        } else {
477          // or just first reference
478          $this_port[$oid] = $matches[1];
479        }
480        print_debug("Port '$oid' rewritten: '" . $this_port[$oid] . "' -> '" . $this_port[$oid] . "'");
481
482        if (isset($matches[$oid_base]))
483        {
484          $this_port[$oid_base] = $matches[$oid_base];
485        }
486        if (isset($matches[$oid_num]))
487        {
488          if ($device['os'] == 'cisco-altiga' && $matches[$oid_num] === '') // This derp only for altiga (I hope so)
489          {
490            // See cisco-altiga os definition
491            // If port_label_num match set, but it empty, use ifIndex as num
492            $this_port[$oid_num] = $this_port['ifIndex'];
493            $this_port[$oid] .= $this_port['ifIndex'];
494          } else {
495            $this_port[$oid_num] = $matches[$oid_num];
496          }
497        }
498
499        // Additionally possible to parse port_label_short
500        if (isset($matches[$oid_short]))
501        {
502          $this_port[$oid_short] = $matches[$oid_short];
503        }
504
505        // Additionally possible to parse ifAlias from ifDescr (ie timos)
506        if (isset($matches['ifAlias']))
507        {
508          $this_port['ifAlias'] = $matches['ifAlias'];
509        }
510        break;
511      }
512    }
513  } else {
514    // Common port name rewrites (do not escape)
515    $this_port['port_label'] = rewrite_ifname($this_port['port_label'], FALSE);
516  }
517
518  if (!isset($this_port['port_label_base'])) // skip when already set by previous processing, ie os definitions
519  {
520    // Extract bracket part from port label and remove it
521    $label_bracket = '';
522    if (preg_match('/\s*(\([^\)]+\))$/', $this_port['port_label'], $matches))
523    {
524      // GigaVUE-212 Port  8/48 (Network Port)
525      // rtif(172.20.30.46/28)
526      print_debug('Port label ('.$this_port['port_label'].') matched #1'); // Just for find issues
527      $label_bracket = $this_port['port_label']; // fallback
528      list($this_port['port_label']) = explode($matches[0], $this_port['port_label'], 2);
529    }
530    else if (preg_match('!^10*(?:/10*)*\s*[MGT]Bit\s+(.*)!i', $this_port['port_label'], $matches))
531    {
532      // remove 10/100 Mbit part from beginning, this broke detect label_base/label_num (see hirschmann-switch os)
533      // 10/100 MBit Ethernet Switch Interface 6
534      // 1 MBit Ethernet Switch Interface 6
535      print_debug('Port label ('.$this_port['port_label'].') matched #2'); // Just for find issues
536      $label_bracket = $this_port['port_label']; // fallback
537      $this_port['port_label'] = $matches[1];
538    }
539    else if (preg_match('/^(.+)\s*:\s+(.+)/', $this_port['port_label'], $matches))
540    {
541      // Another case with colon
542      // gigabitEthernet 1/0/24 : copper
543      // port 3: Gigabit Fiber
544      print_debug('Port label ('.$this_port['port_label'].') matched #3'); // Just for find issues
545      $label_bracket = $this_port['port_label']; // fallback
546      $this_port['port_label'] = $matches[1];
547    }
548
549    // Detect port_label_base and port_label_num
550    //if (preg_match('/\d+(?:(?:[\/:](?:[a-z])?[\d\.:]+)+[a-z\d\.\:]*(?:[\-\_][\w\.\:]+)*|\/\w+$)/i', $this_port['port_label'], $matches))
551    if (preg_match('/\d+((?<periodic>(?:[\/:][a-z]*\d+(?:\.\d+)?)+)(?<last>[\-\_\.][\w\.\:]+)*|\/\w+$)/i', $this_port['port_label'], $matches))
552    {
553      // Multipart numeric
554      /*
555      1/1/1
556      e1-0/0/1.0
557      e1-0/2/0:13.0
558      dwdm0/1/0/6
559      DTI1/1/0
560      Cable8/1/4-upstream2
561      Cable8/1/4
562      16GigabitEthernet1/2/1
563      cau4-0/2/0
564      dot11radio0/0
565      Dialer0/0.1
566      Downstream 0/2/0
567      ControlEthernet0/RSP0/CPU0/S0/10
568      1000BaseTX Port 8/48 Name
569      Backplane-GigabitEthernet0/3
570      Ethernet1/10
571      FC port 0/19
572      GigabitEthernet0/0/0/1
573      GigabitEthernet0/1.ServiceInstance.206
574      Integrated-Cable7/0/0:0
575      Logical Upstream Channel 1/0.0/0
576      Slot0/1
577      sonet_12/1
578      GigaVUE-212 Port  8/48 (Network Port)
579      Stacking Port 1/StackA
580      gigabitEthernet 1/0/24 : copper
581      1:38
582      1/4/x24, mx480-xe-0-0-0
583      1/4/x24
584      */
585      $this_port['port_label_num'] = $matches[0];
586      list($this_port['port_label_base']) = explode($matches[0], $this_port['port_label'], 2);
587      $this_port['port_label'] = $this_port['port_label_base'] . $this_port['port_label_num']; // Remove additional part (after port number)
588    }
589    else if (preg_match('/(?<port_label_num>(?:\d+[a-z])?\d[\d\.\:]*(?:[\-\_]\w+)?)(?: [a-z()\[\] ]+)?$/i', $this_port['port_label'], $matches))
590    {
591      // Simple numeric
592      /*
593      GigaVUE-212 Port  1 (Network Port)
594      MMC-A s3 SW Port
595      Atm0_Physical_Interface
596      wan1_phys
597      fwbr101i0
598      Nortel Ethernet Switch 325-24G Module - Port 1
599      lo0.32768
600      vlan.818
601      jsrv.1
602      Bundle-Ether1.1701
603      Ethernet1
604      ethernet_13
605      eth0
606      eth0.101
607      BVI900
608      A/1
609      e1
610      CATV-MAC 1
611      16
612      */
613      $this_port['port_label_num'] = $matches['port_label_num'];
614      $this_port['port_label_base'] = substr($this_port['port_label'], 0, 0 - strlen($matches[0]));
615      $this_port['port_label'] = $this_port['port_label_base'] . $this_port['port_label_num']; // Remove additional part (after port number)
616    } else {
617      // All other (non-numeric)
618      /*
619      UniPing Server Solution v3/SMS Enet Port
620      MMC-A s2 SW Port
621      Control Plane
622      */
623      $this_port['port_label_base'] = $this_port['port_label'];
624    }
625
626    // When not empty label brackets and empty numeric part, re-add brackets to label
627    if (!empty($label_bracket) && $this_port['port_label_num'] == '')
628    {
629      // rtif(172.20.30.46/28)
630      $this_port['port_label'] = $label_bracket;
631      $this_port['port_label_base'] = $this_port['port_label'];
632      $this_port['port_label_num'] = '';
633    }
634  }
635
636  // Make short version (do not escape)
637  if (isset($this_port['port_label_short']))
638  {
639    // Short already parsed from definitions (not sure if need additional shorting)
640    $this_port['port_label_short'] = short_ifname($this_port['port_label_short'], NULL, FALSE);
641  } else {
642    $this_port['port_label_short'] = short_ifname($this_port['port_label'], NULL, FALSE);
643  }
644
645  // Set entity variables for use by code which uses entities
646  // Base label part: TenGigabitEthernet3/3 -> TenGigabitEthernet, GigabitEthernet4/8.722 -> GigabitEthernet, Vlan2603 -> Vlan
647  //$port['port_label_base'] = preg_replace('/^([A-Za-z ]*).*/', '$1', $port['port_label']);
648  //$port['port_label_num']  = substr($port['port_label'], strlen($port['port_label_base'])); // Second label part
649  //
650  //  // Index example for TenGigabitEthernet3/10.324:
651  //  //  $ports_links['Ethernet'][] = array('label_base' => 'TenGigabitEthernet', 'label_num0' => '3', 'label_num1' => '10', 'label_num2' => '324')
652  //  $label_num  = preg_replace('![^\d\.\/]!', '', substr($data['port_label'], strlen($data['port_label_base']))); // Remove base part and all not-numeric chars
653  //  preg_match('!^(\d+)(?:\/(\d+)(?:\.(\d+))*)*!', $label_num, $label_nums); // Split by slash and point (1/1.324)
654  //  $ports_links[$data['human_type']][$data['ifIndex']] = array(
655  //    'label'      => $data['port_label'],
656  //    'label_base' => $data['port_label_base'],
657  //    'label_num0' => $label_nums[0],
658  //    'label_num1' => $label_nums[1],
659  //    'label_num2' => $label_nums[2],
660  //    'link'       => generate_port_link($data, $data['port_label_short'])
661  //  );
662
663  return TRUE;
664}
665
666/**
667 * Humanize port.
668 *
669 * Returns a the $port array with processed information:
670 * label, humans_speed, human_type, html_class and human_mac
671 * row_class, table_tab_colour
672 *
673 * Escaping should not be done here, since these values are used in the API too.
674 *
675 * @param array $port
676 * @return array $port
677 *
678 */
679// TESTME needs unit testing
680function humanize_port(&$port)
681{
682  global $config, $cache;
683
684  // Exit if already humanized
685  if ($port['humanized']) { return; }
686
687  $port['attribs'] = get_entity_attribs('port', $port['port_id']);
688
689  // If we can get the device data from the global cache, do it, else pull it from the db (mostly for external scripts)
690  if (is_array($GLOBALS['cache']['devices']['id'][$port['device_id']]))
691  {
692    $device = &$GLOBALS['cache']['devices']['id'][$port['device_id']];
693  } else {
694    $device = device_by_id_cache($port['device_id']);
695  }
696
697  // Workaround for devices/ports who long time not updated and have empty port_label
698  if (empty($port['port_label']) || strlen($port['port_label_base'].$port['port_label_num']) == 0)
699  {
700    process_port_label($port, $device);
701  }
702
703  // Set humanised values for use in UI
704  $port['human_speed'] = humanspeed($port['ifSpeed']);
705  $port['human_type']  = rewrite_iftype($port['ifType']);
706  $port['html_class']  = port_html_class($port['ifOperStatus'], $port['ifAdminStatus'], $port['encrypted']);
707  $port['human_mac']   = format_mac($port['ifPhysAddress']);
708
709  // Set entity_* values for code which expects them.
710  $port['entity_name']      = $port['port_label'];
711  $port['entity_shortname'] = $port['port_label_short'];
712  $port['entity_descr']     = $port['ifAlias'];
713
714  $port['table_tab_colour'] = "#aaaaaa"; $port['row_class'] = ""; $port['icon'] = 'port-ignored'; // Default
715  $port['admin_status'] = $port['ifAdminStatus'];
716  if     ($port['ifAdminStatus'] == "down")
717  {
718    $port['admin_status'] = 'disabled';
719    $port['row_class'] = "disabled";
720    $port['icon'] = 'port-disabled';
721  }
722  elseif ($port['ifAdminStatus'] == "up")
723  {
724    $port['admin_status'] = 'enabled';
725    switch ($port['ifOperStatus'])
726    {
727      case 'up':
728        $port['table_tab_colour'] = "#194B7F"; $port['row_class'] = "up";      $port['icon'] = 'port-up';
729        break;
730      case 'monitoring':
731        // This is monitoring ([e|r]span) ports
732        $port['table_tab_colour'] = "#008C00"; $port['row_class'] = "success"; $port['icon'] = 'port-up';
733        break;
734      case 'down':
735        $port['table_tab_colour'] = "#cc0000"; $port['row_class'] = "error";   $port['icon'] = 'port-down';
736        break;
737      case 'lowerLayerDown':
738        $port['table_tab_colour'] = "#ff6600"; $port['row_class'] = "warning"; $port['icon'] = 'port-down';
739        break;
740      case 'testing':
741      case 'unknown':
742      case 'dormant':
743      case 'notPresent':
744        $port['table_tab_colour'] = "#85004b"; $port['row_class'] = "info";    $port['icon'] = 'port-ignored';
745        break;
746    }
747  }
748
749  // If the device is down, colour the row/tab as 'warning' meaning that the entity is down because of something below it.
750  if ($device['status'] == '0')
751  {
752    $port['table_tab_colour'] = "#ff6600"; $port['row_class'] = "warning"; $port['icon'] = 'port-ignored';
753  }
754
755  $port['in_rate'] = $port['ifInOctets_rate'] * 8;
756  $port['out_rate'] = $port['ifOutOctets_rate'] * 8;
757
758  // Colour in bps based on speed if > 50, else by UI convention.
759  if ($port['ifSpeed'] > 0)
760  {
761    $in_perc  = round($port['in_rate']/$port['ifSpeed']*100);
762    $out_perc = round($port['out_rate']/$port['ifSpeed']*100);
763  } else {
764    // exclude division by zero error
765    $in_perc  = 0;
766    $out_perc = 0;
767  }
768  if ($port['in_rate'] == 0)
769  {
770    $port['bps_in_style'] = '';
771  } elseif ($in_perc < '50') {
772    $port['bps_in_style'] = 'color: #008C00;';
773  } else {
774    $port['bps_in_style'] = 'color: ' . percent_colour($in_perc) . '; ';
775  }
776
777  // Colour out bps based on speed if > 50, else by UI convention.
778  if ($port['out_rate'] == 0)
779  {
780    $port['bps_out_style'] = '';
781  } elseif ($out_perc < '50') {
782    $port['bps_out_style'] = 'color: #394182;';
783  } else {
784    $port['bps_out_style'] = 'color: ' . percent_colour($out_perc) . '; ';
785  }
786
787  // Colour in and out pps based on UI convention
788  $port['pps_in_style'] = ($port['ifInUcastPkts_rate'] == 0) ? '' : 'color: #740074;';
789  $port['pps_out_style'] = ($port['ifOutUcastPkts_rate'] == 0) ? '' : 'color: #FF7400;';
790
791  $port['humanized'] = TRUE; /// Set this so we can check it later.
792
793}
794
795// Rewrite arrays
796/// FIXME. Clean, rename GLOBAL $rewrite_* variables into $config['rewrite'] definition
797
798// List of real names for cisco entities
799$entPhysicalVendorTypes = array(
800  'cevC7xxxIo1feTxIsl'    => 'C7200-IO-FE-MII',
801  'cevChassis7140Dualfe'  => 'C7140-2FE',
802  'cevChassis7204'        => 'C7204',
803  'cevChassis7204Vxr'     => 'C7204VXR',
804  'cevChassis7206'        => 'C7206',
805  'cevChassis7206Vxr'     => 'C7206VXR',
806  'cevCpu7200Npe200'      => 'NPE-200',
807  'cevCpu7200Npe225'      => 'NPE-225',
808  'cevCpu7200Npe300'      => 'NPE-300',
809  'cevCpu7200Npe400'      => 'NPE-400',
810  'cevCpu7200Npeg1'       => 'NPE-G1',
811  'cevCpu7200Npeg2'       => 'NPE-G2',
812  'cevPa1feTxIsl'         => 'PA-FE-TX-ISL',
813  'cevPa2feTxI82543'      => 'PA-2FE-TX',
814  'cevPa8e'               => 'PA-8E',
815  'cevPaA8tX21'           => 'PA-8T-X21',
816  'cevMGBIC1000BaseLX'    => '1000BaseLX GBIC',
817  'cevPort10GigBaseLR'    => '10GigBaseLR'
818);
819
820$rewrite_junos_hardware = array(
821  '.1.3.6.1.4.1.4874.1.1.1.6.2' => 'E120',
822  '.1.3.6.1.4.1.4874.1.1.1.6.1' => 'E320',
823  '.1.3.6.1.4.1.4874.1.1.1.1.1' => 'ERX1400',
824  '.1.3.6.1.4.1.4874.1.1.1.1.3' => 'ERX1440',
825  '.1.3.6.1.4.1.4874.1.1.1.1.5' => 'ERX310',
826  '.1.3.6.1.4.1.4874.1.1.1.1.2' => 'ERX700',
827  '.1.3.6.1.4.1.4874.1.1.1.1.4' => 'ERX705',
828  '.1.3.6.1.4.1.2636.1.1.1.2.43' => 'EX2200',
829  '.1.3.6.1.4.1.2636.1.1.1.2.30' => 'EX3200',
830  '.1.3.6.1.4.1.2636.1.1.1.2.76' => 'EX3300',
831  '.1.3.6.1.4.1.2636.1.1.1.2.31' => 'EX4200',
832  '.1.3.6.1.4.1.2636.1.1.1.2.44' => 'EX4500',
833  '.1.3.6.1.4.1.2636.1.1.1.2.74' => 'EX6210',
834  '.1.3.6.1.4.1.2636.1.1.1.2.32' => 'EX8208',
835  '.1.3.6.1.4.1.2636.1.1.1.2.33' => 'EX8216',
836  '.1.3.6.1.4.1.2636.1.1.1.2.16' => 'IRM',
837  '.1.3.6.1.4.1.2636.1.1.1.2.13' => 'J2300',
838  '.1.3.6.1.4.1.2636.1.1.1.2.23' => 'J2320',
839  '.1.3.6.1.4.1.2636.1.1.1.2.24' => 'J2350',
840  '.1.3.6.1.4.1.2636.1.1.1.2.14' => 'J4300',
841  '.1.3.6.1.4.1.2636.1.1.1.2.22' => 'J4320',
842  '.1.3.6.1.4.1.2636.1.1.1.2.19' => 'J4350',
843  '.1.3.6.1.4.1.2636.1.1.1.2.15' => 'J6300',
844  '.1.3.6.1.4.1.2636.1.1.1.2.20' => 'J6350',
845  '.1.3.6.1.4.1.2636.1.1.1.2.38' => 'JCS1200',
846  '.1.3.6.1.4.1.2636.10' => 'BX7000',
847  '.1.3.6.1.4.1.12532.252.2.1' => 'SA-2000',
848  '.1.3.6.1.4.1.12532.252.6.1' => 'SA-6000',
849  '.1.3.6.1.4.1.4874.1.1.1.5.1' => 'UMC Sys Mgmt',
850  '.1.3.6.1.4.1.2636.3.41.1.1.5.4' => 'WXC1800',
851  '.1.3.6.1.4.1.2636.3.41.1.1.5.1' => 'WXC250',
852  '.1.3.6.1.4.1.2636.3.41.1.1.5.5' => 'WXC2600',
853  '.1.3.6.1.4.1.2636.3.41.1.1.5.6' => 'WXC3400',
854  '.1.3.6.1.4.1.2636.3.41.1.1.5.2' => 'WXC500',
855  '.1.3.6.1.4.1.2636.3.41.1.1.5.3' => 'WXC590',
856  '.1.3.6.1.4.1.2636.3.41.1.1.5.7' => 'WXC7800',
857  '.1.3.6.1.4.1.2636.1.1.1.2.4' => 'M10',
858  '.1.3.6.1.4.1.2636.1.1.1.2.11' => 'M10i',
859  '.1.3.6.1.4.1.2636.1.1.1.2.18' => 'M120',
860  '.1.3.6.1.4.1.2636.1.1.1.2.3' => 'M160',
861  '.1.3.6.1.4.1.2636.1.1.1.2.2' => 'M20',
862  '.1.3.6.1.4.1.2636.1.1.1.2.9' => 'M320',
863  '.1.3.6.1.4.1.2636.1.1.1.2.1' => 'M40',
864  '.1.3.6.1.4.1.2636.1.1.1.2.8' => 'M40e',
865  '.1.3.6.1.4.1.2636.1.1.1.2.5' => 'M5',
866  '.1.3.6.1.4.1.2636.1.1.1.2.10' => 'M7i',
867  '.1.3.6.1.4.1.2636.1.1.1.2.68' => 'MAG6610',
868  '.1.3.6.1.4.1.2636.1.1.1.2.67' => 'MAG6611',
869  '.1.3.6.1.4.1.2636.1.1.1.2.66' => 'MAG8600',
870  '.1.3.6.1.4.1.2636.1.1.1.2.89' => 'MX10',
871  '.1.3.6.1.4.1.2636.1.1.1.2.29' => 'MX240',
872  '.1.3.6.1.4.1.2636.1.1.1.2.88' => 'MX40',
873  '.1.3.6.1.4.1.2636.1.1.1.2.25' => 'MX480',
874  '.1.3.6.1.4.1.2636.1.1.1.2.90' => 'MX5',
875  '.1.3.6.1.4.1.2636.1.1.1.2.57' => 'MX80',
876  '.1.3.6.1.4.1.2636.1.1.1.2.21' => 'MX960',
877  '.1.3.6.1.4.1.3224.1.1' => 'Netscreen',
878  '.1.3.6.1.4.1.3224.1.3' => 'Netscreen 10',
879  '.1.3.6.1.4.1.3224.1.4' => 'Netscreen 100',
880  '.1.3.6.1.4.1.3224.1.5' => 'Netscreen 1000',
881  '.1.3.6.1.4.1.3224.1.9' => 'Netscreen 204',
882  '.1.3.6.1.4.1.3224.1.10' => 'Netscreen 208',
883  '.1.3.6.1.4.1.3224.1.8' => 'Netscreen 25',
884  '.1.3.6.1.4.1.3224.1.2' => 'Netscreen 5',
885  '.1.3.6.1.4.1.3224.1.7' => 'Netscreen 50',
886  '.1.3.6.1.4.1.3224.1.6' => 'Netscreen 500',
887  '.1.3.6.1.4.1.3224.1.13' => 'Netscreen 5000',
888  '.1.3.6.1.4.1.3224.1.14' => 'Netscreen 5GT',
889  '.1.3.6.1.4.1.3224.1.17' => 'Netscreen 5GT-ADSL-A',
890  '.1.3.6.1.4.1.3224.1.23' => 'Netscreen 5GT-ADSL-A-WLAN',
891  '.1.3.6.1.4.1.3224.1.19' => 'Netscreen 5GT-ADSL-B',
892  '.1.3.6.1.4.1.3224.1.25' => 'Netscreen 5GT-ADSL-B-WLAN',
893  '.1.3.6.1.4.1.3224.1.21' => 'Netscreen 5GT-WLAN',
894  '.1.3.6.1.4.1.3224.1.12' => 'Netscreen 5XP',
895  '.1.3.6.1.4.1.3224.1.11' => 'Netscreen 5XT',
896  '.1.3.6.1.4.1.3224.1.15' => 'Netscreen Client',
897  '.1.3.6.1.4.1.3224.1.28' => 'Netscreen ISG1000',
898  '.1.3.6.1.4.1.3224.1.16' => 'Netscreen ISG2000',
899  '.1.3.6.1.4.1.3224.1.52' => 'Netscreen SSG140',
900  '.1.3.6.1.4.1.3224.1.53' => 'Netscreen SSG140',
901  '.1.3.6.1.4.1.3224.1.35' => 'Netscreen SSG20',
902  '.1.3.6.1.4.1.3224.1.36' => 'Netscreen SSG20-WLAN',
903  '.1.3.6.1.4.1.3224.1.54' => 'Netscreen SSG320',
904  '.1.3.6.1.4.1.3224.1.55' => 'Netscreen SSG350',
905  '.1.3.6.1.4.1.3224.1.29' => 'Netscreen SSG5',
906  '.1.3.6.1.4.1.3224.1.30' => 'Netscreen SSG5-ISDN',
907  '.1.3.6.1.4.1.3224.1.33' => 'Netscreen SSG5-ISDN-WLAN',
908  '.1.3.6.1.4.1.3224.1.31' => 'Netscreen SSG5-v92',
909  '.1.3.6.1.4.1.3224.1.34' => 'Netscreen SSG5-v92-WLAN',
910  '.1.3.6.1.4.1.3224.1.32' => 'Netscreen SSG5-WLAN',
911  '.1.3.6.1.4.1.3224.1.50' => 'Netscreen SSG520',
912  '.1.3.6.1.4.1.3224.1.18' => 'Netscreen SSG550',
913  '.1.3.6.1.4.1.3224.1.51' => 'Netscreen SSG550',
914  '.1.3.6.1.4.1.2636.1.1.1.2.84' => 'QFX3000',
915  '.1.3.6.1.4.1.2636.1.1.1.2.85' => 'QFX5000',
916  '.1.3.6.1.4.1.2636.1.1.1.2.82' => 'QFX Switch',
917  '.1.3.6.1.4.1.2636.1.1.1.2.41' => 'SRX100',
918  '.1.3.6.1.4.1.2636.1.1.1.2.64' => 'SRX110',
919  '.1.3.6.1.4.1.2636.1.1.1.2.49' => 'SRX1400',
920  '.1.3.6.1.4.1.2636.1.1.1.2.36' => 'SRX210',
921  '.1.3.6.1.4.1.2636.1.1.1.2.58' => 'SRX220',
922  '.1.3.6.1.4.1.2636.1.1.1.2.39' => 'SRX240',
923  '.1.3.6.1.4.1.2636.1.1.1.2.35' => 'SRX3400',
924  '.1.3.6.1.4.1.2636.1.1.1.2.34' => 'SRX3600',
925  '.1.3.6.1.4.1.2636.1.1.1.2.86' => 'SRX550',
926  '.1.3.6.1.4.1.2636.1.1.1.2.28' => 'SRX5600',
927  '.1.3.6.1.4.1.2636.1.1.1.2.26' => 'SRX5800',
928  '.1.3.6.1.4.1.2636.1.1.1.2.40' => 'SRX650',
929  '.1.3.6.1.4.1.2636.1.1.1.2.27' => 'T1600',
930  '.1.3.6.1.4.1.2636.1.1.1.2.7' => 'T320',
931  '.1.3.6.1.4.1.2636.1.1.1.2.6' => 'T640',
932  '.1.3.6.1.4.1.2636.1.1.1.2.17' => 'TX',
933  '.1.3.6.1.4.1.2636.1.1.1.2.37' => 'TXPlus',
934);
935
936# FIXME needs a rewrite, preferrably in form above? ie cat3524tXLEn etc
937$rewrite_cisco_hardware = array(
938  '.1.3.6.1.4.1.9.1.275' => 'C2948G-L3',
939);
940
941$rewrite_breeze_type = array(
942  'aubs'     => 'AU-BS',    // modular access unit
943  'ausa'     => 'AU-SA',    // stand-alone access unit
944  'su-6-1d'  => 'SU-6-1D',  // subscriber unit supporting 6 Mbps (after 5.0 - deprecated)
945  'su-6-bd'  => 'SU-6-BD',  // subscriber unit supporting 6 Mbps
946  'su-24-bd' => 'SU-24-BD', // subscriber unit supporting 24 Mbps
947  'bu-b14'   => 'BU-B14',   // BreezeNET Base Unit supporting 14 Mbps
948  'bu-b28'   => 'BU-B28',   // BreezeNET Base Unit supporting 28 Mbps
949  'rb-b14'   => 'RB-B14',   // BreezeNET Remote Bridge supporting 14 Mbps
950  'rb-b28'   => 'RB-B28',   // BreezeNET Remote Bridge supporting 28 Mbps
951  'su-bd'    => 'SU-BD',    // subscriber unit
952  'su-54-bd' => 'SU-54-BD', // subscriber unit supporting 54 Mbps
953  'su-3-1d'  => 'SU-3-1D',  // subscriber unit supporting 3 Mbps (after 5.0 - deprecated)
954  'su-3-4d'  => 'SU-3-4D',  // subscriber unit supporting 3 Mbps
955  'ausbs'    => 'AUS-BS',   // modular access unit supporting maximum 25 subscribers
956  'aussa'    => 'AUS-SA',   // stand-alone access unit supporting maximum 25 subscribers
957  'aubs4900' => 'AU-BS-4900', // BreezeAccess 4900 modular access unit
958  'ausa4900' => 'AU-SA-4900', // BreezeAccess 4900 stand alone access unit
959  'subd4900' => 'SU-BD-4900', // BreezeAccess 4900 subscriber unit
960  'bu-b100'  => 'BU-B100',  // BreezeNET Base Unit unlimited throughput
961  'rb-b100'  => 'BU-B100',  // BreezeNET Remote Bridge unlimited throughput
962  'su-i'     => 'SU-I',
963  'au-ez'    => 'AU-EZ',
964  'su-ez'    => 'SU-EZ',
965  'su-v'     => 'SU-V',     // subscriber unit supporting 12 Mbps downlink and 8 Mbps uplink
966  'bu-b10'   => 'BU-B10',   // BreezeNET Base Unit supporting 5 Mbps
967  'rb-b10'   => 'RB-B10',   // BreezeNET Base Unit supporting 5 Mbps
968  'su-8-bd'  => 'SU-8-BD',  // subscriber unit supporting 8 Mbps
969  'su-1-bd'  => 'SU-1-BD',  // subscriber unit supporting 1 Mbps
970  'su-3-l'   => 'SU-3-L',   // subscriber unit supporting 3 Mbps
971  'su-6-l'   => 'SU-6-L',   // subscriber unit supporting 6 Mbps
972  'su-12-l'  => 'SU-12-L',  // subscriber unit supporting 12 Mbps
973  'au'       => 'AU',       // security access unit
974  'su'       => 'SU',       // security subscriber unit
975);
976
977$rewrite_cpqida_hardware = array(
978  'other' => 'Other',
979  'ida' => 'IDA',
980  'idaExpansion' => 'IDA Expansion',
981  'ida-2' => 'IDA - 2',
982  'smart' => 'SMART',
983  'smart-2e' => 'SMART - 2/E',
984  'smart-2p' => 'SMART - 2/P',
985  'smart-2sl' => 'SMART - 2SL',
986  'smart-3100es' => 'Smart - 3100ES',
987  'smart-3200' => 'Smart - 3200',
988  'smart-2dh' => 'SMART - 2DH',
989  'smart-221' => 'Smart - 221',
990  'sa-4250es' => 'Smart Array 4250ES',
991  'sa-4200' => 'Smart Array 4200',
992  'sa-integrated' => 'Integrated Smart Array',
993  'sa-431' => 'Smart Array 431',
994  'sa-5300' => 'Smart Array 5300',
995  'raidLc2' => 'RAID LC2 Controller',
996  'sa-5i' => 'Smart Array 5i',
997  'sa-532' => 'Smart Array 532',
998  'sa-5312' => 'Smart Array 5312',
999  'sa-641' => 'Smart Array 641',
1000  'sa-642' => 'Smart Array 642',
1001  'sa-6400' => 'Smart Array 6400',
1002  'sa-6400em' => 'Smart Array 6400 EM',
1003  'sa-6i' => 'Smart Array 6i',
1004  'sa-generic' => 'Generic Array',
1005  'sa-p600' => 'Smart Array P600',
1006  'sa-p400' => 'Smart Array P400',
1007  'sa-e200' => 'Smart Array E200',
1008  'sa-e200i' => 'Smart Array E200i',
1009  'sa-p400i' => 'Smart Array P400i',
1010  'sa-p800' => 'Smart Array P800',
1011  'sa-e500' => 'Smart Array E500',
1012  'sa-p700m' => 'Smart Array P700m',
1013  'sa-p212' => 'Smart Array P212',
1014  'sa-p410' => 'Smart Array P410',
1015  'sa-p410i' => 'Smart Array P410i',
1016  'sa-p411' => 'Smart Array P411',
1017  'sa-b110i' => 'Smart Array B110i SATA RAID',
1018  'sa-p712m' => 'Smart Array P712m',
1019  'sa-p711m' => 'Smart Array P711m',
1020  'sa-p812' => 'Smart Array P812',
1021  'sw-1210m' => 'StorageWorks 1210m',
1022  'sa-p220i' => 'Smart Array P220i',
1023  'sa-p222' => 'Smart Array P222',
1024  'sa-p420' => 'Smart Array P420',
1025  'sa-p420i' => 'Smart Array P420i',
1026  'sa-p421' => 'Smart Array P421',
1027  'sa-b320i' => 'Smart Array B320i',
1028  'sa-p822' => 'Smart Array P822',
1029  'sa-p721m' => 'Smart Array P721m',
1030  'sa-b120i' => 'Smart Array B120i',
1031  'hps-1224' => 'HP Storage p1224',
1032  'hps-1228' => 'HP Storage p1228',
1033  'hps-1228m' => 'HP Storage p1228m',
1034  'sa-p822se' => 'Smart Array P822se',
1035  'hps-1224e' => 'HP Storage p1224e',
1036  'hps-1228e' => 'HP Storage p1228e',
1037  'hps-1228em' => 'HP Storage p1228em',
1038  'sa-p230i' => 'Smart Array P230i',
1039  'sa-p430i' => 'Smart Array P430i',
1040  'sa-p430' => 'Smart Array P430',
1041  'sa-p431' => 'Smart Array P431',
1042  'sa-p731m' => 'Smart Array P731m',
1043  'sa-p830i' => 'Smart Array P830i',
1044  'sa-p830' => 'Smart Array P830',
1045  'sa-p831' => 'Smart Array P831'
1046);
1047
1048$rewrite_liebert_hardware = array(
1049  // UpsProducts - Liebert UPS Registrations
1050  'lgpSeries7200'                     => array('name' => 'Series 7200 UPS',                             'type' => 'ups'),
1051  'lgpUPStationGXT'                   => array('name' => 'UPStationGXT UPS',                            'type' => 'ups'),
1052  'lgpPowerSureInteractive'           => array('name' => 'PowerSure Interactive UPS',                   'type' => 'ups'),
1053  'lgpNfinity'                        => array('name' => 'Nfinity UPS',                                 'type' => 'ups'),
1054  'lgpNpower'                         => array('name' => 'Npower UPS',                                  'type' => 'ups'),
1055  'lgpGXT2Dual'                       => array('name' => 'GXT2 Dual Inverter',                          'type' => 'ups'),
1056  'lgpPowerSureInteractive2'          => array('name' => 'PowerSure Interactive 2 UPS',                 'type' => 'ups'),
1057  'lgpNX'                             => array('name' => 'ENPC Nx UPS',                                 'type' => 'ups'),
1058  'lgpHiNet'                          => array('name' => 'Hiross HiNet UPS',                            'type' => 'ups'),
1059  'lgpNXL'                            => array('name' => 'NXL UPS',                                     'type' => 'ups'),
1060  'lgpSuper400'                       => array('name' => 'Super 400 UPS',                               'type' => 'ups'),
1061  'lgpSeries600or610'                 => array('name' => 'Series 600/610 UPS',                          'type' => 'ups'),
1062  'lgpSeries300'                      => array('name' => 'Series 300 UPS',                              'type' => 'ups'),
1063  'lgpSeries610SMS'                   => array('name' => 'Series 610 Single Module System (SMS) UPS',   'type' => 'ups'),
1064  'lgpSeries610MMU'                   => array('name' => 'Series 610 Multi Module Unit (MMU) UPS',      'type' => 'ups'),
1065  'lgpSeries610SCC'                   => array('name' => 'Series 610 System Control Cabinet (SCC) UPS', 'type' => 'ups'),
1066  'lgpNXr'                            => array('name' => 'APM UPS',                                     'type' => 'ups'),
1067  // AcProducts - Liebert Environmental Air Conditioning Registrations
1068  'lgpAdvancedMicroprocessor'         => array('name' => 'Environmental Advanced Microprocessor control',        'type' => 'environment'),
1069  'lgpStandardMicroprocessor'         => array('name' => 'Environmental Standard Microprocessor control',        'type' => 'environment'),
1070  'lgpMiniMate2'                      => array('name' => 'Environmental Mini-Mate 2',                            'type' => 'environment'),
1071  'lgpHimod'                          => array('name' => 'Environmental Himod',                                  'type' => 'environment'),
1072  'lgpCEMS100orLECS15'                => array('name' => 'Australia Environmental CEMS100 and LECS15 control',   'type' => 'environment'),
1073  'lgpIcom'                           => array('name' => 'Environmental iCOM control',                           'type' => 'environment'),
1074  'lgpIcomPA'                         => array('name' => 'iCOM PA (Floor mount) Environmental',                  'type' => 'environment'),
1075  'lgpIcomXD'                         => array('name' => 'iCOM XD (Rack cooling with compressor) Environmental', 'type' => 'environment'),
1076  'lgpIcomXP'                         => array('name' => 'iCOM XP (Pumped refrigerant) Environmental',           'type' => 'environment'),
1077  'lgpIcomSC'                         => array('name' => 'iCOM SC (Chiller) Environmental',                      'type' => 'environment'),
1078  'lgpIcomCR'                         => array('name' => 'iCOM CR (Computer Row) Environmental',                 'type' => 'environment'),
1079  // iCOM PA Family - Liebert PA (Floor mount) Environmental Registrations
1080  'lgpIcomPAtypeDS'                   => array('name' => 'DS Environmental',                            'type' => 'environment'),
1081  'lgpIcomPAtypeHPM'                  => array('name' => 'HPM Environmental',                           'type' => 'environment'),
1082  'lgpIcomPAtypeChallenger'           => array('name' => 'Challenger Environmental',                    'type' => 'environment'),
1083  'lgpIcomPAtypePeX'                  => array('name' => 'PeX Environmental',                           'type' => 'environment'),
1084  'lgpIcomPAtypeDeluxeSys3'           => array('name' => 'Deluxe System 3 Environmental',               'type' => 'environment'),
1085  'lgpIcomPAtypeJumboCW'              => array('name' => 'Jumbo CW Environmental',                      'type' => 'environment'),
1086  'lgpIcomPAtypeDSE'                  => array('name' => 'DSE Environmental',                           'type' => 'environment'),
1087  'lgpIcomPAtypePEXS'                 => array('name' => 'PEX-S Environmental',                         'type' => 'environment'),
1088  'lgpIcomPAtypePDX'                  => array('name' => 'PDX - PCW Environmental',                     'type' => 'environment'),
1089  // iCOM XD Family - Liebert XD Environmental Registrations
1090  'lgpIcomXDtypeXDF'                  => array('name' => 'XDF Environmental',                           'type' => 'environment'),
1091  'lgpIcomXDtypeXDFN'                 => array('name' => 'XDFN Environmental',                          'type' => 'environment'),
1092  'lgpIcomXPtypeXDP'                  => array('name' => 'XDP Environmental',                           'type' => 'environment'),
1093  'lgpIcomXPtypeXDPCray'              => array('name' => 'XDP Environmental products for Cray',         'type' => 'environment'),
1094  'lgpIcomXPtypeXDC'                  => array('name' => 'XDC Environmental',                           'type' => 'environment'),
1095  'lgpIcomXPtypeXDPW'                 => array('name' => 'XDP-W Environmental',                         'type' => 'environment'),
1096  // iCOM SC Family - Liebert SC (Chillers) Environmental Registrations
1097  'lgpIcomSCtypeHPC'                  => array('name' => 'HPC Environmental',                           'type' => 'environment'),
1098  'lgpIcomSCtypeHPCSSmall'            => array('name' => 'HPC-S Small',                                 'type' => 'environment'),
1099  'lgpIcomSCtypeHPCSLarge'            => array('name' => 'HPC-S Large',                                 'type' => 'environment'),
1100  'lgpIcomSCtypeHPCR'                 => array('name' => 'HPC-R',                                       'type' => 'environment'),
1101  'lgpIcomSCtypeHPCM'                 => array('name' => 'HPC-M',                                       'type' => 'environment'),
1102  'lgpIcomSCtypeHPCL'                 => array('name' => 'HPC-L',                                       'type' => 'environment'),
1103  'lgpIcomSCtypeHPCW'                 => array('name' => 'HPC-W',                                       'type' => 'environment'),
1104  // iCOM CR Family - Liebert CR (Computer Row) Environmental Registrations
1105  'lgpIcomCRtypeCRV'                  => array('name' => 'CRV Environmental',                           'type' => 'environment'),
1106  // PowerConditioningProducts - Liebert Power Conditioning Registrations
1107  'lgpPMP'                            => array('name' => 'PMP (Power Monitoring Panel)',                'type' => 'power'),
1108  'lgpEPMP'                           => array('name' => 'EPMP (Extended Power Monitoring Panel)',      'type' => 'power'),
1109  // Transfer Switch Products - Liebert Transfer Switch Registrations
1110  'lgpStaticTransferSwitchEDS'        => array('name' => 'EDS Static Transfer Switch',                  'type' => 'network'),
1111  'lgpStaticTransferSwitch1'          => array('name' => 'Static Transfer Switch 1',                    'type' => 'network'),
1112  'lgpStaticTransferSwitch2'          => array('name' => 'Static Transfer Switch 2',                    'type' => 'network'),
1113  'lgpStaticTransferSwitch2FourPole'  => array('name' => 'Static Transfer Switch 2 - 4Pole',            'type' => 'network'),
1114  // MultiLink Products - Liebert MultiLink Registrations
1115  'lgpMultiLinkBasicNotification'     => array('name' => 'MultiLink MLBN device proxy',                 'type' => 'power'),
1116  // Power Distribution Products - Liebert Power Conditioning Distribution
1117  'lgpRackPDU'                        => array('name' => 'Rack Power Distribution Products (RPDU)',     'type' => 'pdu'),
1118  'lgpMPX'                            => array('name' => 'MPX product distribution (PDU)',              'type' => 'pdu'),
1119  'lgpMPH'                            => array('name' => 'MPH product distribution (PDU)',              'type' => 'pdu'),
1120  'lgpRackPDU2'                       => array('name' => 'Rack Power Distribution Products 2 (RPDU2)',  'type' => 'pdu'),
1121  'lgpRPC2kMPX'                       => array('name' => 'MPX product distribution 2 (PDU2)',           'type' => 'pdu'),
1122  'lgpRPC2kMPH'                       => array('name' => 'MPH product distribution 2 (PDU2)',           'type' => 'pdu'),
1123  // Combined System Product Registrations
1124  'lgpPMPandLDMF'                     => array('name' => 'PMP version 4/LDMF',                          'type' => 'power'),
1125  'lgpPMPgeneric'                     => array('name' => 'PMP version 4',                               'type' => 'power'),
1126  'lgpPMPonFPC'                       => array('name' => 'PMP version 4 for FPC',                       'type' => 'power'),
1127  'lgpPMPonPPC'                       => array('name' => 'PMP version 4 for PPC',                       'type' => 'power'),
1128  'lgpPMPonFDC'                       => array('name' => 'PMP version 4 for FDC',                       'type' => 'power'),
1129  'lgpPMPonRDC'                       => array('name' => 'PMP version 4 for RDC',                       'type' => 'power'),
1130  'lgpPMPonEXC'                       => array('name' => 'PMP version 4 for EXC',                       'type' => 'power'),
1131  'lgpPMPonSTS2'                      => array('name' => 'PMP version 4 for STS2',                      'type' => 'power'),
1132  'lgpPMPonSTS2PDU'                   => array('name' => 'PMP version 4 for STS2/PDU',                  'type' => 'power'),
1133);
1134
1135$rewrite_iftype = array(
1136  'other' => 'Other',
1137  'regular1822',
1138  'hdh1822',
1139  'ddnX25',
1140  'rfc877x25',
1141  'ethernetCsmacd' => 'Ethernet',
1142  'iso88023Csmacd' => 'Ethernet',
1143  'iso88024TokenBus',
1144  'iso88025TokenRing' => 'Token Ring',
1145  'iso88026Man',
1146  'starLan' => 'StarLAN',
1147  'proteon10Mbit',
1148  'proteon80Mbit',
1149  'hyperchannel',
1150  'fddi' => 'FDDI',
1151  'lapb',
1152  'sdlc',
1153  'ds1' => 'DS1',
1154  'e1' => 'E1',
1155  'basicISDN' => 'Basic Rate ISDN',
1156  'primaryISDN' => 'Primary Rate ISDN',
1157  'propPointToPointSerial' => 'PtP Serial',
1158  'ppp' => 'PPP',
1159  'softwareLoopback' => 'Loopback',
1160  'eon' => 'CLNP over IP',
1161  'ethernet3Mbit' => 'Ethernet',
1162  'nsip' => 'XNS over IP',
1163  'slip' => 'SLIP',
1164  'ultra' => 'ULTRA technologies',
1165  'ds3' => 'DS3',
1166  'sip' => 'SMDS',
1167  'frameRelay' => 'Frame Relay',
1168  'rs232' => 'RS232 Serial',
1169  'para' => 'Parallel',
1170  'arcnet' => 'Arcnet',
1171  'arcnetPlus' => 'Arcnet Plus',
1172  'atm' => 'ATM Cells',
1173  'miox25',
1174  'sonet' => 'SONET or SDH',
1175  'x25ple',
1176  'iso88022llc',
1177  'localTalk',
1178  'smdsDxi',
1179  'frameRelayService' => 'FRNETSERV-MIB',
1180  'v35',
1181  'hssi',
1182  'hippi',
1183  'modem' => 'Generic Modem',
1184  'aal5' => 'AAL5 over ATM',
1185  'sonetPath' => 'SONET Path',
1186  'sonetVT' => 'SONET VT',
1187  'smdsIcip' => 'SMDS InterCarrier Interface',
1188  'propVirtual' => 'Virtual/Internal',
1189  'propMultiplexor' => 'proprietary multiplexing',
1190  'ieee80212' => '100BaseVG',
1191  'fibreChannel' => 'Fibre Channel',
1192  'hippiInterface' => 'HIPPI',
1193  'frameRelayInterconnect' => 'Frame Relay',
1194  'aflane8023' => 'ATM Emulated LAN for 802.3',
1195  'aflane8025' => 'ATM Emulated LAN for 802.5',
1196  'cctEmul' => 'ATM Emulated circuit ',
1197  'fastEther' => 'Ethernet',
1198  'isdn' => 'ISDN and X.25',
1199  'v11' => 'CCITT V.11/X.21',
1200  'v36' => 'CCITT V.36 ',
1201  'g703at64k' => 'CCITT G703 at 64Kbps',
1202  'g703at2mb' => 'Obsolete see DS1-MIB',
1203  'qllc' => 'SNA QLLC',
1204  'fastEtherFX' => 'Ethernet',
1205  'channel' => 'Channel',
1206  'ieee80211' => 'IEEE802.11 Radio',
1207  'ibm370parChan' => 'IBM System 360/370 OEMI Channel',
1208  'escon' => 'IBM Enterprise Systems Connection',
1209  'dlsw' => 'Data Link Switching',
1210  'isdns' => 'ISDN S/T',
1211  'isdnu' => 'ISDN U',
1212  'lapd' => 'Link Access Protocol D',
1213  'ipSwitch' => 'IP Switching Objects',
1214  'rsrb' => 'Remote Source Route Bridging',
1215  'atmLogical' => 'ATM Logical Port',
1216  'ds0' => 'Digital Signal Level 0',
1217  'ds0Bundle' => 'Group of DS0s on the same DS1',
1218  'bsc' => 'Bisynchronous Protocol',
1219  'async' => 'Asynchronous Protocol',
1220  'cnr' => 'Combat Net Radio',
1221  'iso88025Dtr' => 'ISO 802.5r DTR',
1222  'eplrs' => 'Ext Pos Loc Report Sys',
1223  'arap' => 'Appletalk Remote Access Protocol',
1224  'propCnls' => 'Proprietary Connectionless Protocol',
1225  'hostPad' => 'CCITT-ITU X.29 PAD Protocol',
1226  'termPad' => 'CCITT-ITU X.3 PAD Facility',
1227  'frameRelayMPI' => 'Multiproto Interconnect over FR',
1228  'x213' => 'CCITT-ITU X213',
1229  'adsl' => 'ADSL',
1230  'radsl' => 'Rate-Adapt. DSL',
1231  'sdsl' => 'SDSL',
1232  'vdsl' => 'VDSL',
1233  'iso88025CRFPInt' => 'ISO 802.5 CRFP',
1234  'myrinet' => 'Myricom Myrinet',
1235  'voiceEM' => 'Voice recEive and transMit',
1236  'voiceFXO' => 'Voice FXO',
1237  'voiceFXS' => 'Voice FXS',
1238  'voiceEncap' => 'Voice Encapsulation',
1239  'voiceOverIp' => 'Voice over IP',
1240  'atmDxi' => 'ATM DXI',
1241  'atmFuni' => 'ATM FUNI',
1242  'atmIma' => 'ATM IMA',
1243  'pppMultilinkBundle' => 'PPP Multilink Bundle',
1244  'ipOverCdlc' => 'IBM ipOverCdlc',
1245  'ipOverClaw' => 'IBM Common Link Access to Workstn',
1246  'stackToStack' => 'IBM stackToStack',
1247  'virtualIpAddress' => 'IBM VIPA',
1248  'mpc' => 'IBM multi-protocol channel support',
1249  'ipOverAtm' => 'IBM ipOverAtm',
1250  'iso88025Fiber' => 'ISO 802.5j Fiber Token Ring',
1251  'tdlc  ' => 'IBM twinaxial data link control',
1252  'gigabitEthernet' => 'Ethernet',
1253  'hdlc' => 'HDLC',
1254  'lapf' => 'LAP F',
1255  'v37' => 'V.37',
1256  'x25mlp' => 'Multi-Link Protocol',
1257  'x25huntGroup' => 'X25 Hunt Group',
1258  'transpHdlc' => 'Transp HDLC',
1259  'interleave' => 'Interleave channel',
1260  'fast' => 'Fast channel',
1261  'ip' => 'IP',
1262  'docsCableMaclayer' => 'CATV Mac Layer',
1263  'docsCableDownstream' => 'CATV Downstream interface',
1264  'docsCableUpstream' => 'CATV Upstream interface',
1265  'a12MppSwitch' => 'Avalon Parallel Processor',
1266  'tunnel' => 'Tunnel',
1267  'coffee' => 'coffee pot',
1268  'ces' => 'Circuit Emulation Service',
1269  'atmSubInterface' => 'ATM Sub Interface',
1270  'l2vlan' => 'L2 VLAN (802.1Q)',
1271  'l3ipvlan' => 'L3 VLAN (IP)',
1272  'l3ipxvlan' => 'L3 VLAN (IPX)',
1273  'digitalPowerline' => 'IP over Power Lines',
1274  'mediaMailOverIp' => 'Multimedia Mail over IP',
1275  'dtm' => 'Dynamic Syncronous Transfer Mode',
1276  'dcn' => 'Data Communications Network',
1277  'ipForward' => 'IP Forwarding Interface',
1278  'msdsl' => 'Multi-rate Symmetric DSL',
1279  'ieee1394' => 'IEEE1394 High Performance Serial Bus',
1280  'if-gsn--HIPPI-6400 ',
1281  'dvbRccMacLayer' => 'DVB-RCC MAC Layer',
1282  'dvbRccDownstream' => 'DVB-RCC Downstream Channel',
1283  'dvbRccUpstream' => 'DVB-RCC Upstream Channel',
1284  'atmVirtual' => 'ATM Virtual Interface',
1285  'mplsTunnel' => 'MPLS Tunnel Virtual Interface',
1286  'srp' => 'Spatial Reuse Protocol       ',
1287  'voiceOverAtm' => 'Voice Over ATM',
1288  'voiceOverFrameRelay' => 'Voice Over FR',
1289  'idsl' => 'DSL over ISDN',
1290  'compositeLink' => 'Avici Composite Link Interface',
1291  'ss7SigLink' => 'SS7 Signaling Link ',
1292  'propWirelessP2P' => 'Prop. P2P wireless interface',
1293  'frForward' => 'Frame Forward Interface',
1294  'rfc1483       ' => 'Multiprotocol over ATM AAL5',
1295  'usb' => 'USB Interface',
1296  'ieee8023adLag' => '802.3ad LAg',
1297  'bgppolicyaccounting' => 'BGP Policy Accounting',
1298  'frf16MfrBundle' => 'FRF .16 Multilink Frame Relay ',
1299  'h323Gatekeeper' => 'H323 Gatekeeper',
1300  'h323Proxy' => 'H323 Proxy',
1301  'mpls' => 'MPLS ',
1302  'mfSigLink' => 'Multi-frequency signaling link',
1303  'hdsl2' => 'High Bit-Rate DSL - 2nd generation',
1304  'shdsl' => 'Multirate HDSL2',
1305  'ds1FDL' => 'Facility Data Link 4Kbps on a DS1',
1306  'pos' => 'Packet over SONET/SDH Interface',
1307  'dvbAsiIn' => 'DVB-ASI Input',
1308  'dvbAsiOut' => 'DVB-ASI Output ',
1309  'plc' => 'Power Line Communtications',
1310  'nfas' => 'Non Facility Associated Signaling',
1311  'tr008' => 'TR008',
1312  'gr303RDT' => 'Remote Digital Terminal',
1313  'gr303IDT' => 'Integrated Digital Terminal',
1314  'isup' => 'ISUP',
1315  'propDocsWirelessMaclayer' => 'Cisco proprietary Maclayer',
1316  'propDocsWirelessDownstream' => 'Cisco proprietary Downstream',
1317  'propDocsWirelessUpstream' => 'Cisco proprietary Upstream',
1318  'hiperlan2' => 'HIPERLAN Type 2 Radio Interface',
1319  'propBWAp2Mp' => 'PropBroadbandWirelessAccesspt2multipt',
1320  'sonetOverheadChannel' => 'SONET Overhead Channel',
1321  'digitalWrapperOverheadChannel' => 'Digital Wrapper',
1322  'aal2' => 'ATM adaptation layer 2',
1323  'radioMAC' => 'MAC layer over radio links',
1324  'atmRadio' => 'ATM over radio links',
1325  'imt' => 'Inter Machine Trunks',
1326  'mvl' => 'Multiple Virtual Lines DSL',
1327  'reachDSL' => 'Long Reach DSL',
1328  'frDlciEndPt' => 'Frame Relay DLCI End Point',
1329  'atmVciEndPt' => 'ATM VCI End Point',
1330  'opticalChannel' => 'Optical Channel',
1331  'opticalTransport' => 'Optical Transport',
1332  'propAtm' => 'Proprietary ATM',
1333  'voiceOverCable' => 'Voice Over Cable',
1334  'infiniband' => 'Infiniband',
1335  'teLink' => 'TE Link',
1336  'q2931' => 'Q.2931',
1337  'virtualTg' => 'Virtual Trunk Group',
1338  'sipTg' => 'SIP Trunk Group',
1339  'sipSig' => 'SIP Signaling',
1340  'docsCableUpstreamChannel' => 'CATV Upstream Channel',
1341  'econet' => 'Acorn Econet',
1342  'pon155' => 'FSAN 155Mb Symetrical PON',
1343  'pon622' => 'FSAN 622Mb Symetrical PON',
1344  'bridge' => 'Transparent bridge interface',
1345  'linegroup' => 'Interface common to multiple lines',
1346  'voiceEMFGD' => 'voice E&M Feature Group D',
1347  'voiceFGDEANA' => 'voice FGD Exchange Access North American',
1348  'voiceDID' => 'voice Direct Inward Dialing',
1349  'mpegTransport' => 'MPEG transport interface',
1350  'sixToFour' => '6to4 interface',
1351  'gtp' => 'GTP (GPRS Tunneling Protocol)',
1352  'pdnEtherLoop1' => 'Paradyne EtherLoop 1',
1353  'pdnEtherLoop2' => 'Paradyne EtherLoop 2',
1354  'opticalChannelGroup' => 'Optical Channel Group',
1355  'homepna' => 'HomePNA ITU-T G.989',
1356  'gfp' => 'GFP',
1357  'ciscoISLvlan' => 'ISL VLAN',
1358  'actelisMetaLOOP' => 'MetaLOOP',
1359  'fcipLink' => 'FCIP Link ',
1360  'rpr' => 'Resilient Packet Ring Interface Type',
1361  'qam' => 'RF Qam Interface',
1362  'lmp' => 'Link Management Protocol',
1363  'cblVectaStar' => 'Cambridge Broadband Networks Limited VectaStar',
1364  'docsCableMCmtsDownstream' => 'CATV Modular CMTS Downstream Interface',
1365  'adsl2' => 'Asymmetric Digital Subscriber Loop Version 2 ',
1366  'macSecControlledIF' => 'MACSecControlled ',
1367  'macSecUncontrolledIF' => 'MACSecUncontrolled',
1368  'aviciOpticalEther' => 'Avici Optical Ethernet Aggregate',
1369  'atmbond' => 'atmbond',
1370  'voiceFGDOS' => 'voice FGD Operator Services',
1371  'mocaVersion1' => 'MultiMedia over Coax Alliance (MoCA) Interface',
1372  'ieee80216WMAN' => 'IEEE 802.16 WMAN interface',
1373  'adsl2plus' => 'Asymmetric Digital Subscriber Loop Version 2, ',
1374  'dvbRcsMacLayer' => 'DVB-RCS MAC Layer',
1375  'dvbTdm' => 'DVB Satellite TDM',
1376  'dvbRcsTdma' => 'DVB-RCS TDMA',
1377  'x86Laps' => 'LAPS based on ITU-T X.86/Y.1323',
1378  'wwanPP' => '3GPP WWAN',
1379  'wwanPP2' => '3GPP2 WWAN',
1380  'voiceEBS' => 'voice P-phone EBS physical interface',
1381  'ifPwType' => 'Pseudowire',
1382  'ilan' => 'Internal LAN on a bridge per IEEE 802.1ap',
1383  'pip' => 'Provider Instance Port IEEE 802.1ah PBB',
1384  'aluELP' => 'A-Lu ELP',
1385  'gpon' => 'GPON',
1386  'vdsl2' => 'VDSL2)',
1387  'capwapDot11Profile' => 'WLAN Profile',
1388  'capwapDot11Bss' => 'WLAN BSS',
1389  'capwapWtpVirtualRadio' => 'WTP Virtual Radio',
1390  'bits' => 'bitsport',
1391  'docsCableUpstreamRfPort' => 'DOCSIS CATV Upstream RF',
1392  'cableDownstreamRfPort' => 'CATV Downstream RF',
1393  'vmwareVirtualNic' => 'VMware Virtual NIC',
1394  'ieee802154' => 'IEEE 802.15.4 WPAN',
1395  'otnOdu' => 'OTN ODU',
1396  'otnOtu' => 'OTN OTU',
1397  'ifVfiType' => 'VPLS Forwarding Instance',
1398  'g9981' => 'G.998.1 Bonded',
1399  'g9982' => 'G.998.2 Bonded',
1400  'g9983' => 'G.998.3 Bonded',
1401  'aluEpon' => 'EPON',
1402  'aluEponOnu' => 'EPON ONU',
1403  'aluEponPhysicalUni' => 'EPON Physical UNI',
1404  'aluEponLogicalLink' => 'EPON Logical Link',
1405  'aluGponOnu' => 'GPON ONU',
1406  'aluGponPhysicalUni' => 'GPON Physical UNI',
1407  'vmwareNicTeam' => 'VMware NIC Team',
1408);
1409
1410$rewrite_ifname = array(
1411  '-802.1q vlan subif' => '',
1412  '-802.1q' => '',
1413  '-aal5 layer' => ' aal5',
1414  'hp procurve switch software loopback interface' => 'Loopback',
1415  //'uniping server solution v3/sms' => '', // moved to os definition
1416  'control plane interface' => 'Control Plane',
1417  '802.1q encapsulation tag' => 'Vlan',
1418  'stacking port' => 'Port',
1419  '_Physical_Interface' => '',
1420
1421  // Case changes.
1422  // FIXME. I'm not sure that this is correct for label changes (mike)
1423  'ether' => 'Ether',
1424  'gig' => 'Gig',
1425  'fast' => 'Fast',
1426  'ten' => 'Ten',
1427  'forty' => 'Forty',
1428  'hundred' => 'Hundred',
1429  'bvi' => 'BVI',
1430  'vlan' => 'Vlan',
1431  'ether' => 'Ether',
1432  'tunnel' => 'Tunnel',
1433  'serial' => 'Serial',
1434  'null' => 'Null',
1435  'atm' => 'Atm',
1436  'port-channel' => 'Port-Channel',
1437  'dial' => 'Dial',
1438  'loopback' => 'Loopback',
1439);
1440
1441$rewrite_ifname_regexp = array(
1442  //'/Nortel .* Module - /i' => '', // moved no avaya group
1443  '/Baystack .* - /i' => '',
1444  '/DEC [a-z\d]+ PCI /i' => '',
1445  '/\s?Switch Interface/' => '',
1446  '/\ {2,}/' => ' ',
1447);
1448
1449$rewrite_shortif = array(
1450  'bundle-ether' => 'BE',         // IOS XR
1451  'controlethernet' => 'CE',      // IOS XR
1452  'hundredgigabitethernet' => 'Hu',
1453  'fortygigabitethernet' => 'Fo',
1454  'tengigabitethernet' => 'Te',
1455  'tengige' => 'Te',
1456  'gigabitethernet' => 'Gi',
1457  'gigabit ethernet' => 'Gi',
1458  'fastethernet' => 'Fa',
1459  'fast ethernet' => 'Fa',
1460  'managementethernet' => 'Mgmt', // DNOS
1461  'ethernet' => 'Et',
1462  'twentyfivegige' => 'Twe',
1463  'fortygige' => 'Fo',
1464  'hundredgige' => 'Hu',
1465  'management' => 'Mgmt',
1466  'serial' => 'Se',
1467  'pos' => 'Pos',
1468  'port-channel' => 'Po',
1469  'atm' => 'Atm',
1470  'null' => 'Null',
1471  'loopback' => 'Lo',
1472  'dialer' => 'Di',
1473  'vlan' => 'Vlan',
1474  'tunnel' => 'Tu',
1475  'serviceinstance' => 'SI',
1476  'dwdm' => 'DWDM',
1477  'link aggregation' => 'Lagg',
1478  'backplane' => 'Bpl',
1479);
1480
1481$rewrite_shortif_regexp = array(
1482  '/^10\w+ (Port)/i' => '\1',      // 1000BaseTX Port 8/48 -> Port 8/48
1483  '/^(?:GigaVUE)\S* (Port)/i' => '\1', // GigaVUE-212 Port 8/48
1484  '/.*(Upstream|Downstream)(\s*)[^\d]*(\d.*)/' => '\1\2\3', // Logical Upstream Channel 1/0.0/0, Video Downstream 0/0/38, Downstream RF Port 4/7
1485  '/^mgmteth(\d.*)/i' => 'Mgmt\1', // IOS XR
1486);
1487
1488$rewrite_adslLineType = array(
1489  'noChannel'          => 'No Channel',
1490  'fastOnly'           => 'Fastpath',
1491  'interleavedOnly'    => 'Interleaved',
1492  'fastOrInterleaved'  => 'Fast/Interleaved',
1493  'fastAndInterleaved' => 'Fast+Interleaved'
1494);
1495
1496$rewrite_hrDevice = array (
1497  'GenuineIntel:' => '',
1498  'AuthenticAMD:' => '',
1499  'Intel(R)' => '',
1500  'CPU' => '',
1501  '(R)' => '',
1502  '  ' => ' ',
1503);
1504
1505// Rewrite functions
1506
1507/**
1508 * Rewrites device hardware based on device os/sysObjectID and hw definitions
1509 *
1510 * @param array $device Device array required keys -> os, sysObjectID
1511 * @param string $sysObjectID_new If passed, than use "new" sysObjectID instead from device array
1512 * @return string Device hw name or empty string
1513 */
1514function rewrite_definition_hardware($device, $sysObjectID_new = NULL)
1515{
1516  $model_array = get_model_array($device, $sysObjectID_new);
1517  if (is_array($model_array) && isset($model_array['name']))
1518  {
1519    return $model_array['name'];
1520  }
1521}
1522
1523/**
1524 * Rewrites device type based on device os/sysObjectID and hw definitions
1525 *
1526 * @param array $device Device array required keys -> os, sysObjectID
1527 * @param string $sysObjectID_new If passed, than use "new" sysObjectID instead from device array
1528 * @return string Device type or empty string
1529 */
1530function rewrite_definition_type($device, $sysObjectID_new = NULL)
1531{
1532  $model_array = get_model_array($device, $sysObjectID_new);
1533  if (is_array($model_array) && isset($model_array['type']))
1534  {
1535    return $model_array['type'];
1536  }
1537}
1538
1539// DOCME needs phpdoc block
1540// TESTME needs unit testing
1541function rewrite_extreme_hardware($hardware)
1542{
1543
1544  $hardware = str_replace('EXTREME-BASE-MIB::', '', $hardware);
1545
1546  // Common replaces
1547  $from = array();
1548  $to   = array();
1549  $from[] = '/^summit/';       $to[] = 'Summit ';               // summitX440G2-48t-10G4-DC
1550  $from[] = '/^x/';            $to[] = 'Summit X';              // x690-48x-4q-2c
1551  $from[] = '/^isw/';          $to[] = 'Industrial Switch isw'; // isw-8GP-G4
1552  $from[] = '/^one/';          $to[] = 'One';                   // oneC-A-600
1553  $from[] = '/^aviatCtr/';     $to[] = 'CTR';                   // aviatCtr-8440
1554  $from[] = '/^e4g/';          $to[] = 'E4G';                   // e4g-200-12x
1555  $from[] = '/^bdx8/';         $to[] = 'BlackDiamond X';        // bdx8
1556  $from[] = '/^bd/';           $to[] = 'BlackDiamond ';         // bd20804
1557  $from[] = '/^blackDiamond/'; $to[] = 'BlackDiamond ';         // blackDiamond6816
1558  $from[] = '/^ags/';          $to[] = 'AGS';                   // ags150-24p
1559  $from[] = '/^altitude/';     $to[] = 'Altitude ';             // altitude4700
1560  $from[] = '/^sentriant/';    $to[] = 'Sentriant ';            // sentriantPS200v1
1561  $from[] = '/^nwi/';          $to[] = 'NWI';                   // nwi-e450a
1562  $from[] = '/^enetSwitch/';   $to[] = 'EnetSwitch ';           // enetSwitch24Port
1563  $hardware = preg_replace($from, $to, $hardware);
1564
1565  return $hardware;
1566}
1567
1568// DOCME needs phpdoc block
1569// TESTME needs unit testing
1570function rewrite_cpqida_hardware($hardware)
1571{
1572  global $rewrite_cpqida_hardware;
1573
1574  $hardware = array_str_replace($rewrite_cpqida_hardware, $hardware);
1575
1576  return ($hardware);
1577}
1578
1579// DOCME needs phpdoc block
1580// TESTME needs unit testing
1581function rewrite_liebert_hardware($hardware)
1582{
1583  global $rewrite_liebert_hardware;
1584
1585  if (isset($rewrite_liebert_hardware[$hardware]))
1586  {
1587    $hardware = $rewrite_liebert_hardware[$hardware]['name'];
1588  }
1589
1590  return ($hardware);
1591}
1592
1593// DOCME needs phpdoc block
1594// TESTME needs unit testing
1595function rewrite_junose_hardware($hardware)
1596{
1597  global $rewrite_junos_hardware;
1598
1599  $hardware = $rewrite_junos_hardware[$hardware];
1600  return ($hardware);
1601}
1602
1603// DOCME needs phpdoc block
1604// TESTME needs unit testing
1605function rewrite_junos_hardware($hardware)
1606{
1607  global $rewrite_junos_hardware;
1608
1609  $hardware = $rewrite_junos_hardware[$hardware];
1610  return ($hardware);
1611}
1612
1613// DOCME needs phpdoc block
1614// TESTME needs unit testing
1615function rewrite_breeze_type($type)
1616{
1617  $type = strtolower($type);
1618  if (isset($GLOBALS['rewrite_breeze_type'][$type]))
1619  {
1620    return $GLOBALS['rewrite_breeze_type'][$type];
1621  } else {
1622    return strtoupper($type);
1623  }
1624}
1625
1626// DOCME needs phpdoc block
1627// TESTME needs unit testing
1628function rewrite_unix_hardware($descr, $hw = NULL)
1629{
1630  $hardware = (!empty($hw) ? trim($hw): 'Generic');
1631
1632  if     (preg_match('/i[3456]86/i',    $descr)) { $hardware .= ' x86 [32bit]'; }
1633  elseif (preg_match('/x86_64|amd64/i', $descr)) { $hardware .= ' x86 [64bit]'; }
1634  elseif (stristr($descr, 'ia64'))    { $hardware .= ' IA [64bit]'; }
1635  elseif (stristr($descr, 'ppc'))     { $hardware .= ' PPC [32bit]'; }
1636  elseif (stristr($descr, 'sparc32')) { $hardware .= ' SPARC [32bit]'; }
1637  elseif (stristr($descr, 'sparc64')) { $hardware .= ' SPARC [64bit]'; }
1638  elseif (stristr($descr, 'mips64'))  { $hardware .= ' MIPS [64bit]'; }
1639  elseif (stristr($descr, 'mips'))    { $hardware .= ' MIPS [32bit]'; }
1640  elseif (preg_match('/armv(\d+)/i', $descr, $matches))
1641  {
1642    $hardware .= ' ARMv' . $matches[1];
1643  }
1644  //elseif (stristr($descr, 'armv5'))   { $hardware .= ' ARMv5'; }
1645  //elseif (stristr($descr, 'armv6'))   { $hardware .= ' ARMv6'; }
1646  //elseif (stristr($descr, 'armv7'))   { $hardware .= ' ARMv7'; }
1647  elseif (stristr($descr, 'armv'))    { $hardware .= ' ARM'; }
1648
1649  return ($hardware);
1650}
1651
1652// DOCME needs phpdoc block
1653// TESTME needs unit testing
1654function rewrite_ftos_vlanid($device, $ifindex)
1655{
1656  // damn DELL use them one known indexes
1657  //dot1qVlanStaticName.1107787777 = Vlan 1
1658  //dot1qVlanStaticName.1107787998 = mgmt
1659  $ftos_vlan = dbFetchCell('SELECT ifName FROM `ports` WHERE `device_id` = ? AND `ifIndex` = ?', array($device['device_id'], $ifindex));
1660  list(,$vlanid) = explode(' ', $ftos_vlan);
1661  return $vlanid;
1662}
1663
1664// DOCME needs phpdoc block
1665// TESTME needs unit testing
1666function rewrite_iftype($type)
1667{
1668  $type = array_key_replace($GLOBALS['rewrite_iftype'], $type);
1669  return $type;
1670}
1671
1672// NOTE. For graphs use $escape = FALSE
1673// TESTME needs unit testing
1674function rewrite_ifname($inf, $escape = TRUE)
1675{
1676  //$inf = strtolower($inf); // ew. -tom
1677  $inf = array_str_replace($GLOBALS['rewrite_ifname'], $inf);
1678  $inf = array_preg_replace($GLOBALS['rewrite_ifname_regexp'], $inf);
1679  if ($escape) { $inf = escape_html($inf); } // By default use htmlentities
1680
1681  return $inf;
1682}
1683
1684// DOCME needs phpdoc block
1685// TESTME needs unit testing
1686function rewrite_adslLineType($adslLineType)
1687{
1688  global $rewrite_adslLineType;
1689
1690  if (isset($rewrite_adslLineType[$adslLineType])) { $adslLineType = $rewrite_adslLineType[$adslLineType]; }
1691  return($adslLineType);
1692}
1693
1694// DOCME needs phpdoc block
1695// TESTME needs unit testing
1696function rewrite_hrDevice($dev)
1697{
1698  global $rewrite_hrDevice;
1699
1700  $dev = array_str_replace($rewrite_hrDevice, $dev);
1701  $dev = preg_replace("/\ +/"," ", $dev);
1702  $dev = trim($dev);
1703
1704  return $dev;
1705}
1706
1707// DOCME needs phpdoc block
1708// TESTME needs unit testing
1709function short_hostname($hostname, $len = NULL, $escape = TRUE)
1710{
1711  $len = (is_numeric($len) ? (int)$len : (int)$GLOBALS['config']['short_hostname']['length']);
1712
1713  if (function_exists('custom_shorthost'))
1714  {
1715    $short_hostname = custom_shorthost($hostname, $len);
1716  }
1717  else if (function_exists('custom_short_hostname'))
1718  {
1719    $short_hostname = custom_short_hostname($hostname, $len);
1720  } else {
1721
1722    if (get_ip_version($hostname)) { return $hostname; } // If hostname is IP address, always return full hostname
1723
1724    $parts = explode('.', $hostname);
1725    $short_hostname = $parts[0];
1726    $i = 1;
1727    while ($i < count($parts) && strlen($short_hostname.'.'.$parts[$i]) < $len)
1728    {
1729      $short_hostname = $short_hostname.'.'.$parts[$i];
1730      $i++;
1731    }
1732  }
1733  if ($escape) { $short_hostname = escape_html($short_hostname); }
1734
1735  return $short_hostname;
1736}
1737
1738// DOCME needs phpdoc block
1739// TESTME needs unit testing
1740// NOTE, this is shorting for ifAlias! Can be rename to short_ifalias() ?
1741function short_port_descr($descr, $len = NULL, $escape = TRUE)
1742{
1743  $len = (is_numeric($len) ? (int)$len : (int)$GLOBALS['config']['short_port_descr']['length']);
1744
1745  if (function_exists('custom_short_port_descr'))
1746  {
1747    $descr = custom_short_port_descr($descr, $len);
1748  } else {
1749
1750    list($descr) = explode("(", $descr);
1751    list($descr) = explode("[", $descr);
1752    list($descr) = explode("{", $descr);
1753    list($descr) = explode("|", $descr);
1754    list($descr) = explode("<", $descr);
1755    $descr = truncate(trim($descr), $len, '');
1756  }
1757  if ($escape) { $descr = escape_html($descr); }
1758
1759  return $descr;
1760}
1761
1762// NOTE. For graphs use $escape = FALSE
1763// NOTE. short_ifname() differs from short_port_descr()
1764// short_ifname('FastEternet0/10') == 'Fa0/10'
1765// DOCME needs phpdoc block
1766// TESTME needs unit testing
1767function short_ifname($if, $len = NULL, $escape = TRUE)
1768{
1769  $len = (is_numeric($len) ? (int)$len : FALSE);
1770
1771  $if = rewrite_ifname($if, $escape);
1772  // $if = strtolower($if);
1773  $if = array_str_replace($GLOBALS['rewrite_shortif'], $if);
1774  $if = array_preg_replace($GLOBALS['rewrite_shortif_regexp'], $if);
1775  if ($len) { $if = truncate($if, $len, ''); }
1776
1777  return $if;
1778}
1779
1780// DOCME needs phpdoc block
1781function rewrite_entity_name($string)
1782{
1783  $string = str_replace("Distributed Forwarding Card", "DFC", $string);
1784  $string = str_replace("7600 Series SPA Interface Processor-", "7600 SIP-", $string);
1785  $string = preg_replace("/Rev\.\ [0-9\.]+\ /", "", $string);
1786  $string = str_replace("12000 Series Performance Route Processor", "12000 PRP", $string);
1787  $string = preg_replace("/^12000/", "", $string);
1788  $string = str_replace("Gigabit Ethernet", "GigE", $string);
1789  $string = preg_replace("/^ASR1000\ /", "", $string);
1790  //$string = str_replace("Routing Processor", "RP", $string);
1791  //$string = str_replace("Route Processor", "RP", $string);
1792  //$string = str_replace("Switching Processor", "SP", $string);
1793  $string = str_replace("Sub-Module", "Module ", $string);
1794  $string = str_replace("DFC Card", "DFC", $string);
1795  $string = str_replace("Centralized Forwarding Card", "CFC", $string);
1796  $string = str_replace(array('fan-tray'), 'Fan Tray', $string);
1797  $string = str_replace(array('Temp: ', 'CPU of ', 'CPU ', '(TM)', '(R)', '(r)'), '', $string);
1798  $string = str_replace('GenuineIntel Intel', 'Intel', $string);
1799  $string = str_replace(array(' Inc.', ' Computer Corporation', ' Corporation'), '', $string);
1800  $string = str_replace('IBM IBM', 'IBM', $string);
1801  $string = preg_replace("/(HP \w+) Switch/", "$1", $string);
1802  $string = preg_replace("/power[ -]supply( \d+)?(?: (?:module|sensor))?/i", "Power Supply$1", $string);
1803  $string = preg_replace("/([Vv]oltage|[Tt]ransceiver|[Pp]ower|[Cc]urrent|[Tt]emperature|[Ff]an|input|fail)\ [Ss]ensor/", "$1", $string);
1804  $string = preg_replace("/^(temperature|voltage|current|power)s?\ /", "", $string);
1805  $string = preg_replace('/\s{2,}/', ' ', $string);
1806  $string = preg_replace('/([a-z])([A-Z]{2,})/', '$1 $2', $string); // turn "fixedAC" into "fixed AC"
1807
1808  return trim($string);
1809}
1810
1811// DOCME needs phpdoc block
1812// TESTME needs unit testing
1813function rewrite_storage($string)
1814{
1815  $string = preg_replace('/.*mounted on: (.*)/', "\\1", $string);                 // JunOS
1816  $string = preg_replace("/(.*), type: (.*), dev: (.*)/", "\\1", $string);        // FreeBSD: '/mnt/Media, type: zfs, dev: Media'
1817  $string = preg_replace("/(.*) Label:(.*) Serial Number (.*)/", "\\1", $string); // Windows: E:\ Label:Large Space Serial Number 26ad0d98
1818
1819  return trim($string);
1820}
1821
1822// DOCME needs phpdoc block
1823// TESTME needs unit testing
1824function rewrite_location($location)
1825{
1826  global $config, $attribs;
1827
1828  $location = str_replace(array('\"', '"'), '', $location);
1829
1830  // Allow override sysLocation from DB.
1831  if ($attribs['override_sysLocation_bool'])
1832  {
1833    $new_location = $attribs['override_sysLocation_string'];
1834    $by = 'DB override';
1835  }
1836  // This will call a user-defineable function to rewrite the location however the user wants.
1837  if (!isset($new_location) && function_exists('custom_rewrite_location'))
1838  {
1839    $new_location = custom_rewrite_location($location);
1840    $by = 'function custom_rewrite_location()';
1841  }
1842  // This uses a statically defined array to map locations.
1843  if (!isset($new_location))
1844  {
1845    if (isset($config['location']['map'][$location]))
1846    {
1847      $new_location = $config['location']['map'][$location];
1848      $by = '$config[\'location\'][\'map\']';
1849    }
1850    else if (isset($config['location']['map_regexp']))
1851    {
1852      foreach ($config['location']['map_regexp'] as $pattern => $entry)
1853      {
1854        if (preg_match($pattern, $location))
1855        {
1856          $new_location = $entry;
1857          $by = '$config[\'location\'][\'map_regexp\']';
1858          break; // stop foreach
1859        }
1860      }
1861    }
1862  }
1863
1864  if (isset($new_location))
1865  {
1866    print_debug("sysLocation rewritten from '$location' to '$new_location' by $by.");
1867    $location = $new_location;
1868  }
1869  return $location;
1870}
1871
1872/**
1873 * This function cleanup vendor/manufacturer name and
1874 * unification multiple same names to single common vendor name.
1875 */
1876function rewrite_vendor($string)
1877{
1878  global $config;
1879
1880  $clean_name = $string;
1881
1882  // By first, clean all additional abbreviations in vendor name
1883  $clean_array = array(
1884    '/(?:\s+|,\s*)(?:inc|corp|comm|co|elec|tech|llc)(?![a-z])/i' => '', // abbreviations
1885    '/(?:\s+|,\s*)(?:Systems|Computer|Corporation|Company|Communications|Networks|Electronics)(?![a-z])/i' => '',
1886  );
1887  foreach ($clean_array as $pattern => $replace)
1888  {
1889    if (preg_match_all($pattern, $string, $matches))
1890    {
1891      foreach($matches[0] as $match)
1892      {
1893        $clean_name = str_replace($match, $replace, $clean_name);
1894      }
1895    }
1896  }
1897  $clean_name = trim($clean_name, " \t\n\r\0\x0B.,;'\"()"); // Clean punctuations after rewrites
1898
1899  // Remove string duplicates
1900  $clean_name_array = array_unique(explode(' ', $clean_name));
1901  $clean_name = implode(' ', $clean_name_array);
1902
1903  // Now try to find exist vendor definition
1904  $clean_key = safename(strtolower($clean_name));
1905  if (isset($config['vendors'][$clean_key]))
1906  {
1907    // Founded definition by original string
1908    return $config['vendors'][$clean_key]['name'];
1909  }
1910  $key  = safename(strtolower($string));
1911  if (isset($config['vendors'][$key]))
1912  {
1913    // Founded definition by clean string
1914    return $config['vendors'][$key]['name'];
1915  }
1916
1917  // Now try to find definition by full search in definitions
1918  foreach ($config['vendors'] as $vendor_key => $entry)
1919  {
1920    if (strlen($entry['name']) <= 3)
1921    {
1922      // In case, when vendor name too short, that seems as abbr, ie GE
1923      if (strcasecmp($clean_name, $entry['name']) == 0 || // Cleaned string
1924          strcasecmp($string, $entry['name']) == 0)       // Original string
1925      {
1926        // Founded in definitions
1927        return $entry['name'];
1928      }
1929      $search_array = array();
1930    } else {
1931      $search_array = array($entry['name']);
1932    }
1933
1934    if (isset($entry['full_name'])) { $search_array[] = $entry['full_name']; } // Full name of vendor
1935    if (isset($entry['alternatives'])) { $search_array = array_merge($search_array, $entry['alternatives']); } // Alternative (possible) names of vendor
1936
1937    if (str_istarts($clean_name, $search_array) || // Cleaned string
1938        str_istarts($string, $search_array))       // Original string
1939    {
1940      // Founded in definitions
1941      return $entry['name'];
1942    }
1943  }
1944
1945  if (strlen($clean_name) < 5 ||
1946      preg_match('/^([A-Z0-9][a-z]+[\ \-]?[A-Z]+[a-z]*|[A-Z0-9]+[\ \-][A-Za-z]+|[A-Z]{2,}[a-z]+)/', $clean_name))
1947  {
1948    // This is MultiCase name or small name, keeps as is
1949    //echo("\n"); print_error($clean_name . ': MULTICASE ');
1950    return $clean_name;
1951  } else {
1952    // Last, just return cleaned name
1953    //echo("\n"); print_error($clean_name . ': UCWORDS');
1954    return ucwords(strtolower($clean_name));
1955  }
1956}
1957
1958// Underlying rewrite functions
1959
1960/**
1961 * Replace strings equals to key string with appropriate value from array: key -> replace
1962 *
1963 * @param array  $array     Array with string and replace string (key -> replace)
1964 * @param string $string    String subject where replace
1965 * @return string           Result string with replaced strings
1966 */
1967function array_key_replace($array, $string)
1968{
1969  if (array_key_exists($string, $array))
1970  {
1971    $string = $array[$string];
1972  }
1973  return $string;
1974}
1975
1976/**
1977 * Replace strings matched by key string with appropriate value from array: string -> replace
1978 * Note, by default CASE INSENSITIVE
1979 *
1980 * @param array  $array     Array with string and replace string (string -> replace)
1981 * @param string $string    String subject where replace
1982 * @return string           Result string with replaced strings
1983 */
1984function array_str_replace($array, $string, $case_sensitive = FALSE)
1985{
1986  $search = array();
1987  $replace = array();
1988
1989  foreach ($array as $key => $entry)
1990  {
1991    $search[] = $key;
1992    $replace[] = $entry;
1993  }
1994
1995  if ($case_sensitive)
1996  {
1997    $string = str_replace($search, $replace, $string);
1998  } else {
1999    $string = str_ireplace($search, $replace, $string);
2000  }
2001
2002  return $string;
2003}
2004
2005/**
2006 * Replace strings matched by pattern key with appropriate value from array: pattern -> replace
2007 *
2008 * @param array  $array     Array with pattern and replace string (pattern -> replace)
2009 * @param string $string    String subject where replace
2010 * @return string           Result string with replaced patterns
2011 */
2012function array_preg_replace($array, $string)
2013{
2014  foreach ($array as $search => $replace)
2015  {
2016    $string = preg_replace($search, $replace, $string);
2017  }
2018
2019  return $string;
2020}
2021
2022/**
2023 * Replace tag(s) inside string with appropriate key from array: %tag% -> $array['tag']
2024 * Note, not exist tags in array will cleaned from string!
2025 *
2026 * @param array  $array     Array with keys appropriate for tags, wich used for replace
2027 * @param string $string    String with tag(s) for replace (between percent sign, ie: %key%)
2028 * @param string $tag_scope Scope string for detect tag(s), default: %
2029 * @return string           Result string with replaced tags
2030 */
2031function array_tag_replace($array, $string, $tag_scope = '%')
2032{
2033  // If passed array, do tag replace recursive (for values only)
2034  if (is_array($string))
2035  {
2036    foreach ($string as $key => $value)
2037    {
2038      $string[$key] = array_tag_replace($array, $value, $tag_scope);
2039    }
2040    return $string;
2041  }
2042
2043  $new_array = array();
2044
2045  // Generate new array of tags including delimiter
2046  foreach($array as $key => $value)
2047  {
2048    $new_array[$tag_scope.$key.$tag_scope] = $value;
2049  }
2050
2051  // Replace tags
2052  $string = array_str_replace($new_array, $string, TRUE);
2053  //$string = strtr($string, $new_array); // never use this slowest function in the world
2054
2055  // Remove unused tags
2056  if ($tag_scope !== '/')
2057  {
2058    $pattern_clean = '/'.$tag_scope.'\S+?'.$tag_scope.'/';
2059  } else {
2060    $pattern_clean = '%/\S+?/%';
2061  }
2062  $string = preg_replace($pattern_clean, '', $string);
2063
2064  return $string;
2065}
2066
2067// DOCME needs phpdoc block
2068// TESTME needs unit testing
2069function country_from_code($code)
2070{
2071  global $config;
2072
2073  $countries = $config['rewrites']['countries'];
2074  $code = strtoupper(trim($code));
2075  switch (strlen($code))
2076  {
2077    case 0:
2078    case 1:
2079      return "Unknown";
2080    case 2: // ISO 2
2081    case 3: // ISO 3
2082      // Return country by code
2083      if (array_key_exists($code, $countries))
2084      {
2085        return $countries[$code];
2086      }
2087      return "Unknown";
2088    default:
2089      // Try to search by country name
2090      $names = array_unique(array_values($countries));
2091      foreach ($names as $country)
2092      {
2093        if (str_istarts($country, $code) || str_istarts($code, $country)) { return $country; }
2094      }
2095      return "Unknown";
2096  }
2097}
2098
2099// EOF
2100