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