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: