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