added HALFOP (+h, %) support and Binding filters
authorpk910 <philipp@zoelle1.de>
Sun, 18 Dec 2011 14:04:01 +0000 (15:04 +0100)
committerpk910 <philipp@zoelle1.de>
Sun, 18 Dec 2011 14:08:47 +0000 (15:08 +0100)
ModCMD/Binding.class.php
ModCMD/ModCMD.class.php
Uplink/P10_Channel.class.php
Uplink/P10_ModeSets.class.php
Uplink/Uplink.class.php

index 5bf9a75fd1026e8d0b6e5ac1433a561c7b1766a0..ed980c0219e8997b1388e80e1b1eca17a174ad16 100644 (file)
 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
index f07e7b044ca44f373873f500939b7db743b22152..76b1c3045a3e10a782e1dc28587ef4358eec230c 100644 (file)
@@ -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) {
index 4fe3a205ae27552f402a1d6e735e675d4f66d983..e58882a7b8b2695508105c1cd06a7388381b79a2 100644 (file)
@@ -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);
        }
        
index 0ff322c6d351d1aebfd0d0188f9f1c57a79f8e97..b003057c7b2e489cc08419cc014d6dcb72473c30 100644 (file)
@@ -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;
index c88c2ea211c5870caa3e9e5441794b3be837650e..387f32406e207c71966fabda389990a0b783c4a5 100644 (file)
@@ -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);
                        }