File:
1.11.0a/server/base/freenats.inc.php (
View as Code)
1: 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; $a238: {
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; $a322: {
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."
";
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; $aEventHandlers[$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: