function ReadConfig($input, $is_include=FALSE) { global $weathermap_error_suppress; $curnode=null; $curlink=null; $matches=0; $nodesseen=0; $linksseen=0; $scalesseen=0; $last_seen="GLOBAL"; $filename = ""; $objectlinecount=0; // check if $input is more than one line. if it is, it's a text of a config file // if it isn't, it's the filename $lines = array(); if( (strchr($input,"\n")!=FALSE) || (strchr($input,"\r")!=FALSE ) ) { wm_debug("ReadConfig Detected that this is a config fragment.\n"); // strip out any Windows line-endings that have gotten in here $input=str_replace("\r", "", $input); $lines = split("/n",$input); $filename = "{text insert}"; } else { wm_debug("ReadConfig Detected that this is a config filename.\n"); $filename = $input; if($is_include){ wm_debug("ReadConfig Detected that this is an INCLUDED config filename.\n"); if($is_include && in_array($filename, $this->included_files)) { wm_warn("Attempt to include '$filename' twice! Skipping it.\n"); return(FALSE); } else { $this->included_files[] = $filename; $this->has_includes = TRUE; } } $fd=fopen($filename, "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); $lines[] = $buffer; } fclose($fd); } } $linecount = 0; $objectlinecount = 0; foreach($lines as $buffer) { $linematched=0; $linecount++; if (preg_match("/^\s*#/", $buffer)) { // this is a comment line } else { $buffer = trim($buffer); // for any other config elements that are shared between nodes and links, they can use this unset($curobj); $curobj = NULL; if($last_seen == "LINK") $curobj = &$curlink; if($last_seen == "NODE") $curobj = &$curnode; if($last_seen == "GLOBAL") $curobj = &$this; $objectlinecount++; #if (preg_match("/^\s*(LINK|NODE)\s+([A-Za-z][A-Za-z0-9_\.\-\:]*)\s*$/i", $buffer, $matches)) if (preg_match("/^\s*(LINK|NODE)\s+(\S+)\s*$/i", $buffer, $matches)) { $objectlinecount = 0; if(1==1) { $this->ReadConfig_Commit($curobj); } else { // first, save the previous item, before starting work on the new one if ($last_seen == "NODE") { $this->nodes[$curnode->name]=$curnode; if($curnode->template == 'DEFAULT') $this->node_template_tree[ "DEFAULT" ][]= $curnode->name; wm_debug ("Saving Node: " . $curnode->name . "\n"); } if ($last_seen == "LINK") { if (isset($curlink->a) && isset($curlink->b)) { $this->links[$curlink->name]=$curlink; wm_debug ("Saving Link: " . $curlink->name . "\n"); } else { $this->links[$curlink->name]=$curlink; wm_debug ("Saving Template-Only Link: " . $curlink->name . "\n"); } if($curlink->template == 'DEFAULT') $this->link_template_tree[ "DEFAULT" ][]= $curlink->name; } } if ($matches[1] == 'LINK') { if ($matches[2] == 'DEFAULT') { if ($linksseen > 0) { wm_warn ("LINK DEFAULT is not the first LINK. Defaults will not apply to earlier LINKs. [WMWARN26]\n"); } unset($curlink); wm_debug("Loaded LINK DEFAULT\n"); $curlink = $this->links['DEFAULT']; } else { unset($curlink); if(isset($this->links[$matches[2]])) { wm_warn("Duplicate link name ".$matches[2]." at line $linecount - only the last one defined is used. [WMWARN25]\n"); } wm_debug("New LINK ".$matches[2]."\n"); $curlink=new WeatherMapLink; $curlink->name=$matches[2]; $curlink->Reset($this); $linksseen++; } $last_seen="LINK"; $curlink->configline = $linecount; $linematched++; $curobj = &$curlink; } if ($matches[1] == 'NODE') { if ($matches[2] == 'DEFAULT') { if ($nodesseen > 0) { wm_warn ("NODE DEFAULT is not the first NODE. Defaults will not apply to earlier NODEs. [WMWARN27]\n"); } unset($curnode); wm_debug("Loaded NODE DEFAULT\n"); $curnode = $this->nodes['DEFAULT']; } else { unset($curnode); if(isset($this->nodes[$matches[2]])) { wm_warn("Duplicate node name ".$matches[2]." at line $linecount - only the last one defined is used. [WMWARN24]\n"); } $curnode=new WeatherMapNode; $curnode->name=$matches[2]; $curnode->Reset($this); $nodesseen++; } $curnode->configline = $linecount; $last_seen="NODE"; $linematched++; $curobj = &$curnode; } # record where we first heard about this object $curobj->defined_in = $filename; } // most of the config keywords just copy stuff into object properties. // these are all dealt with from this one array. The special-cases // follow on from that $config_keywords = array( array('LINK','/^\s*(MAXVALUE|BANDWIDTH)\s+(\d+\.?\d*[KMGT]?)\s+(\d+\.?\d*[KMGT]?)\s*$/i',array('max_bandwidth_in_cfg'=>2,'max_bandwidth_out_cfg'=>3)), array('LINK','/^\s*(MAXVALUE|BANDWIDTH)\s+(\d+\.?\d*[KMGT]?)\s*$/i',array('max_bandwidth_in_cfg'=>2,'max_bandwidth_out_cfg'=>2)), array('NODE','/^\s*(MAXVALUE)\s+(\d+\.?\d*[KMGT]?)\s+(\d+\.?\d*[KMGT]?)\s*$/i',array('max_bandwidth_in_cfg'=>2,'max_bandwidth_out_cfg'=>3)), array('NODE','/^\s*(MAXVALUE)\s+(\d+\.?\d*[KMGT]?)\s*$/i',array('max_bandwidth_in_cfg'=>2,'max_bandwidth_out_cfg'=>2)), array('GLOBAL','/^\s*BACKGROUND\s+(.*)\s*$/i',array('background'=>1)), array('GLOBAL','/^\s*HTMLOUTPUTFILE\s+(.*)\s*$/i',array('htmloutputfile'=>1)), array('GLOBAL','/^\s*HTMLSTYLESHEET\s+(.*)\s*$/i',array('htmlstylesheet'=>1)), array('GLOBAL','/^\s*IMAGEOUTPUTFILE\s+(.*)\s*$/i',array('imageoutputfile'=>1)), array('GLOBAL','/^\s*IMAGEURI\s+(.*)\s*$/i',array('imageuri'=>1)), array('GLOBAL','/^\s*TITLE\s+(.*)\s*$/i',array('title'=>1)), array('GLOBAL','/^\s*HTMLSTYLE\s+(static|overlib)\s*$/i',array('htmlstyle'=>1)), array('GLOBAL','/^\s*KEYFONT\s+(\d+)\s*$/i',array('keyfont'=>1)), array('GLOBAL','/^\s*TITLEFONT\s+(\d+)\s*$/i',array('titlefont'=>1)), array('GLOBAL','/^\s*TIMEFONT\s+(\d+)\s*$/i',array('timefont'=>1)), array('GLOBAL','/^\s*TITLEPOS\s+(-?\d+)\s+(-?\d+)\s*$/i',array('titlex'=>1, 'titley'=>2)), array('GLOBAL','/^\s*TITLEPOS\s+(-?\d+)\s+(-?\d+)\s+(.*)\s*$/i',array('titlex'=>1, 'titley'=>2, 'title'=>3)), array('GLOBAL','/^\s*TIMEPOS\s+(-?\d+)\s+(-?\d+)\s*$/i',array('timex'=>1, 'timey'=>2)), array('GLOBAL','/^\s*TIMEPOS\s+(-?\d+)\s+(-?\d+)\s+(.*)\s*$/i',array('timex'=>1, 'timey'=>2, 'stamptext'=>3)), array('GLOBAL','/^\s*MINTIMEPOS\s+(-?\d+)\s+(-?\d+)\s*$/i',array('mintimex'=>1, 'mintimey'=>2)), array('GLOBAL','/^\s*MINTIMEPOS\s+(-?\d+)\s+(-?\d+)\s+(.*)\s*$/i',array('mintimex'=>1, 'mintimey'=>2, 'minstamptext'=>3)), array('GLOBAL','/^\s*MAXTIMEPOS\s+(-?\d+)\s+(-?\d+)\s*$/i',array('maxtimex'=>1, 'maxtimey'=>2)), array('GLOBAL','/^\s*MAXTIMEPOS\s+(-?\d+)\s+(-?\d+)\s+(.*)\s*$/i',array('maxtimex'=>1, 'maxtimey'=>2, 'maxstamptext'=>3)), array('NODE', "/^\s*LABEL\s*$/i", array('label'=>'')), # special case for blank labels array('NODE', "/^\s*LABEL\s+(.*)\s*$/i", array('label'=>1)), array('(LINK|GLOBAL)', "/^\s*WIDTH\s+(\d+)\s*$/i", array('width'=>1)), array('(LINK|GLOBAL)', "/^\s*HEIGHT\s+(\d+)\s*$/i", array('height'=>1)), array('LINK', "/^\s*WIDTH\s+(\d+\.\d+)\s*$/i", array('width'=>1)), array('LINK', '/^\s*ARROWSTYLE\s+(classic|compact)\s*$/i', array('arrowstyle'=>1)), array('LINK', '/^\s*VIASTYLE\s+(curved|angled)\s*$/i', array('viastyle'=>1)), array('LINK', '/^\s*INCOMMENT\s+(.*)\s*$/i', array('comments[IN]'=>1)), array('LINK', '/^\s*OUTCOMMENT\s+(.*)\s*$/i', array('comments[OUT]'=>1)), array('LINK', '/^\s*BWFONT\s+(\d+)\s*$/i', array('bwfont'=>1)), array('LINK', '/^\s*COMMENTFONT\s+(\d+)\s*$/i', array('commentfont'=>1)), array('LINK', '/^\s*COMMENTSTYLE\s+(edge|center)\s*$/i', array('commentstyle'=>1)), array('LINK', '/^\s*DUPLEX\s+(full|half)\s*$/i', array('duplex'=>1)), array('LINK', '/^\s*BWSTYLE\s+(classic|angled)\s*$/i', array('labelboxstyle'=>1)), array('LINK', '/^\s*LINKSTYLE\s+(twoway|oneway)\s*$/i', array('linkstyle'=>1)), array('LINK', '/^\s*BWLABELPOS\s+(\d+)\s(\d+)\s*$/i', array('labeloffset_in'=>1,'labeloffset_out'=>2)), array('LINK', '/^\s*COMMENTPOS\s+(\d+)\s(\d+)\s*$/i', array('commentoffset_in'=>1, 'commentoffset_out'=>2)), array('LINK', '/^\s*USESCALE\s+([A-Za-z][A-Za-z0-9_]*)\s*$/i', array('usescale'=>1)), array('LINK', '/^\s*USESCALE\s+([A-Za-z][A-Za-z0-9_]*)\s+(absolute|percent)\s*$/i', array('usescale'=>1,'scaletype'=>2)), array('LINK', '/^\s*SPLITPOS\s+(\d+)\s*$/i', array('splitpos'=>1)), array('NODE', '/^\s*LABELOFFSET\s+([-+]?\d+)\s+([-+]?\d+)\s*$/i', array('labeloffsetx'=>1,'labeloffsety'=>2)), array('NODE', '/^\s*LABELOFFSET\s+(C|NE|SE|NW|SW|N|S|E|W)\s*$/i', array('labeloffset'=>1)), array('NODE', '/^\s*LABELOFFSET\s+((C|NE|SE|NW|SW|N|S|E|W)\d+)\s*$/i', array('labeloffset'=>1)), array('NODE', '/^\s*LABELOFFSET\s+(-?\d+r\d+)\s*$/i', array('labeloffset'=>1)), array('NODE', '/^\s*LABELFONT\s+(\d+)\s*$/i', array('labelfont'=>1)), array('NODE', '/^\s*LABELANGLE\s+(0|90|180|270)\s*$/i', array('labelangle'=>1)), # array('(NODE|LINK)', '/^\s*TEMPLATE\s+(\S+)\s*$/i', array('template'=>1)), array('LINK', '/^\s*OUTBWFORMAT\s+(.*)\s*$/i', array('bwlabelformats[OUT]'=>1,'labelstyle'=>'--')), array('LINK', '/^\s*INBWFORMAT\s+(.*)\s*$/i', array('bwlabelformats[IN]'=>1,'labelstyle'=>'--')), # array('NODE','/^\s*ICON\s+none\s*$/i',array('iconfile'=>'')), array('NODE','/^\s*ICON\s+(\S+)\s*$/i',array('iconfile'=>1, 'iconscalew'=>'#0', 'iconscaleh'=>'#0')), array('NODE','/^\s*ICON\s+(\S+)\s*$/i',array('iconfile'=>1)), array('NODE','/^\s*ICON\s+(\d+)\s+(\d+)\s+(inpie|outpie|box|rbox|round|gauge|nink)\s*$/i',array('iconfile'=>3, 'iconscalew'=>1, 'iconscaleh'=>2)), array('NODE','/^\s*ICON\s+(\d+)\s+(\d+)\s+(\S+)\s*$/i',array('iconfile'=>3, 'iconscalew'=>1, 'iconscaleh'=>2)), array('NODE','/^\s*NOTES\s+(.*)\s*$/i',array('notestext[IN]'=>1,'notestext[OUT]'=>1)), array('LINK','/^\s*NOTES\s+(.*)\s*$/i',array('notestext[IN]'=>1,'notestext[OUT]'=>1)), array('LINK','/^\s*INNOTES\s+(.*)\s*$/i',array('notestext[IN]'=>1)), array('LINK','/^\s*OUTNOTES\s+(.*)\s*$/i',array('notestext[OUT]'=>1)), array('NODE','/^\s*INFOURL\s+(.*)\s*$/i',array('infourl[IN]'=>1,'infourl[OUT]'=>1)), array('LINK','/^\s*INFOURL\s+(.*)\s*$/i',array('infourl[IN]'=>1,'infourl[OUT]'=>1)), array('LINK','/^\s*ININFOURL\s+(.*)\s*$/i',array('infourl[IN]'=>1)), array('LINK','/^\s*OUTINFOURL\s+(.*)\s*$/i',array('infourl[OUT]'=>1)), array('NODE','/^\s*OVERLIBCAPTION\s+(.*)\s*$/i',array('overlibcaption[IN]'=>1,'overlibcaption[OUT]'=>1)), array('LINK','/^\s*OVERLIBCAPTION\s+(.*)\s*$/i',array('overlibcaption[IN]'=>1,'overlibcaption[OUT]'=>1)), array('LINK','/^\s*INOVERLIBCAPTION\s+(.*)\s*$/i',array('overlibcaption[IN]'=>1)), array('LINK','/^\s*OUTOVERLIBCAPTION\s+(.*)\s*$/i',array('overlibcaption[OUT]'=>1)), array('(NODE|LINK)', "/^\s*ZORDER\s+([-+]?\d+)\s*$/i", array('zorder'=>1)), array('(NODE|LINK)', "/^\s*OVERLIBWIDTH\s+(\d+)\s*$/i", array('overlibwidth'=>1)), array('(NODE|LINK)', "/^\s*OVERLIBHEIGHT\s+(\d+)\s*$/i", array('overlibheight'=>1)), array('NODE', "/^\s*POSITION\s+([-+]?\d+)\s+([-+]?\d+)\s*$/i", array('x'=>1,'y'=>2)), array('NODE', "/^\s*POSITION\s+(\S+)\s+([-+]?\d+)\s+([-+]?\d+)\s*$/i", array('x'=>2,'y'=>3,'original_x'=>2,'original_y'=>3,'relative_to'=>1,'relative_resolved'=>FALSE)), array('NODE', "/^\s*POSITION\s+(\S+)\s+([-+]?\d+)r(\d+)\s*$/i", array('x'=>2,'y'=>3,'original_x'=>2,'original_y'=>3,'relative_to'=>1,'polar'=>TRUE,'relative_resolved'=>FALSE)) ); // alternative for use later where quoted strings are more useful $args = wm_parse_string($buffer); // this loop replaces a whole pile of duplicated ifs with something with consistent handling foreach ($config_keywords as $keyword) { if(preg_match("/".$keyword[0]."/",$last_seen)) { $statskey = $last_seen."-".$keyword[1]; $statskey = str_replace( array('/^\s*','\s*$/i'),array('',''), $statskey); if(!isset($this->usage_stats[$statskey])) $this->usage_stats[$statskey] = 0; if(preg_match($keyword[1],$buffer,$matches)) { # print "CONFIG MATCHED: ".$keyword[1]."\n"; $this->usage_stats[$statskey]++; foreach ($keyword[2] as $key=>$val) { // so we can poke in numbers too, if the value starts with # // then take the # off, and treat the rest as a number literal if(preg_match("/^#(.*)/",$val,$m)) { $val = $m[1]; } elseif(is_numeric($val)) { // if it's a number, then it;s a match number, // otherwise it's a literal to be put into a variable $val = $matches[$val]; } assert('is_object($curobj)'); if(preg_match('/^(.*)\[([^\]]+)\]$/',$key,$m)) { $index = constant($m[2]); $key = $m[1]; $curobj->{$key}[$index] = $val; } else { $curobj->$key = $val; } } $linematched++; # print "\n\n"; break; } } } if (preg_match("/^\s*NODES\s+(\S+)\s+(\S+)\s*$/i", $buffer, $matches)) { if ($last_seen == 'LINK') { $valid_nodes=2; foreach (array(1, 2)as $i) { $endoffset[$i]='C'; $nodenames[$i]=$matches[$i]; // percentage of compass - must be first if (preg_match("/:(NE|SE|NW|SW|N|S|E|W|C)(\d+)$/i", $matches[$i], $submatches)) { $endoffset[$i]=$submatches[1].$submatches[2]; $nodenames[$i]=preg_replace("/:(NE|SE|NW|SW|N|S|E|W|C)\d+$/i", '', $matches[$i]); $this->need_size_precalc=TRUE; } if (preg_match("/:(NE|SE|NW|SW|N|S|E|W|C)$/i", $matches[$i], $submatches)) { $endoffset[$i]=$submatches[1]; $nodenames[$i]=preg_replace("/:(NE|SE|NW|SW|N|S|E|W|C)$/i", '', $matches[$i]); $this->need_size_precalc=TRUE; } if( preg_match("/:(-?\d+r\d+)$/i", $matches[$i], $submatches) ) { $endoffset[$i]=$submatches[1]; $nodenames[$i]=preg_replace("/:(-?\d+r\d+)$/i", '', $matches[$i]); $this->need_size_precalc=TRUE; } if (preg_match("/:([-+]?\d+):([-+]?\d+)$/i", $matches[$i], $submatches)) { $xoff = $submatches[1]; $yoff = $submatches[2]; $endoffset[$i]=$xoff.":".$yoff; $nodenames[$i]=preg_replace("/:$xoff:$yoff$/i", '', $matches[$i]); $this->need_size_precalc=TRUE; } if (!array_key_exists($nodenames[$i], $this->nodes)) { wm_warn ("Unknown node '" . $nodenames[$i] . "' on line $linecount of config\n"); $valid_nodes--; } } // TODO - really, this should kill the whole link, and reset for the next one if ($valid_nodes == 2) { $curlink->a=$this->nodes[$nodenames[1]]; $curlink->b=$this->nodes[$nodenames[2]]; $curlink->a_offset=$endoffset[1]; $curlink->b_offset=$endoffset[2]; } else { // this'll stop the current link being added $last_seen="broken"; } $linematched++; } } if ( $last_seen=='GLOBAL' && preg_match("/^\s*INCLUDE\s+(.*)\s*$/i", $buffer, $matches)) { if(file_exists($matches[1])){ wm_debug("Including '{$matches[1]}'\n"); $this->ReadConfig($matches[1], TRUE); $last_seen = "GLOBAL"; }else{ wm_warn("INCLUDE File '{$matches[1]}' not found!\n"); } $linematched++; } if ( ( $last_seen=='NODE' || $last_seen=='LINK' ) && preg_match("/^\s*TARGET\s+(.*)\s*$/i", $buffer, $matches)) { $linematched++; # $targets=preg_split('/\s+/', $matches[1], -1, PREG_SPLIT_NO_EMPTY); $rawtargetlist = $matches[1]." "; if($args[0]=='TARGET') { // wipe any existing targets, otherwise things in the DEFAULT accumulate with the new ones $curobj->targets = array(); array_shift($args); // take off the actual TARGET keyword foreach($args as $arg) { // we store the original TARGET string, and line number, along with the breakdown, to make nicer error messages later // array of 7 things: // - only 0,1,2,3,4 are used at the moment (more used to be before DS plugins) // 0 => final target string (filled in by ReadData) // 1 => multiplier (filled in by ReadData) // 2 => config filename where this line appears // 3 => linenumber in that file // 4 => the original target string // 5 => the plugin to use to pull data $newtarget=array('','',$filename,$linecount,$arg,"",""); if ($curobj) { wm_debug(" TARGET: $arg\n"); $curobj->targets[]=$newtarget; } } } } if ($last_seen == 'LINK' && preg_match( "/^\s*BWLABEL\s+(bits|percent|unformatted|none)\s*$/i", $buffer, $matches)) { $format_in = ''; $format_out = ''; $style = strtolower($matches[1]); if($style=='percent') { $format_in = FMT_PERC_IN; $format_out = FMT_PERC_OUT; } if($style=='bits') { $format_in = FMT_BITS_IN; $format_out = FMT_BITS_OUT; } if($style=='unformatted') { $format_in = FMT_UNFORM_IN; $format_out = FMT_UNFORM_OUT; } $curobj->labelstyle=$style; $curobj->bwlabelformats[IN] = $format_in; $curobj->bwlabelformats[OUT] = $format_out; $linematched++; } if (preg_match("/^\s*SET\s+(\S+)\s+(.*)\s*$/i", $buffer, $matches)) { $curobj->add_hint($matches[1],trim($matches[2])); if($curobj->my_type() == "map" && substr($matches[1],0,7)=='nowarn_') { $weathermap_error_suppress[$matches[1]] = 1; } $linematched++; } // allow setting a variable to "" if (preg_match("/^\s*SET\s+(\S+)\s*$/i", $buffer, $matches)) { $curobj->add_hint($matches[1],''); if($curobj->my_type() == "map" && substr($matches[1],0,7)=='nowarn_') { $weathermap_error_suppress[$matches[1]] = 1; } $linematched++; } if (preg_match("/^\s*(IN|OUT)?OVERLIBGRAPH\s+(.+)$/i", $buffer, $matches)) { $this->has_overlibs = TRUE; if($last_seen == 'NODE' && $matches[1] != '') { wm_warn("IN/OUTOVERLIBGRAPH make no sense for a NODE! [WMWARN42]\n"); } else if($last_seen == 'LINK' || $last_seen=='NODE' ) { $urls = preg_split('/\s+/', $matches[2], -1, PREG_SPLIT_NO_EMPTY); if($matches[1] == 'IN') $index = IN; if($matches[1] == 'OUT') $index = OUT; if($matches[1] == '') { $curobj->overliburl[IN]=$urls; $curobj->overliburl[OUT]=$urls; } else { $curobj->overliburl[$index]=$urls; } $linematched++; } } // array('(NODE|LINK)', '/^\s*TEMPLATE\s+(\S+)\s*$/i', array('template'=>1)), if ( ( $last_seen=='NODE' || $last_seen=='LINK' ) && preg_match("/^\s*TEMPLATE\s+(\S+)\s*$/i", $buffer, $matches)) { $tname = $matches[1]; if( ($last_seen=='NODE' && isset($this->nodes[$tname])) || ($last_seen=='LINK' && isset($this->links[$tname])) ) { $curobj->template = $matches[1]; wm_debug("Resetting to template $last_seen ".$curobj->template."\n"); $curobj->Reset($this); if( $objectlinecount > 1 ) wm_warn("line $linecount: TEMPLATE is not first line of object. Some data may be lost. [WMWARN39]\n"); // build up a list of templates - this will be useful later for the tree view if($last_seen == 'NODE') $this->node_template_tree[ $tname ][]= $curobj->name; if($last_seen == 'LINK') $this->link_template_tree[ $tname ][]= $curobj->name; } else { wm_warn("line $linecount: $last_seen TEMPLATE '$tname' doesn't exist! (if it does exist, check it's defined first) [WMWARN40]\n"); } $linematched++; } if ($last_seen == 'LINK' && preg_match("/^\s*VIA\s+([-+]?\d+)\s+([-+]?\d+)\s*$/i", $buffer, $matches)) { $curlink->vialist[]=array ( $matches[1], $matches[2] ); $linematched++; } if ($last_seen == 'LINK' && preg_match("/^\s*VIA\s+(\S+)\s+([-+]?\d+)\s+([-+]?\d+)\s*$/i", $buffer, $matches)) { $curlink->vialist[]=array ( $matches[2], $matches[3], $matches[1] ); $linematched++; } if( ($last_seen == 'NODE') && preg_match("/^\s*USE(ICON)?SCALE\s+([A-Za-z][A-Za-z0-9_]*)(\s+(in|out))?(\s+(absolute|percent))?\s*$/i",$buffer,$matches)) { $svar = ''; $stype = 'percent'; if(isset($matches[3])) { $svar = trim($matches[3]); } if(isset($matches[6])) { $stype = strtolower(trim($matches[6])); } // opens the door for other scaley things... switch($matches[1]) { case 'ICON': $varname = 'iconscalevar'; $uvarname = 'useiconscale'; $tvarname = 'iconscaletype'; // if(!function_exists("imagefilter")) // { // warn("ICON SCALEs require imagefilter, which is not present in your PHP [WMWARN040]\n"); // } break; default: $varname = 'scalevar'; $uvarname = 'usescale'; $tvarname = 'scaletype'; break; } if($svar != '') { $curnode->$varname = $svar; } $curnode->$tvarname = $stype; $curnode->$uvarname = $matches[2]; // warn("Set $varname and $uvarname\n"); // print ">> $stype $svar ".$matches[2]." ".$curnode->name." \n"; $linematched++; } // one REGEXP to rule them all: // if(preg_match("/^\s*SCALE\s+([A-Za-z][A-Za-z0-9_]*\s+)?(\d+\.?\d*)\s+(\d+\.?\d*)\s+(\d+)\s+(\d+)\s+(\d+)(?:\s+(\d+)\s+(\d+)\s+(\d+))?\s*$/i", // 0.95b if(preg_match("/^\s*SCALE\s+([A-Za-z][A-Za-z0-9_]*\s+)?(\d+\.?\d*)\s+(\d+\.?\d*)\s+(\d+)\s+(\d+)\s+(\d+)(?:\s+(\d+)\s+(\d+)\s+(\d+))?\s*(.*)$/i", if(preg_match("/^\s*SCALE\s+([A-Za-z][A-Za-z0-9_]*\s+)?(\-?\d+\.?\d*[munKMGT]?)\s+(\-?\d+\.?\d*[munKMGT]?)\s+(?:(\d+)\s+(\d+)\s+(\d+)(?:\s+(\d+)\s+(\d+)\s+(\d+))?|(none))\s*(.*)$/i", $buffer, $matches)) { // The default scale name is DEFAULT if($matches[1]=='') $matches[1] = 'DEFAULT'; else $matches[1] = trim($matches[1]); $key=$matches[2] . '_' . $matches[3]; $this->colours[$matches[1]][$key]['key']=$key; $tag = $matches[11]; $this->colours[$matches[1]][$key]['tag']=$tag; $this->colours[$matches[1]][$key]['bottom'] = unformat_number($matches[2], $this->kilo); $this->colours[$matches[1]][$key]['top'] = unformat_number($matches[3], $this->kilo); $this->colours[$matches[1]][$key]['special'] = 0; if(isset($matches[10]) && $matches[10] == 'none') { $this->colours[$matches[1]][$key]['red1'] = -1; $this->colours[$matches[1]][$key]['green1'] = -1; $this->colours[$matches[1]][$key]['blue1'] = -1; } else { $this->colours[$matches[1]][$key]['red1'] = (int)($matches[4]); $this->colours[$matches[1]][$key]['green1'] = (int)($matches[5]); $this->colours[$matches[1]][$key]['blue1'] = (int)($matches[6]); } // this is the second colour, if there is one if(isset($matches[7]) && $matches[7] != '') { $this->colours[$matches[1]][$key]['red2'] = (int) ($matches[7]); $this->colours[$matches[1]][$key]['green2'] = (int) ($matches[8]); $this->colours[$matches[1]][$key]['blue2'] = (int) ($matches[9]); } if(! isset($this->numscales[$matches[1]])) { $this->numscales[$matches[1]]=1; } else { $this->numscales[$matches[1]]++; } // we count if we've seen any default scale, otherwise, we have to add // one at the end. if($matches[1]=='DEFAULT') { $scalesseen++; } $linematched++; } if (preg_match("/^\s*KEYPOS\s+([A-Za-z][A-Za-z0-9_]*\s+)?(-?\d+)\s+(-?\d+)(.*)/i", $buffer, $matches)) { $whichkey = trim($matches[1]); if($whichkey == '') $whichkey = 'DEFAULT'; $this->keyx[$whichkey]=$matches[2]; $this->keyy[$whichkey]=$matches[3]; $extra=trim($matches[4]); if ($extra != '') $this->keytext[$whichkey] = $extra; if(!isset($this->keytext[$whichkey])) $this->keytext[$whichkey] = "DEFAULT TITLE"; if(!isset($this->keystyle[$whichkey])) $this->keystyle[$whichkey] = "classic"; $linematched++; } // truetype font definition (actually, we don't really check if it's truetype) - filename + size if (preg_match("/^\s*FONTDEFINE\s+(\d+)\s+(\S+)\s+(\d+)\s*$/i", $buffer, $matches)) { if (function_exists("imagettfbbox")) { // test if this font is valid, before adding it to the font table... $bounds=@imagettfbbox($matches[3], 0, $matches[2], "Ignore me"); if (isset($bounds[0])) { $this->fonts[$matches[1]] = new WMFont(); $this->fonts[$matches[1]]->type="truetype"; $this->fonts[$matches[1]]->file=$matches[2]; $this->fonts[$matches[1]]->size=$matches[3]; } else { wm_warn ("Failed to load ttf font " . $matches[2] . " - at config line $linecount [WMWARN30]"); } } else { wm_warn ("imagettfbbox() is not a defined function. You don't seem to have FreeType compiled into your gd module. [WMWARN31]\n"); } $linematched++; } // GD font definition (no size here) if (preg_match("/^\s*FONTDEFINE\s+(\d+)\s+(\S+)\s*$/i", $buffer, $matches)) { $newfont=imageloadfont($matches[2]); if ($newfont) { $this->fonts[$matches[1]] = new WMFont(); $this->fonts[$matches[1]]->type="gd"; $this->fonts[$matches[1]]->file=$matches[2]; $this->fonts[$matches[1]]->gdnumber=$newfont; } else { wm_warn ("Failed to load GD font: " . $matches[2] . " ($newfont) at config line $linecount [WMWARN32]\n"); } $linematched++; } if(preg_match("/^\s*KEYSTYLE\s+([A-Za-z][A-Za-z0-9_]+\s+)?(classic|horizontal|vertical|inverted|tags)\s?(\d+)?\s*$/i",$buffer, $matches)) { $whichkey = trim($matches[1]); if($whichkey == '') $whichkey = 'DEFAULT'; $this->keystyle[$whichkey] = strtolower($matches[2]); if(isset($matches[3]) && $matches[3] != '') { $this->keysize[$whichkey] = $matches[3]; } else { $this->keysize[$whichkey] = $this->keysize['DEFAULT']; } $linematched++; } if (preg_match("/^\s*KILO\s+(\d+)\s*$/i", $buffer, $matches)) { $this->kilo=$matches[1]; # $this->defaultlink->owner->kilo=$matches[1]; # $this->links['DEFAULT']=$matches[1]; $linematched++; } if (preg_match( "/^\s*(TIME|TITLE|KEYBG|KEYTEXT|KEYOUTLINE|BG)COLOR\s+(\d+)\s+(\d+)\s+(\d+)\s*$/i", $buffer, $matches)) { $key=$matches[1]; # "Found colour line for $key\n"; $this->colours['DEFAULT'][$key]['red1']=$matches[2]; $this->colours['DEFAULT'][$key]['green1']=$matches[3]; $this->colours['DEFAULT'][$key]['blue1']=$matches[4]; $this->colours['DEFAULT'][$key]['bottom']=-2; $this->colours['DEFAULT'][$key]['top']=-1; $this->colours['DEFAULT'][$key]['special']=1; $linematched++; } if (($last_seen == 'NODE') && (preg_match( "/^\s*(AICONOUTLINE|AICONFILL|LABELFONT|LABELFONTSHADOW|LABELBG|LABELOUTLINE)COLOR\s+((\d+)\s+(\d+)\s+(\d+)|none|contrast|copy)\s*$/i", $buffer, $matches))) { $key=$matches[1]; $field=strtolower($matches[1]) . 'colour'; $val = strtolower($matches[2]); if(isset($matches[3])) // this is a regular colour setting thing { $curnode->$field=array( $matches[3],$matches[4],$matches[5]); $linematched++; } if($val == 'none' && ($matches[1]=='LABELFONTSHADOW' || $matches[1]=='LABELBG' || $matches[1]=='LABELOUTLINE' || $matches[1]=='AICONOUTLINE')) { $curnode->$field=array(-1,-1,-1); $linematched++; } if($val == 'contrast' && $matches[1]=='LABELFONT') { $curnode->$field=array(-3,-3,-3); $linematched++; } if($matches[2] == 'copy' && $matches[1]=='AICONFILL') { $curnode->$field=array(-2,-2,-2); $linematched++; } } if (($last_seen == 'LINK') && (preg_match( "/^\s*(COMMENTFONT|BWBOX|BWFONT|BWOUTLINE|OUTLINE)COLOR\s+((\d+)\s+(\d+)\s+(\d+)|none|contrast|copy)\s*$/i", $buffer, $matches))) { $key=$matches[1]; $field=strtolower($matches[1]) . 'colour'; $val = strtolower($matches[2]); if(isset($matches[3])) // this is a regular colour setting thing { $curlink->$field=array( $matches[3],$matches[4],$matches[5]); $linematched++; } if($val == 'none' && ($key=='BWBOX' || $key=='BWOUTLINE' || $key=='OUTLINE')) { // print "***********************************\n"; $curlink->$field=array(-1,-1,-1); $linematched++; } if($val == 'contrast' && $key=='COMMENTFONT') { // print "***********************************\n"; $curlink->$field=array(-3,-3,-3); $linematched++; } } if ($last_seen == 'LINK' && preg_match( "/^\s*ARROWSTYLE\s+(\d+)\s+(\d+)\s*$/i", $buffer, $matches)) { $curlink->arrowstyle=$matches[1] . ' ' . $matches[2]; $linematched++; } if ($linematched == 0 && trim($buffer) != '') { wm_warn ("Unrecognised config on line $linecount: $buffer\n"); } if ($linematched > 1) { wm_warn ("Same line ($linecount) interpreted twice. This is a program error. Please report to Howie with your config!\nThe line was: $buffer"); } } // if blankline } // while if(1==1) { $this->ReadConfig_Commit($curobj); } else { if ($last_seen == "NODE") { $this->nodes[$curnode->name]=$curnode; wm_debug ("Saving Node: " . $curnode->name . "\n"); if($curnode->template == 'DEFAULT') $this->node_template_tree[ "DEFAULT" ][]= $curnode->name; } if ($last_seen == "LINK") { if (isset($curlink->a) && isset($curlink->b)) { $this->links[$curlink->name]=$curlink; wm_debug ("Saving Link: " . $curlink->name . "\n"); if($curlink->template == 'DEFAULT') $this->link_template_tree[ "DEFAULT" ][]= $curlink->name; } else { wm_warn ("Dropping LINK " . $curlink->name . " - it hasn't got 2 NODES!"); } } } wm_debug("ReadConfig has finished reading the config ($linecount lines)\n"); wm_debug("------------------------------------------\n"); // load some default colouring, otherwise it all goes wrong if ($scalesseen == 0) { wm_debug ("Adding default SCALE colour set (no SCALE lines seen).\n"); $defaults=array ( '0_0' => array('bottom' => 0, 'top' => 0, 'red1' => 192, 'green1' => 192, 'blue1' => 192, 'special'=>0), '0_1' => array('bottom' => 0, 'top' => 1, 'red1' => 255, 'green1' => 255, 'blue1' => 255, 'special'=>0), '1_10' => array('bottom' => 1, 'top' => 10, 'red1' => 140, 'green1' => 0, 'blue1' => 255, 'special'=>0), '10_25' => array('bottom' => 10, 'top' => 25, 'red1' => 32, 'green1' => 32, 'blue1' => 255, 'special'=>0), '25_40' => array('bottom' => 25, 'top' => 40, 'red1' => 0, 'green1' => 192, 'blue1' => 255, 'special'=>0), '40_55' => array('bottom' => 40, 'top' => 55, 'red1' => 0, 'green1' => 240, 'blue1' => 0, 'special'=>0), '55_70' => array('bottom' => 55, 'top' => 70, 'red1' => 240, 'green1' => 240, 'blue1' => 0, 'special'=>0), '70_85' => array('bottom' => 70, 'top' => 85, 'red1' => 255, 'green1' => 192, 'blue1' => 0, 'special'=>0), '85_100' => array('bottom' => 85, 'top' => 100, 'red1' => 255, 'green1' => 0, 'blue1' => 0, 'special'=>0) ); foreach ($defaults as $key => $def) { $this->colours['DEFAULT'][$key]=$def; $this->colours['DEFAULT'][$key]['key']=$key; $scalesseen++; } // we have a 0-0 line now, so we need to hide that. $this->add_hint("key_hidezero_DEFAULT",1); } else { wm_debug ("Already have $scalesseen scales, no defaults added.\n"); } $this->numscales['DEFAULT']=$scalesseen; $this->configfile="$filename"; if($this->has_overlibs && $this->htmlstyle == 'static') { wm_warn("OVERLIBGRAPH is used, but HTMLSTYLE is static. This is probably wrong. [WMWARN41]\n"); } wm_debug("Building cache of z-layers and finalising bandwidth.\n"); // $allitems = array_merge($this->links, $this->nodes); $allitems = array(); foreach ($this->nodes as $node) { $allitems[] = $node; } foreach ($this->links as $link) { $allitems[] = $link; } # foreach ($allitems as &$item) foreach ($allitems as $ky=>$vl) { $item =& $allitems[$ky]; $z = $item->zorder; if(!isset($this->seen_zlayers[$z]) || !is_array($this->seen_zlayers[$z])) { $this->seen_zlayers[$z]=array(); } array_push($this->seen_zlayers[$z], $item); // while we're looping through, let's set the real bandwidths if($item->my_type() == "LINK") { $this->links[$item->name]->max_bandwidth_in = unformat_number($item->max_bandwidth_in_cfg, $this->kilo); $this->links[$item->name]->max_bandwidth_out = unformat_number($item->max_bandwidth_out_cfg, $this->kilo); } elseif($item->my_type() == "NODE") { $this->nodes[$item->name]->max_bandwidth_in = unformat_number($item->max_bandwidth_in_cfg, $this->kilo); $this->nodes[$item->name]->max_bandwidth_out = unformat_number($item->max_bandwidth_out_cfg, $this->kilo); } else { wm_warn("Internal bug - found an item of type: ".$item->my_type()."\n"); } // $item->max_bandwidth_in=unformat_number($item->max_bandwidth_in_cfg, $this->kilo); // $item->max_bandwidth_out=unformat_number($item->max_bandwidth_out_cfg, $this->kilo); wm_debug (sprintf(" Setting bandwidth on ".$item->my_type()." $item->name (%s -> %d bps, %s -> %d bps, KILO = %d)\n", $item->max_bandwidth_in_cfg, $item->max_bandwidth_in, $item->max_bandwidth_out_cfg, $item->max_bandwidth_out, $this->kilo)); } wm_debug("Found ".sizeof($this->seen_zlayers)." z-layers including builtins (0,100).\n"); // calculate any relative positions here - that way, nothing else // really needs to know about them wm_debug("Resolving relative positions for NODEs...\n"); // safety net for cyclic dependencies $i=100; do { $skipped = 0; $set=0; foreach ($this->nodes as $node) { if( ($node->relative_to != '') && (!$node->relative_resolved)) { wm_debug("Resolving relative position for NODE ".$node->name." to ".$node->relative_to."\n"); if(array_key_exists($node->relative_to,$this->nodes)) { // check if we are relative to another node which is in turn relative to something // we need to resolve that one before we can resolve this one! if( ($this->nodes[$node->relative_to]->relative_to != '') && (!$this->nodes[$node->relative_to]->relative_resolved) ) { wm_debug("Skipping unresolved relative_to. Let's hope it's not a circular one\n"); $skipped++; } else { $rx = $this->nodes[$node->relative_to]->x; $ry = $this->nodes[$node->relative_to]->y; if($node->polar) { // treat this one as a POLAR relative coordinate. // - draw rings around a node! $angle = $node->x; $distance = $node->y; $newpos_x = $rx + $distance * sin(deg2rad($angle)); $newpos_y = $ry - $distance * cos(deg2rad($angle)); wm_debug("->$newpos_x,$newpos_y\n"); $this->nodes[$node->name]->x = $newpos_x; $this->nodes[$node->name]->y = $newpos_y; $this->nodes[$node->name]->relative_resolved=TRUE; $set++; } else { // save the relative coords, so that WriteConfig can work // resolve the relative stuff $newpos_x = $rx + $this->nodes[$node->name]->x; $newpos_y = $ry + $this->nodes[$node->name]->y; wm_debug("->$newpos_x,$newpos_y\n"); $this->nodes[$node->name]->x = $newpos_x; $this->nodes[$node->name]->y = $newpos_y; $this->nodes[$node->name]->relative_resolved=TRUE; $set++; } } } else { wm_warn("NODE ".$node->name." has a relative position to an unknown node! [WMWARN10]\n"); } } } wm_debug("Relative Positions Cycle $i - set $set and Skipped $skipped for unresolved dependencies\n"); $i--; } while( ($set>0) && ($i!=0) ); if($skipped>0) { wm_warn("There are Circular dependencies in relative POSITION lines for $skipped nodes. [WMWARN11]\n"); } wm_debug("-----------------------------------\n"); wm_debug("Running Pre-Processing Plugins...\n"); foreach ($this->preprocessclasses as $pre_class) { wm_debug("Running $pre_class"."->run()\n"); $this->plugins['pre'][$pre_class]->run($this); } wm_debug("Finished Pre-Processing Plugins...\n"); return (TRUE); }
$newaction = 'add_link2'; # print $newaction; $selected = 'NODE:'.$param2; break; case "add_link2": $map->ReadConfig($mapfile); $a = $_REQUEST['param2']; $b = $_REQUEST['param']; # $b = substr($b,0,-2); $log = "[$a -> $b]"; if($a != $b && isset($map->nodes[$a]) && isset($map->nodes[$b]) ) { $newlink = new WeatherMapLink; $newlink->Reset($map); $newlink->a = $map->nodes[$a]; $newlink->b = $map->nodes[$b]; // $newlink->SetBandwidth($map->defaultlink->max_bandwidth_in_cfg, $map->defaultlink->max_bandwidth_out_cfg); $newlink->width = $map->links['DEFAULT']->width; // make sure the link name is unique. We can have multiple links between // the same nodes, these days $newlinkname = "$a-$b"; while(array_key_exists($newlinkname,$map->links)) { $newlinkname .= "a";
function addLink($nodeName1, $nodeName2, $linkName = "", $template = "DEFAULT") { if (!$this->isLoaded()) { throw new WMException("Map must be loaded before editing API called."); } $success = false; $log = ""; $newLinkName = ""; // XXX - do we care if node1==node2? if ($nodeName1 != $nodeName2 && $this->map->nodeExists($nodeName1) && $this->map->nodeExists($nodeName2)) { $newLinkName = $linkName != "" ? $linkName : "{$nodeName1}-{$nodeName2}"; // make sure the link name is unique. We can have multiple links between // the same nodes, these days while (array_key_exists($newLinkName, $this->map->links)) { $newLinkName .= "a"; } $newLink = new WeatherMapLink($newLinkName, $template, $this->map); $newLink->defined_in = $this->map->configfile; $newLink->setEndNodes($this->map->getNode($nodeName1), $this->map->getNode($nodeName2)); $this->map->addLink($newLink); $success = true; $log = "created link {$newLinkName} between {$nodeName1} and {$nodeName2}"; } return array($newLinkName, $success, $log); }