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