/**
  * @param string $targetString The string from the config file
  * @param the $map A reference to the map object (redundant)
  * @param the $mapItem A reference to the object this target is attached to
  * @return array invalue, outvalue, unix timestamp that the data was valid
  */
 function ReadData($targetString, &$map, &$mapItem)
 {
     $data[IN] = null;
     $data[OUT] = null;
     $data_time = 0;
     $matches = 0;
     if (preg_match("/^time:(.*)\$/", $targetString, $matches)) {
         $timezone = $matches[1];
         $offset = "now";
         if (preg_match("/^([^:]+):(.*)\$/", $timezone, $matches2)) {
             $timezone = $matches2[1];
             $offset = $matches2[2];
             // test that the offset is valid
             $timestamp = strtotime($offset);
             if ($timestamp === false || $timestamp === -1) {
                 warn("Time ReadData: Offset String ({$offset}) is bogus - ignoring [WMTIME03]\n");
                 $offset = "now";
             }
         }
         $timezone_l = strtolower($timezone);
         if (array_key_exists($timezone_l, $this->timezones)) {
             $tz = $this->timezones[$timezone_l];
             wm_debug("Time ReadData: Timezone exists: {$tz}\n");
             $dateTime = new DateTime($offset, new DateTimeZone($tz));
             $mapItem->add_note("time_time12", $dateTime->format("h:i"));
             $mapItem->add_note("time_time12ap", $dateTime->format("h:i A"));
             $mapItem->add_note("time_time24", $dateTime->format("H:i"));
             $mapItem->add_note("time_timet", $dateTime->format("U"));
             $mapItem->add_note("time_timezone", $tz);
             $data[IN] = $dateTime->format("H");
             $data[OUT] = $dateTime->format("i");
             $data_time = time();
             $matches++;
         }
         if ($matches == 0) {
             wm_warn("Time ReadData: Couldn't recognize {$timezone} as a valid timezone name [WMTIME02]\n");
         }
     } else {
         // some error code to go in here
         wm_warn("Time ReadData: Couldn't recognize {$targetString} \n");
     }
     wm_debug("Time ReadData: Returning (" . WMUtility::valueOrNull($data[IN]) . "," . WMUtility::valueOrNull($data[OUT]) . ",{$data_time})\n");
     return array($data[IN], $data[OUT], $data_time);
 }
 function ReadData($targetstring, &$map, &$item)
 {
     $data[IN] = NULL;
     $data[OUT] = NULL;
     $data_time = 0;
     $itemname = $item->name;
     $matches = 0;
     $fd = fopen($targetstring, "r");
     if ($fd) {
         while (!feof($fd)) {
             $buffer = fgets($fd, 4096);
             # strip out any Windows line-endings that have gotten in here
             $buffer = str_replace("\r", "", $buffer);
             if (preg_match("/^{$itemname}\t(\\d+\\.?\\d*[KMGT]*)\t(\\d+\\.?\\d*[KMGT]*)/", $buffer, $matches)) {
                 $data[IN] = unformat_number($matches[1]);
                 $data[OUT] = unformat_number($matches[2]);
             }
         }
         $stats = stat($targetstring);
         $data_time = $stats['mtime'];
     } else {
         // some error code to go in here
         wm_debug("TabText ReadData: Couldn't open ({$targetstring}). \n");
     }
     wm_debug("TabText ReadData: Returning (" . ($data[IN] === NULL ? 'NULL' : $data[IN]) . "," . ($data[OUT] === NULL ? 'NULL' : $data[OUT]) . ",{$data_time})\n");
     return array($data[IN], $data[OUT], $data_time);
 }
 function run(&$map)
 {
     $enable = $map->get_hint('post_zabbix_graphs');
     if ($enable) {
         $this->zabbixApi = new SimpleZabbixApi($map->get_hint('zabbix_url'), $map->get_hint('zabbix_user'), $map->get_hint('zabbix_password'));
         if ($this->zabbixApi->isConnected()) {
             $baseUrl = $map->get_hint('post_zabbix_graph_base_url');
             $addGraphLink = $map->get_hint('post_zabbix_graph_link');
             $graphWidth = $map->get_hint('post_zabbix_graph_width');
             $graphHeight = $map->get_hint('post_zabbix_graph_height');
             $graphPeriod = $map->get_hint('post_zabbix_graph_period');
             foreach (array_merge($map->links, $map->nodes) as $item) {
                 foreach (range(0, 1) as $k) {
                     // IN and OUT, if necessary
                     $graph = $item->overliburl[$k];
                     foreach ($graph as $index => $graphItem) {
                         if (preg_match('/^zabbix:([-a-zA-Z0-9_\\.\\/\\[\\]]+):([-a-zA-Z0-9_\\.\\/\\[\\]]+):([-a-zA-Z0-9_\\.\\/\\[\\]]+)$/', $graphItem, $matches)) {
                             $keyname = $matches[1];
                             $host = $matches[2];
                             $key = $matches[3];
                             wm_debug("Zabbix ReadData: Found (" . $host . "," . $key . ")\n");
                             $graphId = $this->zabbixApi->getGraphId($host, $keyname, $key);
                             if (isset($graphId)) {
                                 if ($addGraphLink) {
                                     $item->infourl[$k] = $baseUrl . '/charts.php?form_refresh=1&fullscreen=0&graphid=' . $graphId;
                                 }
                                 $item->overliburl[$k][$index] = $baseUrl . '/chart2.php?width=' . $graphWidth . '&height=' . $graphHeight . '&period=' . $graphPeriod . '&stime=now&graphid=' . $graphId;
                             }
                         }
                     }
                 }
             }
         }
     }
 }
 function ReadData($targetString, &$map, &$mapItem)
 {
     $data[IN] = null;
     $data[OUT] = null;
     $data_time = 0;
     if (preg_match("/^dbplug:([^:]+)\$/", $targetString, $matches)) {
         $database_user = $map->get_hint('dbplug_dbuser');
         $database_pass = $map->get_hint('dbplug_dbpass');
         $database_name = $map->get_hint('dbplug_dbname');
         $database_host = $map->get_hint('dbplug_dbhost');
         $key = mysql_real_escape_string($matches[1]);
         // This is the one line you will certainly need to change
         $SQL = "select in,out from table where host={$key} LIMIT 1";
         if (mysql_connect($database_host, $database_user, $database_pass)) {
             if (mysql_select_db($database_name)) {
                 $result = mysql_query($SQL);
                 if (!$result) {
                     wm_warn("dbplug ReadData: Invalid query: " . mysql_error() . "\n");
                 } else {
                     $row = mysql_fetch_assoc($result);
                     $data[IN] = $row['in'];
                     $data[OUT] = $row['out'];
                 }
             } else {
                 wm_warn("dbplug ReadData: failed to select database: " . mysql_error() . "\n");
             }
         } else {
             wm_warn("dbplug ReadData: failed to connect to database server: " . mysql_error() . "\n");
         }
         $data_time = now();
     }
     wm_debug("RRD ReadData dbplug: Returning (" . ($data[IN] === null ? 'null' : $data[IN]) . "," . ($data[OUT] === null ? 'null' : $data[IN]) . ", {$data_time})\n");
     return array($data[IN], $data[OUT], $data_time);
 }
 function ReadData($targetString, &$map, &$mapItem)
 {
     $data[IN] = null;
     $data[OUT] = null;
     $data_time = 0;
     $matches = 0;
     if (preg_match($this->regexpsHandled[0], $targetString, $matches)) {
         $dataFileName = $matches[1];
         $dataItemName = $matches[2];
     }
     if (!file_exists($dataFileName)) {
         wm_warn("WMData ReadData: {$dataFileName} doesn't exist [WMWMDATA01]");
         return array(null, null, 0);
     }
     $fileHandle = fopen($targetString, "r");
     if (!$fileHandle) {
         wm_warn("WMData ReadData: Couldn't open ({$dataFileName}). [WMWMDATA02]\n");
         return array(null, null, 0);
     }
     list($found, $data) = $this->findDataItem($fileHandle, $dataItemName, $data);
     if ($found === true) {
         $stats = stat($dataFileName);
         $data_time = $stats['mtime'];
     } else {
         wm_warn("WMData ReadData: Data name '{$dataItemName}' didn't exist in '{$dataFileName}'. [WMWMDATA03]\n");
     }
     wm_debug(sprintf("WMData ReadData: Returning (%s, %s, %s)\n", string_or_null($data[IN]), string_or_null($data[OUT]), $data_time));
     return array($data[IN], $data[OUT], $data_time);
 }
 function ReadData($targetstring, &$map, &$item)
 {
     $data[IN] = null;
     $data[OUT] = null;
     $data_time = 0;
     if (preg_match("/^zabbix:([-a-zA-Z0-9_\\.\\/\\[\\]]+):([-a-zA-Z0-9_\\.\\/\\[\\]]+):([-a-zA-Z0-9_\\.\\/\\[\\]]+):([-a-zA-Z0-9_\\.\\/\\[\\]]+)\$/", $targetstring, $matches)) {
         $zabbix_uri = $map->get_hint('zabbix_uri');
         $zabbix_key = $matches[1];
         $host = $matches[2];
         $in = $matches[3];
         $out = $matches[4];
         wm_debug("Zabbix ReadData: Found (" . $host . "," . $in . "," . $out . ")\n");
         $raw_out_value = $this->zabbixApi->getItemLastValue($host, $zabbix_key, $out);
         $raw_in_value = $this->zabbixApi->getItemLastValue($host, $zabbix_key, $in);
         $in_value = $raw_in_value["lastvalue"];
         $out_value = $raw_out_value["lastvalue"];
         $data_time = $raw_out_value["lastclock"];
         if (isset($in_value)) {
             $data[IN] = $in_value;
         }
         if (isset($out_value)) {
             $data[OUT] = $out_value;
         }
     }
     wm_debug("Zabbix ReadData: Returning (" . ($data[IN] === null ? 'null' : $data[IN]) . "," . ($data[OUT] === null ? 'null' : $data[IN]) . ",{$data_time})\n");
     return array($data[IN], $data[OUT], $data_time);
 }
 function ReadData($targetstring, &$map, &$item)
 {
     $data[IN] = NULL;
     $data[OUT] = NULL;
     $data_time = 0;
     $itemname = $item->name;
     $matches = 0;
     if (preg_match("/^time:(.*)\$/", $targetstring, $matches)) {
         $timezone = $matches[1];
         $timezone_l = strtolower($timezone);
         $timezone_identifiers = DateTimeZone::listIdentifiers();
         foreach ($timezone_identifiers as $tz) {
             if (strtolower($tz) == $timezone_l) {
                 wm_debug("Time ReadData: Timezone exists: {$tz}\n");
                 $dateTime = new DateTime("now", new DateTimeZone($tz));
                 $item->add_note("time_time12", $dateTime->format("h:i"));
                 $item->add_note("time_time12ap", $dateTime->format("h:i A"));
                 $item->add_note("time_time24", $dateTime->format("H:i"));
                 $item->add_note("time_timezone", $tz);
                 $data[IN] = $dateTime->format("H");
                 $data_time = time();
                 $data[OUT] = $dateTime->format("i");
                 $matches++;
             }
         }
         if ($matches == 0) {
             wm_warn("Time ReadData: Couldn't recognize {$timezone} as a valid timezone name [WMTIME02]\n");
         }
     } else {
         // some error code to go in here
         wm_warn("Time ReadData: Couldn't recognize {$targetstring} \n");
     }
     wm_debug("Time ReadData: Returning (" . ($data[IN] === NULL ? 'NULL' : $data[IN]) . "," . ($data[OUT] === NULL ? 'NULL' : $data[OUT]) . ",{$data_time})\n");
     return array($data[IN], $data[OUT], $data_time);
 }
 public function getSlope()
 {
     if ($this->dx == 0) {
         // special case - if slope is infinite, fudge it to be REALLY BIG instead. Close enough for TV.
         wm_debug("Slope is infinite.\n");
         return 10000000000.0;
     }
     return $this->dy / $this->dx;
 }
 function ReadData($targetString, &$map, &$mapItem)
 {
     $data[IN] = null;
     $data[OUT] = null;
     $data_time = 0;
     if (preg_match("/^cactihost:(\\d+)\$/", $targetString, $matches)) {
         $cacti_id = intval($matches[1]);
         $SQL = "select * from host where id={$cacti_id}";
         // 0=disabled
         // 1=down
         // 2=recovering
         // 3=up
         // (4 is tholdbreached in cactimonitor, so skipped here for compatibility)
         // 5=unknown
         $state = -1;
         $result = db_fetch_row($SQL);
         if (isset($result)) {
             // create a note, which can be used in icon filenames or labels more nicely
             if ($result['status'] == 5) {
                 $state = 5;
                 $statename = 'unknown';
             }
             if ($result['status'] == 1) {
                 $state = 1;
                 $statename = 'down';
             }
             if ($result['status'] == 2) {
                 $state = 2;
                 $statename = 'recovering';
             }
             if ($result['status'] == 3) {
                 $state = 3;
                 $statename = 'up';
             }
             if ($result['disabled']) {
                 $state = 0;
                 $statename = 'disabled';
             }
             $data[IN] = $state;
             $data[OUT] = $state;
             $mapItem->add_note("state", $statename);
             $mapItem->add_note("cacti_description", $result['description']);
             $mapItem->add_note("cacti_hostname", $result['hostname']);
             $mapItem->add_note("cacti_curtime", $result['cur_time']);
             $mapItem->add_note("cacti_avgtime", $result['avg_time']);
             $mapItem->add_note("cacti_mintime", $result['min_time']);
             $mapItem->add_note("cacti_maxtime", $result['max_time']);
             $mapItem->add_note("cacti_availability", $result['availability']);
             $mapItem->add_note("cacti_faildate", $result['status_fail_date']);
             $mapItem->add_note("cacti_recdate", $result['status_rec_date']);
         }
     }
     wm_debug("CactiHost ReadData: Returning (" . ($data[IN] === null ? 'null' : $data[IN]) . "," . ($data[OUT] === null ? 'null' : $data[OUT]) . ",{$data_time})\n");
     return array($data[IN], $data[OUT], $data_time);
 }
 public function run()
 {
     $enable = $this->owner->get_hint("post_test_enable");
     if ($enable) {
         wm_debug(__CLASS__ . " is here\n");
         // do your work in here...
         $orig = $this->owner->get_note("test");
         $this->owner->add_note("test", $orig . " TESTYTEST");
     } else {
         wm_debug(__CLASS__ . " Not Enabled\n");
     }
 }
 /**
  * @param $timezone
  * @param $offset
  * @return array
  * @internal param $mapItem
  * @internal param $data
  * @internal param $matches
  * @internal param $timezone_l
  */
 private function getTimeForTimeZone($timezone, $offset)
 {
     $timezone_l = strtolower($timezone);
     if (array_key_exists($timezone_l, $this->timezones)) {
         $timezone_name = $this->timezones[$timezone_l];
         wm_debug("Time ReadData: Timezone exists: {$timezone_name}\n");
         $dateTime = new DateTime($offset, new DateTimeZone($timezone_name));
         return array($dateTime, $timezone_name);
     }
     wm_warn("Time ReadData: Couldn't recognize {$timezone} as a valid timezone name [WMTIME02]\n");
     return null;
 }
 function ReadData($targetString, &$map, &$mapItem)
 {
     $data[IN] = null;
     $data[OUT] = null;
     $data_time = 0;
     if (preg_match('/^cactihost:(\\d+)$/', $targetString, $matches)) {
         $cacti_id = intval($matches[1]);
         $data = $this->readDataFromCacti($mapItem, $cacti_id, $data);
     }
     wm_debug("CactiHost ReadData: Returning (" . ($data[IN] === null ? 'null' : $data[IN]) . "," . ($data[OUT] === null ? 'null' : $data[OUT]) . ",{$data_time})\n");
     return array($data[IN], $data[OUT], $data_time);
 }
 function run(&$map)
 {
     $enable = $map->get_hint("post_test_enable");
     if ($enable) {
         wm_debug(__CLASS__ . " is here\n");
         // do your work in here...
         $orig = $map->get_note("test");
         $map->add_note("test", $orig . " TESTYTEST");
         // -------------------------
     } else {
         wm_debug(__CLASS__ . " Not Enabled\n");
     }
 }
 function ReadData($targetString, &$map, &$mapItem)
 {
     $data[IN] = null;
     $data[OUT] = null;
     $data_time = 0;
     if (1 === preg_match('/^cacti:(\\d+)$/', $targetString, $matches)) {
         $local_data_id = intval($matches[1]);
         $SQL = 'select * from weathermap_data where local_data_id=' . $local_data_id;
         $result = db_fetch_row($SQL);
     }
     wm_debug(sprintf("cacti ReadData: Returning (%s, %s, %s)\n", string_or_null($data[IN]), string_or_null($data[OUT]), $data_time));
     return array($data[IN], $data[OUT], $data_time);
 }
예제 #15
0
function UpdateCactiData(&$item, $local_data_id)
{
    $map = $item->owner;
    wm_debug("fetching for {$local_data_id}\n");
    if (isset($map->dsinfocache[$local_data_id])) {
        $to_set = $map->dsinfocache[$local_data_id];
    } else {
        $to_set = array();
        $set_speed = intval($item->get_hint("cacti_use_ifspeed"));
        $r3 = db_fetch_assoc(sprintf("select data_local.host_id, field_name,field_value from data_local,host_snmp_cache  USE INDEX (host_id) where data_local.id=%d and data_local.host_id=host_snmp_cache.host_id and data_local.snmp_index=host_snmp_cache.snmp_index and data_local.snmp_query_id=host_snmp_cache.snmp_query_id", $local_data_id));
        foreach ($r3 as $vv) {
            $vname = "cacti_" . $vv['field_name'];
            $to_set[$vname] = $vv['field_value'];
        }
        if ($set_speed != 0) {
            $ifSpeed = intval($to_set['cacti_ifSpeed']);
            $ifHighSpeed = intval($to_set['cacti_ifHighSpeed']);
            $speed = 0;
            if ($ifSpeed > 0) {
                $speed = $ifSpeed;
            }
            # see https://lists.oetiker.ch/pipermail/mrtg/2004-November/029312.html
            if ($ifHighSpeed > 20) {
                $speed = $ifHighSpeed . "M";
            }
            if ($speed > 0) {
                // might need to dust these off for php4...
                if ($item->my_type() == 'NODE') {
                    $map->nodes[$item->name]->max_bandwidth_in = $speed;
                    $map->nodes[$item->name]->max_bandwidth_out = $speed;
                }
                if ($item->my_type() == 'LINK') {
                    $map->links[$item->name]->max_bandwidth_in = $speed;
                    $map->links[$item->name]->max_bandwidth_out = $speed;
                }
            }
        }
        if (isset($vv['host_id'])) {
            $to_set['cacti_host_id'] = intval($vv['host_id']);
        }
        $r4 = db_fetch_row(sprintf("SELECT DISTINCT graph_templates_item.local_graph_id,title_cache FROM graph_templates_item,graph_templates_graph,data_template_rrd WHERE data_template_rrd.id=task_item_id and graph_templates_graph.local_graph_id = graph_templates_item.local_graph_id and local_data_id=%d LIMIT 1", $local_data_id));
        if (isset($r4['local_graph_id'])) {
            $to_set["cacti_graph_id"] = intval($r4['local_graph_id']);
        }
        $map->dsinfocache[$local_data_id] = $to_set;
    }
    # By now, we have the values, one way or another.
    foreach ($to_set as $k => $v) {
        $item->add_note($k, $v);
    }
}
 /**
  * @param $fullpath
  * @return resource
  */
 protected function validateAndOpenFile($fullpath)
 {
     wm_debug("Opening {$fullpath}\n");
     if (!file_exists($fullpath)) {
         wm_warn("File '{$fullpath}' doesn't exist.");
         return null;
     }
     if (!is_readable($fullpath)) {
         wm_warn("File '{$fullpath}' isn't readable.");
         return null;
     }
     $fileHandle = fopen($fullpath, "r");
     return $fileHandle;
 }
 function ReadData($targetString, &$map, &$mapItem)
 {
     $data[IN] = null;
     $data[OUT] = null;
     $data_time = 0;
     $matchvalue = $mapItem->get_hint('mrtg_value');
     $matchperiod = $mapItem->get_hint('mrtg_period');
     $swap = intval($mapItem->get_hint('mrtg_swap'));
     $negate = intval($mapItem->get_hint('mrtg_negate'));
     if ($matchvalue == '') {
         $matchvalue = "cu";
     }
     if ($matchperiod == '') {
         $matchperiod = "d";
     }
     $fd = fopen($targetString, "r");
     if ($fd) {
         while (!feof($fd)) {
             $buffer = fgets($fd, 4096);
             wm_debug("MRTG ReadData: Matching on '{$matchvalue}in {$matchperiod}' and '{$matchvalue}out {$matchperiod}'\n");
             if (preg_match("/<\\!-- {$matchvalue}in {$matchperiod} ([-+]?\\d+\\.?\\d*) -->/", $buffer, $matches)) {
                 $data[IN] = $matches[1] * 8;
             }
             if (preg_match("/<\\!-- {$matchvalue}out {$matchperiod} ([-+]?\\d+\\.?\\d*) -->/", $buffer, $matches)) {
                 $data[OUT] = $matches[1] * 8;
             }
         }
         fclose($fd);
         # don't bother with the modified time if the target is a URL
         if (!preg_match('/^[a-z]+:\\/\\//', $targetString)) {
             $data_time = filemtime($targetString);
         }
     } else {
         // some error code to go in here
         wm_debug("MRTG ReadData: Couldn't open ({$targetString}). \n");
     }
     if ($swap == 1) {
         wm_debug("MRTG ReadData: Swapping IN and OUT\n");
         $t = $data[OUT];
         $data[OUT] = $data[IN];
         $data[IN] = $t;
     }
     if ($negate) {
         wm_debug("MRTG ReadData: Negating values\n");
         $data[OUT] = -$data[OUT];
         $data[IN] = -$data[IN];
     }
     wm_debug("MRTG ReadData: Returning (" . ($data[IN] === null ? 'null' : $data[IN]) . "," . ($data[OUT] === null ? 'null' : $data[OUT]) . ",{$data_time})\n");
     return array($data[IN], $data[OUT], $data_time);
 }
예제 #18
0
function UpdateCactiData(&$item, $local_data_id)
{
    $map = $item->owner;
    wm_debug("fetching for {$local_data_id}\n");
    if (isset($map->dsinfocache[$local_data_id])) {
        $to_set = $map->dsinfocache[$local_data_id];
    } else {
        $to_set = array();
        $set_speed = intval($item->get_hint("cacti_use_ifspeed"));
        $r3 = db_fetch_assoc(sprintf("select data_local.host_id, field_name,field_value\n                     from data_local,host_snmp_cache  USE INDEX (host_id)\n                     where data_local.id=%d\n                       and data_local.host_id=host_snmp_cache.host_id\n                       and data_local.snmp_index=host_snmp_cache.snmp_index\n                       and data_local.snmp_query_id=host_snmp_cache.snmp_query_id", $local_data_id));
        foreach ($r3 as $vv) {
            $vname = "cacti_" . $vv['field_name'];
            $to_set[$vname] = $vv['field_value'];
        }
        if ($set_speed != 0) {
            $ifSpeed = intval($to_set['cacti_ifSpeed']);
            $ifHighSpeed = intval($to_set['cacti_ifHighSpeed']);
            $speed = 0;
            if ($ifSpeed > 0) {
                $speed = $ifSpeed;
            }
            # see https://lists.oetiker.ch/pipermail/mrtg/2004-November/029312.html
            if ($ifHighSpeed > 20) {
                // NOTE: this is NOT using $kilo - it's always 1000000 bits/sec according to the MIB
                $speed = $ifHighSpeed * 1000000;
            }
            if ($speed > 0) {
                $item->max_bandwidth_in = $speed;
                $item->max_bandwidth_out = $speed;
            }
        }
        if (isset($vv['host_id'])) {
            $to_set['cacti_host_id'] = intval($vv['host_id']);
        }
        $r4 = db_fetch_row(sprintf("SELECT DISTINCT graph_templates_item.local_graph_id,title_cache\n                      FROM graph_templates_item,graph_templates_graph,data_template_rrd\n                      WHERE data_template_rrd.id=task_item_id\n                        and graph_templates_graph.local_graph_id = graph_templates_item.local_graph_id\n                        and local_data_id=%d\n                      LIMIT 1", $local_data_id));
        if (isset($r4['local_graph_id'])) {
            $to_set["cacti_graph_id"] = intval($r4['local_graph_id']);
        }
        $map->dsinfocache[$local_data_id] = $to_set;
    }
    # By now, we have the values, one way or another.
    foreach ($to_set as $k => $v) {
        $item->add_note($k, $v);
    }
}
 function ReadData($targetString, &$map, &$mapItem)
 {
     $inbw = null;
     $outbw = null;
     $data_time = 0;
     if (preg_match($this->regexpsHandled[0], $targetString, $matches)) {
         $inbw = WMUtility::interpretNumberWithMetricPrefix($matches[1], $map->kilo);
         $outbw = WMUtility::interpretNumberWithMetricPrefix($matches[2], $map->kilo);
         $data_time = time();
     }
     if (preg_match($this->regexpsHandled[1], $targetString, $matches)) {
         $inbw = WMUtility::interpretNumberWithMetricPrefix($matches[1], $map->kilo);
         $outbw = $inbw;
         $data_time = time();
     }
     wm_debug("Static ReadData: Returning ({$inbw}, {$outbw}, {$data_time})\n");
     return array($inbw, $outbw, $data_time);
 }
 function ReadData($targetstring, &$map, &$item)
 {
     $inbw = NULL;
     $outbw = NULL;
     $data_time = 0;
     if (preg_match("/^static:(\\-?\\d+\\.?\\d*[KMGT]*):(\\-?\\d+\\.?\\d*[KMGT]*)\$/", $targetstring, $matches)) {
         $inbw = unformat_number($matches[1], $map->kilo);
         $outbw = unformat_number($matches[2], $map->kilo);
         $data_time = time();
     }
     if (preg_match("/^static:(\\-?\\d+\\.?\\d*[KMGT]*)\$/", $targetstring, $matches)) {
         $inbw = unformat_number($matches[1], $map->kilo);
         $outbw = $inbw;
         $data_time = time();
     }
     wm_debug("Static ReadData: Returning ({$inbw},{$outbw},{$data_time})\n");
     return array($inbw, $outbw, $data_time);
 }
 public static function calculateOffset($offsetstring, $width, $height)
 {
     if (preg_match('/^([-+]?\\d+):([-+]?\\d+)$/', $offsetstring, $matches)) {
         wm_debug("Numeric Offset found\n");
         return array($matches[1], $matches[2]);
     }
     if (preg_match('/(NE|SE|NW|SW|N|S|E|W|C)(\\d+)?$/i', $offsetstring, $matches)) {
         return self::calculateCompassOffset($matches[1], isset($matches[2]) ? $matches[2] : null, $width, $height);
     }
     if (preg_match('/(-?\\d+)r(\\d+)$/i', $offsetstring, $matches)) {
         $angle = intval($matches[1]);
         $distance = intval($matches[2]);
         $rangle = deg2rad($angle);
         $offsets = array($distance * sin($rangle), -$distance * cos($rangle));
         return $offsets;
     }
     // TODO - where is the named offset handling!!
     wm_warn("Got a position offset that didn't make sense ({$offsetstring}).");
     return array(0, 0);
 }
 function ReadData($targetstring, &$map, &$item)
 {
     $data[IN] = null;
     $data[OUT] = null;
     $data_time = 0;
     $itemname = $item->name;
     $matches = 0;
     if (preg_match("/^wmdata:([^:]*):(.*)", $targetstring, $matches)) {
         $datafile = $matches[1];
         $dataname = $matches[2];
     }
     if (file_exists($datafile)) {
         $fd = fopen($targetstring, "r");
         if ($fd) {
             $found = false;
             while (!feof($fd)) {
                 $buffer = fgets($fd, 4096);
                 # strip out any Windows line-endings that have gotten in here
                 $buffer = str_replace("\r", "", $buffer);
                 $fields = explode("\t", $buffer);
                 if ($fields[0] == $dataname) {
                     $data[IN] = $fields[1];
                     $data[OUT] = $fields[2];
                     $found = true;
                 }
             }
             if ($found === true) {
                 $stats = stat($datafile);
                 $data_time = $stats['mtime'];
             } else {
                 wm_warn("WMData ReadData: Data name ({$dataname}) didn't exist in ({$datafile}). [WMWMDATA03]\n");
             }
         } else {
             wm_warn("WMData ReadData: Couldn't open ({$datafile}). [WMWMDATA02]\n");
         }
     } else {
         wm_warn("WMData ReadData: {$datafile} doesn't exist [WMWMDATA01]");
     }
     wm_debug(sprintf("WMData ReadData: Returning (%s, %s, %s)\n", string_or_null($data[IN]), string_or_null($data[OUT]), $data_time));
     return array($data[IN], $data[OUT], $data_time);
 }
 public function ReadData($targetString, &$map, &$mapItem)
 {
     $data[IN] = null;
     $data[OUT] = null;
     $data_time = 0;
     $timeout = intval($this->owner->get_hint("snmp_timeout", 1000000));
     $abort_count = intval($this->owner->get_hint("snmp_abort_count"), 0);
     $retries = intval($this->owner->get_hint("snmp_retries"), 2);
     if (preg_match($this->regexpsHandled[0], $targetString, $matches)) {
         $community = $matches[1];
         $host = $matches[2];
         $oids = array();
         $oids[IN] = $matches[3];
         $oids[OUT] = $matches[4];
         if ($abort_count == 0 || $abort_count > 0 && (!isset($this->down_cache[$host]) || intval($this->down_cache[$host]) < $abort_count)) {
             $this->changeSNMPSettings();
             $channels = array("in" => IN, "out" => OUT);
             foreach ($channels as $channelName => $channel) {
                 if ($oids[$channel] != '-') {
                     $result = snmpget($host, $community, $oids[$channel], $timeout, $retries);
                     if ($result !== false) {
                         $data[$channel] = floatval($result);
                         $mapItem->add_hint("snmp_" . $channelName . "_raw", $result);
                     } else {
                         $this->down_cache[$host]++;
                     }
                 }
                 wm_debug("SNMP ReadData: Got {$result} for {$channelName}\n");
             }
             $data_time = time();
             $this->restoreSNMPSettings();
         } else {
             wm_warn("SNMP for {$host} has reached {$abort_count} failures. Skipping. [WMSNMP01]");
         }
     }
     wm_debug("SNMP ReadData: Returning (" . ($data[IN] === null ? 'null' : $data[IN]) . "," . ($data[OUT] === null ? 'null' : $data[OUT]) . ",{$data_time})\n");
     return array($data[IN], $data[OUT], $data_time);
 }
 function ReadData($targetstring, &$map, &$item)
 {
     $data_in = NULL;
     $data_out = NULL;
     $data_time = 0;
     if (preg_match($this->regex_pattern, $targetstring, $matches)) {
         $host = $matches[1];
         $keyin = $matches[3];
         $keyout = $matches[4];
         // make HTTP request
         $url = "http://{$host}/render/?rawData&from=-5minutes";
         // if key is -, return NULL for this datasource
         if ($keyin != '-') {
             $url .= "&target={$keyin}";
         }
         if ($keyout != '-') {
             $url .= "&target={$keyout}";
         }
         wm_debug("GRAPHITE DS: Connecting to {$url}\n");
         $ch = curl_init($url);
         curl_setopt_array($ch, array(CURLOPT_RETURNTRANSFER => true, CURLOPT_TIMEOUT => 3));
         $data = curl_exec($ch);
         $status = curl_getinfo($ch, CURLINFO_HTTP_CODE);
         if ($status != 200) {
             wm_debug("GRAPHITE DS: Got HTTP code {$status} from Graphite\n");
             return;
         }
         # Data in form: target,starttime,endtime,step|datapoints
         # one line for each target
         foreach (explode("\n", $data) as $line) {
             if (!strpos($line, '|')) {
                 continue;
             }
             list($meta, $values) = explode('|', $line, 2);
             $values = explode(',', trim($values));
             list($target, $timestart, $timeend, $timestep) = explode(',', trim($meta));
             # get most recent value that is not 'None'
             $data_time = $timeend;
             foreach (array_reverse($values) as $value) {
                 if ($value !== 'None') {
                     break;
                 }
                 $data_time -= $timestep;
             }
             if ($value === 'None') {
                 // no value found
                 wm_debug("GRAPHITE DS: No valid data points found for {$target}\n");
             } else {
                 if ($target == $keyin) {
                     $data_in = floatval($value);
                 } elseif ($target == $keyout) {
                     $data_out = floatval($value);
                 }
             }
         }
         /*return array($value, $value, time());*/
         wm_debug("GRAPHITE DS: returning " . ($data_in === NULL ? 'NULL' : $data_in) . " , " . ($data_out === NULL ? 'NULL' : $data_out) . "\n");
         return array($data_in, $data_out, $data_time);
     }
     return false;
 }
예제 #25
0
     $map->add_hint($key, $value);
 }
 if (isset($options_output['sizedebug']) && !$options_output['sizedebug'] || !isset($options_output['sizedebug'])) {
     if ($randomdata == 1) {
         $map->RandomData();
     } else {
         $map->ReadData();
     }
 }
 # exit();
 if ($imagefile != '') {
     $map->DrawMap($imagefile);
     $map->imagefile = $imagefile;
 }
 if ($htmlfile != '') {
     wm_debug("Writing HTML to {$htmlfile}\n");
     $fd = fopen($htmlfile, 'w');
     fwrite($fd, '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"><html xmlns="http://www.w3.org/1999/xhtml"><head>');
     fwrite($fd, "<base href=\"{$map->basehref}\">");
     if ($map->htmlstylesheet != '') {
         fwrite($fd, '<link rel="stylesheet" type="text/css" href="' . $map->htmlstylesheet . '" />');
     }
     fwrite($fd, '<meta http-equiv="refresh" content="300" /><title>' . $map->ProcessString($map->title, $map) . '</title></head><body>');
     if ($map->htmlstyle == "overlib") {
         fwrite($fd, "<div id=\"overDiv\" style=\"position:absolute; visibility:hidden; z-index:1000;\"></div>\n");
         fwrite($fd, "<script type=\"text/javascript\" src=\"overlib.js\"><!-- overLIB (c) Erik Bosrup --></script> \n");
     }
     fwrite($fd, $map->MakeHTML());
     fwrite($fd, '<hr /><span id="byline">Network Map created with <a href="http://www.network-weathermap.com/?vs=' . $WEATHERMAP_VERSION . '">PHP Network Weathermap v' . $WEATHERMAP_VERSION . '</a></span></body></html>');
     fclose($fd);
 }
예제 #26
0
    
		    $map->nodes[$newnodename] = $node;
		    array_push($map->seen_zlayers[$node->zorder], $node);
    
		    $map->WriteConfig($mapfile);
		}
		break;

		// no action was defined - starting a new map?
	default:
		$map->ReadConfig($mapfile);
		break;   
	}	
	
	//by here, there should be a valid $map - either a blank one, the existing one, or the existing one with requested changes
	wm_debug("Finished modifying\n");

	// now we'll just draw the full editor page, with our new knowledge

	$imageurl = '?mapname='.urlencode($mapname) . '&amp;action=draw';
	if($selected != '')
	{
		$imageurl .= '&amp;selected='.urlencode(wm_editor_sanitize_selected($selected));
	}

	$imageurl .= '&amp;unique='.time();

	// build up the editor's list of used images
	if($map->background != '') $map->used_images[] = $map->background;
	foreach ($map->nodes as $n)
	{
 function ReadData($targetstring, &$map, &$item)
 {
     global $config;
     $dsnames[IN] = "traffic_in";
     $dsnames[OUT] = "traffic_out";
     $data[IN] = NULL;
     $data[OUT] = NULL;
     $SQL[IN] = 'select null';
     $SQL[OUT] = 'select null';
     $rrdfile = $targetstring;
     if ($map->get_hint("rrd_default_in_ds") != '') {
         $dsnames[IN] = $map->get_hint("rrd_default_in_ds");
         wm_debug("Default 'in' DS name changed to " . $dsnames[IN] . ".\n");
     }
     if ($map->get_hint("rrd_default_out_ds") != '') {
         $dsnames[OUT] = $map->get_hint("rrd_default_out_ds");
         wm_debug("Default 'out' DS name changed to " . $dsnames[OUT] . ".\n");
     }
     $multiplier = 8;
     // default bytes-to-bits
     $inbw = NULL;
     $outbw = NULL;
     $data_time = 0;
     if (preg_match("/^(.*\\.rrd):([\\-a-zA-Z0-9_]+):([\\-a-zA-Z0-9_]+)\$/", $targetstring, $matches)) {
         $rrdfile = $matches[1];
         $dsnames[IN] = $matches[2];
         $dsnames[OUT] = $matches[3];
         wm_debug("Special DS names seen (" . $dsnames[IN] . " and " . $dsnames[OUT] . ").\n");
     }
     if (preg_match("/^rrd:(.*)/", $rrdfile, $matches)) {
         $rrdfile = $matches[1];
     }
     if (preg_match("/^gauge:(.*)/", $rrdfile, $matches)) {
         $rrdfile = $matches[1];
         $multiplier = 1;
     }
     if (preg_match("/^scale:([+-]?\\d*\\.?\\d*):(.*)/", $rrdfile, $matches)) {
         $rrdfile = $matches[2];
         $multiplier = $matches[1];
     }
     wm_debug("SCALING result by {$multiplier}\n");
     // try and make a complete path, if we've been given a clue
     // (if the path starts with a . or a / then assume the user knows what they are doing)
     if (!preg_match("/^(\\/|\\.)/", $rrdfile)) {
         $rrdbase = $map->get_hint('rrd_default_path');
         if ($rrdbase != '') {
             $rrdfile = $rrdbase . "/" . $rrdfile;
         }
     }
     $cfname = intval($map->get_hint('rrd_cf'));
     if ($cfname == '') {
         $cfname = 'AVERAGE';
     }
     $period = intval($map->get_hint('rrd_period'));
     if ($period == 0) {
         $period = 800;
     }
     $start = $map->get_hint('rrd_start');
     if ($start == '') {
         $start = "now-{$period}";
         $end = "now";
     } else {
         $end = "start+" . $period;
     }
     $use_poller_output = intval($map->get_hint('rrd_use_poller_output'));
     $nowarn_po_agg = intval($map->get_hint("nowarn_rrd_poller_output_aggregation"));
     $aggregatefunction = $map->get_hint('rrd_aggregate_function');
     if ($aggregatefunction != '' && $use_poller_output == 1) {
         $use_poller_output = 0;
         if ($nowarn_po_agg == 0) {
             wm_warn("Can't use poller_output for rrd-aggregated data - disabling rrd_use_poller_output [WMRRD10]\n");
         }
     }
     if ($use_poller_output == 1) {
         wm_debug("Going to try poller_output, as requested.\n");
         WeatherMapDataSource_rrd::wmrrd_read_from_poller_output($rrdfile, "AVERAGE", $start, $end, $dsnames, $data, $map, $data_time, $item);
     }
     // if poller_output didn't get anything, or if it couldn't/didn't run, do it the old-fashioned way
     // - this will still be the case for the first couple of runs after enabling poller_output support
     //   because there won't be valid data in the weathermap_data table yet.
     if ($dsnames[IN] != '-' && $data[IN] === NULL || $dsnames[OUT] != '-' && $data[OUT] === NULL) {
         if ($use_poller_output == 1) {
             wm_debug("poller_output didn't get anything useful. Kicking it old skool.\n");
         }
         if (file_exists($rrdfile) or file_exists($map->chdir . "/" . $rrdfile)) {
             wm_debug("RRD ReadData: Target DS names are " . $dsnames[IN] . " and " . $dsnames[OUT] . "\n");
             $values = array();
             if (1 == 0 && extension_loaded('RRDTool')) {
                 WeatherMapDataSource_rrd::wmrrd_read_from_php_rrd($rrdfile, $cfname, $start, $end, $dsnames, $data, $map, $data_time, $item);
             } else {
                 if ($aggregatefunction != '') {
                     WeatherMapDataSource_rrd::wmrrd_read_from_real_rrdtool_aggregate($rrdfile, $cfname, $aggregatefunction, $start, $end, $dsnames, $data, $map, $data_time, $item);
                 } else {
                     // do this the tried and trusted old-fashioned way
                     WeatherMapDataSource_rrd::wmrrd_read_from_real_rrdtool($rrdfile, $cfname, $start, $end, $dsnames, $data, $map, $data_time, $item);
                 }
             }
         } else {
             wm_warn("Target {$rrdfile} doesn't exist. Is it a file? [WMRRD06]\n");
         }
     }
     // if the Locale says that , is the decimal point, then rrdtool
     // will honour it. However, floatval() doesn't, so let's replace
     // any , with . (there are never thousands separators, luckily)
     //
     if ($data[IN] !== NULL) {
         $data[IN] = floatval(str_replace(",", ".", $data[IN]));
         $data[IN] = $data[IN] * $multiplier;
     }
     if ($data[OUT] !== NULL) {
         $data[OUT] = floatval(str_replace(",", ".", $data[OUT]));
         $data[OUT] = $data[OUT] * $multiplier;
     }
     wm_debug("RRD ReadData: Returning (" . ($data[IN] === NULL ? 'NULL' : $data[IN]) . "," . ($data[OUT] === NULL ? 'NULL' : $data[OUT]) . ",{$data_time})\n");
     return array($data[IN], $data[OUT], $data_time);
 }
 function DrawLegendHorizontal($keyWidth = 400)
 {
     $title = $this->keytitle;
     $nScales = $this->spanCount();
     wm_debug("Drawing {$nScales} colours into SCALE\n");
     $fontObject = $this->keyfont;
     $x = 0;
     $y = 0;
     $scaleFactor = $keyWidth / 100;
     list($tileWidth, $tileHeight) = $fontObject->calculateImageStringSize("100%");
     $boxLeft = $x;
     $scaleLeft = $boxLeft + 4 + $scaleFactor / 2;
     $boxRight = $scaleLeft + $keyWidth + $tileWidth + 4 + $scaleFactor / 2;
     $boxTop = $y;
     $scaleTop = $boxTop + $tileHeight + 6;
     $scaleBottom = $scaleTop + $tileHeight * 1.5;
     $boxBottom = $scaleBottom + $tileHeight * 2 + 6;
     wm_debug("Size is %dx%d (From %dx%d tile)\n", $boxRight + 1, $boxBottom + 1, $tileWidth, $tileHeight);
     $gdScaleImage = imagecreatetruecolor($boxRight + 1, $boxBottom + 1);
     $scaleReference = 'gdref_legend_' . $this->name;
     // Start with a transparent box, in case the fill or outline colour is 'none'
     imageSaveAlpha($gdScaleImage, true);
     $transparentColour = imagecolorallocatealpha($gdScaleImage, 128, 0, 0, 127);
     imagefill($gdScaleImage, 0, 0, $transparentColour);
     // $this->preAllocateScaleColours($gdScaleImage, $scaleReference);
     $bgColour = $this->keybgcolour;
     $outlineColour = $this->keyoutlinecolour;
     wm_debug("BG is {$bgColour}, Outline is {$outlineColour}\n");
     if ($bgColour->isRealColour()) {
         imagefilledrectangle($gdScaleImage, $boxLeft, $boxTop, $boxRight, $boxBottom, $bgColour->gdAllocate($gdScaleImage));
     }
     if ($outlineColour->isRealColour()) {
         imagerectangle($gdScaleImage, $boxLeft, $boxTop, $boxRight, $boxBottom, $outlineColour->gdAllocate($gdScaleImage));
     }
     $fontObject->drawImageString($gdScaleImage, $scaleLeft, $scaleBottom + $tileHeight * 2 + 2, $title, $this->keytextcolour->gdAllocate($gdScaleImage));
     for ($percentage = 0; $percentage <= 100; $percentage++) {
         $xOffset = $percentage * $scaleFactor;
         if ($percentage % 25 == 0) {
             imageline($gdScaleImage, $scaleLeft + $xOffset, $scaleTop - $tileHeight, $scaleLeft + $xOffset, $scaleBottom + $tileHeight, $this->keytextcolour->gdAllocate($gdScaleImage));
             $labelString = sprintf("%d%%", $percentage);
             $fontObject->drawImageString($gdScaleImage, $scaleLeft + $xOffset + 2, $scaleTop - 2, $labelString, $this->keytextcolour->gdAllocate($gdScaleImage));
         }
         list($col, ) = $this->findScaleHit($percentage);
         if ($col->isRealColour()) {
             $cc = $col->gdAllocate($gdScaleImage);
             imagefilledrectangle($gdScaleImage, $scaleLeft + $xOffset - $scaleFactor / 2, $scaleTop, $scaleLeft + $xOffset + $scaleFactor / 2, $scaleBottom, $cc);
         }
     }
     return $gdScaleImage;
 }
 public function readData(&$map, &$mapItem)
 {
     wm_debug("ReadData for {$mapItem} ({$this->pluginName} {$this->pluginRunnable})\n");
     if (!$this->pluginRunnable) {
         wm_debug("Plugin %s isn't runnable\n", $this->pluginName);
         return;
     }
     if ($this->scaleFactor != 1) {
         wm_debug("Will multiply result by %f\n", $this->scaleFactor);
     }
     list($in, $out, $dataTime) = $this->pluginObject->ReadData($this->finalTargetString, $map, $mapItem);
     if ($in === null && $out === null) {
         wm_warn(sprintf("ReadData: %s, target: %s had no valid data, according to %s [WMWARN70]\n", $mapItem, $this->finalTargetString, $this->pluginName));
         return;
     }
     wm_debug("Collected data %f,%f\n", $in, $out);
     $in *= $this->scaleFactor;
     $out *= $this->scaleFactor;
     $this->values[IN] = $in;
     $this->values[OUT] = $out;
     $this->timestamp = $dataTime;
     $this->dataValid = true;
 }
 function WriteConfig()
 {
     $output = '';
     # $output .= "# ID ".$this->id." - first seen in ".$this->defined_in."\n";
     if ($this->config_override != '') {
         $output = $this->config_override . "\n";
     } else {
         # $defdef = $this->owner->defaultlink;
         $dd = $this->owner->links[$this->template];
         wm_debug("Writing config for LINK {$this->name} against {$this->template}\n");
         $basic_params = array(array('width', 'WIDTH', CONFIG_TYPE_LITERAL), array('zorder', 'ZORDER', CONFIG_TYPE_LITERAL), array('overlibwidth', 'OVERLIBWIDTH', CONFIG_TYPE_LITERAL), array('overlibheight', 'OVERLIBHEIGHT', CONFIG_TYPE_LITERAL), array('arrowstyle', 'ARROWSTYLE', CONFIG_TYPE_LITERAL), array('viastyle', 'VIASTYLE', CONFIG_TYPE_LITERAL), array('linkstyle', 'LINKSTYLE', CONFIG_TYPE_LITERAL), array('splitpos', 'SPLITPOS', CONFIG_TYPE_LITERAL), array('duplex', 'DUPLEX', CONFIG_TYPE_LITERAL), array('commentstyle', 'COMMENTSTYLE', CONFIG_TYPE_LITERAL), array('labelboxstyle', 'BWSTYLE', CONFIG_TYPE_LITERAL), array('bwfont', 'BWFONT', CONFIG_TYPE_LITERAL), array('commentfont', 'COMMENTFONT', CONFIG_TYPE_LITERAL), array('bwoutlinecolour', 'BWOUTLINECOLOR', CONFIG_TYPE_COLOR), array('bwboxcolour', 'BWBOXCOLOR', CONFIG_TYPE_COLOR), array('outlinecolour', 'OUTLINECOLOR', CONFIG_TYPE_COLOR), array('commentfontcolour', 'COMMENTFONTCOLOR', CONFIG_TYPE_COLOR), array('bwfontcolour', 'BWFONTCOLOR', CONFIG_TYPE_COLOR));
         # TEMPLATE must come first. DEFAULT
         if ($this->template != 'DEFAULT' && $this->template != ':: DEFAULT ::') {
             $output .= "\tTEMPLATE " . $this->template . "\n";
         }
         foreach ($basic_params as $param) {
             $field = $param[0];
             $keyword = $param[1];
             # $output .= "# For $keyword: ".$this->$field." vs ".$dd->$field."\n";
             if ($this->{$field} != $dd->{$field}) {
                 if ($param[2] == CONFIG_TYPE_COLOR) {
                     $output .= "\t{$keyword} " . render_colour($this->{$field}) . "\n";
                 }
                 if ($param[2] == CONFIG_TYPE_LITERAL) {
                     $output .= "\t{$keyword} " . $this->{$field} . "\n";
                 }
             }
         }
         $val = $this->usescale . " " . $this->scaletype;
         $comparison = $dd->usescale . " " . $dd->scaletype;
         if ($val != $comparison) {
             $output .= "\tUSESCALE " . $val . "\n";
         }
         if ($this->infourl[IN] == $this->infourl[OUT]) {
             $dirs = array(IN => "");
             // only use the IN value, since they're both the same, but don't prefix the output keyword
         } else {
             $dirs = array(IN => "IN", OUT => "OUT");
             // the full monty two-keyword version
         }
         foreach ($dirs as $dir => $tdir) {
             if ($this->infourl[$dir] != $dd->infourl[$dir]) {
                 $output .= "\t" . $tdir . "INFOURL " . $this->infourl[$dir] . "\n";
             }
         }
         if ($this->overlibcaption[IN] == $this->overlibcaption[OUT]) {
             $dirs = array(IN => "");
             // only use the IN value, since they're both the same, but don't prefix the output keyword
         } else {
             $dirs = array(IN => "IN", OUT => "OUT");
             // the full monty two-keyword version
         }
         foreach ($dirs as $dir => $tdir) {
             if ($this->overlibcaption[$dir] != $dd->overlibcaption[$dir]) {
                 $output .= "\t" . $tdir . "OVERLIBCAPTION " . $this->overlibcaption[$dir] . "\n";
             }
         }
         if ($this->notestext[IN] == $this->notestext[OUT]) {
             $dirs = array(IN => "");
             // only use the IN value, since they're both the same, but don't prefix the output keyword
         } else {
             $dirs = array(IN => "IN", OUT => "OUT");
             // the full monty two-keyword version
         }
         foreach ($dirs as $dir => $tdir) {
             if ($this->notestext[$dir] != $dd->notestext[$dir]) {
                 $output .= "\t" . $tdir . "NOTES " . $this->notestext[$dir] . "\n";
             }
         }
         if ($this->overliburl[IN] == $this->overliburl[OUT]) {
             $dirs = array(IN => "");
             // only use the IN value, since they're both the same, but don't prefix the output keyword
         } else {
             $dirs = array(IN => "IN", OUT => "OUT");
             // the full monty two-keyword version
         }
         foreach ($dirs as $dir => $tdir) {
             if ($this->overliburl[$dir] != $dd->overliburl[$dir]) {
                 $output .= "\t" . $tdir . "OVERLIBGRAPH " . join(" ", $this->overliburl[$dir]) . "\n";
             }
         }
         // if formats have been set, but they're just the longform of the built-in styles, set them back to the built-in styles
         if ($this->labelstyle == '--' && $this->bwlabelformats[IN] == FMT_PERC_IN && $this->bwlabelformats[OUT] == FMT_PERC_OUT) {
             $this->labelstyle = 'percent';
         }
         if ($this->labelstyle == '--' && $this->bwlabelformats[IN] == FMT_BITS_IN && $this->bwlabelformats[OUT] == FMT_BITS_OUT) {
             $this->labelstyle = 'bits';
         }
         if ($this->labelstyle == '--' && $this->bwlabelformats[IN] == FMT_UNFORM_IN && $this->bwlabelformats[OUT] == FMT_UNFORM_OUT) {
             $this->labelstyle = 'unformatted';
         }
         // if specific formats have been set, then the style will be '--'
         // if it isn't then use the named style
         if ($this->labelstyle != $dd->labelstyle && $this->labelstyle != '--') {
             $output .= "\tBWLABEL " . $this->labelstyle . "\n";
         }
         // if either IN or OUT field changes, then both must be written because a regular BWLABEL can't do it
         // XXX this looks wrong
         $comparison = $dd->bwlabelformats[IN];
         $comparison2 = $dd->bwlabelformats[OUT];
         if ($this->labelstyle == '--' && ($this->bwlabelformats[IN] != $comparison || $this->bwlabelformats[OUT] != '--')) {
             $output .= "\tINBWFORMAT " . $this->bwlabelformats[IN] . "\n";
             $output .= "\tOUTBWFORMAT " . $this->bwlabelformats[OUT] . "\n";
         }
         $comparison = $dd->labeloffset_in;
         $comparison2 = $dd->labeloffset_out;
         if ($this->labeloffset_in != $comparison || $this->labeloffset_out != $comparison2) {
             $output .= "\tBWLABELPOS " . $this->labeloffset_in . " " . $this->labeloffset_out . "\n";
         }
         $comparison = $dd->commentoffset_in . ":" . $dd->commentoffset_out;
         $mine = $this->commentoffset_in . ":" . $this->commentoffset_out;
         if ($mine != $comparison) {
             $output .= "\tCOMMENTPOS " . $this->commentoffset_in . " " . $this->commentoffset_out . "\n";
         }
         $comparison = $dd->targets;
         if ($this->targets != $comparison) {
             $output .= "\tTARGET";
             foreach ($this->targets as $target) {
                 if (strpos($target[4], " ") == FALSE) {
                     $output .= " " . $target[4];
                 } else {
                     $output .= ' "' . $target[4] . '"';
                 }
             }
             $output .= "\n";
         }
         foreach (array(IN, OUT) as $dir) {
             if ($dir == IN) {
                 $tdir = "IN";
             }
             if ($dir == OUT) {
                 $tdir = "OUT";
             }
             $comparison = $dd->comments[$dir];
             if ($this->comments[$dir] != $comparison) {
                 $output .= "\t" . $tdir . "COMMENT " . $this->comments[$dir] . "\n";
             }
         }
         if (isset($this->a) && isset($this->b)) {
             $output .= "\tNODES " . $this->a->name;
             if ($this->a_offset != 'C') {
                 $output .= ":" . $this->a_offset;
             }
             $output .= " " . $this->b->name;
             if ($this->b_offset != 'C') {
                 $output .= ":" . $this->b_offset;
             }
             $output .= "\n";
         }
         if (count($this->vialist) > 0) {
             foreach ($this->vialist as $via) {
                 if (isset($via[2])) {
                     $output .= sprintf("\tVIA %s %d %d\n", $via[2], $via[0], $via[1]);
                 } else {
                     $output .= sprintf("\tVIA %d %d\n", $via[0], $via[1]);
                 }
             }
         }
         if ($this->max_bandwidth_in != $dd->max_bandwidth_in || $this->max_bandwidth_out != $dd->max_bandwidth_out || $this->name == 'DEFAULT') {
             if ($this->max_bandwidth_in == $this->max_bandwidth_out) {
                 $output .= "\tBANDWIDTH " . $this->max_bandwidth_in_cfg . "\n";
             } else {
                 $output .= "\tBANDWIDTH " . $this->max_bandwidth_in_cfg . " " . $this->max_bandwidth_out_cfg . "\n";
             }
         }
         foreach ($this->hints as $hintname => $hint) {
             // all hints for DEFAULT node are for writing
             // only changed ones, or unique ones, otherwise
             if ($this->name == 'DEFAULT' || isset($dd->hints[$hintname]) && $dd->hints[$hintname] != $hint || !isset($dd->hints[$hintname])) {
                 $output .= "\tSET {$hintname} {$hint}\n";
             }
         }
         if ($output != '') {
             $output = "LINK " . $this->name . "\n" . $output . "\n";
         }
     }
     return $output;
 }