File: 1.00.3a/server/base/freenats.inc.php (View as HTML)

  1: <?php // freenats.inc.php
  2: /* -------------------------------------------------------------
  3: This file is part of FreeNATS
  4: 
  5: FreeNATS is (C) Copyright 2008 PurplePixie Systems
  6: 
  7: FreeNATS is free software: you can redistribute it and/or modify
  8: it under the terms of the GNU General Public License as published by
  9: the Free Software Foundation, either version 3 of the License, or
 10: (at your option) any later version.
 11: 
 12: FreeNATS is distributed in the hope that it will be useful,
 13: but WITHOUT ANY WARRANTY; without even the implied warranty of
 14: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 15: GNU General Public License for more details.
 16: 
 17: You should have received a copy of the GNU General Public License
 18: along with FreeNATS.  If not, see www.gnu.org/licenses
 19: 
 20: For more information see www.purplepixie.org/freenats
 21: -------------------------------------------------------------- */
 22: 
 23: class TFreeNATS
 24: {
 25: var $init=false;
 26: var $DB;
 27: var $Cfg;
 28: var $Tests;
 29: var $Version="1.00.3";
 30: var $Release="a";
 31: var $EventHandlers=array();
 32: 
 33: function TFreeNATS()
 34: 	{
 35: 	$this->Tests=new TNATS_Tests(); // need this available during the include phase pre-start
 36: 	}
 37: 
 38: function Start()
 39: 	{
 40: 	global $BaseDir;
 41: 	if ( (!isset($BaseDir)) || ($BaseDir=="") ) $BaseDir="./";
 42: 	$this->DB=new TNATS_DB();
 43: 	$this->Cfg=new TNATS_Cfg();
 44: 	$this->DB->Connect();
 45: 	$this->Cfg->Load($this->DB);
 46: 	// Site Includes
 47: 	// Tests
 48: 	if ($this->Cfg->Get("site.include.tests",0)==1)
 49: 		{
 50: 		foreach(glob($BaseDir."site/tests/*.php") as $phpfile)
 51: 			{
 52: 			$this->Event("Including ".$phpfile,10,"NATS","Start");
 53: 			include_once($phpfile);
 54: 			}
 55: 		}
 56: 	// Events
 57: 	if ($this->Cfg->Get("site.include.events",0)==1)
 58: 		{
 59: 		foreach(glob($BaseDir."site/events/*.php") as $phpfile)
 60: 			{
 61: 			$this->Event("Including ".$phpfile,10,"NATS","Start");
 62: 			include_once($phpfile);
 63: 			}
 64: 		}
 65: 	$this->init=true;
 66: 	}
 67: 	
 68: function Stop()
 69: 	{
 70: 	$this->DB->Disconnect();
 71: 	$this->init=false;
 72: 	}	
 73: 	
 74: function Event($logevent,$loglevel=1,$modid="NONE",$catid="NONE")
 75: 	{
 76: 	global $NATS_Session;
 77: 	if ((isset($NATS_Session))&&($NATS_Session->auth)) $username=$NATS_Session->username;
 78: 	else $username="";
 79: 	$l=$this->Cfg->Get("log.level");
 80: 	//echo "** $l **\n";
 81: 	if ( $l=="" ) $l=10; // debug logging if no variable
 82: 	if ( $l < $loglevel ) return false;
 83: 	if (strlen($logevent)>249) $logevent=substr($logevent,0,245)."...";
 84: 	$q="INSERT INTO fnlog(postedx,modid,catid,loglevel,logevent,username) VALUES(".time().",";
 85: 	$q.="\"".ss($modid)."\",\"".ss($catid)."\",".ss($loglevel).",\"".ss($logevent)."\",\"".ss($username)."\")";
 86: 	//echo $q;
 87: 	$this->DB->Query($q,false);
 88: 	}
 89: 
 90: function AlertAction($nodeid,$alertlevel,$change,$alerttext)
 91: 	{
 92: 	echo "Called for node: ".$nodeid."\n";
 93: 	if ($change==0) return false;
 94: 	//echo $nodeid.":".$alertlevel.":".$change.":".$alerttext."\n";
 95: 	// get all the alertactions for this node id
 96: 	$q="SELECT aaid FROM fnnalink WHERE nodeid=\"".ss($nodeid)."\"";
 97: 	$r=$this->DB->Query($q);
 98: 	while ($arow=$this->DB->Fetch_Array($r))
 99: 		{
100: 		// get details for this alert action
101: 		$aq="SELECT * FROM fnalertaction WHERE aaid=".$arow['aaid']." LIMIT 0,1";
102: 		//echo $aq."\n";
103: 		$ar=$this->DB->Query($aq);
104: 		$aa=$this->DB->Fetch_Array($ar);
105: 		$this->DB->Free($ar);
106: 		//echo $aa['atype']."FISH\n";
107: 		
108: 		// UGGGGGGGG continue!!
109: 		if ( ($aa['atype']=="") || ($aa['atype']=="Disabled") ) continue;
110: 		if ( ($aa['awarnings']==0) && ($alertlevel<2) ) continue;
111: 		if ( ($aa['adecrease']==0) && ($change<1) ) continue;
112: 		
113: 		// made it this far
114: 		if ($aa['mdata']!="") $ndata=$aa['mdata']."\n".$nodeid.": ".$alerttext;
115: 		else $ndata=$nodeid.": ".$alerttext;
116: 		$uq="UPDATE fnalertaction SET mdata=\"".ss($ndata)."\" WHERE aaid=".$arow['aaid'];
117: 		//echo $uq."\n";
118: 		$this->DB->Query($uq);
119: 		}
120: 	}
121: 	
122: function ActionFlush()
123: 	{
124: 	global $allowed,$BaseDir; // allowed chars from screen in YA BODGE
125: 	$q="SELECT * FROM fnalertaction WHERE mdata!=\"\"";
126: 	$r=$this->DB->Query($q);
127: 	while ($row=$this->DB->Fetch_Array($r))
128: 		{
129: 			
130: 			$doalert=true;
131: 			
132: 		// clear mdata right at the start to get around duplicate emails whilst processing
133: 			$q="UPDATE fnalertaction SET mdata=\"\" WHERE aaid=".$row['aaid'];
134: 			$this->DB->Query($q);
135: 			
136: 			if ($this->DB->Affected_Rows()<=0) // already flushed or failed to flush
137: 				{
138: 				$doalert=false;
139: 				$this->Event("Alert Action Already Flushed - Skipping",8,"Flush","Action");
140: 				}
141: 			
142: 		// alert counter
143: 		$td=date("Ymd");
144: 		if ($td!=$row['ctrdate']) // new day or no flush record
145: 			{
146: 			$q="UPDATE fnalertaction SET ctrdate=\"".$td."\",ctrtoday=1 WHERE aaid=".$row['aaid'];
147: 			$this->DB->Query($q);
148: 			}
149: 		else
150: 			{
151: 			
152: 				if ( ($row['ctrlimit']==0) || ($row['ctrlimit']>$row['ctrtoday']) ) // no limit or below
153: 					{
154: 					$q="UPDATE fnalertaction SET ctrtoday=ctrtoday+1 WHERE aaid=".$row['aaid'];
155: 					$this->DB->Query($q);
156: 					}
157: 				else // at or over limit
158: 					{
159: 					$this->Event("Alert Action Limit Reached - Skipping",2,"Flush","Action");
160: 					$doalert=false;
161: 					}
162: 			
163: 			}
164: 			
165: 			
166: 		if ($row['atype']=="email")
167: 			{
168: 			if ($row['esubject']==0) $sub="";
169: 			else if ($row['esubject']==1) $sub="FreeNATS Alert";
170: 			else $sub="** FreeNATS Alert **";
171: 			$body="";
172: 			if ($row['etype']==0) $body=$row['mdata'];
173: 			else $body="FreeNATS Alert,\r\n".$row['mdata']."\r\n--FreeNATS @ ".nicedt(time());
174: 			//$tolist=preg_split("[\n\r]",$row['etolist']);
175: 			$tolist=array();
176: 			$f=0;
177: 			$tolist[0]="";
178: 			for ($a=0; $a<strlen($row['etolist']); $a++)
179: 				{
180: 				$chr=$row['etolist'][$a];
181: 				//echo $chr;
182: 				if (strpos($allowed,$chr)===false) // special char
183: 					{
184: 					$f++;
185: 					$tolist[$f]="";
186: 					}
187: 				else
188: 					{
189: 					$tolist[$f].=$chr;
190: 					}
191: 				}
192: 			
193: 			foreach($tolist as $toaddr)
194: 				{
195: 				$toaddr=nices($toaddr);
196: 				if ($toaddr!="")
197: 					{
198: 					$smtpserver=$this->Cfg->Get("mail.smtpserver","");
199: 					if ($smtpserver=="")
200: 						{
201: 						// mail() method - local delivery
202: 						$header="From: ".$row['efrom']."\r\n";
203: 						if ($doalert)
204: 							{
205: 							mail($toaddr,$sub,$body,$header);
206: 							$this->Event("Sent alert email to ".$toaddr,4,"Flush","Email");
207: 							}		
208: 						}
209: 					else // use phpmailer direct SMTP delivery
210: 						{
211: 						include_once($BaseDir."phpmailer/class.phpmailer.php");
212: 						$fromname=$this->Cfg->Get("mail.fromname","FreeNATS");
213: 						$smtpusername=$this->Cfg->Get("mail.smtp.username","");
214: 						if ($smtpusername!="") $smtpauth=true;
215: 						else $smtpauth=false;
216: 						$smtppassword=$this->Cfg->Get("mail.smtp.password","");
217: 						$smtphostname=$this->Cfg->Get("mail.smtp.hostname","");
218: 						$mail=new PHPMailer();
219: 						$mail->IsSMTP();
220: 						$mail->Host=$smtpserver;
221: 						$mail->From=$row['efrom'];
222: 						$mail->FromName=$fromname;
223: 						$mail->AddAddress($toaddr);
224: 						$mail->Subject=$sub;
225: 						$mail->Body=$body;
226: 						$mail->WordWrap=50;
227: 						if ($smtphostname!="") $mail->Hostname=$smtphostname;
228: 						if ($smtpauth)
229: 							{
230: 							$mail->SMTPAuth=true;
231: 							$mail->Username=$smtpusername;
232: 							$mail->Password=$smtppassword;
233: 							}
234: 						if (!$mail->Send())
235: 							{ // failed
236: 							$this->Event("phpMailer to ".$toaddr." failed",1,"Flush","Email");
237: 							$this->Event("phpMailer Error: ".$mail->ErrorInfo,1,"Flush","Email");
238: 							}
239: 						else
240: 							{
241: 							$this->Event("phpMailer Sent Email To ".$toaddr,4,"Flush","Email");
242: 							}
243: 						}
244: 						
245: 					}
246: 				}
247: 				
248: 				
249: 				
250: 			}
251: 		else if ($row['atype']=="url")
252: 			{
253: 			// url send
254: 			if ($row['etype']==0) $body=$row['mdata'];
255: 			else $body="FreeNATS Alert,\r\n".$row['mdata']."\r\n--FreeNATS @ ".nicedt(time());
256: 			
257: 			$body=urlencode($body);
258: 			$tolist=array();
259: 			$f=0;
260: 			$tolist[0]="";
261: 			for ($a=0; $a<strlen($row['etolist']); $a++)
262: 				{
263: 				$chr=$row['etolist'][$a];
264: 				//echo $chr;
265: 				if (strpos($allowed,$chr)===false) // special char
266: 					{
267: 					$f++;
268: 					$tolist[$f]="";
269: 					}
270: 				else
271: 					{
272: 					$tolist[$f].=$chr;
273: 					}
274: 				}
275: 			
276: 			foreach($tolist as $tourl)
277: 				{
278: 				if ($doalert)
279: 					{
280: 					$url=$tourl.$body;
281: 					$fp=@fopen($url,"r");
282: 					if ($fp>0) fclose($fp);
283: 					else $this->Event("URL Alert Failed ".$url,1,"Flush","URL");
284: 					$this->Event("URL Alert ".$url,4,"Flush","URL");
285: 					}
286: 				}
287: 			
288: 			
289: 			}
290: 		else if ($row['atype']=="mqueue")
291: 			{
292: 			// message queue
293: 			$eventdata=array("aaid"=>$row['aaid'],"name"=>$row['aname'],"data"=>$row['mdata']);
294: 			$result=$this->EventHandler("alert_action",$eventdata);
295: 			if ($result===false) // put the data back into the queue
296: 				{
297: 				$q="UPDATE fnalertaction SET mdata=\"".$row['mdata']."\"+mdata WHERE aaid=".$row['aaid'];
298: 				$this->DB->Query($q);
299: 				if ($this->DB->Affected_Rows()<=0)
300: 					$this->Event("Persist MDATA Failed for AAID ".$row['aaid'],2,"Flush","MQueue");
301: 				}
302: 			else $this->Event("Queue Cleared for AAID ".$row['aaid']." by Handler",4,"Flush","MQueue");
303: 			}
304: 			
305: 		}
306: 	}	
307: 
308: function GetAlerts()
309: 	{
310: 	$q="SELECT nodeid,alertlevel FROM fnalert WHERE closedx=0";
311: 	$r=$this->DB->Query($q);
312: 	$c=0;
313: 	$al=array();
314: 	while ($row=$this->DB->Fetch_Array($r))
315: 		{
316: 		$al[$c]['nodeid']=$row['nodeid'];
317: 		$al[$c]['alertlevel']=$row['alertlevel'];
318: 		$c++;
319: 		}
320: 	if ($c>0) return $al;
321: 	else return false;
322: 	}
323: 	
324: function SetAlerts($nodeid,$alertlevel,$alerts="")
325: 	{
326: 	if ($alerts=="") $alerts=array();
327: 	// get current alert level
328: 	$q="SELECT alertlevel,nodealert FROM fnnode WHERE nodeid=\"".ss($nodeid)."\"";
329: 	$r=$this->DB->Query($q);
330: 	$row=$this->DB->Fetch_Array($r);
331: 	$this->DB->Free($r);
332: 	$cal=$row['alertlevel'];
333: 	
334: 	$eventdata=array("nodeid"=>$nodeid,"alertlevel"=>$alertlevel,
335: 		"oldalertlevel"=>$cal);
336: 	$this->EventHandler("set_alerts",$eventdata);
337: 		
338: 	if ($alertlevel!=$cal)
339: 		{
340: 		// update table
341: 		$q="UPDATE fnnode SET alertlevel=".ss($alertlevel)." WHERE nodeid=\"".ss($nodeid)."\"";
342: 		$this->DB->Query($q);
343: 		}
344: 		
345: 	// do not continue if node alert isn't set
346: 	if ($row['nodealert']!=1) return 0;
347: 		
348: 	// ALERTS
349: 	// is there an existing alert for this node
350: 	$q="SELECT alertid,alertlevel FROM fnalert WHERE nodeid=\"".ss($nodeid)."\" AND closedx=0";
351: 	$r=$this->DB->Query($q);
352: 	if ($row=$this->DB->Fetch_Array($r))
353: 		{ // yes there is
354: 		// if new alert level is 0 let's close it
355: 		if ($alertlevel==0)
356: 			{
357: 			$alertid=$row['alertid'];
358: 			$q="UPDATE fnalert SET closedx=".time()." WHERE alertid=".$row['alertid'];
359: 			$this->DB->Query($q);
360: 			if (is_array($alerts)) $alerts[]="Alert Closed";
361: 			else
362: 				{
363: 				//$alerts=array();
364: 				$alerts[]="Alert Closed";
365: 				}
366: 			$eventdata=array("nodeid"=>$nodeid);
367: 			$this->EventHandler("alert_close",$eventdata);
368: 			}
369: 		else
370: 			{
371: 			$alertid=$row['alertid'];
372: 			// otherwise update the alert to the new value (was: regardless, now just if not a 0)
373: 			$q="UPDATE fnalert SET alertlevel=".ss($alertlevel)." WHERE alertid=".$alertid;
374: 			$this->DB->Query($q);
375: 			}
376: 		}
377: 	else
378: 		{ // no there's not
379: 		if ($alertlevel>0) // only if an actual alert
380: 			{
381: 			$q="INSERT INTO fnalert(nodeid,alertlevel,openedx) VALUES(";
382: 			$q.="\"".ss($nodeid)."\",".ss($alertlevel).",".time().")";
383: 			$this->DB->Query($q);
384: 			$alertid=$this->DB->Insert_Id();
385: 			$eventdata=array("nodeid"=>$nodeid);
386: 			$this->EventHandler("alert_open",$eventdata);
387: 			}
388: 		}
389: 	// ALERT LOG with $alertid
390: 	$t=time();
391: 	$at="";
392: 	if (is_array($alerts))
393: 		{
394: 		foreach($alerts as $alert)
395: 			{
396: 			if (isset($alertid)) // misses on manual runs methinx
397: 				{
398: 				if ($at!="") $at.=", ";
399: 				$at.=$alert;
400: 				//echo $at."\n";
401: 				$iq="INSERT INTO fnalertlog(alertid,postedx,logentry) VALUES(";
402: 				$iq.=$alertid.",".$t.",\"".ss($alert)."\")";
403: 				//echo $iq;
404: 				$this->DB->Query($iq);
405: 				}
406: 			}
407: 		}
408: 		
409: 	$this->AlertAction($nodeid,$alertlevel,$alertlevel-$cal,$at);
410: 	
411: 		
412: 		
413: 	}
414: 
415: function NodeAlertLevel($nodeid)
416: 	{
417: 	$q="SELECT alertlevel FROM fnnode WHERE nodeid=\"".ss($nodeid)."\"";
418: 	$r=$this->DB->Query($q);
419: 	if ($row=$this->DB->Fetch_Array($r)) return $row['alertlevel'];
420: 	else return -1;
421: 	}	
422: 
423: function GroupAlertLevel($groupid)
424: 	{
425: 	$lvl=-1;
426: 	$q="SELECT nodeid FROM fngrouplink WHERE groupid=\"".ss($groupid)."\"";
427: 	$r=$this->DB->Query($q);
428: 	while ($row=$this->DB->Fetch_Array($r))
429: 		{
430: 		$nl=$this->NodeAlertLevel($row['nodeid']);
431: 		if ($nl>$lvl) $lvl=$nl;
432: 		}
433: 	$this->DB->Free($r);
434: 	return $lvl;
435: 	}
436: 	
437: function PhoneHome($mode=0,$type="ping") // 0 - php, 1 - html, 2 - data
438: {
439: if ($mode<2)
440: 	{
441: 	$qs="?type=".$type."&data=version=".$this->Version;
442: 	if (isset($_SERVER['REMOTE_ADDR']))
443: 		$qs.=",ip=".$_SERVER['REMOTE_ADDR'];
444: 	$ploc="http://www.purplepixie.org/freenats/report/";
445: 	if ($mode==1) $ploc.="ping.html";
446: 	else $ploc.="ping.php";
447: 	
448: 	$ploc.=$qs;
449: 	
450: 	$lp=@fopen($ploc,"r");
451: 	if ($lp>0) @fclose($lp);
452: 	}
453: else
454: 	{
455: 	// data post -- !!
456: 	}
457: }
458: 
459: function GetNode($nodeid)
460: 	{
461: 	$return_row=false;
462: 	$q="SELECT * FROM fnnode WHERE nodeid=\"".ss($nodeid)."\" LIMIT 0,1";
463: 	$r=$this->DB->Query($q);
464: 	if ($row=$this->DB->Fetch_Array($r))
465: 		$return_row=true;
466: 		
467: 	$this->DB->Free($r);
468: 	if ($return_row) // found a valid
469: 		{
470: 		if ($row['nodename']!="") $row['name']=$row['nodename']; // make a "nice" name for it
471: 		else $row['name']=$row['nodeid'];
472: 		
473: 		$row['alerttext']=oText($row['alertlevel']); // textual alert status
474: 		
475: 		$row['lastrundt']=nicedt($row['lastrunx']); // text date-time last run
476: 		$row['lastrunago']=dtago($row['lastrunx'],false); // last run ago
477: 		
478: 		// protection
479: 		$row['nskey']="";
480: 		
481: 		return $row;
482: 		}
483: 	else
484: 		return false; // or failed
485: 	}
486: 	
487: function SetNode($nodeid,$data)
488: 	{
489: 	$q="UPDATE fnnode SET ";
490: 	$first=true;
491: 	foreach($data as $key => $val)
492: 		{
493: 		if ($first) $first=false;
494: 		else $q.=",";
495: 		$q.=ss($key)."=\"".ss($val)."\"";
496: 		}
497: 	$q.=" WHERE nodeid=\"".ss($nodeid)."\"";
498: 	$this->DB->Query($q);
499: 	if ($this->DB->Affected_Rows()>0) return true;
500: 	
501: 	if ($this->DB->Error()) // query failed
502: 		{
503: 		$errstr1="Query Failed: ".$q;
504: 		$errstr2="Query Failed: ".$this->DB->Error_String();
505: 		$this->Event($errstr1,2,"Node","Set");
506: 		$this->Event($errstr1,2,"Node","Set");
507: 		return false;
508: 		}
509: 	return true; // query succeeded but nothing was updated
510: 	}
511: 	
512: function EnableNode($nodeid,$enabled=true)
513: 	{
514: 	if ($enabled) $ne=1;
515: 	else $ne=0;
516: 	$data=array("nodeenabled"=>$ne);
517: 	return $this->SetNode($nodeid,$data);
518: 	}
519: 	
520: function DisableNode($nodeid)
521: 	{
522: 	return $this->EnableNode($nodeid,false);
523: 	}
524: 	
525: function SetNodeSchedule($nodeid,$scheduleid)
526: 	{
527: 	$data=array("scheduleid"=>$scheduleid);
528: 	return $this->SetNode($nodeid,$data);
529: 	}
530: 	
531: function GetGroup($groupid)
532: 	{
533: 	$q="SELECT * FROM fngroup WHERE groupid=".ss($groupid)." LIMIT 0,1";
534: 	$r=$this->DB->Query($q);
535: 	if (!$row=$this->DB->Fetch_Array($r)) return false;
536: 	
537: 	$this->DB->Free($r);
538: 	$row['alertlevel']=$this->GroupAlertLevel($groupid);
539: 	$row['alerttext']=oText($row['alertlevel']);
540: 	return $row;
541: 	}
542: 	
543: function GetTest($testid,$protect=false)
544: 	{
545: 	if ($testid=="") return false;
546: 	$class=$testid[0];
547: 	if (is_numeric($class))
548: 		{
549: 		// test ID will stay the same
550: 		$class="L";
551: 		$anytestid=$testid;
552: 		}
553: 	else
554: 		{
555: 		//$testid=substr($testid,1); // as it will here also so direct use to graphs can be made
556: 		$anytestid=substr($testid,1); // the classless version
557: 		}
558: 		
559: 	$q="";
560: 	switch($class)
561: 		{
562: 		case "L": // local tests 
563: 			$q="SELECT * FROM fnlocaltest WHERE localtestid=".ss($anytestid)." LIMIT 0,1";
564: 			break;
565: 		case "N": // node-side test
566: 			$q="SELECT * FROM fnnstest WHERE nstestid=".ss($anytestid)." LIMIT 0,1";
567: 			break;
568: 		default:
569: 			return false; // can't lookup this class
570: 		}
571: 		
572: 	if ($q=="") return false;
573: 	
574: 	$r=$this->DB->Query($q);
575: 	
576: 	if (!$row=$this->DB->Fetch_Array($r)) return false;
577: 	
578: 	$row['class']=$class;
579: 	$row['testid']=$testid;
580: 	$row['anytestid']=$anytestid;
581: 	$row['alerttext']=oText($row['alertlevel']);
582: 	$row['lastrundt']=nicedt($row['lastrunx']);
583: 	$row['lastrunago']=dtago($row['lastrunx'],false);
584: 	
585: 	if  ($row['testname']!="")  $row['name']=$row['testname'];
586: 	else
587: 			{
588: 			if ($class=="L")
589: 				{
590: 				$row['name']=lText($row['testtype']); // TODO OTHER TESTS
591: 				if ($row['testparam']!="") $row['name'].=" (".$row['testparam'].")";
592: 				}
593: 			else if ($class=="N")
594: 				{
595: 				if ($row['testdesc']!="") $row['name']=$row['testdesc'];
596: 				else $row['name']=$row['testtype'];
597: 				}
598: 			}
599: 			
600: 	if ($protect&&($class=="L")) // module test protection
601: 		{
602: 		if ($this->Tests->Exists($row['testtype'])) // in the module register
603: 			{
604: 			$this->Tests->Tests[$row['testtype']]->Create();
605: 			$this->Tests->Tests[$row['testtype']]->instance->ProtectOutput($row);
606: 			}
607: 		}
608: 	
609: 	$this->DB->Free($r);
610: 	
611: 	return $row;
612: 	}
613: 
614: 	
615: function DeleteTest($testid)
616: 	{
617: 	if ($testid=="") return false;
618: 	$class=$testid[0];
619: 	if (is_numeric($class))
620: 		{
621: 		// test ID will stay the same
622: 		$class="L";
623: 		$anytestid=$testid;
624: 		}
625: 	else
626: 		{
627: 		$anytestid=substr($testid,1); // the classless version
628: 		}
629: 		
630: 	$q="";
631: 	switch($class)
632: 		{
633: 		case "L": // local tests 
634: 			$q="DELETE FROM fnlocaltest WHERE localtestid=".ss($anytestid);
635: 			break;
636: 		case "N": // node-side test
637: 			$q="DELETE FROM fnnstest WHERE nstestid=".ss($anytestid);
638: 			break;
639: 		default:
640: 			return false; // can't lookup this class
641: 		}
642: 		
643: 	if ($q=="") return false;
644: 	
645: 	$this->DB->Query($q);
646: 	$tests=$this->DB->Affected_Rows();
647: 	
648: 	$rq="DELETE FROM fnrecord WHERE testid=\"".ss($testid)."\"";
649: 	$this->DB->Query($rq);
650: 	$records=$this->DB->Affected_Rows();
651: 	
652: 	$eq="DELETE FROM fneval WHERE testid=\"".ss($testid)."\"";
653: 	$this->DB->Query($eq);
654: 	$eval=$this->DB->Affected_Rows();
655: 	
656: 	$s="Deleted test ".$testid." (".$tests." tests, ".$records." records, ".$eval." evaluators)";
657: 	$this->Event($s,6,"Test","Delete");
658: 	}
659: 	
660: 	
661: 	
662: function InvalidateTest($testid,$rightnow=false)
663: 	{
664: 	$class=$testid[0];
665: 	if (is_numeric($class)) $class="L";
666: 	else $testid=substr($testid,1);
667: 	if ($rightnow)
668: 		{
669: 		$nextx=time();
670: 		$q="UPDATE ";
671: 		if ($class=="L") $q.="fnlocaltest";
672: 		// other ones here
673: 		
674: 		$q.=" SET nextrunx=".$nextx." WHERE ";
675: 		
676: 		if ($class=="L") $q.="localtestid=".$testid;
677: 		// other ones here
678: 		
679: 		$this->DB->Query($q);
680: 		return true;
681: 		}
682: 	// otherwise use it's interval
683: 	$q="SELECT testinterval FROM ";
684: 	
685: 	if ($class=="L") $q.="fnlocaltest WHERE localtestid=";
686: 	// other ones here
687: 	
688: 	$q.=$testid;
689: 	$r=$this->DB->Query($q);
690: 	if ($row=$this->DB->Fetch_Array($r))
691: 		{
692: 		$this->DB->Free($r);
693: 		$nextx=next_run_x($row['testinterval']);
694: 		$q="UPDATE ";
695: 		if ($class=="L") $q.="fnlocaltest";
696: 		// other ones here
697: 		
698: 		$q.=" SET nextrunx=".$nextx." WHERE ";
699: 		
700: 		if ($class=="L") $q.="localtestid=".$testid;
701: 		// other ones here
702: 		
703: 		$this->DB->Query($q);
704: 		return true;
705: 		}
706: 	return false;
707: 	}		
708: 	
709: function InvalidateNode($nodeid,$rightnow=false,$testsaswell=false)
710: 	{
711: 	if ($rightnow)
712: 		{
713: 		$nextx=time();
714: 		$q="UPDATE fnnode SET nextrunx=".$nextx." WHERE nodeid=\"".ss($nodeid)."\"";
715: 		$this->DB->Query($q);
716: 		if ($testsaswell)
717: 			{
718: 			$q="UPDATE fnlocaltest SET nextrunx=".$nextx." WHERE nodeid=\"".ss($nodeid)."\"";
719: 			$this->DB->Query($q);
720: 			}
721: 		return true;
722: 		}
723: 	// otherwise set to it's interval
724: 	$q="SELECT testinterval FROM fnnode WHERE nodeid=\"".ss($nodeid)."\"";
725: 	$r=$this->DB->Query($q);
726: 	if ($row=$this->DB->Fetch_Array($r))
727: 		{
728: 		$nextx=next_run_x($row['testinterval']);
729: 		$uq="UPDATE fnnode SET nextrunx=".$nextx." WHERE nodeid=\"".ss($nodeid)."\"";
730: 		$this->DB->Query($uq);
731: 		$this->DB->Free($r);
732: 		if ($testsaswell)
733: 			{
734: 			$uq="UPDATE fnlocaltest SET nextrunx=".$nextx." WHERE nodeid=\"".ss($nodeid)."\"";
735: 			$this->DB->Query($uq);
736: 			}
737: 		return true;
738: 		}
739: 	return false;
740: 	}
741: 	
742: 	
743: function NodeSide_Pull($nodeid)
744: 	{
745: 	$eventdata=array("nodeid"=>$nodeid,"success"=>false);
746: 	$q="SELECT nsenabled,nspullenabled,nsurl,nskey,nsinterval FROM fnnode WHERE nodeid=\"".ss($nodeid)."\" LIMIT 0,1";
747: 	$r=$this->DB->Query($q);
748: 	if (!$row=$this->DB->Fetch_Array($r)) return false;
749: 	
750: 	$this->DB->Free($r);
751: 	
752: 	$url=$row['nsurl'];
753: 	if ($row['nskey']!="") $url.="?nodekey=".$row['nskey'];
754: 	$this->Event("NodeSide_Pull Started for ".$nodeid,10,"Node","Pull");
755: 	
756: 	$xmlobj=new TNodeXML();
757: 	
758: 	$fp=@fopen($url,"r");
759: 	if ($fp<=0)
760: 		{
761: 		$this->Event("Pull Failed URL ".$url,1,"Node","Pull");
762: 		$this->EventHandler("nodeside_pull",$eventdata);
763: 		return false;
764: 		}
765: 	$xml="";
766: 	while (!feof($fp))
767: 		{
768: 		$xml.=fgets($fp,4096);
769: 		}
770: 	if ($xml=="")
771: 		{
772: 		$this->EventHandler("nodeside_pull",$eventdata);
773: 		return false;
774: 		}
775: 	
776: 	//echo $xml;
777: 	
778: 	$result=$xmlobj->Parse($xml);
779: 	
780: 	if ($xmlobj->Error()!="")
781: 		{
782: 		$this->Event("NodeXML Error: ".$xmlobj->Error(),1,"Node","Pull");
783: 		$this->EventHandler("nodeside_pull",$eventdata);
784: 		return false;
785: 		}
786: 	$this->Event("NodeSide_Pull Fetched ".$xmlobj->Tests." tests for ".$nodeid,10,"Node","Pull");
787: 	// Now just to actually process it...
788: 	$eventdata['success']=true;
789: 	$this->EventHandler("nodeside_pull",$eventdata);
790: 	$this->NodeSide_Process($nodeid,$xmlobj);
791: 	return true;
792: 	}	
793: 	
794: function NodeSide_Process($nodeid,&$xmlobj)
795: 	{ // nodeid + takes a TNodeXML Object
796: 	$alvl=0;
797: 	$this->Event("NodeSide_Process for ".$nodeid,10,"Node","Pull");
798: 	$q="SELECT * FROM fnnstest WHERE nodeid=\"".ss($nodeid)."\"";
799: 	$r=$this->DB->Query($q);
800: 	$tests=array();
801: 	while ($row=$this->DB->Fetch_Array($r))
802: 		{
803: 		$tests[$row['testtype']]=$row;
804: 		if (isset($xmlobj->Catalogue[$row['testtype']]))
805: 			{ // this test is in the DB and catalogue
806: 			$tests[$row['testtype']]['incat']=true;
807: 			if ($row['testenabled']==1) // it is enabled - so we test it
808: 				{
809: 				if ($row['simpleeval']==1) $level=$xmlobj->Catalogue[$row['testtype']]['ALERTLEVEL']; // use provided level
810: 				else $level=nats_eval("N".$row['nstestid'],$xmlobj->Catalogue[$row['testtype']]['VALUE']);
811: 				$dbs="Nodeside ".$row['testtype']." on ".$row['nodeid']." = ".$level;
812: 				if ($level==0) $debuglev=8;
813: 				else if ($level>0) $debuglev=5;
814: 				else $debuglev=2;
815: 				$this->Event($dbs,$debuglev,"Node","Process");
816: 				
817: 				if ($level>$alvl) $alvl=$level;
818: 				
819: 				if ($row['testrecord']==1) // record it
820: 					{
821: 					$testvalue=$xmlobj->Catalogue[$row['testtype']]['VALUE'];
822: 					if (!is_numeric($testvalue)) $testvalue=0;
823: 					$iq="INSERT INTO fnrecord(testid,alertlevel,recordx,nodeid,testvalue) VALUES(";
824: 					$iq.="\"N".$row['nstestid']."\",".$level.",".time().",\"".$row['nodeid']."\",".$testvalue.")";
825: 					$this->DB->Query($iq);
826: 					if ($this->DB->Affected_Rows()<=0)
827: 						$this->Event("Nodeside ".$row['testtype']." Failed to Record",1,"Node","Process");
828: 					}
829: 					
830: 				// We don't do any alerting here - the tester will do that for us!
831: 				$uq="UPDATE fnnstest SET lastrunx=".time().",lastvalue=\"".ss($xmlobj->Catalogue[$row['testtype']]['VALUE'])."\",alertlevel=".$level." ";
832: 				$uq.="WHERE nstestid=".$row['nstestid'];
833: 				$this->DB->Query($uq);
834: 				if ($this->DB->Affected_Rows()<=0)
835: 						$this->Event("Nodeside ".$row['testtype']." Failed to Update or Same Values",5,"Node","Process");
836: 				
837: 				}
838: 					
839: 			// check to see if the desc has changed
840: 			if ($row['testdesc']!=$xmlobj->Catalogue[$row['testtype']]['DESC'])
841: 				{
842: 				$duq="UPDATE fnnstest SET testdesc=\"".ss($xmlobj->Catalogue[$row['testtype']]['DESC'])."\" WHERE nstestid=".$row['nstestid'];
843: 				$this->DB->Query($duq);
844: 				}
845: 				
846: 			}
847: 		else
848: 			{
849: 			// test in the DB but NOT in the catalogue
850: 			//$xmlobj->Catalogue[$row['testtype']]['incat']=false;
851: 			if ($row['testenabled']==1)
852: 				{ // enabled so shown in lists etc
853: 				// Update it to show failed status
854: 				$this->Event("No nodeside data for test N".$row['nstestid'],3,"Node","Process");
855: 				$uq="UPDATE fnnstest SET alertlevel=2,lastvalue=-1 WHERE nstestid=".$row['nstestid'];
856: 				$this->DB->Query($uq);
857: 				$alvl=2;
858: 				}
859: 			else // not enabled so simply delete
860: 				{
861: 				$this->DeleteTest("N".$row['nstestid']);
862: 				}
863: 			}
864: 		}
865: 	$this->DB->Free($r);
866: 	
867: 	
868: 	// and finally we look for new tests i.e. in the cat but not in the DB
869: 	foreach($xmlobj->Catalogue as $val)
870: 		{
871: 		$key=$val['NAME'];
872: 		if (!isset($tests[$key])) // not in the DB
873: 			{
874: 			$q="INSERT INTO fnnstest(nodeid,testtype,testdesc,lastvalue,lastrunx,alertlevel) ";
875: 			$q.="VALUES(\"".ss($nodeid)."\",\"".$key."\",\"".ss($val['DESC'])."\",\"".ss($val['VALUE'])."\",".time().",".ss($val['ALERTLEVEL']).")";
876: 			//echo $q."<br>";
877: 			$this->DB->Query($q);
878: 			}
879: 		}
880: 		
881: 	$eventdata=array("nodeid"=>$nodeid,"alertlevel"=>$alvl);
882: 	$this->EventHandler("nodeside_process",$eventdata);
883: 	
884: 	
885: 	}
886: 	
887: 	
888: function AddEventHandler($event,$function)
889: {
890: 	if (!isset($this->EventHandlers[$event])) $this->EventHandlers[$event]=array();
891: 	$this->EventHandlers[$event][]=$function;
892: }
893: 
894: function EventHandler($event,$data)
895: {
896: 	if ( isset($data) && is_array($data) ) $data['event']=$event;
897: 	
898: 	if (isset($this->EventHandlers[$event])) // handler(s) exist
899: 	{
900: 	for($a=0; $a<count($this->EventHandlers[$event]); $a++)
901: 		{
902: 		if (function_exists($this->EventHandlers[$event][$a]))
903: 			{
904: 			$this->Event("Event ".$event." -> ".$this->EventHandlers[$event][$a],6,"Event","Handler");
905: 			return $this->EventHandlers[$event][$a]($data);
906: 			}
907: 		else
908: 			{
909: 			$t="Illegal Handler ".$this->EventHandlers[$event][$a]." for ".$event;
910: 			$this->Event($t,2,"Event","Handler");
911: 			return false;
912: 			}
913: 		}
914: 	}
915: 	else return false;
916: }
917: 	
918: }
919: ?>