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