From 2e900783aa961dd56ec4733231656fd8928aaa55 Mon Sep 17 00:00:00 2001 From: pk910 Date: Sun, 18 Dec 2011 15:04:01 +0100 Subject: [PATCH] added HALFOP (+h, %) support and Binding filters --- ModCMD/Binding.class.php | 17 +++++++-- ModCMD/ModCMD.class.php | 41 ++++++++++++---------- Uplink/P10_Channel.class.php | 7 ++-- Uplink/P10_ModeSets.class.php | 4 ++- Uplink/Uplink.class.php | 66 ++++++++++++++++++++--------------- 5 files changed, 82 insertions(+), 53 deletions(-) diff --git a/ModCMD/Binding.class.php b/ModCMD/Binding.class.php index 5bf9a75..ed980c0 100644 --- a/ModCMD/Binding.class.php +++ b/ModCMD/Binding.class.php @@ -26,20 +26,31 @@ class Binding { private $bot; private $method; + private $filter; - public function __construct($bot, $method) { + public function __construct($bot, $method, $filter) { $this->bot = $bot; $this->method = $method; + $this->filter = $filter; } public function trigger($params) { call_user_func_array(array($this->bot, $this->method), $params); } - public function match($bot, $method) { - return ($bot === $this->bot && (!$method || strtolower($this->method) == strtolower($method))); + public function match($bot, $method, $filter) { + return ($bot === $this->bot && (!$method || strtolower($this->method) == strtolower($method)) && (!$filter || $this->match_filter($filter, false))); } + public function match_filter($filter, $preg = true) { + if(!$this->filter) return true; + if(is_object($filter) || is_object($this->filter)) { + return $filter === $this->filter; + } else if($preg && is_string($filter && is_string($this->filter))) { + return preg_match($this->filter, $filter); + } else + return $filter == $this->filter; + } } ?> \ No newline at end of file diff --git a/ModCMD/ModCMD.class.php b/ModCMD/ModCMD.class.php index f07e7b0..76b1c30 100644 --- a/ModCMD/ModCMD.class.php +++ b/ModCMD/ModCMD.class.php @@ -57,24 +57,24 @@ class ModCMD implements EventHandler { return self::$eventHandler; } - public static function bind($bot, $type, $method) { + public static function bind($bot, $type, $method, $filter = NULL) { if(is_a($bot, "Bot") && method_exists($bot, $method)) { if(array_key_exists($type, self::$bindings)) { foreach(self::$bindings[$type] as $binding) { - if($binding->match($bot, $method)) + if($binding->match($bot, $method, $filter)) return; } } else self::$bindings[$type] = array(); - self::$bindings[$type][] = new Binding($bot, $method); + self::$bindings[$type][] = new Binding($bot, $method, $filter); } } - public static function unbind($bot, $type, $method) { + public static function unbind($bot, $type, $method, $filter = NULL) { if(is_a($bot, "Bot")) { if(array_key_exists($type, self::$bindings)) { foreach(self::$bindings[$type] as $id => $binding) { - if($binding->match($bot, $method)) { + if($binding->match($bot, $method, $filter)) { unset(self::$bindings[$type][$id]); break; } @@ -87,7 +87,7 @@ class ModCMD implements EventHandler { if(is_a($bot, "Bot")) { foreach(self::$bindings as $type => $bindings) { foreach($bindings as $id => $binding) { - if($binding->match($bot, null)) { + if($binding->match($bot, null, null)) { unset(self::$bindings[$type][$id]); } } @@ -99,10 +99,15 @@ class ModCMD implements EventHandler { * EVENT HANDLER * ********************************************************************************************/ - private function event($type, $parameters) { + private function event($type, $parameters, $matchings = array(null)) { if(array_key_exists($type, self::$bindings)) { foreach(self::$bindings[$type] as $binding) { - $binding->trigger($parameters); + $match = false; + foreach($matchings as $matching) { + if(($match = $binding->match_filter($matching))) break; + } + if($match) + $binding->trigger($parameters); } } } @@ -132,43 +137,43 @@ class ModCMD implements EventHandler { } public function event_join($user, $channel, $isBurst) { - $this->event(BIND_JOIN, array($user, $channel, $isBurst)); + $this->event(BIND_JOIN, array($user, $channel, $isBurst), array($user, $channel)); } public function event_part($user, $channel, $reason) { - $this->event(BIND_PART, array($user, $channel, $reason)); + $this->event(BIND_PART, array($user, $channel, $reason), array($user, $channel)); } public function event_kick($user, $target, $channel, $reason) { - $this->event(BIND_KICK, array($user, $target, $channel, $reason)); + $this->event(BIND_KICK, array($user, $target, $channel, $reason), array($user, $channel, $target)); } public function event_chanmode($user, $channel, $modes) { - $this->event(BIND_CHANMODE, array($user, $channel, $modes)); + $this->event(BIND_CHANMODE, array($user, $channel, $modes), array($user, $channel)); } public function event_chanmessage($user, $channel, $message) { - $this->event(BIND_CHANMSG, array($user, $channel, $message)); + $this->event(BIND_CHANMSG, array($user, $channel, $message), array($user, $channel)); } public function event_channotice($user, $channel, $message) { - $this->event(BIND_CHANNOTICE, array($user, $channel, $message)); + $this->event(BIND_CHANNOTICE, array($user, $channel, $message), array($user, $channel)); } public function event_privmessage($user, $target, $message) { - $this->event(BIND_PRIVMSG, array($user, $target, $message)); + $this->event(BIND_PRIVMSG, array($user, $target, $message), array($user, $target)); } public function event_privnotice($user, $target, $message) { - $this->event(BIND_PRIVNOTICE, array($user, $target, $message)); + $this->event(BIND_PRIVNOTICE, array($user, $target, $message), array($user, $target)); } public function event_preparse($from, $command, $arguments) { - $this->event(BIND_PREPARSE, array($from, $command, $arguments)); + $this->event(BIND_PREPARSE, array($from, $command, $arguments), array($command)); } public function event_unknown_cmd($from, $command, $arguments) { - $this->event(BIND_UNKNOWNCMD, array($from, $command, $arguments)); + $this->event(BIND_UNKNOWNCMD, array($from, $command, $arguments), array($command)); } public function event_chanctcp($user, $channel, $command, $text) { diff --git a/Uplink/P10_Channel.class.php b/Uplink/P10_Channel.class.php index 4fe3a20..e58882a 100644 --- a/Uplink/P10_Channel.class.php +++ b/Uplink/P10_Channel.class.php @@ -54,7 +54,8 @@ class P10_Channel { private $create_time; private $users = array(); const USERPRIV_OPED = 0x0001; - const USERPRIV_VOICE = 0x0002; + const USERPRIV_HALFOP = 0x0002; + const USERPRIV_VOICE = 0x0004; private $userPrivs = array(); public function __construct($name) { @@ -94,9 +95,9 @@ class P10_Channel { $user->addChannel($this); } - public function burstUser($user, $opped, $voiced) { + public function burstUser($user, $opped, $halfopped, $voiced) { $this->users[$user->getNumeric()] = $user; - $this->userPrivs[$user->getNumeric()] = ($opped ? self::USERPRIV_OPED : 0) | ($voiced ? self::USERPRIV_VOICE : 0); + $this->userPrivs[$user->getNumeric()] = ($opped ? self::USERPRIV_OPED : 0) | ($halfopped ? self::USERPRIV_HALFOP : 0) | ($voiced ? self::USERPRIV_VOICE : 0); $user->addChannel($this); } diff --git a/Uplink/P10_ModeSets.class.php b/Uplink/P10_ModeSets.class.php index 0ff322c..b003057 100644 --- a/Uplink/P10_ModeSets.class.php +++ b/Uplink/P10_ModeSets.class.php @@ -71,6 +71,7 @@ class P10_ChannelModeSet { //special behavior "o" => self::MODE_TYPE_B, + "h" => self::MODE_TYPE_B, "v" => self::MODE_TYPE_B ); private static $modevalues = null; @@ -137,7 +138,7 @@ class P10_ChannelModeSet { trigger_error("unknown mode (".$mode.") on setModes (".$modes.").", E_USER_WARNING); continue; } - if($mode == "o" || $mode == "v") { + if($mode == "o" || $mode == "h" || $mode == "v") { if($this->setPrivs($add, $mode, $args[$c++])) { if($returndiff && $add) { $modestradd .= $mode; @@ -208,6 +209,7 @@ class P10_ChannelModeSet { $privs = $this->channel->getUserPrivs($user); $privFlag = 0; if($mode == "o") $privFlag = P10_Channel::USERPRIV_OPED; + if($mode == "h") $privFlag = P10_Channel::USERPRIV_HALFOP; if($mode == "v") $privFlag = P10_Channel::USERPRIV_VOICE; if(!($add xor ($privs & $privFlag))) return false; diff --git a/Uplink/Uplink.class.php b/Uplink/Uplink.class.php index c88c2ea..387f324 100644 --- a/Uplink/Uplink.class.php +++ b/Uplink/Uplink.class.php @@ -438,7 +438,7 @@ class Uplink { $userstr = ""; } $users = explode(",",$userstr); - $isop = false; $isvoice = false; + $isop = false; $ishalfop = false; $isvoice = false; foreach($users as $user) { if($user == "") continue; $uexp = explode(":", $user); @@ -448,9 +448,11 @@ class Uplink { } if(count($uexp) > 1) { $isop = false; + $ishalfop = false; $isvoice = false; for($i = 0; $i < strlen($uexp[1]); $i++) { if($uexp[1][0] == "@") $isop = true; + if($uexp[1][0] == "%") $ishalfop = true; if($uexp[1][0] == "+") $isvoice = true; } } @@ -459,7 +461,7 @@ class Uplink { trigger_error("burst parse error: cant find User '".$uexp[0]."'.", E_USER_ERROR); return; } - $channel->burstUser($user, $isop, $isvoice); + $channel->burstUser($user, $isop, $ishalfop, $isvoice); if($this->eventHandler) $this->eventHandler->event_join($user, $channel, true); } @@ -780,39 +782,46 @@ class Uplink { $this->send("N", $nick, $connect_time, $ident, $host, $modes, $ip, $numeric, $realname); } foreach(P10_Channel::getChannels() as $channel) { - $sorted_users = array('ov' => array(), 'o' => array(), 'v' => array(), '-' => array()); + $privs_to_burst = array('o', 'h', 'v' ); + $priv_values = array(P10_Channel::USERPRIV_OPED, P10_Channel::USERPRIV_HALFOP, P10_Channel::USERPRIV_VOICE ); + $priv_combinations = array(); + $sorted_users = array(); + $combinations = expr(2, count($privs_to_burst)); //binary possibilities => 2^count($privs_to_burst) + for($i = 0; $i < $combinations; $i++) { + //make a binary number out of $i + $binary = decbin($i); + while(strlen($binary) < count($privs_to_burst)) + $binary = '0'.$binary; + $combination_name = ''; + $combination_value = 0; + for($j = 0; $j < count($privs_to_burst); $j++) { + if($binary[$j] == '1') { + $combination_name .= $privs_to_burst[$j]; + $combination_value .= $priv_values[$j]; + } + } + $priv_combinations[] = array("name" => $combination_name, "value" => $combination_value); + $sorted_users[$combination_value] = array(); + } $local_users = false; foreach($channel->getUsers() as $user) { if(substr($user->getNumeric(), 0, 2) != $this->server->getNumeric()) continue; //skip users that are not on the local server $privs = $channel->getUserPrivs($user); - $strPrivs = ""; - if(($privs & P10_Channel::USERPRIV_OPED)) $strPrivs .= "o"; - if(($privs & P10_Channel::USERPRIV_VOICE)) $strPrivs .= "v"; - if($strPrivs == "") $strPrivs = "-"; $local_users = true; - $sorted_users[$strPrivs][] = $user; + $sorted_users[$privs][] = $user; } if(!$local_users) continue; $userStr = ""; - foreach($sorted_users['-'] as $user) { - if($userStr != "") $userStr.=","; - $userStr .= $user->getNumeric(); - } - foreach($sorted_users['ov'] as $i => $user) { - if($userStr != "") $userStr.=","; - $userStr .= $user->getNumeric(); - if($i == 0) $userStr .= ":ov"; - } - foreach($sorted_users['o'] as $i => $user) { - if($userStr != "") $userStr.=","; - $userStr .= $user->getNumeric(); - if($i == 0) $userStr .= ":o"; - } - foreach($sorted_users['v'] as $i => $user) { - if($userStr != "") $userStr.=","; - $userStr .= $user->getNumeric(); - if($i == 0) $userStr .= ":v"; - } + foreach($priv_combinations as $combination) { + $i = 0; + foreach($sorted_users[$combination['value']] as $user) { + if($userStr != "") $userStr.=","; + $userStr .= $user->getNumeric(); + if(($i++) == 0 && $combination['value'] > 0) { + $userStr .= $combination['name']; + } + } + } $banString = ""; //TODO: Build ban String $burstString = ""; @@ -890,8 +899,9 @@ class Uplink { if($privs != 0) { $channel->setUserPrivs($user, $privs); if(($this->flags & self::FLAG_CONNECTED)) { - $modestr = "+".(($privs & P10_Channel::USERPRIV_OPED) ? "o" : "").(($privs & P10_Channel::USERPRIV_VOICE) ? "v" : ""); + $modestr = "+".(($privs & P10_Channel::USERPRIV_OPED) ? "o" : "").(($privs & P10_Channel::USERPRIV_HALFOP) ? "h" : "").(($privs & P10_Channel::USERPRIV_VOICE) ? "v" : ""); $modestr .= (($privs & P10_Channel::USERPRIV_OPED) ? " ".$user->getNumeric() : ""); + $modestr .= (($privs & P10_Channel::USERPRIV_HALFOP) ? " ".$user->getNumeric() : ""); $modestr .= (($privs & P10_Channel::USERPRIV_VOICE) ? " ".$user->getNumeric() : ""); $this->send("OM", $user->getNumeric(), $chanName, $modestr); } -- 2.20.1