File: 1.17.2a/server/base/freenats.inc.php (View as Code)

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