2016-08-28 20:53:52 +00:00
< ? php
/*
* Copyright ( C ) 2014 < singh @ devilcode . org >
* Modified and Relicensed by < f0o @ devilcode . org > under the expressed
* permission by the Copyright - Holder < singh @ devilcode . org >.
*
* This program is free software : you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation , either version 3 of the License , or
* ( at your option ) any later version .
*
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
*
* You should have received a copy of the GNU General Public License
2021-02-08 23:29:04 +00:00
* along with this program . If not , see < https :// www . gnu . org / licenses />.
2016-08-28 20:53:52 +00:00
* */
namespace LibreNMS ;
2023-08-28 05:13:40 +00:00
use App\Models\Device ;
use App\Models\Eventlog ;
use App\Models\Port ;
use App\Models\Service ;
use App\Models\User ;
2018-08-17 20:29:20 +00:00
use LibreNMS\DB\Eloquent ;
2020-05-24 02:14:36 +00:00
use LibreNMS\Enum\AlertState ;
2023-10-04 15:17:34 +00:00
use LibreNMS\Util\Mail ;
2021-03-28 22:25:30 +00:00
use LibreNMS\Util\Number ;
use LibreNMS\Util\Time ;
2022-10-02 05:41:56 +00:00
use LibreNMS\Util\Version ;
2017-04-06 21:02:37 +00:00
2016-08-28 22:32:55 +00:00
class IRCBot
{
2021-03-31 15:29:22 +00:00
private $config ;
private $user ;
2020-09-22 12:30:54 +00:00
private $last_activity = 0 ;
2016-08-28 20:53:52 +00:00
private $data = '' ;
private $authd = [];
private $debug = false ;
private $server = '' ;
private $port = '' ;
private $ssl = false ;
private $pass = '' ;
private $nick = 'LibreNMS' ;
2020-09-22 12:30:54 +00:00
private $tempnick = null ;
2016-08-28 20:53:52 +00:00
private $chan = [];
private $commands = [
'auth' ,
'quit' ,
'listdevices' ,
'device' ,
'port' ,
'down' ,
'version' ,
'status' ,
'log' ,
'help' ,
'reload' ,
'join' ,
];
2020-09-22 12:30:54 +00:00
private $command = '' ;
2016-08-28 20:53:52 +00:00
private $external = [];
private $tick = 62500 ;
2020-09-22 12:30:54 +00:00
private $j = 0 ;
private $socket = [];
private $floodcount = 0 ;
2021-03-31 15:29:22 +00:00
private $max_retry = 5 ;
private $nickwait ;
private $buff ;
private $tokens ;
2016-08-28 22:32:55 +00:00
public function __construct ()
{
2016-08-28 20:53:52 +00:00
$this -> log ( 'Setting up IRC-Bot..' );
2019-06-23 05:29:12 +00:00
$this -> config = Config :: getAll ();
2016-08-28 20:53:52 +00:00
$this -> debug = $this -> config [ 'irc_debug' ];
$this -> config [ 'irc_authtime' ] = $this -> config [ 'irc_authtime' ] ? $this -> config [ 'irc_authtime' ] : 3 ;
$this -> max_retry = $this -> config [ 'irc_maxretry' ];
$this -> server = $this -> config [ 'irc_host' ];
if ( $this -> config [ 'irc_port' ][ 0 ] == '+' ) {
$this -> ssl = true ;
$this -> port = substr ( $this -> config [ 'irc_port' ], 1 );
2016-08-28 22:32:55 +00:00
} else {
2016-08-28 20:53:52 +00:00
$this -> port = $this -> config [ 'irc_port' ];
}
if ( $this -> config [ 'irc_nick' ]) {
$this -> nick = $this -> config [ 'irc_nick' ];
}
if ( $this -> config [ 'irc_alert_chan' ]) {
if ( strstr ( $this -> config [ 'irc_alert_chan' ], ',' )) {
$this -> config [ 'irc_alert_chan' ] = explode ( ',' , $this -> config [ 'irc_alert_chan' ]);
2020-09-22 12:31:39 +00:00
} elseif ( ! is_array ( $this -> config [ 'irc_alert_chan' ])) {
2016-08-28 20:53:52 +00:00
$this -> config [ 'irc_alert_chan' ] = [ $this -> config [ 'irc_alert_chan' ]];
}
2020-09-30 04:12:09 +00:00
$this -> chan = $this -> config [ 'irc_alert_chan' ];
2016-08-28 20:53:52 +00:00
}
if ( $this -> config [ 'irc_pass' ]) {
$this -> pass = $this -> config [ 'irc_pass' ];
}
2016-08-28 22:32:55 +00:00
$this -> loadExternal ();
2016-08-28 20:53:52 +00:00
$this -> log ( 'Starting IRC-Bot..' );
$this -> init ();
}
//end __construct()
2016-08-28 22:32:55 +00:00
private function loadExternal ()
{
2016-08-28 20:53:52 +00:00
if ( ! $this -> config [ 'irc_external' ]) {
return true ;
}
$this -> log ( 'Caching external commands...' );
if ( ! is_array ( $this -> config [ 'irc_external' ])) {
$this -> config [ 'irc_external' ] = explode ( ',' , $this -> config [ 'irc_external' ]);
}
foreach ( $this -> config [ 'irc_external' ] as $ext ) {
2020-09-23 11:38:42 +00:00
$this -> log ( " Command $ext ... " );
2016-08-28 20:53:52 +00:00
if (( $this -> external [ $ext ] = file_get_contents ( 'includes/ircbot/' . $ext . '.inc.php' )) == '' ) {
2020-09-23 11:38:42 +00:00
$this -> log ( 'failed!' );
2016-08-28 20:53:52 +00:00
unset ( $this -> external [ $ext ]);
}
}
2023-05-24 20:21:54 +00:00
return $this -> log ( 'Cached ' . count ( $this -> external ) . ' commands.' );
2016-08-28 20:53:52 +00:00
}
//end load_external()
2016-08-28 22:32:55 +00:00
private function init ()
{
2016-08-28 20:53:52 +00:00
if ( $this -> config [ 'irc_alert' ]) {
2022-10-25 21:10:35 +00:00
if ( ! $this -> connectAlert ()) {
sleep ( 5 );
return false ;
}
2016-08-28 20:53:52 +00:00
}
$this -> last_activity = time ();
$this -> j = 2 ;
$this -> connect ();
$this -> log ( 'Connected' );
if ( $this -> pass ) {
fwrite ( $this -> socket [ 'irc' ], 'PASS ' . $this -> pass . " \n \r " );
}
$this -> doAuth ();
2020-09-22 17:29:54 +00:00
$this -> nickwait = 0 ;
2016-08-28 20:53:52 +00:00
while ( true ) {
foreach ( $this -> socket as $n => $socket ) {
if ( ! is_resource ( $socket ) || feof ( $socket )) {
$this -> log ( " Socket ' $n ' closed. Restarting. " );
break 2 ;
}
}
2017-06-03 11:39:20 +00:00
if ( isset ( $this -> tempnick )) {
2020-09-22 17:29:54 +00:00
if ( $this -> nickwait > 100 ) {
$this -> ircRaw ( 'NICK ' . $this -> nick );
$this -> nickwait = 0 ;
}
$this -> nickwait += 1 ;
2017-06-03 11:39:20 +00:00
}
2016-08-28 20:53:52 +00:00
$this -> getData ();
if ( $this -> config [ 'irc_alert' ]) {
$this -> alertData ();
}
2017-10-26 06:56:09 +00:00
2016-08-28 20:53:52 +00:00
if ( $this -> config [ 'irc_conn_timeout' ]) {
$inactive_seconds = time () - $this -> last_activity ;
$max_inactive = $this -> config [ 'irc_conn_timeout' ];
if ( $inactive_seconds > $max_inactive ) {
$this -> log ( 'No data from server since ' . $max_inactive . ' seconds. Restarting.' );
break ;
}
}
usleep ( $this -> tick );
}
2022-10-25 21:10:35 +00:00
sleep ( 10 );
2016-08-28 20:53:52 +00:00
return $this -> init ();
}
//end init()
2016-08-28 22:32:55 +00:00
private function connectAlert ()
{
2023-04-28 14:03:24 +00:00
$container_dir = '/data' ;
if ( file_exists ( $container_dir ) and posix_getpwuid ( fileowner ( $container_dir ))[ 'name' ] == 'librenms' ) {
$f = $container_dir . '/.ircbot.alert' ;
} else {
$f = $this -> config [ 'install_dir' ] . '/.ircbot.alert' ;
}
2016-08-28 20:53:52 +00:00
if (( file_exists ( $f ) && filetype ( $f ) != 'fifo' && ! unlink ( $f )) || ( ! file_exists ( $f ) && ! shell_exec ( " mkfifo $f && echo 1 " ))) {
$this -> log ( 'Error - Cannot create Alert-File' );
2020-09-21 12:54:51 +00:00
2016-08-28 20:53:52 +00:00
return false ;
}
2023-03-13 21:32:22 +00:00
if ( $this -> socket [ 'alert' ] = fopen ( $f , 'r+' )) {
2016-08-28 20:53:52 +00:00
$this -> log ( 'Opened Alert-File' );
stream_set_blocking ( $this -> socket [ 'alert' ], false );
2020-09-21 12:54:51 +00:00
2016-08-28 20:53:52 +00:00
return true ;
}
$this -> log ( 'Error - Cannot open Alert-File' );
2020-09-21 12:54:51 +00:00
2016-08-28 20:53:52 +00:00
return false ;
}
//end connect_alert()
2016-08-28 22:32:55 +00:00
private function read ( $buff )
{
2020-09-22 12:32:08 +00:00
$r = fread ( $this -> socket [ $buff ], 8192 );
2016-08-28 20:53:52 +00:00
$this -> buff [ $buff ] .= $r ;
$r = strlen ( $r );
if ( strstr ( $this -> buff [ $buff ], " \n " )) {
$tmp = explode ( " \n " , $this -> buff [ $buff ], 2 );
2023-03-13 21:32:22 +00:00
$this -> buff [ $buff ] = substr ( $this -> buff [ $buff ], strlen ( $tmp [ 0 ]) + 1 );
2016-08-28 20:53:52 +00:00
if ( $this -> debug ) {
$this -> log ( " Returning buffer ' $buff ': ' " . trim ( $tmp [ 0 ]) . " ' " );
}
return $tmp [ 0 ];
}
if ( $this -> debug && $r > 0 ) {
$this -> log ( " Expanding buffer ' $buff ' = ' " . trim ( $this -> buff [ $buff ]) . " ' " );
}
return false ;
}
//end read()
2016-08-28 22:32:55 +00:00
private function alertData ()
{
2016-08-28 20:53:52 +00:00
if (( $alert = $this -> read ( 'alert' )) !== false ) {
$alert = json_decode ( $alert , true );
if ( ! is_array ( $alert )) {
return false ;
}
2020-09-23 11:38:42 +00:00
if ( $this -> debug ) {
$this -> log ( 'Alert received ' . $alert [ 'title' ]);
$this -> log ( 'Alert state ' . $alert [ 'state' ]);
$this -> log ( 'Alert severity ' . $alert [ 'severity' ]);
$this -> log ( 'Alert channels ' . print_r ( $this -> config [ 'irc_alert_chan' ], true ));
}
2016-08-28 20:53:52 +00:00
2016-08-28 22:32:55 +00:00
switch ( $alert [ 'state' ]) {
2020-05-24 02:14:36 +00:00
case AlertState :: WORSE :
2016-08-28 22:32:55 +00:00
$severity_extended = '+' ;
break ;
2020-05-24 02:14:36 +00:00
case AlertState :: BETTER :
2016-08-28 22:32:55 +00:00
$severity_extended = '-' ;
break ;
default :
$severity_extended = '' ;
2020-09-21 12:54:51 +00:00
}
2020-11-23 06:35:19 +00:00
$severity = '' ;
if ( isset ( $alert [ 'severity' ])) {
$severity = str_replace ([ 'warning' , 'critical' , 'normal' ], [ $this -> _color ( 'Warning' , 'yellow' ), $this -> _color ( 'Critical' , 'red' ), $this -> _color ( 'Info' , 'lightblue' )], $alert [ 'severity' ]) . $severity_extended . ' ' ;
}
2016-08-28 20:53:52 +00:00
2020-05-24 02:14:36 +00:00
if ( $alert [ 'state' ] == AlertState :: RECOVERED and $this -> config [ 'irc_alert_utf8' ]) {
2017-05-31 14:05:06 +00:00
$severity = str_replace ([ 'Warning' , 'Critical' ], [ '̶W̶a̶r̶n̶i̶n̶g' , '̶C̶r̶i̶t̶i̶c̶a̶l' ], $severity );
2016-08-28 20:53:52 +00:00
}
if ( $this -> config [ 'irc_alert_chan' ]) {
foreach ( $this -> config [ 'irc_alert_chan' ] as $chan ) {
2020-10-02 12:54:12 +00:00
$this -> sendAlert ( $chan , $severity , $alert );
2020-11-23 06:35:19 +00:00
$this -> ircRaw ( 'BOTFLOODCHECK' );
2016-08-28 20:53:52 +00:00
}
2020-11-23 06:35:19 +00:00
} else {
foreach ( $this -> authd as $nick => $data ) {
if ( $data [ 'expire' ] >= time ()) {
$this -> sendAlert ( $nick , $severity , $alert );
}
2016-08-28 20:53:52 +00:00
}
}
2020-10-02 12:54:12 +00:00
}
2016-08-28 20:53:52 +00:00
}
//end alertData()
2020-10-02 12:54:12 +00:00
private function sendAlert ( $sendto , $severity , $alert )
{
2020-10-06 19:07:49 +00:00
$sendto = explode ( ' ' , $sendto )[ 0 ];
2020-10-02 12:54:12 +00:00
$this -> ircRaw ( 'PRIVMSG ' . $sendto . ' :' . $severity . trim ( $alert [ 'title' ]));
if ( $this -> config [ 'irc_alert_short' ]) {
// Only send the title if set to short
return ;
}
foreach ( explode ( " \n " , $alert [ 'msg' ]) as $line ) {
$line = trim ( $line );
if ( strlen ( $line ) < 1 ) {
continue ;
}
$line = $this -> _html2irc ( $line );
$line = strip_tags ( $line );
// We don't need to repeat the title
if ( trim ( $line ) != trim ( $alert [ 'title' ])) {
$this -> log ( " Sending alert $line " );
if ( $this -> config [ 'irc_floodlimit' ] > 100 ) {
$this -> floodcount += strlen ( $line );
} elseif ( $this -> config [ 'irc_floodlimit' ] > 1 ) {
$this -> floodcount += 1 ;
}
if (( $this -> config [ 'irc_floodlimit' ] > 0 ) && ( $this -> floodcount > $this -> config [ 'irc_floodlimit' ])) {
$this -> log ( 'Reached floodlimit ' . $this -> floodcount );
$this -> ircRaw ( 'BOTFLOODCHECK' );
sleep ( 2 );
$this -> floodcount = 0 ;
}
$this -> ircRaw ( 'PRIVMSG ' . $sendto . ' :' . $line );
}
}
}
//end sendAlert()
2016-08-28 22:32:55 +00:00
private function getData ()
{
2016-08-28 20:53:52 +00:00
if (( $data = $this -> read ( 'irc' )) !== false ) {
$this -> last_activity = time ();
$this -> data = $data ;
$ex = explode ( ' ' , $this -> data );
if ( $ex [ 0 ] == 'PING' ) {
2016-08-28 22:32:55 +00:00
return $this -> ircRaw ( 'PONG ' . $ex [ 1 ]);
2016-08-28 20:53:52 +00:00
}
if ( $ex [ 1 ] == 376 || $ex [ 1 ] == 422 || ( $ex [ 1 ] == 'MODE' && $ex [ 2 ] == $this -> nick )) {
if ( $this -> j == 2 ) {
$this -> joinChan ();
$this -> j = 0 ;
}
}
2023-03-13 21:32:22 +00:00
if ( $this -> config [ 'irc_ctcp' ] && preg_match ( '/^:' . chr ( 1 ) . '.*/' , $ex [ 3 ])) {
2017-06-05 21:45:18 +00:00
// Handle CTCP
$ctcp = trim ( preg_replace ( '/[^A-Z]/' , '' , $ex [ 3 ]));
$ctcp_reply = null ;
$this -> log ( 'Received irc CTCP: ' . $ctcp . ' from ' . $this -> getUser ( $this -> data ));
switch ( $ctcp ) {
case 'VERSION' :
$ctcp_reply = chr ( 1 ) . " $ctcp " . $this -> config [ 'irc_ctcp_version' ] . chr ( 1 );
break ;
case 'PING' :
$ctcp_reply = chr ( 1 ) . " $ctcp " . $ex [ 4 ] . ' ' . $ex [ 5 ] . chr ( 1 );
break ;
case 'TIME' :
$ctcp_reply = chr ( 1 ) . " $ctcp " . date ( 'c' ) . chr ( 1 );
break ;
}
if ( $ctcp_reply !== null ) {
$this -> log ( 'Sending irc CTCP: ' . 'NOTICE ' . $this -> getUser ( $this -> data ) . ' :' . $ctcp_reply );
2020-09-21 12:54:51 +00:00
2017-06-05 21:45:18 +00:00
return $this -> ircRaw ( 'NOTICE ' . $this -> getUser ( $this -> data ) . ' :' . $ctcp_reply );
}
}
2017-06-03 11:39:20 +00:00
if (( $ex [ 1 ] == 'NICK' ) && ( preg_replace ( '/^:/' , '' , $ex [ 2 ]) == $this -> nick )) {
// Nickname changed successfully
if ( $this -> debug ) {
$this -> log ( 'Regained our real nick' );
}
unset ( $this -> tempnick );
}
if (( $ex [ 1 ] == 433 ) || ( $ex [ 1 ] == 437 )) {
// Nickname already in use / temp unavailable
if ( $this -> debug ) {
$this -> log ( 'Nickname already in use...' );
}
if ( $ex [ 2 ] != '*' ) {
$this -> tempnick = $ex [ 2 ];
}
if ( ! isset ( $this -> tempnick )) {
$this -> tempnick = $this -> nick . rand ( 0 , 99 );
}
if ( $this -> debug ) {
$this -> log ( 'Using temp nick ' . $this -> tempnick );
}
2020-09-21 12:54:51 +00:00
2017-06-03 11:39:20 +00:00
return $this -> ircRaw ( 'NICK ' . $this -> tempnick );
}
2020-11-23 06:35:19 +00:00
if ( $ex [ 1 ] == 421 ) {
// Unknown command
if ( $ex [ 3 ] == 'BOTFLOODCHECK' ) {
$this -> floodcount = 0 ;
}
}
2016-08-28 20:53:52 +00:00
$this -> command = str_replace ([ chr ( 10 ), chr ( 13 )], '' , $ex [ 3 ]);
if ( strstr ( $this -> command , ':.' )) {
$this -> handleCommand ();
}
}
}
//end getData()
2016-08-28 22:32:55 +00:00
private function joinChan ( $chan = false )
{
2016-08-28 20:53:52 +00:00
if ( $chan ) {
$this -> chan [] = $chan ;
}
foreach ( $this -> chan as $chan ) {
2016-08-28 22:32:55 +00:00
$this -> ircRaw ( 'JOIN ' . $chan );
2016-08-28 20:53:52 +00:00
}
return true ;
}
//end joinChan()
2016-08-28 22:32:55 +00:00
private function handleCommand ()
{
2016-08-28 20:53:52 +00:00
$this -> command = str_replace ( ':.' , '' , $this -> command );
2021-07-26 14:00:34 +00:00
$tmp = explode ( ':.' . $this -> command . ' ' , $this -> data );
2016-08-28 22:32:55 +00:00
$this -> user = $this -> getAuthdUser ();
2020-09-23 11:38:42 +00:00
$this -> log ( 'isAuthd-1? ' . $this -> isAuthd ());
2017-06-02 20:27:29 +00:00
if ( ! $this -> isAuthd () && ( isset ( $this -> config [ 'irc_auth' ]))) {
$this -> hostAuth ();
}
2020-09-23 11:38:42 +00:00
$this -> log ( 'isAuthd-2? ' . $this -> isAuthd ());
2016-08-28 20:53:52 +00:00
if ( $this -> isAuthd () || trim ( $this -> command ) == 'auth' ) {
$this -> proceedCommand ( str_replace ( " \n " , '' , trim ( $this -> command )), trim ( $tmp [ 1 ]));
}
$this -> authd [ $this -> getUser ( $this -> data )] = $this -> user ;
2020-09-21 12:54:51 +00:00
2016-08-28 20:53:52 +00:00
return false ;
}
//end handleCommand()
2016-08-28 22:32:55 +00:00
private function proceedCommand ( $command , $params )
{
2016-08-28 20:53:52 +00:00
$command = strtolower ( $command );
if ( in_array ( $command , $this -> commands )) {
$this -> chkdb ();
$this -> log ( $command . " ( ' " . $params . " ' ) " );
2020-09-21 12:54:51 +00:00
2016-08-28 20:53:52 +00:00
return $this -> { '_' . $command }( $params );
2016-08-28 22:32:55 +00:00
} elseif ( $this -> external [ $command ]) {
2016-08-28 20:53:52 +00:00
$this -> chkdb ();
$this -> log ( $command . " ( ' " . $params . " ' ) [Ext] " );
2020-09-21 12:54:51 +00:00
2016-08-28 20:53:52 +00:00
return eval ( $this -> external [ $command ]);
}
return false ;
}
//end proceedCommand()
2016-08-28 22:32:55 +00:00
private function respond ( $msg )
{
2016-08-28 20:53:52 +00:00
$chan = $this -> getChan ( $this -> data );
2020-09-21 12:54:51 +00:00
2016-08-28 20:53:52 +00:00
return $this -> sendMessage ( $msg , strstr ( $chan , '#' ) ? $chan : $this -> getUser ( $this -> data ));
}
//end respond()
2016-08-28 22:32:55 +00:00
private function getChan ( $param )
{
2016-08-28 20:53:52 +00:00
$data = explode ( 'PRIVMSG ' , $this -> data , 3 );
$data = explode ( ' ' , $data [ 1 ], 2 );
2020-09-21 12:54:51 +00:00
2016-08-28 20:53:52 +00:00
return $data [ 0 ];
}
//end getChan()
2016-08-28 22:32:55 +00:00
private function getUser ( $param )
{
2016-08-28 20:53:52 +00:00
$arrData = explode ( '!' , $param , 2 );
2020-09-21 12:54:51 +00:00
2016-08-28 20:53:52 +00:00
return str_replace ( ':' , '' , $arrData [ 0 ]);
}
2020-09-21 12:54:51 +00:00
2016-08-28 20:53:52 +00:00
//end getUser()
2017-06-02 20:27:29 +00:00
private function getUserHost ( $param )
{
$arrData = explode ( ' ' , $param , 2 );
2020-09-21 12:54:51 +00:00
2017-06-02 20:27:29 +00:00
return str_replace ( ':' , '' , $arrData [ 0 ]);
}
2020-09-21 12:54:51 +00:00
2017-06-02 20:27:29 +00:00
//end getUserHost()
2016-08-28 20:53:52 +00:00
2017-04-06 21:02:37 +00:00
private function connect ( $try = 0 )
2016-08-28 22:32:55 +00:00
{
2016-08-28 20:53:52 +00:00
if ( $try > $this -> max_retry ) {
$this -> log ( 'Failed too many connection attempts, aborting' );
2020-09-21 12:54:51 +00:00
2023-03-13 21:32:22 +00:00
return exit ;
2016-08-28 20:53:52 +00:00
}
2016-09-03 13:54:37 +00:00
$this -> log ( 'Trying to connect (' . ( $try + 1 ) . ') to ' . $this -> server . ':' . $this -> port . ( $this -> ssl ? ' (SSL)' : '' ));
2016-08-28 20:53:52 +00:00
if ( $this -> socket [ 'irc' ]) {
2017-06-03 11:39:20 +00:00
$this -> ircRaw ( 'QUIT :Reloading' );
2016-08-28 20:53:52 +00:00
fclose ( $this -> socket [ 'irc' ]);
}
if ( $this -> ssl ) {
$server = 'ssl://' . $this -> server ;
2016-08-28 22:32:55 +00:00
} else {
2016-08-28 20:53:52 +00:00
$server = $this -> server ;
}
if ( $this -> ssl && $this -> config [ 'irc_disable_ssl_check' ]) {
2024-01-05 04:39:12 +00:00
$ssl_context_params = [ 'ssl' => [ 'allow_self_signed' => true , 'verify_peer' => false , 'verify_peer_name' => false ]];
2016-08-28 20:53:52 +00:00
$ssl_context = stream_context_create ( $ssl_context_params );
$this -> socket [ 'irc' ] = stream_socket_client ( $server . ':' . $this -> port , $errno , $errstr , 30 , STREAM_CLIENT_CONNECT , $ssl_context );
2016-08-28 22:32:55 +00:00
} else {
2016-08-28 20:53:52 +00:00
$this -> socket [ 'irc' ] = fsockopen ( $server , $this -> port );
}
if ( ! is_resource ( $this -> socket [ 'irc' ])) {
2016-09-03 13:54:37 +00:00
if ( $try < 5 ) {
sleep ( 5 );
} elseif ( $try < 10 ) {
sleep ( 60 );
} else {
sleep ( 300 );
}
2020-09-21 12:54:51 +00:00
2016-08-28 20:53:52 +00:00
return $this -> connect ( $try + 1 );
2016-08-28 22:32:55 +00:00
} else {
2016-08-28 20:53:52 +00:00
stream_set_blocking ( $this -> socket [ 'irc' ], false );
2020-09-21 12:54:51 +00:00
2016-08-28 20:53:52 +00:00
return true ;
}
}
//end connect()
2016-08-28 22:32:55 +00:00
private function doAuth ()
{
if ( $this -> ircRaw ( 'USER ' . $this -> nick . ' 0 ' . $this -> nick . ' :' . $this -> nick ) && $this -> ircRaw ( 'NICK ' . $this -> nick )) {
2016-08-28 20:53:52 +00:00
return true ;
}
return false ;
}
//end doAuth()
2016-08-28 22:32:55 +00:00
private function sendMessage ( $message , $chan )
{
2016-08-28 20:53:52 +00:00
if ( $this -> debug ) {
$this -> log ( " Sending 'PRIVMSG " . trim ( $chan ) . ' :' . trim ( $message ) . " ' " );
}
2016-08-28 22:32:55 +00:00
return $this -> ircRaw ( 'PRIVMSG ' . trim ( $chan ) . ' :' . trim ( $message ));
2016-08-28 20:53:52 +00:00
}
//end sendMessage()
2016-08-28 22:32:55 +00:00
private function log ( $msg )
{
2020-09-23 11:38:42 +00:00
$log = '[' . date ( 'r' ) . '] IRCbot ' . trim ( $msg ) . " \n " ;
echo $log ;
file_put_contents ( $this -> config [ 'log_dir' ] . '/irc.log' , $log , FILE_APPEND );
2020-09-21 12:54:51 +00:00
2016-08-28 20:53:52 +00:00
return true ;
}
//end log()
2016-08-28 22:32:55 +00:00
private function chkdb ()
{
2018-08-17 20:29:20 +00:00
if ( ! Eloquent :: isConnected ()) {
2017-04-06 21:02:37 +00:00
try {
2022-04-23 00:12:07 +00:00
Eloquent :: DB () -> statement ( 'SELECT VERSION()' );
2018-08-17 20:29:20 +00:00
} catch ( \PDOException $e ) {
2017-04-06 21:02:37 +00:00
$this -> log ( 'Cannot connect to MySQL: ' . $e -> getMessage ());
2020-09-21 12:54:51 +00:00
2023-03-13 21:32:22 +00:00
return exit ;
2016-08-28 20:53:52 +00:00
}
}
2020-09-21 12:54:51 +00:00
2017-04-06 21:02:37 +00:00
return true ;
2016-08-28 20:53:52 +00:00
}
//end chkdb()
2016-08-28 22:32:55 +00:00
private function isAuthd ()
{
2016-08-28 20:53:52 +00:00
if ( $this -> user [ 'expire' ] >= time ()) {
$this -> user [ 'expire' ] = ( time () + ( $this -> config [ 'irc_authtime' ] * 3600 ));
2020-09-21 12:54:51 +00:00
2016-08-28 20:53:52 +00:00
return true ;
2016-08-28 22:32:55 +00:00
} else {
2016-08-28 20:53:52 +00:00
return false ;
}
}
//end isAuthd()
2016-08-28 22:32:55 +00:00
private function getAuthdUser ()
{
2016-08-28 20:53:52 +00:00
return $this -> authd [ $this -> getUser ( $this -> data )];
2017-06-02 20:27:29 +00:00
}
2020-09-21 12:54:51 +00:00
2017-06-02 20:27:29 +00:00
//end getAuthUser()
private function hostAuth ()
{
2020-09-23 11:38:42 +00:00
$this -> log ( 'HostAuth' );
2017-11-18 10:33:03 +00:00
global $authorizer ;
2017-06-02 20:27:29 +00:00
foreach ( $this -> config [ 'irc_auth' ] as $nms_user => $hosts ) {
foreach ( $hosts as $host ) {
$host = preg_replace ( " / \ */ " , '.*' , $host );
2020-09-23 11:38:42 +00:00
if ( $this -> debug ) {
$this -> log ( " HostAuth on irc matching $host to " . $this -> getUserHost ( $this -> data ));
}
2017-06-02 20:27:29 +00:00
if ( preg_match ( " / $host / " , $this -> getUserHost ( $this -> data ))) {
2023-08-28 05:13:40 +00:00
$user = User :: firstWhere ( 'username' , $nms_user );
$this -> user [ 'user' ] = $user ;
2017-06-02 20:27:29 +00:00
$this -> user [ 'expire' ] = ( time () + ( $this -> config [ 'irc_authtime' ] * 3600 ));
if ( $this -> debug ) {
2023-08-28 05:13:40 +00:00
$this -> log ( " HostAuth on irc for ' " . $user -> username . " ', ID: ' " . $user -> user_id . " ', Host: ' " . $host );
2017-06-02 20:27:29 +00:00
}
2020-09-21 12:54:51 +00:00
2017-06-02 20:27:29 +00:00
return true ;
}
}
}
2020-09-21 12:54:51 +00:00
2017-06-02 20:27:29 +00:00
return false ;
}
2016-08-28 20:53:52 +00:00
2017-06-02 20:27:29 +00:00
//end hostAuth
2016-08-28 20:53:52 +00:00
2016-08-28 22:32:55 +00:00
private function ircRaw ( $params )
{
2023-05-24 20:21:54 +00:00
return fwrite ( $this -> socket [ 'irc' ], $params . " \r \n " );
2016-08-28 20:53:52 +00:00
}
//end irc_raw()
2016-08-28 22:32:55 +00:00
private function _auth ( $params )
{
2017-11-18 10:33:03 +00:00
global $authorizer ;
2016-08-28 20:53:52 +00:00
$params = explode ( ' ' , $params , 2 );
if ( strlen ( $params [ 0 ]) == 64 ) {
if ( $this -> tokens [ $this -> getUser ( $this -> data )] == $params [ 0 ]) {
$this -> user [ 'expire' ] = ( time () + ( $this -> config [ 'irc_authtime' ] * 3600 ));
return $this -> respond ( 'Authenticated.' );
2016-08-28 22:32:55 +00:00
} else {
2016-08-28 20:53:52 +00:00
return $this -> respond ( 'Nope.' );
}
2016-08-28 22:32:55 +00:00
} else {
2023-08-28 05:13:40 +00:00
$user = User :: firstWhere ( 'username' , $params [ 0 ]);
if ( $user -> email && $user -> username == $params [ 0 ]) {
2016-08-28 20:53:52 +00:00
$token = hash ( 'gost' , openssl_random_pseudo_bytes ( 1024 ));
$this -> tokens [ $this -> getUser ( $this -> data )] = $token ;
2023-08-28 05:13:40 +00:00
$this -> user [ 'user' ] = $user ;
2016-08-28 20:53:52 +00:00
if ( $this -> debug ) {
2023-08-28 05:13:40 +00:00
$this -> log ( " Auth for ' " . $params [ 0 ] . " ', ID: ' " . $user -> user_id . " ', Token: ' " . $token . " ', Mail: ' " . $user -> email . " ' " );
2016-08-28 20:53:52 +00:00
}
2023-10-04 15:17:34 +00:00
if ( Mail :: send ( $user -> email , 'LibreNMS IRC-Bot Authtoken' , " Your Authtoken for the IRC-Bot: \r \n \r \n " . $token . " \r \n \r \n " , false ) === true ) {
2016-08-28 20:53:52 +00:00
return $this -> respond ( 'Token sent!' );
2016-08-28 22:32:55 +00:00
} else {
2016-08-28 20:53:52 +00:00
return $this -> respond ( 'Sorry, seems like mail doesnt like us.' );
}
2016-08-28 22:32:55 +00:00
} else {
2016-08-28 20:53:52 +00:00
return $this -> respond ( 'Who are you again?' );
}
} //end if
}
//end _auth()
2020-09-22 12:34:01 +00:00
private function _reload ( $params )
2016-08-28 22:32:55 +00:00
{
2023-08-28 05:13:40 +00:00
if ( $this -> user [ 'user' ] -> can ( 'irc.reload' )) {
2020-09-22 12:34:01 +00:00
if ( $params == 'external' ) {
$this -> respond ( 'Reloading external scripts.' );
2020-09-22 12:48:51 +00:00
2020-09-22 12:34:01 +00:00
return $this -> loadExternal ();
}
2024-09-10 07:59:20 +00:00
$new_config = Config :: load ();
2016-08-28 20:53:52 +00:00
$this -> respond ( 'Reloading configuration & defaults' );
2024-09-10 07:59:20 +00:00
if ( $new_config != $this -> config ) {
2021-03-29 22:43:05 +00:00
$this -> __construct ();
return ;
2016-08-28 20:53:52 +00:00
}
2016-08-28 22:32:55 +00:00
} else {
2016-08-28 20:53:52 +00:00
return $this -> respond ( 'Permission denied.' );
}
}
//end _reload()
2016-08-28 22:32:55 +00:00
private function _join ( $params )
{
2023-08-28 05:13:40 +00:00
if ( $this -> user [ 'user' ] -> can ( 'irc.join' )) {
2016-08-28 20:53:52 +00:00
return $this -> joinChan ( $params );
2016-08-28 22:32:55 +00:00
} else {
2016-08-28 20:53:52 +00:00
return $this -> respond ( 'Permission denied.' );
}
}
//end _join()
2016-08-28 22:32:55 +00:00
private function _quit ( $params )
{
2023-08-28 05:13:40 +00:00
if ( $this -> user [ 'user' ] -> can ( 'irc.quit' )) {
2017-06-03 11:39:20 +00:00
$this -> ircRaw ( 'QUIT :Requested' );
2020-09-21 12:54:51 +00:00
2023-03-13 21:32:22 +00:00
return exit ;
2016-08-28 22:32:55 +00:00
} else {
2016-08-28 20:53:52 +00:00
return $this -> respond ( 'Permission denied.' );
}
}
//end _quit()
2016-08-28 22:32:55 +00:00
private function _help ( $params )
{
2023-05-24 20:21:54 +00:00
$msg = implode ( ', ' , $this -> commands );
2020-09-22 12:34:01 +00:00
if ( count ( $this -> external ) > 0 ) {
2023-05-24 20:21:54 +00:00
$msg .= ', ' . implode ( ', ' , array_keys ( $this -> external ));
2016-08-28 20:53:52 +00:00
}
return $this -> respond ( " Available commands: $msg " );
}
//end _help()
2016-08-28 22:32:55 +00:00
private function _version ( $params )
{
2022-10-02 05:41:56 +00:00
$version = Version :: get ();
2020-09-21 12:54:51 +00:00
2022-10-02 05:41:56 +00:00
$msg = $this -> config [ 'project_name' ] . ', Version: ' . $version -> name () . ', DB schema: ' . $version -> databaseMigrationCount () . ', PHP: ' . PHP_VERSION ;
2016-09-07 06:33:24 +00:00
return $this -> respond ( $msg );
2016-08-28 20:53:52 +00:00
}
//end _version()
2016-08-28 22:32:55 +00:00
private function _log ( $params )
{
2016-08-28 20:53:52 +00:00
$num = 1 ;
2020-11-23 06:35:19 +00:00
$hostname = '' ;
$params = explode ( ' ' , $params );
if ( $params [ 0 ] > 1 ) {
$num = $params [ 0 ];
2016-08-28 20:53:52 +00:00
}
2020-11-23 06:35:19 +00:00
if ( strlen ( $params [ 1 ]) > 0 ) {
$hostname = preg_replace ( " /[^A-z0-9 \ . \ -]/ " , '' , $params [ 1 ]);
}
2023-08-28 05:13:40 +00:00
$tmp = Eventlog :: with ( 'device' ) -> hasAccess ( $this -> user [ 'user' ]) -> whereIn ( 'device_id' , function ( $query ) use ( $hostname ) {
return $query -> where ( 'hostname' , 'like' , $hostname . '%' ) -> select ( 'device_id' );
}) -> select ([ 'event_id' , 'datetime' , 'type' , 'message' ]) -> orderBy ( 'event_id' ) -> limit (( int ) $num ) -> get ();
/** @var Eventlog $logline */
2020-11-23 06:35:19 +00:00
foreach ( $tmp as $logline ) {
2023-08-28 05:13:40 +00:00
$response = $logline -> datetime . ' ' ;
$response .= $this -> _color ( $logline -> device -> displayName (), null , null , 'bold' ) . ' ' ;
2020-11-23 06:35:19 +00:00
if ( $this -> config [ 'irc_alert_utf8' ]) {
2023-08-28 05:13:40 +00:00
if ( preg_match ( '/critical alert/' , $logline -> message )) {
$response .= preg_replace ( '/critical alert/' , $this -> _color ( 'critical alert' , 'red' ), $logline -> message ) . ' ' ;
} elseif ( preg_match ( '/warning alert/' , $logline -> message )) {
$response .= preg_replace ( '/warning alert/' , $this -> _color ( 'warning alert' , 'yellow' ), $logline -> message ) . ' ' ;
} elseif ( preg_match ( '/recovery/' , $logline -> message )) {
$response .= preg_replace ( '/recovery/' , $this -> _color ( 'recovery' , 'green' ), $logline -> message ) . ' ' ;
2020-11-23 06:35:19 +00:00
} else {
2023-08-28 05:13:40 +00:00
$response .= $logline -> message . ' ' ;
2020-11-23 06:35:19 +00:00
}
} else {
2023-08-28 05:13:40 +00:00
$response .= $logline -> message . ' ' ;
2020-11-23 06:35:19 +00:00
}
2023-08-28 05:13:40 +00:00
if ( $logline -> type != 'NULL' ) {
$response .= $logline -> type . ' ' ;
2020-11-23 06:35:19 +00:00
}
if ( $this -> config [ 'irc_floodlimit' ] > 100 ) {
$this -> floodcount += strlen ( $response );
} elseif ( $this -> config [ 'irc_floodlimit' ] > 1 ) {
$this -> floodcount += 1 ;
}
if (( $this -> config [ 'irc_floodlimit' ] > 0 ) && ( $this -> floodcount > $this -> config [ 'irc_floodlimit' ])) {
$this -> ircRaw ( 'BOTFLOODCHECK' );
sleep ( 2 );
$this -> floodcount = 0 ;
}
$this -> respond ( $response );
2016-08-28 20:53:52 +00:00
}
2020-11-23 06:35:19 +00:00
if ( ! $tmp ) {
2016-08-28 20:53:52 +00:00
$this -> respond ( 'Nothing to see, maybe a bug?' );
}
return true ;
}
//end _log()
2016-08-28 22:32:55 +00:00
private function _down ( $params )
{
2023-08-28 05:13:40 +00:00
$devices = Device :: hasAccess ( $this -> user [ 'user' ]) -> isDown ()
-> select ([ 'device_id' , 'hostname' , 'sysName' , 'display' , 'ip' ]) -> get ();
2016-08-28 20:53:52 +00:00
2023-08-28 05:13:40 +00:00
$msg = $devices -> map -> displayName () -> implode ( ', ' );
2020-09-21 12:54:51 +00:00
2023-08-28 05:13:40 +00:00
return $this -> respond ( $msg ? : 'Nothing to show :)' );
2016-08-28 20:53:52 +00:00
}
//end _down()
2016-08-28 22:32:55 +00:00
private function _device ( $params )
{
2016-08-28 20:53:52 +00:00
$params = explode ( ' ' , $params );
$hostname = $params [ 0 ];
2023-08-28 05:13:40 +00:00
$device = Device :: hasAccess ( $this -> user [ 'user' ]) -> firstWhere ( 'hostname' , $hostname );
2016-08-28 20:53:52 +00:00
if ( ! $device ) {
return $this -> respond ( 'Error: Bad or Missing hostname, use .listdevices to show all devices.' );
}
2023-08-28 05:13:40 +00:00
$status = $device -> status ? 'Up ' . Time :: formatInterval ( $device -> uptime ) : 'Down' ;
$status .= $device -> ignore ? '*Ignored*' : '' ;
$status .= $device -> disabled ? '*Disabled*' : '' ;
2016-08-28 20:53:52 +00:00
2023-08-28 05:13:40 +00:00
return $this -> respond ( $device -> displayName () . ': ' . $device -> os . ' ' . $device -> version . ' ' . $device -> features . ' ' . $status );
2020-09-21 12:54:51 +00:00
}
2016-08-28 20:53:52 +00:00
//end _device()
2016-08-28 22:32:55 +00:00
private function _port ( $params )
{
2016-08-28 20:53:52 +00:00
$params = explode ( ' ' , $params );
$hostname = $params [ 0 ];
$ifname = $params [ 1 ];
if ( ! $hostname || ! $ifname ) {
return $this -> respond ( 'Error: Missing hostname or ifname.' );
}
2023-08-28 05:13:40 +00:00
$device = Device :: hasAccess ( $this -> user [ 'user' ]) -> firstWhere ( 'hostname' , $hostname );
if ( ! $device ) {
return $this -> respond ( 'Error: Bad or Missing hostname, use .listdevices to show all devices.' );
}
$port = $device -> ports () -> hasAccess ( $this -> user [ 'user' ]) -> where ( 'ifName' , $ifname ) -> orWhere ( 'ifDescr' , $ifname );
if ( ! $port ) {
return $this -> respond ( 'Error: Port not found or you do not have access.' );
2016-08-28 20:53:52 +00:00
}
2021-03-28 22:25:30 +00:00
$bps_in = Number :: formatSi ( $port [ 'ifInOctets_rate' ] * 8 , 2 , 3 , 'bps' );
$bps_out = Number :: formatSi ( $port [ 'ifOutOctets_rate' ] * 8 , 2 , 3 , 'bps' );
$pps_in = Number :: formatBi ( $port [ 'ifInUcastPkts_rate' ], 2 , 3 , 'pps' );
$pps_out = Number :: formatBi ( $port [ 'ifOutUcastPkts_rate' ], 2 , 3 , 'pps' );
2016-08-28 20:53:52 +00:00
2021-03-28 22:25:30 +00:00
return $this -> respond ( $port [ 'ifAdminStatus' ] . '/' . $port [ 'ifOperStatus' ] . ' ' . $bps_in . ' > bps > ' . $bps_out . ' | ' . $pps_in . ' > PPS > ' . $pps_out );
2020-09-21 12:54:51 +00:00
}
2016-08-28 20:53:52 +00:00
//end _port()
2016-08-28 22:32:55 +00:00
private function _listdevices ( $params )
{
2023-08-28 05:13:40 +00:00
$devices = Device :: hasAccess ( $this -> user [ 'user' ]) -> pluck ( 'hostname' );
2016-08-28 20:53:52 +00:00
2023-08-28 05:13:40 +00:00
$msg = $devices -> implode ( ', ' );
2020-09-21 12:54:51 +00:00
2023-08-28 05:13:40 +00:00
return $this -> respond ( $msg ? : 'Nothing to show..?' );
2016-08-28 20:53:52 +00:00
}
//end _listdevices()
2016-08-28 22:32:55 +00:00
private function _status ( $params )
{
2016-08-28 20:53:52 +00:00
$params = explode ( ' ' , $params );
$statustype = $params [ 0 ];
2021-03-29 22:43:05 +00:00
2016-08-28 20:53:52 +00:00
switch ( $statustype ) {
2016-08-28 22:32:55 +00:00
case 'devices' :
case 'device' :
case 'dev' :
2023-08-28 05:13:40 +00:00
$devcount = Device :: hasAccess ( $this -> user [ 'user' ]) -> count ();
$devup = Device :: hasAccess ( $this -> user [ 'user' ]) -> isUp () -> count ();
$devdown = Device :: hasAccess ( $this -> user [ 'user' ]) -> isDown () -> count ();
$devign = Device :: hasAccess ( $this -> user [ 'user' ]) -> isIgnored () -> count ();
$devdis = Device :: hasAccess ( $this -> user [ 'user' ]) -> isDisabled () -> count ();
2017-06-02 19:07:09 +00:00
if ( $devup > 0 ) {
$devup = $this -> _color ( $devup , 'green' );
}
if ( $devdown > 0 ) {
$devdown = $this -> _color ( $devdown , 'red' );
2017-06-06 11:42:49 +00:00
$devcount = $this -> _color ( $devcount , 'yellow' , null , 'bold' );
2017-06-02 19:07:09 +00:00
} else {
$devcount = $this -> _color ( $devcount , 'green' , null , 'bold' );
}
2016-08-28 22:32:55 +00:00
$msg = 'Devices: ' . $devcount . ' (' . $devup . ' up, ' . $devdown . ' down, ' . $devign . ' ignored, ' . $devdis . ' disabled' . ')' ;
break ;
case 'ports' :
case 'port' :
case 'prt' :
2023-08-28 05:13:40 +00:00
$prtcount = Port :: hasAccess ( $this -> user [ 'user' ]) -> count ();
$prtup = Port :: hasAccess ( $this -> user [ 'user' ]) -> isUp () -> count ();
$prtdown = Port :: hasAccess ( $this -> user [ 'user' ]) -> isDown () -> whereHas ( 'device' , fn ( $q ) => $q -> where ( 'ignore' , 0 )) -> count ();
$prtsht = Port :: hasAccess ( $this -> user [ 'user' ]) -> isShutdown () -> whereHas ( 'device' , fn ( $q ) => $q -> where ( 'ignore' , 0 )) -> count ();
$prtign = Port :: hasAccess ( $this -> user [ 'user' ]) -> where ( function ( $query ) {
$query -> isIgnored () -> orWhereHas ( 'device' , fn ( $q ) => $q -> where ( 'ignore' , 1 ));
}) -> count ();
2017-11-07 20:30:59 +00:00
// $prterr = dbFetchCell("SELECT count(*) FROM ports AS I, devices AS D WHERE D.device_id = I.device_id AND (I.ignore = '0' OR D.ignore = '0') AND (I.ifInErrors_delta > '0' OR I.ifOutErrors_delta > '0')".$p_a);
2017-06-02 19:07:09 +00:00
if ( $prtup > 0 ) {
$prtup = $this -> _color ( $prtup , 'green' );
}
if ( $prtdown > 0 ) {
$prtdown = $this -> _color ( $prtdown , 'red' );
2017-06-06 11:42:49 +00:00
$prtcount = $this -> _color ( $prtcount , 'yellow' , null , 'bold' );
2017-06-02 19:07:09 +00:00
} else {
$prtcount = $this -> _color ( $prtcount , 'green' , null , 'bold' );
}
2016-08-28 22:32:55 +00:00
$msg = 'Ports: ' . $prtcount . ' (' . $prtup . ' up, ' . $prtdown . ' down, ' . $prtign . ' ignored, ' . $prtsht . ' shutdown' . ')' ;
break ;
case 'services' :
case 'service' :
case 'srv' :
2017-11-07 20:30:59 +00:00
$status_counts = [];
$status_colors = [ 0 => 'green' , 3 => 'lightblue' , 1 => 'yellow' , 2 => 'red' ];
2023-08-28 05:13:40 +00:00
$srvcount = Service :: hasAccess ( $this -> user [ 'user' ]) -> count ();
$srvign = Service :: hasAccess ( $this -> user [ 'user' ]) -> isIgnored () -> count ();
$srvdis = Service :: hasAccess ( $this -> user [ 'user' ]) -> isDisabled () -> count ();
$service_status = Service :: hasAccess ( $this -> user [ 'user' ]) -> isActive () -> groupBy ( 'service_status' )
-> select ( 'service_status' , \DB :: raw ( 'count(*) as count' )) -> get ()
-> pluck ( 'count' , 'service_status' );
2017-11-07 20:30:59 +00:00
foreach ( $status_colors as $status => $color ) {
2023-08-28 05:13:40 +00:00
if ( $service_status -> has ( $status )) {
$status_counts [ $status ] = $this -> _color ( $service_status -> get ( $status ), $color );
2017-11-07 20:30:59 +00:00
$srvcount = $this -> _color ( $srvcount , $color , null , 'bold' ); // upgrade the main count color
} else {
$status_counts [ $status ] = 0 ;
}
2017-06-02 19:07:09 +00:00
}
2017-11-07 20:30:59 +00:00
$msg = " Services: $srvcount ( { $status_counts [ 0 ] } up, { $status_counts [ 2 ] } down, { $status_counts [ 1 ] } warning, { $status_counts [ 3 ] } unknown, $srvign ignored, $srvdis disabled) " ;
2016-08-28 22:32:55 +00:00
break ;
default :
$msg = 'Error: STATUS requires one of the following: <devices|device|dev>|<ports|port|prt>|<services|service|src>' ;
break ;
2016-08-28 20:53:52 +00:00
} //end switch
return $this -> respond ( $msg );
}
2020-09-21 12:54:51 +00:00
2016-08-28 20:53:52 +00:00
//end _status()
2017-06-02 19:07:09 +00:00
private function _color ( $text , $fg_color , $bg_color = null , $other = null )
{
$colors = [
'white' => '00' ,
'black' => '01' ,
'blue' => '02' ,
'green' => '03' ,
'red' => '04' ,
'brown' => '05' ,
'purple' => '06' ,
'orange' => '07' ,
'yellow' => '08' ,
'lightgreen' => '09' ,
'cyan' => '10' ,
'lightcyan' => '11' ,
'lightblue' => '12' ,
'pink' => '13' ,
'grey' => '14' ,
'lightgrey' => '15' ,
];
$ret = chr ( 3 );
2017-06-06 11:42:49 +00:00
if ( array_key_exists ( $fg_color , $colors )) {
2017-06-02 19:07:09 +00:00
$ret .= $colors [ $fg_color ];
2017-06-06 11:42:49 +00:00
if ( array_key_exists ( $bg_color , $colors )) {
2017-06-02 19:07:09 +00:00
$ret .= ',' . $colors [ $fg_color ];
}
}
switch ( $other ) {
case 'bold' :
$ret .= chr ( 2 );
break ;
case 'underline' :
$ret .= chr ( 31 );
break ;
case 'italics' :
case 'reverse' :
$ret .= chr ( 22 );
break ;
}
$ret .= $text ;
$ret .= chr ( 15 );
2020-09-21 12:54:51 +00:00
2017-06-02 19:07:09 +00:00
return $ret ;
}
2020-09-21 12:54:51 +00:00
2017-06-02 19:07:09 +00:00
// end _color
2020-10-02 12:54:12 +00:00
private function _html2irc ( $string )
{
$string = urldecode ( $string );
$string = preg_replace ( '#<b>#i' , chr ( 2 ), $string );
$string = preg_replace ( '#</b>#i' , chr ( 2 ), $string );
$string = preg_replace ( '#<i>#i' , chr ( 22 ), $string );
$string = preg_replace ( '#</i>#i' , chr ( 22 ), $string );
$string = preg_replace ( '#<u>#i' , chr ( 31 ), $string );
$string = preg_replace ( '#</u>#i' , chr ( 31 ), $string );
$colors = [
2024-01-05 04:39:12 +00:00
'white' => '00' ,
'black' => '01' ,
'blue' => '02' ,
'green' => '03' ,
'red' => '04' ,
'brown' => '05' ,
'purple' => '06' ,
'orange' => '07' ,
'yellow' => '08' ,
2020-10-02 12:54:12 +00:00
'lightgreen' => '09' ,
2024-01-05 04:39:12 +00:00
'cyan' => '10' ,
2020-10-02 12:54:12 +00:00
'lightcyan' => '11' ,
'lightblue' => '12' ,
2024-01-05 04:39:12 +00:00
'pink' => '13' ,
'grey' => '14' ,
2020-10-02 12:54:12 +00:00
'lightgrey' => '15' ,
];
foreach ( $colors as $color => $code ) {
$string = preg_replace ( " #< $color >#i " , chr ( 3 ) . $code , $string );
$string = preg_replace ( " #</ $color >#i " , chr ( 3 ), $string );
}
return $string ;
}
// end _html2irc
2016-08-28 20:53:52 +00:00
} //end class