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