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