File: 1.14.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.14.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: $smtpsec=$this->Cfg->Get("mail.smtpsecure",""); 283: $mail=new PHPMailer(); 284: $mail->IsSMTP(); 285: $mail->Host=$smtpserver; 286: $mail->From=$row['efrom']; 287: $mail->FromName=$fromname; 288: $mail->AddAddress($toaddr); 289: $mail->Subject=$sub; 290: $mail->Body=$body; 291: $mail->WordWrap=50; 292: if ($smtphostname!="") $mail->Hostname=$smtphostname; 293: if ($smtpauth) 294: { 295: $mail->SMTPAuth=true; 296: $mail->Username=$smtpusername; 297: $mail->Password=$smtppassword; 298: } 299: if ($smtpsec!="") $mail->SMTPSecure=$smtpsec; 300: if (!$mail->Send()) 301: { // failed 302: $this->Event("phpMailer to ".$toaddr." failed",1,"Flush","Email"); 303: $this->Event("phpMailer Error: ".$mail->ErrorInfo,1,"Flush","Email"); 304: } 305: else 306: { 307: $this->Event("phpMailer Sent Email To ".$toaddr,4,"Flush","Email"); 308: } 309: } 310: 311: } 312: } 313: 314: 315: 316: } 317: else if ($row['atype']=="url") 318: { 319: // url send 320: if ($row['etype']==0) $body=$row['mdata']; 321: else $body="FreeNATS Alert,\r\n".$row['mdata']."\r\n--FreeNATS @ ".nicedt(time()); 322: 323: $body=urlencode($body); 324: $tolist=array(); 325: $f=0; 326: $tolist[0]=""; 327: for ($a=0; $a328: { 329: $chr=$row['etolist'][$a]; 330: //echo $chr; 331: if (strpos($allowed,$chr)===false) // special char 332: { 333: $f++; 334: $tolist[$f]=""; 335: } 336: else 337: { 338: $tolist[$f].=$chr; 339: } 340: } 341: 342: foreach($tolist as $tourl) 343: { 344: if ($doalert) 345: { 346: $url=$tourl.$body; 347: $fp=@fopen($url,"r"); 348: if ($fp>0) fclose($fp); 349: else $this->Event("URL Alert Failed ".$url,1,"Flush","URL"); 350: $this->Event("URL Alert ".$url,4,"Flush","URL"); 351: } 352: } 353: 354: 355: } 356: else if ($row['atype']=="mqueue") 357: { 358: // message queue 359: $eventdata=array("aaid"=>$row['aaid'],"name"=>$row['aname'],"data"=>$row['mdata']); 360: $result=$this->EventHandler("alert_action",$eventdata); 361: if ($result===false) // put the data back into the queue 362: { 363: $q="UPDATE fnalertaction SET mdata=\"".$row['mdata']."\"+mdata WHERE aaid=".$row['aaid']; 364: $this->DB->Query($q); 365: if ($this->DB->Affected_Rows()<=0) 366: $this->Event("Persist MDATA Failed for AAID ".$row['aaid'],2,"Flush","MQueue"); 367: } 368: else $this->Event("Queue Cleared for AAID ".$row['aaid']." by Handler",4,"Flush","MQueue"); 369: } 370: 371: } 372: } 373: 374: function GetAlerts() 375: { 376: $q="SELECT nodeid,alertlevel FROM fnalert WHERE closedx=0"; 377: $r=$this->DB->Query($q); 378: $c=0; 379: $al=array(); 380: while ($row=$this->DB->Fetch_Array($r)) 381: { 382: $al[$c]['nodeid']=$row['nodeid']; 383: $al[$c]['alertlevel']=$row['alertlevel']; 384: $c++; 385: } 386: if ($c>0) return $al; 387: else return false; 388: } 389: 390: function SetAlerts($nodeid,$alertlevel,$alerts="") 391: { 392: if ($alerts=="") $alerts=array(); 393: // get current alert level 394: $q="SELECT alertlevel,nodealert FROM fnnode WHERE nodeid=\"".ss($nodeid)."\""; 395: $r=$this->DB->Query($q); 396: $row=$this->DB->Fetch_Array($r); 397: $this->DB->Free($r); 398: $cal=$row['alertlevel']; 399: 400: $eventdata=array("nodeid"=>$nodeid,"alertlevel"=>$alertlevel, 401: "oldalertlevel"=>$cal); 402: $this->EventHandler("set_alerts",$eventdata); 403: 404: if ($alertlevel!=$cal) 405: { 406: // update table 407: $q="UPDATE fnnode SET alertlevel=".ss($alertlevel)." WHERE nodeid=\"".ss($nodeid)."\""; 408: $this->DB->Query($q); 409: } 410: 411: // do not continue if node alert isn't set 412: if ($row['nodealert']!=1) return 0; 413: // or if untested 414: if ($alertlevel<0) return 0; 415: 416: // ALERTS 417: // is there an existing alert for this node 418: $q="SELECT alertid,alertlevel FROM fnalert WHERE nodeid=\"".ss($nodeid)."\" AND closedx=0"; 419: $r=$this->DB->Query($q); 420: if ($row=$this->DB->Fetch_Array($r)) 421: { // yes there is 422: // if new alert level is 0 let's close it 423: if ($alertlevel==0) 424: { 425: $alertid=$row['alertid']; 426: $q="UPDATE fnalert SET closedx=".time()." WHERE alertid=".$row['alertid']; 427: $this->DB->Query($q); 428: $closetext=$this->Cfg->Get("site.text.closed","Alert Closed"); 429: if (is_array($alerts)) $alerts[]=$closetext; 430: else 431: { 432: $alerts=array($alerts); // add as first element to new array 433: $alerts[]=$closetext; 434: } 435: $eventdata=array("nodeid"=>$nodeid); 436: $this->EventHandler("alert_close",$eventdata); 437: } 438: else 439: { 440: $alertid=$row['alertid']; 441: // otherwise update the alert to the new value (was: regardless, now just if not a 0) 442: $q="UPDATE fnalert SET alertlevel=".ss($alertlevel)." WHERE alertid=".$alertid; 443: $this->DB->Query($q); 444: } 445: } 446: else 447: { // no there's not 448: $cal=0; // the cal (current alert level) goes to zero if it's a new alert so alert_actions fire ok 449: if ($alertlevel>0) // only if an actual alert 450: { 451: $q="INSERT INTO fnalert(nodeid,alertlevel,openedx) VALUES("; 452: $q.="\"".ss($nodeid)."\",".ss($alertlevel).",".time().")"; 453: $this->DB->Query($q); 454: $alertid=$this->DB->Insert_Id(); 455: $eventdata=array("nodeid"=>$nodeid); 456: $this->EventHandler("alert_open",$eventdata); 457: } 458: } 459: // ALERT LOG with $alertid 460: $t=time(); 461: $at=""; 462: if (is_array($alerts)) 463: { 464: foreach($alerts as $alert) 465: { 466: if (isset($alertid)) // misses on manual runs methinx 467: { 468: if ($at!="") $at.=", "; 469: $at.=$alert; 470: //echo $at."\n"; 471: $iq="INSERT INTO fnalertlog(alertid,postedx,logentry) VALUES("; 472: $iq.=$alertid.",".$t.",\"".ss($alert)."\")"; 473: //echo $iq; 474: $this->DB->Query($iq); 475: } 476: } 477: } 478: 479: $this->AlertAction($nodeid,$alertlevel,$alertlevel-$cal,$at); 480: 481: 482: 483: } 484: 485: function NodeAlertLevel($nodeid) 486: { 487: $q="SELECT alertlevel FROM fnnode WHERE nodeid=\"".ss($nodeid)."\""; 488: $r=$this->DB->Query($q); 489: if ($row=$this->DB->Fetch_Array($r)) return $row['alertlevel']; 490: else return -1; 491: } 492: 493: function GroupAlertLevel($groupid) 494: { 495: $lvl=-1; 496: $q="SELECT nodeid FROM fngrouplink WHERE groupid=\"".ss($groupid)."\""; 497: $r=$this->DB->Query($q); 498: while ($row=$this->DB->Fetch_Array($r)) 499: { 500: $nl=$this->NodeAlertLevel($row['nodeid']); 501: if ($nl>$lvl) $lvl=$nl; 502: } 503: $this->DB->Free($r); 504: return $lvl; 505: } 506: 507: function PhoneHome($mode=0,$type="ping") // 0 - php, 1 - html, 2 - data 508: { 509: if ($mode<2) 510: { 511: $qs="?type=".$type."&data=v=".$this->Version; 512: if (isset($_SERVER['REMOTE_ADDR'])) 513: $qs.=",ip=".$_SERVER['REMOTE_ADDR']; 514: $ploc="http://www.purplepixie.org/freenats/report/"; 515: if ($mode==1) $ploc.="ping.html"; 516: else $ploc.="ping.php"; 517: 518: $ploc.=$qs; 519: 520: $lp=@fopen($ploc,"r"); 521: if ($lp>0) @fclose($lp); 522: } 523: else 524: { 525: // data post -- !! 526: } 527: } 528: 529: function GetNode($nodeid) 530: { 531: $return_row=false; 532: $q="SELECT * FROM fnnode WHERE nodeid=\"".ss($nodeid)."\" LIMIT 0,1"; 533: $r=$this->DB->Query($q); 534: if ($row=$this->DB->Fetch_Array($r)) 535: $return_row=true; 536: 537: $this->DB->Free($r); 538: if ($return_row) // found a valid 539: { 540: if ($row['nodename']!="") $row['name']=$row['nodename']; // make a "nice" name for it 541: else $row['name']=$row['nodeid']; 542: 543: $row['alerttext']=oText($row['alertlevel']); // textual alert status 544: 545: $row['lastrundt']=nicedt($row['lastrunx']); // text date-time last run 546: $row['lastrunago']=dtago($row['lastrunx'],false); // last run ago 547: 548: // protection 549: $row['nskey']=""; 550: 551: return $row; 552: } 553: else 554: return false; // or failed 555: } 556: 557: function GetNodes() 558: { 559: $out=array(); 560: $q="SELECT * FROM fnnode"; 561: $r=$this->DB->Query($q); 562: 563: while ($row=$this->DB->Fetch_Array($r)) 564: { 565: if ($row['nodename']!="") $row['name']=$row['nodename']; // make a "nice" name for it 566: else $row['name']=$row['nodeid']; 567: 568: $row['alerttext']=oText($row['alertlevel']); // textual alert status 569: 570: $row['lastrundt']=nicedt($row['lastrunx']); // text date-time last run 571: $row['lastrunago']=dtago($row['lastrunx'],false); // last run ago 572: 573: // protection 574: $row['nskey']=""; 575: 576: $out[$row['nodeid']]=$row; 577: } 578: $this->DB->Free($r); 579: 580: return $out; 581: } 582: 583: 584: function GetNodeTests($nodeid) 585: { // returns an array of testids for the node (enabled tests only) 586: $tests=array(); 587: 588: // local tests 589: $q="SELECT localtestid FROM fnlocaltest WHERE testenabled=1 AND nodeid=\"".ss($nodeid)."\" ORDER BY localtestid ASC"; 590: $r=$this->DB->Query($q); 591: while ($row=$this->DB->Fetch_Array($r)) 592: { 593: $tests[]="L".$row['localtestid']; 594: } 595: $this->DB->Free($r); 596: 597: // nodeside 598: $q="SELECT nstestid FROM fnnstest WHERE testenabled=1 AND nodeid=\"".ss($nodeid)."\" ORDER BY testtype ASC"; 599: $r=$this->DB->Query($q); 600: while ($row=$this->DB->Fetch_Array($r)) 601: { 602: $tests[]="N".$row['nstestid']; 603: } 604: $this->DB->Free($r); 605: 606: return $tests; 607: } 608: 609: function SetNode($nodeid,$data) 610: { 611: $q="UPDATE fnnode SET "; 612: $first=true; 613: foreach($data as $key => $val) 614: { 615: if ($first) $first=false; 616: else $q.=","; 617: $q.=ss($key)."=\"".ss($val)."\""; 618: } 619: $q.=" WHERE nodeid=\"".ss($nodeid)."\""; 620: $this->DB->Query($q); 621: if ($this->DB->Affected_Rows()>0) return true; 622: 623: if ($this->DB->Error()) // query failed 624: { 625: $errstr1="Query Failed: ".$q; 626: $errstr2="Query Failed: ".$this->DB->Error_String(); 627: $this->Event($errstr1,2,"Node","Set"); 628: $this->Event($errstr1,2,"Node","Set"); 629: return false; 630: } 631: return true; // query succeeded but nothing was updated 632: } 633: 634: function EnableNode($nodeid,$enabled=true) 635: { 636: if ($enabled) $ne=1; 637: else $ne=0; 638: $data=array("nodeenabled"=>$ne); 639: return $this->SetNode($nodeid,$data); 640: } 641: 642: function DisableNode($nodeid) 643: { 644: return $this->EnableNode($nodeid,false); 645: } 646: 647: function SetNodeSchedule($nodeid,$scheduleid) 648: { 649: $data=array("scheduleid"=>$scheduleid); 650: return $this->SetNode($nodeid,$data); 651: } 652: 653: function GetGroup($groupid) 654: { 655: $q="SELECT * FROM fngroup WHERE groupid=".ss($groupid)." LIMIT 0,1"; 656: $r=$this->DB->Query($q); 657: if (!$row=$this->DB->Fetch_Array($r)) return false; 658: 659: $this->DB->Free($r); 660: $row['alertlevel']=$this->GroupAlertLevel($groupid); 661: $row['alerttext']=oText($row['alertlevel']); 662: return $row; 663: } 664: 665: function GetGroups() 666: { 667: $out=array(); 668: $q="SELECT * FROM fngroup"; 669: $r=$this->DB->Query($q); 670: 671: while ($row=$this->DB->Fetch_Array($r)) 672: { 673: $row['alertlevel']=$this->GroupAlertLevel($row['groupid']); 674: $row['alerttext']=oText($row['alertlevel']); 675: $out[$row['groupid']]=$row; 676: } 677: 678: $this->DB->Free($r); 679: return $out; 680: } 681: 682: function GetTest($testid,$protect=false) 683: { 684: if ($testid=="") return false; 685: $class=$testid[0]; 686: if (is_numeric($class)) 687: { 688: // test ID will stay the same 689: $class="L"; 690: $anytestid=$testid; 691: } 692: else 693: { 694: //$testid=substr($testid,1); // as it will here also so direct use to graphs can be made 695: $anytestid=substr($testid,1); // the classless version 696: } 697: 698: $q=""; 699: switch($class) 700: { 701: case "L": // local tests 702: $q="SELECT * FROM fnlocaltest WHERE localtestid=".ss($anytestid)." LIMIT 0,1"; 703: break; 704: case "N": // node-side test 705: $q="SELECT * FROM fnnstest WHERE nstestid=".ss($anytestid)." LIMIT 0,1"; 706: break; 707: default: 708: return false; // can't lookup this class 709: } 710: 711: if ($q=="") return false; 712: 713: $r=$this->DB->Query($q); 714: 715: if (!$row=$this->DB->Fetch_Array($r)) return false; 716: 717: $row['class']=$class; 718: $row['testid']=$testid; 719: $row['anytestid']=$anytestid; 720: $row['alerttext']=oText($row['alertlevel']); 721: $row['lastrundt']=nicedt($row['lastrunx']); 722: $row['lastrunago']=dtago($row['lastrunx'],false); 723: 724: if ($row['testname']!="") $row['name']=$row['testname']; 725: else 726: { 727: if ($class=="L") 728: { 729: $row['name']=lText($row['testtype']); // TODO OTHER TESTS 730: if ($row['testparam']!="") $row['name'].=" (".$row['testparam'].")"; 731: } 732: else if ($class=="N") 733: { 734: if ($row['testdesc']!="") $row['name']=$row['testdesc']; 735: else $row['name']=$row['testtype']; 736: } 737: } 738: 739: if ($protect&&($class=="L")) // module test protection 740: { 741: if ($this->Tests->Exists($row['testtype'])) // in the module register 742: { 743: $this->Tests->Tests[$row['testtype']]->Create(); 744: $this->Tests->Tests[$row['testtype']]->instance->ProtectOutput($row); 745: } 746: } 747: 748: $this->DB->Free($r); 749: 750: return $row; 751: } 752: 753: 754: function DeleteTest($testid) 755: { 756: if ($testid=="") return false; 757: $class=$testid[0]; 758: if (is_numeric($class)) 759: { 760: // test ID will stay the same 761: $class="L"; 762: $anytestid=$testid; 763: } 764: else 765: { 766: $anytestid=substr($testid,1); // the classless version 767: } 768: 769: $q=""; 770: switch($class) 771: { 772: case "L": // local tests 773: $q="DELETE FROM fnlocaltest WHERE localtestid=".ss($anytestid); 774: break; 775: case "N": // node-side test 776: $q="DELETE FROM fnnstest WHERE nstestid=".ss($anytestid); 777: break; 778: default: 779: return false; // can't lookup this class 780: } 781: 782: if ($q=="") return false; 783: 784: $this->DB->Query($q); 785: $tests=$this->DB->Affected_Rows(); 786: 787: $rq="DELETE FROM fnrecord WHERE testid=\"".ss($testid)."\""; 788: $this->DB->Query($rq); 789: $records=$this->DB->Affected_Rows(); 790: 791: $eq="DELETE FROM fneval WHERE testid=\"".ss($testid)."\""; 792: $this->DB->Query($eq); 793: $eval=$this->DB->Affected_Rows(); 794: 795: $s="Deleted test ".$testid." (".$tests." tests, ".$records." records, ".$eval." evaluators)"; 796: $this->Event($s,6,"Test","Delete"); 797: } 798: 799: 800: 801: function InvalidateTest($testid,$rightnow=false) 802: { 803: $class=$testid[0]; 804: if (is_numeric($class)) $class="L"; 805: else $testid=substr($testid,1); 806: if ($rightnow) 807: { 808: $nextx=time(); 809: $q="UPDATE "; 810: if ($class=="L") $q.="fnlocaltest"; 811: // other ones here 812: 813: $q.=" SET nextrunx=".$nextx." WHERE "; 814: 815: if ($class=="L") $q.="localtestid=".$testid; 816: // other ones here 817: 818: $this->DB->Query($q); 819: return true; 820: } 821: // otherwise use it's interval 822: $q="SELECT testinterval FROM "; 823: 824: if ($class=="L") $q.="fnlocaltest WHERE localtestid="; 825: // other ones here 826: 827: $q.=$testid; 828: $r=$this->DB->Query($q); 829: if ($row=$this->DB->Fetch_Array($r)) 830: { 831: $this->DB->Free($r); 832: $nextx=next_run_x($row['testinterval']); 833: $q="UPDATE "; 834: if ($class=="L") $q.="fnlocaltest"; 835: // other ones here 836: 837: $q.=" SET nextrunx=".$nextx." WHERE "; 838: 839: if ($class=="L") $q.="localtestid=".$testid; 840: // other ones here 841: 842: $this->DB->Query($q); 843: return true; 844: } 845: return false; 846: } 847: 848: function InvalidateNode($nodeid,$rightnow=false,$testsaswell=false) 849: { 850: if ($rightnow) 851: { 852: $nextx=time(); 853: $q="UPDATE fnnode SET nextrunx=".$nextx." WHERE nodeid=\"".ss($nodeid)."\""; 854: $this->DB->Query($q); 855: if ($testsaswell) 856: { 857: $q="UPDATE fnlocaltest SET nextrunx=".$nextx." WHERE nodeid=\"".ss($nodeid)."\""; 858: $this->DB->Query($q); 859: } 860: return true; 861: } 862: // otherwise set to it's interval 863: $q="SELECT testinterval FROM fnnode WHERE nodeid=\"".ss($nodeid)."\""; 864: $r=$this->DB->Query($q); 865: if ($row=$this->DB->Fetch_Array($r)) 866: { 867: $nextx=next_run_x($row['testinterval']); 868: $uq="UPDATE fnnode SET nextrunx=".$nextx." WHERE nodeid=\"".ss($nodeid)."\""; 869: $this->DB->Query($uq); 870: $this->DB->Free($r); 871: if ($testsaswell) 872: { 873: $uq="UPDATE fnlocaltest SET nextrunx=".$nextx." WHERE nodeid=\"".ss($nodeid)."\""; 874: $this->DB->Query($uq); 875: } 876: return true; 877: } 878: return false; 879: } 880: 881: 882: function NodeSide_Pull($nodeid) 883: { 884: $eventdata=array("nodeid"=>$nodeid,"success"=>false); 885: $q="SELECT nsenabled,nspullenabled,nsurl,nskey,nsinterval FROM fnnode WHERE nodeid=\"".ss($nodeid)."\" LIMIT 0,1"; 886: $r=$this->DB->Query($q); 887: if (!$row=$this->DB->Fetch_Array($r)) return false; 888: 889: $this->DB->Free($r); 890: 891: $url=$row['nsurl']; 892: if ($row['nskey']!="") $url.="?nodekey=".$row['nskey']; 893: //echo $url."\n"; 894: $this->Event("NodeSide_Pull Started for ".$nodeid,10,"Node","Pull"); 895: 896: $xmlobj=new TNodeXML(); 897: 898: $fp=@fopen($url,"r"); 899: if ($fp<=0) 900: { 901: $this->Event("Pull Failed URL ".$url,1,"Node","Pull"); 902: $this->EventHandler("nodeside_pull",$eventdata); 903: return false; 904: } 905: $xml=""; 906: while (!feof($fp)) 907: { 908: $xml.=fgets($fp,4096); 909: } 910: if ($xml=="") 911: { 912: $this->EventHandler("nodeside_pull",$eventdata); 913: return false; 914: } 915: 916: //echo $xml; 917: 918: $result=$xmlobj->Parse($xml); 919: 920: if ($xmlobj->Error()!="") 921: { 922: $this->Event("NodeXML Error: ".$xmlobj->Error(),1,"Node","Pull"); 923: $this->EventHandler("nodeside_pull",$eventdata); 924: return false; 925: } 926: $this->Event("NodeSide_Pull Fetched ".$xmlobj->Tests." tests for ".$nodeid,10,"Node","Pull"); 927: // Now just to actually process it... 928: $eventdata['success']=true; 929: $this->EventHandler("nodeside_pull",$eventdata); 930: $this->NodeSide_Process($nodeid,$xmlobj); 931: return true; 932: } 933: 934: function NodeSide_Process($nodeid,&$xmlobj) 935: { // nodeid + takes a TNodeXML Object 936: $alvl=0; 937: $this->Event("NodeSide_Process for ".$nodeid,10,"Node","Pull"); 938: $q="SELECT * FROM fnnstest WHERE nodeid=\"".ss($nodeid)."\""; 939: $r=$this->DB->Query($q); 940: $tests=array(); 941: while ($row=$this->DB->Fetch_Array($r)) 942: { 943: $tests[$row['testtype']]=$row; 944: if (isset($xmlobj->Catalogue[$row['testtype']])) 945: { // this test is in the DB and catalogue 946: $tests[$row['testtype']]['incat']=true; 947: if ($row['testenabled']==1) // it is enabled - so we test it 948: { 949: if ($row['simpleeval']==1) $level=$xmlobj->Catalogue[$row['testtype']]['ALERTLEVEL']; // use provided level 950: else $level=nats_eval("N".$row['nstestid'],$xmlobj->Catalogue[$row['testtype']]['VALUE']); 951: $dbs="Nodeside ".$row['testtype']." on ".$row['nodeid']." = ".$level; 952: if ($level==0) $debuglev=8; 953: else if ($level>0) $debuglev=5; 954: else $debuglev=2; 955: $this->Event($dbs,$debuglev,"Node","Process"); 956: 957: if ($level>$alvl) $alvl=$level; 958: 959: if ($row['testrecord']==1) // record it 960: { 961: $testvalue=$xmlobj->Catalogue[$row['testtype']]['VALUE']; 962: $testvalue=str_replace(",",".",$testvalue); 963: if (!is_numeric($testvalue)) $testvalue=0; 964: $iq="INSERT INTO fnrecord(testid,alertlevel,recordx,nodeid,testvalue) VALUES("; 965: $iq.="\"N".$row['nstestid']."\",".$level.",".time().",\"".$row['nodeid']."\",".$testvalue.")"; 966: $this->DB->Query($iq); 967: if ($this->DB->Affected_Rows()<=0) 968: $this->Event("Nodeside ".$row['testtype']." Failed to Record",1,"Node","Process"); 969: } 970: 971: // We don't do any alerting here - the tester will do that for us! 972: $uq="UPDATE fnnstest SET lastrunx=".time().",lastvalue=\"".ss($xmlobj->Catalogue[$row['testtype']]['VALUE'])."\",alertlevel=".$level." "; 973: $uq.="WHERE nstestid=".$row['nstestid']; 974: $this->DB->Query($uq); 975: if ($this->DB->Affected_Rows()<=0) 976: $this->Event("Nodeside ".$row['testtype']." Failed to Update or Same Values",5,"Node","Process"); 977: 978: } 979: 980: // check to see if the desc has changed 981: if ($row['testdesc']!=$xmlobj->Catalogue[$row['testtype']]['DESC']) 982: { 983: $duq="UPDATE fnnstest SET testdesc=\"".ss($xmlobj->Catalogue[$row['testtype']]['DESC'])."\" WHERE nstestid=".$row['nstestid']; 984: $this->DB->Query($duq); 985: } 986: 987: } 988: else 989: { 990: // test in the DB but NOT in the catalogue 991: //$xmlobj->Catalogue[$row['testtype']]['incat']=false; 992: if ($row['testenabled']==1) 993: { // enabled so shown in lists etc 994: // Update it to show failed status 995: $this->Event("No nodeside data for test N".$row['nstestid'],3,"Node","Process"); 996: $uq="UPDATE fnnstest SET alertlevel=2,lastvalue=-1 WHERE nstestid=".$row['nstestid']; 997: $this->DB->Query($uq); 998: $alvl=2; 999: if ($row['testrecord']==1) // record it 1000: { 1001: $testvalue=-1; 1002: $iq="INSERT INTO fnrecord(testid,alertlevel,recordx,nodeid,testvalue) VALUES("; 1003: $iq.="\"N".$row['nstestid']."\",2,".time().",\"".$row['nodeid']."\",".$testvalue.")"; 1004: $this->DB->Query($iq); 1005: if ($this->DB->Affected_Rows()<=0) 1006: $this->Event("Nodeside ".$row['testtype']." Failed to Record",1,"Node","Process"); 1007: } 1008: } 1009: else // not enabled so simply delete 1010: { 1011: $this->DeleteTest("N".$row['nstestid']); 1012: } 1013: } 1014: } 1015: $this->DB->Free($r); 1016: 1017: 1018: // and finally we look for new tests i.e. in the cat but not in the DB 1019: foreach($xmlobj->Catalogue as $val) 1020: { 1021: $key=$val['NAME']; 1022: if (!isset($tests[$key])) // not in the DB 1023: { 1024: $q="INSERT INTO fnnstest(nodeid,testtype,testdesc,lastvalue,lastrunx,alertlevel) "; 1025: $q.="VALUES(\"".ss($nodeid)."\",\"".$key."\",\"".ss($val['DESC'])."\",\"".ss($val['VALUE'])."\",".time().",".ss($val['ALERTLEVEL']).")"; 1026: //echo $q."
";
1027: $this->DB->Query($q); 1028: } 1029: } 1030: 1031: $eventdata=array("nodeid"=>$nodeid,"alertlevel"=>$alvl); 1032: $this->EventHandler("nodeside_process",$eventdata); 1033: 1034: 1035: } 1036: 1037: 1038: function AddEventHandler($event,$function) 1039: { 1040: if (!isset($this->EventHandlers[$event])) $this->EventHandlers[$event]=array(); 1041: $this->EventHandlers[$event][]=$function; 1042: } 1043: 1044: function EventHandler($event,$data) 1045: { 1046: $res=false; 1047: if ( isset($data) && is_array($data) ) $data['event']=$event; 1048: 1049: if (isset($this->EventHandlers[$event])) // handler(s) exist 1050: { 1051: for($a=0; $aEventHandlers[$event]); $a++) 1052: { 1053: if (function_exists($this->EventHandlers[$event][$a])) 1054: { 1055: $this->Event("Event ".$event." -> ".$this->EventHandlers[$event][$a],6,"Event","Handler"); 1056: if($this->EventHandlers[$event][$a]($data)) $res=true; // persist true only 1057: } 1058: else 1059: { 1060: $t="Illegal Handler ".$this->EventHandlers[$event][$a]." for ".$event; 1061: $this->Event($t,2,"Event","Handler"); 1062: //return false; 1063: } 1064: } 1065: } 1066: else return $res; 1067: } 1068: 1069: function StripGPC($data) 1070: { 1071: if (get_magic_quotes_gpc()) return stripslashes($data); 1072: else return $data; 1073: } 1074: 1075: function PageError($code,$desc) 1076: { 1077: $this->PageErrors[]=array( "code" => $code, "desc" => $desc ); 1078: } 1079: 1080: } 1081: ?> 1082: