Location: PHPKode > projects > Weathermap5rrd > weathermap5rrd-1.3.11/modules/drawmap.php
<?php
/*
 * weathermap5rrd - index.php
 *
 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
 *
 * The contents of this file are subject to the Mozilla Public License Version
 * 1.1 (the "License"); you may not use this file except in compliance with
 * the License. You may obtain a copy of the License at
 * http://www.mozilla.org/MPL/
 *
 * Software distributed under the License is distributed on an "AS IS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
 * for the specific language governing rights and limitations under the
 * License.
 *
 * The Original Code is Copyright (C)
 * 2007 Zdenek Styblik <hide@address.com>
 *
 * The Initial Developer of the Original Code is
 * 2007 Zdenek Styblik <hide@address.com>
 *
 * Portions created by the Initial Developer are Copyright (C) 2007
 * the Initial Developer. All Rights Reserved.
 *
 * Contributor(s):
 *
 * Alternatively, the contents of this file may be used under the terms of
 * either the GNU General Public License Version 2 or later (the "GPL"), or
 * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
 * in which case the provisions of the GPL or the LGPL are applicable instead
 * of those above. If you wish to allow use of your version of this file only
 * under the terms of either the GPL or the LGPL, and not to allow others to
 * use your version of this file under the terms of the MPL, indicate your
 * decision by deleting the provisions above and replace them with the notice
 * and other provisions required by the GPL or the LGPL. If you do not delete
 * the provisions above, a recipient may use your version of this file under
 * the terms of any one of the MPL, the GPL or the LGPL.
 *
 * Authors:
 * Zdenek Styblik ~ 2007-2008
 * Alexandre Fontelle ~ 2005-2006
 *
 * original file: draw_map.php
 *
 */
class drawmap extends defaultLib
{
	public $config;
	public $settings;
	public $auto_index;
	// don't perform network tests
	// 1 = yes(don't)
	// 0 = normal behaviour
	public $nonettest = 0; // disables network tests;
	public $arrowwidth;
	// $imgtostdout = 1; write image, print-out image;
	// $imgtostdout = 0; write image, no out;
	public $imgtostdout = 1;
	public $halt = 0; // halt script before image output; debugging;
	/* variable definiton ends */
	function __construct()
 	{
		$this->settings = new StdClass;
		$settings = $this->settings;
		$this->config = new StdClass;
		$this->auto_index = -1;
	}
	function __destruct()
 	{
		unset($this->settings);
		unset($this->config);
		unset($this->graphic);
		unset($this->rrdtools);
	}
	public function init()
	{
		if (! extension_loaded('gd'))
		{
				throw new Exception ("PHP GD module is needed for Weathermap5RRD. Unable to continue.");
		} /* !extension_loaded */
		$settings = $this->settings;
		$config = $this->config;
		$cfgfile = "weathermap.xml";
		if (isset($_GET['config']))
		{
			$cfgfile = $this->stripMe($_GET['config']);
		} /* if isset($_GET['config']) */
		require_once('lib/configfile.php');
		$configfile = new config_file($cfgfile);
		if ($configfile->readconfig() == false)
		{
			throw new Exception ("Unable to read config file '{$cfgfile}'.");
		} /* if $configfile->readconfig() */
		$config = $configfile->getConfig();
		$path = $this->getPath();
		# turn on debuging and halt before image output
		if (isset($_GET['debug']) && $_GET['debug'] == 1)
	 	{
			$this->halt = 1;
		} /* if isset $_GET['debug'] */
		# do not try any network tests
		if (isset($_GET['nonettest']) && $_GET['nonettest'] == 1)
	 	{
			$this->nonettest = 1;
		} /* if isset $_GET['nonettest']*/
		require_once "{$path}lib/graphic.php";
		$graphic = new graphic();
		require_once "{$path}lib/rrd.php";
		$rrdtools = new rrdtools();
		$loopcount = 0;
		while (1)
		{
			$loopcount++;
			# ToDo - possible todo; time set via $this-> || $_POST || $_GET
			$unixtime = time();
			$date = NULL;
			# ToDo - filter; probably group filter
			$filter = NULL;
			# get arrow width
			if (isset($config->arrowwidth))
			{
				$this->arrowwidth = $config->arrowwidth;
			}
			else
			{
				$this->arrowwidth = $configfile->getArrowWidth();
			} /* not isset $config->arrowwidth */
			# point somewhere
			if (isset($config->nodes)) 
			{
				$nodes = $config->nodes;
			}
			else
			{
				$nodes = NULL;
			} /* not isset $config->nodes */
			if (isset($config->links))
			{
				$links = $config->links;
			}
			else
		 	{
				$links = NULL;
			} /* not isset $config->links */
			# <autoscale> gets preferred over <scale>
			if (isset($config->autoscale))
			{
				$scale = $configfile->autoscale($config->autoscale);
			}
			else
			{
				if (isset($config->scale) && is_object($config->scale))
			 	{
					$scale = $config->scale;
				}
				else
			 	{
					# default scale
					$scale = new StdClass;
					$scale->entry[0] = new StdClass;
					$scale->entry[0]->low = 0;
					$scale->entry[0]->high = 100;
					$scale->entry[0]->r = 0;
					$scale->entry[0]->g = 128;
					$scale->entry[0]->b = 255;
				} /* not isset $config->scale */
			} /* not isset $config->autoscale */
			# Create global GD image for network map
			# Size :  X = $width+8
			#         Y = $height+4
			if (!isset($config->background))
		 	{
				$im = imagecreatetruecolor($config->width+8, $config->height+4)
				 	or die ("Cannot Initialize new GD image stream");
				$width = imagesx($im);
				$height = imagesy($im);
				$sizefrombg = 1;
			}
			else
		 	{
				if (file_exists("{$path}background/" . $config->background))
			 	{
					$im1 = imagecreatefrompng("{$path}background/" . $config->background);
					if (!$im1)
					{ 
						/* See if it has failed */
		        $im  = imagecreatetruecolor(150, 30); /* Create a blank image */
     		  	$bgc = imagecolorallocate($im, 255, 255, 255);
		        $tc  = imagecolorallocate($im, 0, 0, 0);
     			  imagefilledrectangle($im, 0, 0, 150, 30, $bgc);
		        /* Output an errmsg */
						imagestring($im, 1, 5, 5, "Error loading {$config->background}", $tc);
						break;
					} 
					else
					{
						$width = imagesx($im1);
						$height = imagesy($im1);
						/* if you experience any problems change following line to 'imagecreate'
						 * and let me know
						 */
						$im = imagecreatetruecolor($width, $height);
						imagecopy($im, $im1, 0, 0, 0, 0, $width, $height);
						imagedestroy($im1);
						$sizefrombg = 1;
					} /* not !$im1 */
				}
				else
			 	{
					setDebugMsg("{$path}htmldir/background/{$config->background}
						specified in configuration file has not been found. Check usage of BACKGROUND directive.");
					$im  = imagecreatetruecolor(150, 30); /* Create a blank image */
     		  $bgc = imagecolorallocate($im, 255, 255, 255);
		      $tc  = imagecolorallocate($im, 0, 0, 0);
     			imagefilledrectangle($im, 0, 0, 150, 30, $bgc);
		      /* Output an errmsg */
					imagestring($im, 1, 5, 5, "Unable to open {$config->background}", $tc);
					break;
				} /* not file_exists $background */
			} /* not !isset $config->background */
			# set font inside graphic
			$graphic->setFont($config->font);
			# Define main colors of GD image
			$graphic->define_colors($im);
			# Allocate black & white colors :)
			$black = $graphic->getBlack();
			$green = $graphic->getGreen();
			$red = $graphic->getRed();
			$white = $graphic->getWhite();
			if (!isset($config->background))
				imagefill($im, 0, 0, $white);
			# Draw a grid over the background image
			if ($config->drawgrid > 0)
		 	{
				$interval = 40;
				$o = $white;
				$e = $black;
				$style = array($o, $o, $e, $e);
				imagesetstyle($im, $style);
				for($grid = $interval; $grid < $width; $grid += $interval)
				{
					imageline($im, $grid, 0, $grid, $height, IMG_COLOR_STYLED);
				} /* for $grid */
				for($grid = $interval; $grid < $height; $grid += $interval)
		 		{
					imageline($im, 0, $grid, $width, $grid, IMG_COLOR_STYLED);
				} /* for $grid */
			} /* if $config->drawgrid */
			# Display icons
			# NOTE: iconx & icony relative position to node x & y ?
			# NOTE: icon position = (iconx + x), (icony + y) ?
			if (!is_null($nodes)) 
			{
				foreach ($nodes as $node)
			 	{
					if (isset($node->icon))
				 	{
						if (file_exists("./{$node->icon}"))
						{
							$icon = @imagecreatefrompng($node->icon);
							$iconwidth = imagesx($icon);
							$iconheight = imagesy($icon);
							if (isset($node->iconresize) && is_numeric($node->iconresize))
						 	{
								$factor = $node->iconresize/100;
							}
							else
						 	{
								$factor = 1;
							} /* not isset $node->iconresize */
							$icon2 = imagecreate($iconwidth*$factor,$iconheight*$factor);
							$iconwhite = imagecolorallocate($icon2, 255, 255, 255);
							imagecolortransparent($icon2, $iconwhite);
							imagecopyresized($icon2, $icon, 0, 0, 0, 0, $iconwidth*$factor, $iconheight*$factor,
							 	$iconwidth, $iconheight);
							if (!isset($node->iconx) || !is_numeric($node->icony) || $node->icony == 0)
						 	{
								$node->iconx = $node->x-$iconwidth*$factor/2;
								$node->icony = $node->y-$iconheight*$factor/2;
							} /* if !isset $node->iconx */
							# if no icon transparency is set, default to 50%
							if (!isset($node->icontransparent) || !is_numeric($node->icontransparent) 
								|| $node->icontransparent == 0)
						 	{
								$node->icontransparent = 50;
							} /* if !isset $node->icontransparent */
							imagecopymerge($im, $icon2, $node->iconx,$node->icony, 0, 0, $iconwidth*$factor,
							 	$iconheight*$factor, $node->icontransparent);
							imagedestroy($icon2);
						}
						else
						{
							setDebugMsg("File \"". $node->icon ."\"
							 	not found. Icon won't be displayed on graph. Please check usage of ICON directive.");
						} /* not file_exists $node->icon */
					} /* if isset $node->icon */
				} /* foreach $nodes */
			} /* if $nodes */
			# Draw as many links as defined in configuration file
			# ####### NOTE #######
			# note: this can cause some 
			# 	llllllloooooooooooooooooooooooooooop,
			# 	so be carefull, kids :)
			# ####### NOTE #######
			if (!is_null($links))
			{
				foreach ($links as $link)
				{
					if (isset($link->target) || (isset($link->targetin) && isset($link->targetout)))
				 	{
						# check-out if target-in && target-out are present
						if (!isset($link->targetin) || empty($link->targetin))
							$link->targetin = $link->target;
						if (!isset($link->targetout) || empty($link->targetout))
							$link->targetout = $link->target;
						# check for inpos and outpos values
						if (!isset($link->inpos) || !is_numeric($link->inpos))
							$link->inpos = 1;
						if (!isset($link->outpos) || !is_numeric($link->outpos))
							$link->outpos = 2;
						if (!isset($link->unit))
							$link->unit = 'bits';
						# fetch traffic values
						## INPUT link
						if ((basename($link->targetin,".htm") != basename($link->targetin))
							|| (basename($link->targetin,".html") != basename($link->targetin))) 
						{
							setDebugMsg("MRTG Target in reading...'{$link->targetin}'");
							# fugly php @ suppression
							$handle = @fopen($link->targetin, "r");
						 	if ($handle == false)
							{
								setDebugMsg("File '{$link->targetin}' not found or unreachable");
								$link->input = 0;
							}
							else 
							{
								$coefin = $rrdtools->rrdtool_getLinkCoef($link->unit);
								$link->input = 0;
								while (!feof($handle))
							 	{
									$line = fgets($handle);
									# <!-- cuin d 562442.0 -->
									if (preg_match('/<\!-- cuin d [0-9\.]+ -->/i', $line, $out))
								 	{
										if (preg_match('/[0-9\.]+/', $out[0], $out))
											$link->input = $out[0] * $coefin;
									} /* if preg_match */
								} /* while !feof */
								fclose($handle);
							} /* not $handle */
						} /* if basename $link->targetin */
						else
						{
							# Read RRDTool values for current link
							# If no date is specified, use the last date stored in RRD database. 
							$msg = "RRDTool binary version detected : " . $rrdtools->rrdtool_getversion();
							setDebugMsg($msg);
							if (is_null($date))
						 	{
								$end = $rrdtools->rrdtool_last($link->targetin);
								$start = $end - $configfile->getRRDstep();
									setDebugMsg("Last time value detected in rrd file : " . $end);
							}
							else
							{
								$start = $date - $configfile->getRRDstep();
								$end = $date;
							} /* not is_null $date */
							$result = $rrdtools->rrdtool_function_fetch($link->targetin, $start, $end);
							# convert into bytes
							if (isset($result["values"][$link->inpos-1][0]))
							{
								$coefin = $rrdtools->rrdtool_getLinkCoef($link->unit);
								# get Kbits
								$link->input = $result["values"][$link->inpos-1][0] * $coefin;
							}
							else
							{
								$link->input = 0;
							} /* not isset $result */
						} /* not basename $link->targetin */
						## OUTPUT link ###
						if ((basename($link->targetout, ".htm") != basename($link->targetout))
							|| (basename($link->targetout, ".html") != basename($link->targetout)))
						{
							setDebugMsg("MRTG Target out reading...'{$link->targetout}'");
							# fugly php @ suppression
							$handle = @fopen($link->targetout, "r");
							if ($handle == false)
							{
								setDebugMsg("File '{$link->targetout}' not found or unreachable");
								$link->output = 0;
							}
							else
						 	{
								$coefout = $rrdtools->rrdtool_getLinkCoef($link->unit);
								$link->output = 0;
								while (!feof($handle))
							 	{
							    $line = fgets($handle);
									# <!-- cuin d 562442.0 -->
									if (preg_match("/<\!-- cuout d [0-9\.]+ -->/i", $line, $out))
								 	{
										if (preg_match('/[0-9\.]+/', $out[0], $out))
											$link->output = $out[0] * $coefout;
									} /* if preg_match */
								} /* while !feof */
								fclose($handle);
							} /* not $handle */
						}  /* if basename $link->targetout */
						else
						{
							# Read RRDTool values for current link
							# If no date is specified, use the last date stored in RRD database. 
							setDebugMsg("RRDTool binary version detected : ". $rrdtools->rrdtool_getversion());
							if (is_null($date))
						 	{
								$end = $rrdtools->rrdtool_last($link->targetout);
								$start = $end - $configfile->getRRDstep();
								setDebugMsg("Last time value detected in rrd file : " . $end);
							}
							else
						 	{
								$start = $date - $configfile->getRRDstep();
								$end = $date;
							} /* not is_null */
							$result = $rrdtools->rrdtool_function_fetch($link->targetout, $start, $end);
							# Get values from array read before and convert values in bytes
							if (isset($result["values"][$link->outpos-1][0]))
						 	{
								$coefout = $rrdtools->rrdtool_getLinkCoef($link->unit);
								# get Kbits
								$link->output = $result["values"][$link->outpos-1][0] * $coefout;
							}
							else
						 	{
								$link->output = 0;
							} /* not isset $result */
						}  /* not basename $link->targetout */
						# check for link rates. if not set, set some.
						if (isset($link->ratein) && is_numeric($link->ratein))
					 	{
							$link->ratein = $link->ratein * $rrdtools->rrdtool_getLinkCoef('Kbits');
						}
						else
						{
							# set default speed to 10Mbit/s
							$link->ratein = 10000 * $rrdtools->rrdtool_getLinkCoef('Kbits');
						} /* not isset $link->ratein */
						if (isset($link->rateout) && is_numeric($link->rateout))
						{
							$link->rateout = $link->rateout * $rrdtools->rrdtool_getLinkCoef('Kbits');
						}
						else
						{
							# set default speed to 10Mbit/s
							$link->rateout = 10024 * $rrdtools->rrdtool_getLinkCoef('Kbits');
						} /* not isset $link->rateout */
						if ( (int)(((($link->output) / $link->rateout) + 0.005) *100) > 100 )
					 	{
							$outrate = 100;
						}
						else
					 	{
							$outrate = (int)(((($link->output) / $link->rateout) + 0.005) * 100);
						} /* not (int) $link->output */
						if ( (int)(((($link->input) / $link->ratein) + 0.005) * 100) > 100 )
					 	{
							$inrate = 100;
						}
						else
					 	{
							$inrate = (int)(((($link->input) / $link->ratein) + 0.005) * 100);
						} /* not (int) $link->input */
						# Do not display 0%, if it is not exactly 0. It will display 1%
						if($link->output != 0 && $outrate == 0)
							$outrate=1; 
						if($link->input != 0 && $inrate == 0)
							$inrate=1;
						### debug ###
						setDebugMsg("link: " . $link->name . " -> "
							. $link->target . ": in=" . $link->input . "/" . $link->ratein . " out=" . $link->output
						 	. "/" . $link->rateout);
						setDebugMsg("link: " . $link->name . " -> "
							. $link->target . ": outrate=" . $outrate . "%, inrate=" . $inrate . "%");
					} /* if isset $link->target */
					else
				 	{
						// link target files are not set 
						$inrate = 0;
						$link->input = 0;
						$outrate = 0;
						$link->output = 0;
						# check for link rates. if not set, set some.
						if (isset($link->ratein) && is_numeric($link->ratein))
						{
							# dummy
						}
						else
						{
							# set default speed to 10Mbit/s
							$link->ratein = 100000;
						} /* not isset $link->ratein */
						if (isset($link->rateout) && is_numeric($link->rateout))
						{
							# dummy
						}
						else
						{
							# set default speed to 10Mbit/s
							$link->rateout = 100000;
						} /* not isset $link->rateout */
					} // not isset($link->target)
					# if arrow is not set, set one by default
					if (!isset($link->arrow))
						$link->arrow = "normal";
					if (isset($link->internode))
				 	{
						// show internodes
						if (isset($link->internodedisplay))
					 	{
							$internodedisplay = 100;
						}
						else
					 	{
							$internodedisplay = 0;
						} /* not isset $Link->internodedi.. */
						# show internode numbers
						if (isset($link->internodedisplaynum) && $link->internodedisplaynum == 1)
						{
							$internodedisplaynum = 1;
						}
						else
						{
							$internodedisplaynum = 0;
						} /* not isset $link->internoded... */
						# internode count
						$inodecount = count($link->internode);
						# show internode mid
						if (isset($link->internodedisplaymid) && $link->internodedisplaymid == 1)
						{
							$internodedisplaymid = 1;
						}
						else
						{
							if (($inodecount%2) == 0)
							{
								$internodedisplaymid = 1;
							}
							else
							{
								$internodedisplaymid = 0;
							} /* not $inodecount%2 */
						} /* not isset $link->internodedi.. */
						# display internodes
						if (isset($link->internode) && is_array($link->internode) && isset($nodes->{$link->from}->x) 
							&& isset($nodes->{$link->from}->y) && isset($nodes->{$link->to}->x) && isset($nodes->{$link->to}->y))
					 	{
							if ($inodecount%2 == 0)
						 	{
								switch ($link->arrow)
							 	{
									case 'circle':
										# draw line from link->from to inode-first
										$graphic->draw_circle3($im, $nodes->{$link->from}->x, $nodes->{$link->from}->y,
											$link->internode[1]->x, $link->internode[1]->y, $this->arrowwidth, 0, 1, $graphic->select_color($im, $inrate, $scale));
										# draw line from link->to to inode-last
										$graphic->draw_circle3($im, $nodes->{$link->to}->x, $nodes->{$link->to}->y,
											$link->internode[$inodecount]->x, $link->internode[$inodecount]->y, $this->arrowwidth, 0, 1, $graphic->select_color($im, $outrate, $scale));
										break;
									case 'halfarrow':
										# draw line from link->from to inode-first
										$graphic->draw_rectangle_half($im, $nodes->{$link->from}->x, $nodes->{$link->from}->y, $link->internode[1]->x, $link->internode[1]->y,
											$this->arrowwidth, 1, $graphic->select_color($im, $inrate, $scale));
										$graphic->draw_arrow_half($im, $link->internode[1]->x, $link->internode[1]->y, $nodes->{$link->from}->x, $nodes->{$link->from}->y,
											$this->arrowwidth, 1, $graphic->select_color($im, $outrate, $scale));
										# draw line from link->to to inode-last
										$graphic->draw_rectangle_half($im, $nodes->{$link->to}->x, $nodes->{$link->to}->y, $link->internode[$inodecount]->x, $link->internode[$inodecount]->y,
											$this->arrowwidth, 1, $graphic->select_color($im, $outrate, $scale));
										$graphic->draw_arrow_half($im,$link->internode[$inodecount]->x, $link->internode[$inodecount]->y, $nodes->{$link->to}->x, $nodes->{$link->to}->y, 
											$this->arrowwidth, 1, $graphic->select_color($im, $inrate, $scale));
										break;
									default:
										# draw line from link->from to inode-first
										$graphic->draw_rectangle($im, $nodes->{$link->from}->x, $nodes->{$link->from}->y,
											$link->internode[1]->x,$link->internode[1]->y,
											$this->arrowwidth, 1, $graphic->select_color($im, $inrate, $scale));
										$graphic->draw_rectangle($im, $nodes->{$link->from}->x, $nodes->{$link->from}->y,
											$link->internode[1]->x, $link->internode[1]->y,
											$this->arrowwidth, 0, $black);
										# draw line from link->to to inode-last
										$graphic->draw_rectangle($im, $nodes->{$link->to}->x, $nodes->{$link->to}->y,
											$link->internode[$inodecount]->x,$link->internode[$inodecount]->y,
											$this->arrowwidth, 1, $graphic->select_color($im, $outrate, $scale));
										$graphic->draw_rectangle($im, $nodes->{$link->to}->x, $nodes->{$link->to}->y,
											$link->internode[$inodecount]->x, $link->internode[$inodecount]->y,
											$this->arrowwidth, 0, $black);
										break;
								} /* switch $link->arrow */	
								# draw lines between nodes
								$nodea = ($inodecount/2) + 1;
								$nodeb = $inodecount/2;
								for ($i = 1; $i <= $inodecount; $i++)
								{
									if ($i+1 <= $inodecount)
									{
										if (($i == $nodea || $i == $nodeb) && ($i+1 == $nodeb || $i+1 == $nodea))
									 	{
											# do nothing
										}
										else
									 	{
											if ($i < $nodea)
										 	{
												$varrate = $inrate;
											}
											else
										 	{
												$varrate = $outrate;
											} /* not $i < $nodea */
											# draw a line
											switch ($link->arrow)
										 	{
												case 'circle':
													$graphic->draw_circle3($im, $link->internode[$i]->x, $link->internode[$i]->y,
														$link->internode[$i+1]->x, $link->internode[$i+1]->y, $this->arrowwidth, 0, 1,
													 	$graphic->select_color($im, $varrate, $scale));
													$graphic->draw_circle3($im, $link->internode[$i]->x, $link->internode[$i]->y,
														$link->internode[$i+1]->x, $link->internode[$i+1]->y, $this->arrowwidth, 0, 1,
													 	$graphic->select_color($im, $varrate, $scale));
													break;
												case 'halfarrow':
													$graphic->draw_rectangle_half($im, $link->internode[$i]->x, $link->internode[$i]->y,
														$link->internode[$i+1]->x, $link->internode[$i+1]->y, $this->arrowwidth, 1,
													 	$graphic->select_color($im, $inrate, $scale));
													$graphic->draw_rectangle_half($im, $link->internode[$i+1]->x, $link->internode[$i+1]->y,
														$link->internode[$i]->x, $link->internode[$i]->y, $this->arrowwidth, 1,
													 	$graphic->select_color($im, $outrate, $scale));
													break;
												default:
													$graphic->draw_rectangle($im, $link->internode[$i]->x, $link->internode[$i]->y,
														$link->internode[$i+1]->x,$link->internode[$i+1]->y, $this->arrowwidth, 1,
													 	$graphic->select_color($im, $varrate, $scale));
													$graphic->draw_rectangle($im, $link->internode[$i]->x, $link->internode[$i]->y,
														$link->internode[$i+1]->x, $link->internode[$i+1]->y, $this->arrowwidth, 0, $black);
													break;
											} /* switch $link->arrow */
										} /* not $i == $nodea */
									} /* if $i+1 */
								} /* for $i+1 */
								# draw arrows and link % between $nodea and $nodeb
								switch ($link->arrow)
								{
									case "circle":
										$graphic->draw_arrow_circle3($im, $link->internode[$nodea]->x, $link->internode[$nodea]->y,
											$graphic->middle($link->internode[$nodea]->x, $link->internode[$nodeb]->x),
										 	$graphic->middle($link->internode[$nodea]->y, $link->internode[$nodeb]->y),
											$this->arrowwidth, 0, 1, $graphic->select_color($im, $outrate, $scale));
										$graphic->draw_arrow_circle3($im, $link->internode[$nodeb]->x, $link->internode[$nodeb]->y,
											$graphic->middle($link->internode[$nodea]->x, $link->internode[$nodeb]->x),
										 	$graphic->middle($link->internode[$nodea]->y, $link->internode[$nodeb]->y),
											$this->arrowwidth, 0, 1, $graphic->select_color($im, $inrate, $scale));
										break;
									case 'halfarrow':
											$graphic->draw_rectangle_half($im, $link->internode[$nodea]->x, $link->internode[$nodea]->y,
												$link->internode[$nodeb]->x, $link->internode[$nodeb]->y, $this->arrowwidth, 1,
											 	$graphic->select_color($im, $outrate, $scale));
											$graphic->draw_rectangle_half($im, $link->internode[$nodeb]->x, $link->internode[$nodeb]->y,
												$link->internode[$nodea]->x, $link->internode[$nodea]->y, $this->arrowwidth, 1,
											 	$graphic->select_color($im, $inrate, $scale));
										break;
									default:
										$graphic->draw_arrow($im, $link->internode[$nodea]->x, $link->internode[$nodea]->y,
											$graphic->middle($link->internode[$nodea]->x, $link->internode[$nodeb]->x),
										 	$graphic->middle($link->internode[$nodea]->y,	$link->internode[$nodeb]->y),
											$this->arrowwidth, 1, $graphic->select_color($im, $outrate, $scale), "normal");
										$graphic->draw_arrow($im, $link->internode[$nodeb]->x, $link->internode[$nodeb]->y,
											$graphic->middle($link->internode[$nodea]->x, $link->internode[$nodeb]->x),
										 	$graphic->middle($link->internode[$nodea]->y, $link->internode[$nodeb]->y),
											$this->arrowwidth, 1, $graphic->select_color($im, $inrate, $scale), "normal");
										break;
								} /* switch $link->arrow */
								# display values over link
								if (isset($link->displayvalue) && $link->displayvalue == 1)
								{
									# Display bandwidth % for links
									if ($link->arrow == "halfarrow")
								 	{
										$graphic->valuesHalf($im, $nodes->{$link->from}, $link->internode[1], $link->output, $outrate,
										 	$config->font, $this->arrowwidth, $black, $white);
										$graphic->valuesHalf($im, $nodes->{$link->to}, $link->internode[$inodecount],
										 	$link->input, $inrate, $config->font, $this->arrowwidth, $black, $white);
									}
									else
								 	{
										$graphic->label($im, "{$inrate}%", $graphic->middle($link->internode[$nodeb]->x,
											$graphic->middle($link->internode[$nodea]->x, $link->internode[$nodeb]->x)), 
											$graphic->middle($link->internode[$nodeb]->y, $graphic->middle($link->internode[$nodea]->y,
											$link->internode[$nodeb]->y)), $config->font, $black, $white);
										$graphic->label($im, "{$outrate}%", $graphic->middle($link->internode[$nodea]->x,
										 	$graphic->middle($link->internode[$nodeb]->x,	$link->internode[$nodea]->x)),
											$graphic->middle($link->internode[$nodea]->y, $graphic->middle($link->internode[$nodeb]->y,
											$link->internode[$nodea]->y)), $config->font, $black, $white);
										# Display bandwidth
										$graphic->displayValue($im, $link->internode[$nodea], $link->internode[$nodeb], $link->input);
										$graphic->displayValue($im, $link->internode[$nodeb], $link->internode[$nodea], $link->output);
									} /* not $link->arrow */
								} /* if isset $link->displayva.. */
							}
							else
						 	{
								if (count($link->internode) == 1)
							 	{
									$j = 1;
									$inodelast = 1;
									$from = $nodes->{$link->from};
									$to = $nodes->{$link->to};
								}
								else
							 	{
									$j = round(count($link->internode)/2, 0);
									$inodelast = count($link->internode);
									$from = $link->internode[$j-1];
									$to = $link->internode[$j+1];
									switch ($link->arrow)
								 	{
										case 'circle':
											# draw line from link->from to inode-first
											$graphic->draw_circle3($im, $nodes->{$link->from}->x, $nodes->{$link->from}->y,
												$link->internode[1]->x, $link->internode[1]->y, $this->arrowwidth, 0, 1,
											 	$graphic->select_color($im, $inrate, $scale));
											# draw line from link->to to inode-last
											$graphic->draw_circle3($im, $nodes->{$link->to}->x, $nodes->{$link->to}->y,
												$link->internode[$inodelast]->x, $link->internode[$inodelast]->y, $this->arrowwidth,
											 	0, 1, $graphic->select_color($im, $outrate, $scale));
											break;
										case 'halfarrow':
											# draw line from link->from to inode-first
											$graphic->draw_rectangle_half($im, $from->x, $from->y, $link->internode[$j]->x,
											 	$link->internode[$j]->y, $this->arrowwidth, 1, $graphic->select_color($im, $inrate, $scale));
											$graphic->draw_rectangle_half($im, $link->internode[$j]->x, $link->internode[$j]->y, $from->x,
											 	$from->y, $this->arrowwidth, 1, $graphic->select_color($im, $outrate, $scale));
											# draw line from link->to to inode-last
											$graphic->draw_rectangle_half($im, $to->x, $to->y, $link->internode[$j]->x,
											 	$link->internode[$j]->y, $this->arrowwidth, 1, $graphic->select_color($im, $outrate, $scale));
											$graphic->draw_rectangle_half($im,$link->internode[$j]->x, $link->internode[$j]->y, $to->x,
											 	$to->y, $this->arrowwidth, 1, $graphic->select_color($im, $inrate, $scale));
											break;
										default:
											# draw line from link->from to inode-first
											$graphic->draw_rectangle($im, $nodes->{$link->from}->x, $nodes->{$link->from}->y,
												$link->internode[1]->x, $link->internode[1]->y, $this->arrowwidth, 1,
											 	$graphic->select_color($im, $inrate, $scale));
											$graphic->draw_rectangle($im, $nodes->{$link->from}->x, $nodes->{$link->from}->y,
											 	$link->internode[1]->x, $link->internode[1]->y, $this->arrowwidth, 0, $black);
											# draw line from link->to to node-last
											$graphic->draw_rectangle($im, $nodes->{$link->to}->x, $nodes->{$link->to}->y,
												$link->internode[$inodelast]->x, $link->internode[$inodelast]->y, $this->arrowwidth,
											 	1, $graphic->select_color($im, $outrate, $scale));
											$graphic->draw_rectangle($im, $to->x, $to->y, $link->internode[$inodelast]->x,
											 	$link->internode[$inodelast]->y, $this->arrowwidth, 0, $black);
											break;
									} /* switch $link->arrow */
								} /* not count(link->internode) */
								# draw arrows
								switch ($link->arrow)
								{
									case "circle":
										$graphic->draw_arrow_circle3($im, $from->x, $from->y,
											$link->internode[$j]->x, $link->internode[$j]->y, $this->arrowwidth, 0, 1,
										 	$graphic->select_color($im, $inrate, $scale));
										$graphic->draw_arrow_circle3($im, $to->x, $to->y,
											$link->internode[$j]->x, $link->internode[$j]->y, $this->arrowwidth, 0, 1,
										 	$graphic->select_color($im, $outrate, $scale));
										break;
									case 'halfarrow':
										# one
										$graphic->draw_arrow_half($im, $link->internode[$inodecount]->x,
											$link->internode[$inodecount]->y, $nodes->{$link->to}->x, $nodes->{$link->to}->y,
											$this->arrowwidth, 1, $graphic->select_color($im, $inrate, $scale));
										$graphic->draw_rectangle_half($im, $nodes->{$link->to}->x, $nodes->{$link->to}->y,
										 	$link->internode[$inodecount]->x, $link->internode[$inodecount]->y,
											$this->arrowwidth, 1, $graphic->select_color($im, $outrate, $scale));
										# two
										$graphic->draw_rectangle_half($im, $nodes->{$link->from}->x, $nodes->{$link->from}->y,
											$link->internode[1]->x, $link->internode[1]->y, $this->arrowwidth, 1,
										 	$graphic->select_color($im, $inrate, $scale));
										$graphic->draw_arrow_half($im, $link->internode[1]->x, $link->internode[1]->y,
											$nodes->{$link->from}->x, $nodes->{$link->from}->y, $this->arrowwidth, 1,
										 	$graphic->select_color($im, $outrate, $scale));
										break;
									default:
										$graphic->draw_arrow($im, $from->x, $from->y, $link->internode[$j]->x,
											$link->internode[$j]->y, $this->arrowwidth, 1,
										 	$graphic->select_color($im, $inrate, $scale));
										$graphic->draw_arrow($im, $from->x, $from->y, $link->internode[$j]->x,
										 	$link->internode[$j]->y, $this->arrowwidth, 0, $black);
										$graphic->draw_arrow($im, $to->x, $to->y, $link->internode[$j]->x,
											$link->internode[$j]->y, $this->arrowwidth, 1,
										 	$graphic->select_color($im, $outrate, $scale));
										$graphic->draw_arrow($im, $to->x, $to->y, $link->internode[$j]->x,
										 	$link->internode[$j]->y, $this->arrowwidth, 0, $black);
										break;
								} /* switch $link->arrow */
								# draw lines between nodes
								for ($i = 1; $i <= $inodelast; $i++)
								{
									if ($i+1 <= $inodelast)
								 	{
										if (($i == ($j-1) && ($i+1) == $j) || ($i == $j && ($i+1) == ($j+1)))
									 	{
											# do nothing
										}
										else
									 	{
											if ($i < $j)
										 	{
												$varrate = $inrate;
											}
											else
										 	{
												$varrate = $outrate;
											} /* $i < $j */
											# draw a line
											switch ($link->arrow)
										 	{
												case 'circle':
													$graphic->draw_circle3($im, $link->internode[$i]->x, $link->internode[$i]->y,
													$link->internode[$i+1]->x, $link->internode[$i+1]->y, $this->arrowwidth, 0, 1, $graphic->select_color($im, $varrate, $scale));
													$graphic->draw_circle3($im, $link->internode[$i]->x, $link->internode[$i]->y,
													$link->internode[$i+1]->x, $link->internode[$i+1]->y, $this->arrowwidth, 0, 1, $graphic->select_color($im, $varrate, $scale));
													break;
												case 'halfarrow':
													$graphic->draw_rectangle_half($im, $link->internode[$i]->x, $link->internode[$i]->y,
													 	$link->internode[$i+1]->x, $link->internode[$i+1]->y, $this->arrowwidth, 1, $graphic->select_color($im, $inrate, $scale));
													$graphic->draw_rectangle_half($im, $link->internode[$i+1]->x, $link->internode[$i+1]->y,
													 	$link->internode[$i]->x, $link->internode[$i]->y, $this->arrowwidth, 1, $graphic->select_color($im, $outrate, $scale));
													break;
												default:
													$graphic->draw_rectangle($im, $link->internode[$i]->x, $link->internode[$i]->y,
														$link->internode[$i+1]->x,$link->internode[$i+1]->y, $this->arrowwidth, 1, $graphic->select_color($im, $varrate, $scale));
													$graphic->draw_rectangle($im, $link->internode[$i]->x, $link->internode[$i]->y,
														$link->internode[$i+1]->x, $link->internode[$i+1]->y, $this->arrowwidth, 0, $black);
													break;
											} /* switch $link->arrow */
										} /* not $i == $j-1 */
									} /* if $i+1 */
									if (isset($link->displayvalue) && $link->displayvalue == 1)
									{
										if ($link->arrow == "halfarrow")
									 	{
											$graphic->valuesHalf($im, $nodes->{$link->from}, $link->internode[1], $link->output, $outrate, $config->font,
											 	$this->arrowwidth, $black, $white);
											$graphic->valuesHalf($im, $nodes->{$link->to}, $link->internode[$inodecount], $link->input, $inrate, $config->font, 
												$this->arrowwidth, $black, $white);
										}
										else
										{
											# Display bandwidth % for links
											$graphic->label($im, "{$inrate}%", $graphic->middle($from->x, $link->internode[$j]->x), 
												$graphic->middle($from->y, $link->internode[$j]->y), $config->font, $black, $white);
											$graphic->label($im, "{$outrate}%", $graphic->middle($to->x, $link->internode[$j]->x),
												$graphic->middle($link->internode[$j]->y, $to->y), $config->font, $black, $white);
											# Display bandwidth
											$graphic->displayValue($im, $from, $link->internode[$j], $link->input, 0);
											$graphic->displayValue($im, $to, $link->internode[$j], $link->output, 0);
										} /* not $link->arrow */
									} /* if isset $link->displayvalue */
								} /* for $i = 1 */
							} /* not count%2 */
							# draw node dot
							if ($internodedisplaymid == 0)
							{
								$mid = round($inodecount/2, 0);
							}
							else
							{
								$mid = NULL;
							} /* not $internodedi.. */
							for ($i = 1; $i <= $inodecount; $i++)
							{
								if ($i == $mid)
							 	{
									# do nothing
								}
								else
								{
									if ($internodedisplaynum == 1)
								 	{
										$gdinternode = $graphic->draw_internode(($i-1), $config->font, $black, $white);
									}
									else
								 	{
										$gdinternode = $graphic->draw_internode(" ", $config->font, $black, $white);
									} /* not $internodedi.. */
									imagecopymerge($im, $gdinternode, $link->internode[$i]->x-imagesx($gdinternode)/2,
										$link->internode[$i]->y-imagesy($gdinternode)/2, 0, 0, imagesx($gdinternode),
									 	imagesy($gdinternode), $internodedisplay);
								} /* not $i == $mid */
							} /* for i = 1 */
						} /* if isset $link -> internode && is_array */
						else
						{
							# do nothing; this should never happen
							setDebugMsg("Unexpected error in drawmap.php. Please report this error!");
						} /* not isset $link -> internode && is_array */
					} /* if isset $link->internode */
					else
					{
						if (isset($nodes->{$link->to}->x) && isset($nodes->{$link->from}->y))
						{
							# else we can draw a simple arrow
							# for both directions!!!
							# note: 1 function per arrow
							switch ($link->arrow)
							{
								case "circle":
									$graphic->draw_arrow_circle3($im, $nodes->{$link->to}->x, $nodes->{$link->to}->y,
										$graphic->middle($nodes->{$link->from}->x, $nodes->{$link->to}->x),
									 	$graphic->middle($nodes->{$link->from}->y, $nodes->{$link->to}->y),
										$this->arrowwidth, 0, 1, $graphic->select_color($im, $outrate, $scale));
									$graphic->draw_arrow_circle3($im, $nodes->{$link->from}->x, $nodes->{$link->from}->y,
										$graphic->middle($nodes->{$link->from}->x, $nodes->{$link->to}->x),
									 	$graphic->middle($nodes->{$link->from}->y, $nodes->{$link->to}->y),
										$this->arrowwidth, 0, 1, $graphic->select_color($im, $inrate, $scale));
									break;
								case 'halfarrow':
									$graphic->draw_arrow_half($im, $nodes->{$link->to}->x, $nodes->{$link->to}->y,
										$nodes->{$link->from}->x, $nodes->{$link->from}->y, $this->arrowwidth, 1,
									 	$graphic->select_color($im, $outrate, $scale));
									$graphic->draw_arrow_half($im, $nodes->{$link->from}->x, $nodes->{$link->from}->y,
										$nodes->{$link->to}->x, $nodes->{$link->to}->y, $this->arrowwidth, 1,
									 	$graphic->select_color($im, $inrate, $scale));
									break;
								default:
									$graphic->draw_arrow($im, $nodes->{$link->to}->x, $nodes->{$link->to}->y,
										$graphic->middle($nodes->{$link->from}->x, $nodes->{$link->to}->x),
									 	$graphic->middle($nodes->{$link->from}->y, $nodes->{$link->to}->y),
										$this->arrowwidth, 1, $graphic->select_color($im, $outrate, $scale), "normal");
									$graphic->draw_arrow($im, $nodes->{$link->from}->x, $nodes->{$link->from}->y,
										$graphic->middle($nodes->{$link->from}->x, $nodes->{$link->to}->x),
									 	$graphic->middle($nodes->{$link->from}->y, $nodes->{$link->to}->y),
										$this->arrowwidth, 1, $graphic->select_color($im, $inrate, $scale), "normal");
									break;
							} /* switch $link->arrow */
							if (isset($link->displayvalue) && $link->displayvalue == 1)
							{
								if ($link->arrow == "halfarrow")
								{
									$graphic->valuesHalf($im, $nodes->{$link->from}, $nodes->{$link->to}, $link->output,
									 	$outrate, $config->font, $this->arrowwidth, $black, $white);
									$graphic->valuesHalf($im, $nodes->{$link->to}, $nodes->{$link->from}, $link->input,
									 	$inrate, $config->font, $this->arrowwidth, $black, $white);
								}
								else
								{
									# Display bandwidth % for links
									$graphic->label($im, "{$outrate}%", $graphic->middle($nodes->{$link->to}->x,
										$graphic->middle($nodes->{$link->from}->x, $nodes->{$link->to}->x)),
									$graphic->middle($nodes->{$link->to}->y, $graphic->middle($nodes->{$link->from}->y,
								 	$nodes->{$link->to}->y)), $config->font, $black, $white);
									$graphic->label($im, "{$inrate}%", $graphic->middle($nodes->{$link->from}->x,
										$graphic->middle($nodes->{$link->to}->x, $nodes->{$link->from}->x)),
										$graphic->middle($nodes->{$link->from}->y, $graphic->middle($nodes->{$link->to}->y,
								 		$nodes->{$link->from}->y)), $config->font, $black, $white);
									# Display bandwidth
									$graphic->displayValue($im, $nodes->{$link->from}, $nodes->{$link->to}, $link->output); 
									$graphic->displayValue($im, $nodes->{$link->to}, $nodes->{$link->from}, $link->input); 
								} /* not $link->arrow */
							} /* if isset $link->displa.. */
						} /* if isset(nodes->{link->to}->x) */
					} /* if isset link->internode */
				} /* foreach $config->links->entry */
			} /* if isset $config->links */
			# Display all node labels
			if (!is_null($nodes))
			{
				foreach ($nodes as $node)
			 	{
					if (!isset($node->labeltype))
						$node->labeltype = "square";
					if (isset($config->ipcheck) && $config->ipcheck == 1 && $this->nonettest == 0
						&& isset($node->ip) && isset($node->check))
				 	{
						if (preg_match('/^(tcp:)[0-9]{1,5}+$/', $node->check) == 1)
					 	{
							$port = substr($node->check, 4);
							if ($this->check_tcp($node->ip, $port) == 1)
						 	{
								$background = $green;
							}
							else
						 	{
								$background = $red;
							} /* not $this->check_tcp */
						}
						else
					 	{
							# assume ping check. however, this can be wrong assumption, because there can be a typo.
							# well, you should check your confing - i told you so :)
							if ($this->check_ping($node->ip) == 1)
						 	{
								$background = $green;
							}
							else
						 	{
								$background = $red;
							} /* not $this->check_ping */
						} /* not preg_match */
					}
					else
				 	{
						$background = $white;
					} /* not isset $config->ipcheck */
					switch ($node->labeltype)
					{
						case "round" :
							$graphic->label_round($im, $node->label, $node->x, $node->y, $config->font, $black, $background);
							break;
						default :
							$graphic->label($im, $node->label, $node->x, $node->y, $config->font, $black, $background);
							break;
					} /* switch $node->labeltype */
				} /* foreach $nodes */
			} /* is_array $nodes */
			# Display title of map
			$gdtitle = $graphic->draw_title($config->title->text, $config->font, $config->title->fg->r,
				$config->title->fg->g, $config->title->fg->b, $config->title->bg->r, $config->title->bg->g,
			 	$config->title->bg->b, $unixtime);
			imagecopy($im, $gdtitle, $config->title->x, $config->title->y-1, 0, 0, imagesx($gdtitle),
			 	imagesy($gdtitle));
			imagedestroy($gdtitle);
			# Display legend of map
			switch ($config->legend->legendstyle)
		 	{
				case "line":
					$gdlegend = $graphic->draw_legend2("Link load", $config->font, $scale);
					break;
				default:
					$gdlegend = $graphic->draw_legend("Traffic load", $config->font, $scale);
					break;
			} /* switch $config->legend */
			imagecopy($im, $gdlegend, $config->legend->x, $config->legend->y, 0, 0, imagesx($gdlegend),
			 	imagesy($gdlegend));
			imagedestroy($gdlegend);
			# write png file to disk if OUTPUTFILE directive is used
			if (isset($config->outputfile) && !empty($config->outputfile))
			{
				if (imagepng($im, $config->outputfile))
			 	{
					setDebugMsg("notice: image '{$config->outputfile}' has been written;");
				} else {
					setDebugMsg("error: unable to write image '{$config->outputfile}'; check permissions!");
				} /* not imagepng */
			}
			else
			{
				setDebugMsg("notice: OUTPUTFILE directive not set;");
			} /* not isset $config->outputfile */
			break;
		} /* while(1) */
		### DEBUG ###
		if ($this->halt == 1)
		{
			echo "<pre>";
			echo "Loops around the Moon: {$loopcount};\n";
			echo "Debug output follows:\n";
			$msg = $this->getDebugMsg();
			if (is_object($msg))
			{
				foreach ($msg->debug->entry as $debugEntry)
				{
					echo "debug message:";
			 		echo trim($debugEntry->text);
					echo ";\n";
				}
			}
			echo "Debug output ends;\n";
			echo "</pre>";
			exit('Halted;');
		} /* if this->halt */
		if ($this->imgtostdout == 1)
		{
			# Generate PNG file for browser
			header('Content-type: image/png');
			// HTTP/1.1
			header("Cache-Control: no-store, no-cache, must-revalidate");
			header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
			header("Cache-Control: post-check=0, pre-check=0", false);
			// HTTP/1.0
			header("Pragma: no-cache");
			imagepng($im);
		} else {
			setDebugMsg("Drawmap: output suppressed;");
		} /* not $this->imgtostdout */
		imagedestroy($im);
		exit();
	}
	# desc: quite quicker check_node function
	# $ip: ipv4;
	# $port: int;
	# @return: bit;
	public function check_tcp($ip = NULL, $port = NULL)
 	{
		if (!is_null($ip) && !is_null($port) && is_numeric($port) && ($port > 0) && ($port <= 65536) && @inet_pton($ip) != false)
		{
			/* i'm sorry, but i can't help myself. another example of php ignorance.
			 * if the host is unavailable then warning message is generated.
			 * for the first, EXCEPTIONs, and for the second, why is manual silent
			 * about it?
			 * Thank you and good night!
			 */
			$fp = @fsockopen($ip, $port, $errno, $errstr, 3);
			if($fp == false)
		 	{
				return 0;
			}
			else 
			{
				stream_set_timeout($fp, 3);
				fclose($fp);
				return 1;
			} /* not $fp */
		}
		else
		{
			return 0;
		} /* not !is_null($ip) */
	}
	# desc: very slow check_node function.
	# $ip: ipv4;
	# @return: bit;
	public function check_ping($ip = NULL)
 	{
		if (!is_null($ip) && @inet_pton($ip) !== false) 
		{
			exec("ping -c 1 {$ip}", $list);
			if (preg_match("/time=[0-9\.]+ ms/i", $list[1], $matches))
		 	{
				return 1;
			}
			else
		 	{
				return 0;
			} /* not preg_match */
		}
		else
	 	{
			return 0;
		} /* not !is_null($ip) */
	}
}
?>
Return current item: Weathermap5rrd