. * * * ************************************************************************ * * Uplink/P10_ModeSets.class.php * * classes to parse and store channel or user modes * */ class P10_ChannelModeSet { const MODE_TYPE_A = 1, MODE_TYPE_B = 2, MODE_TYPE_C = 3, MODE_TYPE_D = 4; /** http://www.irc.org/tech_docs/draft-brocklesby-irc-isupport-03.txt * Section 3.3 CHANMODES * * Type A: Modes that add or remove an address to or from a list. * These modes always take a parameter when sent by the server to a * client; when sent by a client, they may be specified without a * parameter, which requests the server to display the current * contents of the corresponding list on the channel to the client. * * Type B: Modes that change a setting on the channel. These modes * always take a parameter. * * Type C: Modes that change a setting on the channel. These modes * take a parameter only when set; the parameter is absent when the * mode is removed both in the client's and server's MODE command. * * Type D: Modes that change a setting on the channel. These modes * never take a parameter. **/ private static $modes = array( "b" => self::MODE_TYPE_A, "k" => self::MODE_TYPE_B, "a" => self::MODE_TYPE_C, "l" => self::MODE_TYPE_C, "f" => self::MODE_TYPE_C, "F" => self::MODE_TYPE_C, "c" => self::MODE_TYPE_D, "C" => self::MODE_TYPE_D, "i" => self::MODE_TYPE_D, "m" => self::MODE_TYPE_D, "M" => self::MODE_TYPE_D, "n" => self::MODE_TYPE_D, "N" => self::MODE_TYPE_D, "p" => self::MODE_TYPE_D, "r" => self::MODE_TYPE_D, "s" => self::MODE_TYPE_D, "t" => self::MODE_TYPE_D, "u" => self::MODE_TYPE_D, "D" => self::MODE_TYPE_D, "d" => self::MODE_TYPE_D, "R" => self::MODE_TYPE_D, "z" => self::MODE_TYPE_D, "S" => self::MODE_TYPE_D, //special behavior "o" => self::MODE_TYPE_B, "h" => self::MODE_TYPE_B, "v" => self::MODE_TYPE_B ); private static $modevalues = null; private $modeflags = 0; private $modeparams = array(); private $channel; public function __construct($channel) { if(self::$modevalues == null) { //build modevalues array $flag = 1; self::$modevalues = array(); foreach(self::$modes as $mode => $type) { self::$modevalues[$mode] = $flag; $flag <<= 1; } } $this->channel = $channel; } public function parseModes($modes) { $args = explode(" ",$modes); $c = 1; for($i = 0; $i < strlen($args[0]); $i++) { $mode = $args[0][$i]; if($mode == "+") continue; if($mode == "-") { //we have no - flag on parseModes??? trigger_error("unexpected MODE_DEL (-) on parseModes (".$modes.").", E_USER_WARNING); break; } if(!array_key_exists($mode, self::$modevalues)) { trigger_error("unknown mode (".$mode.") on parseModes (".$modes.").", E_USER_WARNING); continue; } $flag = self::$modevalues[$mode]; if(self::$modes[$mode] == self::MODE_TYPE_A) continue; //we shouldn't get such a mode on parseModes $this->modeflags |= $flag; if(self::$modes[$mode] == self::MODE_TYPE_B || self::$modes[$mode] == self::MODE_TYPE_C) { $this->modeparams[$mode] = $args[$c++]; } } return $c-1; } public function setModes($modes, $returndiff = false) { $args = explode(" ",$modes); $c = 1; $add = true; $modestradd = "+"; $paramstradd = ""; $modestrdel = "-"; $paramstrdel = ""; for($i = 0; $i < strlen($args[0]); $i++) { $mode = $args[0][$i]; if($mode == "+") { $add = true; continue; } if($mode == "-") { $add = false; continue; } if(!array_key_exists($mode, self::$modevalues)) { trigger_error("unknown mode (".$mode.") on setModes (".$modes.").", E_USER_WARNING); continue; } if($mode == "o" || $mode == "h" || $mode == "v") { if($this->setPrivs($add, $mode, $args[$c++])) { if($returndiff && $add) { $modestradd .= $mode; $paramstradd .= " ".$args[$c-1]; } else if($returndiff && !$add) { $modestrdel .= $mode; $paramstrdel .= " ".$args[$c-1]; } } continue; } else if($mode == "b") { if($this->handleBan($add, $mode, $args[$c++])) { if($returndiff && $add) { $modestradd .= $mode; $paramstradd .= " ".$args[$c-1]; } else if($returndiff && !$add) { $modestrdel .= $mode; $paramstrdel .= " ".$args[$c-1]; } } continue; } $flag = self::$modevalues[$mode]; if($add) { if($returndiff && !($this->modeflags & $flag)) { $modestradd .= $mode; if(self::$modes[$mode] == self::MODE_TYPE_B || self::$modes[$mode] == self::MODE_TYPE_C) { $paramstradd .= " ".$args[$c]; } } $this->modeflags |= $flag; if(self::$modes[$mode] == self::MODE_TYPE_B || self::$modes[$mode] == self::MODE_TYPE_C) { $this->modeparams[$mode] = $args[$c++]; } } else { if($returndiff && ($this->modeflags & $flag)) { $modestrdel .= $mode; if(self::$modes[$mode] == self::MODE_TYPE_C) { $paramstrdel .= " ".$args[$c]; } } $this->modeflags &= ~$flag; if(self::$modes[$mode] == self::MODE_TYPE_B || self::$modes[$mode] == self::MODE_TYPE_C) { unset($this->modeparams[$mode]); } if(self::$modes[$mode] == self::MODE_TYPE_C) $c++; } } if($returndiff) { $modediff = ($modestradd == "+" ? "" : $modestradd); $modediff .= ($modestrdel == "-" ? "" : $modestrdel); $modediff .= $paramstradd.$paramstrdel; return $modediff; } } private function handleBan($add, $mode, $mask) { //no ban management right now... return true; } private function setPrivs($add, $mode, $user) { $user = P10_User::getUserByNum($user); if($user == null) { trigger_error("Tried to set privs on a User that does not exist.", E_USER_ERROR); return; } $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; if($add) $privs |= $privFlag; else $privs &= ~$privFlag; $this->channel->setUserPrivs($user, $privs); return true; } public function getModeString() { $modestr = "+"; $paramstr = ""; foreach(self::$modevalues as $mode => $flag) { if(($this->modeflags & $flag)) { $modestr .= $mode; if(self::$modes[$mode] == self::MODE_TYPE_B || self::$modes[$mode] == self::MODE_TYPE_C) { $paramstr .= " ".$this->modeparams[$mode]; } } } return $modestr.$paramstr; } public function hasMode($mode) { if(!array_key_exists($mode, self::$modevalues)) { trigger_error("unknown mode (".$mode.") on setModes (".$modes.").", E_USER_WARNING); continue; } $flag = self::$modevalues[$mode]; if(self::$modes[$mode] == self::MODE_TYPE_B || self::$modes[$mode] == self::MODE_TYPE_C) { return (($this->modeflags & $flag) ? $this->modeparams[$mode] : false); } else return ($this->modeflags & $flag); } } class P10_UserModeSet { const MODE_WITHOUT_PARAMETER = 1, MODE_WITH_PARAMETER = 2; private static $modes = array( "o" => self::MODE_WITHOUT_PARAMETER, "O" => self::MODE_WITHOUT_PARAMETER, "i" => self::MODE_WITHOUT_PARAMETER, "w" => self::MODE_WITHOUT_PARAMETER, "s" => self::MODE_WITHOUT_PARAMETER, "d" => self::MODE_WITHOUT_PARAMETER, "k" => self::MODE_WITHOUT_PARAMETER, "g" => self::MODE_WITHOUT_PARAMETER, "r" => self::MODE_WITH_PARAMETER, "f" => self::MODE_WITH_PARAMETER, "n" => self::MODE_WITHOUT_PARAMETER, "I" => self::MODE_WITHOUT_PARAMETER, "X" => self::MODE_WITHOUT_PARAMETER, "S" => self::MODE_WITHOUT_PARAMETER, "H" => self::MODE_WITHOUT_PARAMETER, "c" => self::MODE_WITHOUT_PARAMETER, "W" => self::MODE_WITHOUT_PARAMETER, "t" => self::MODE_WITHOUT_PARAMETER, "D" => self::MODE_WITHOUT_PARAMETER, "x" => self::MODE_WITHOUT_PARAMETER ); private static $modevalues = null; private $modeflags = 0; private $modeparams = array(); public function __construct($modes) { if(self::$modevalues == null) { //build modevalues array $flag = 1; self::$modevalues = array(); foreach(self::$modes as $mode => $type) { self::$modevalues[$mode] = $flag; $flag <<= 1; } } $this->parseModes($modes); } public function parseModes($modes) { $args = explode(" ",$modes); $c = 1; for($i = 0; $i < strlen($args[0]); $i++) { $mode = $args[0][$i]; if($mode == "+") continue; if($mode == "-") { //we have no - flag on parseModes??? trigger_error("unexpected MODE_DEL (-) on parseModes (".$modes.").", E_USER_WARNING); break; } if(!array_key_exists($mode, self::$modevalues)) { trigger_error("unknown mode (".$mode.") on parseModes (".$modes.").", E_USER_WARNING); continue; } $flag = self::$modevalues[$mode]; $this->modeflags |= $flag; if(self::$modes[$mode] == self::MODE_WITH_PARAMETER) { $this->modeparams[$mode] = $args[$c++]; } } } public function setModes($modes, $returndiff = false) { $args = explode(" ",$modes); $c = 1; $add = true; $modestradd = "+"; $paramstradd = ""; $modestrdel = "-"; for($i = 0; $i < strlen($args[0]); $i++) { $mode = $args[0][$i]; if($mode == "+") { $add = true; continue; } if($mode == "-") { $add = false; continue; } if(!array_key_exists($mode, self::$modevalues)) { trigger_error("unknown mode (".$mode.") on setModes (".$modes.").", E_USER_WARNING); continue; } $flag = self::$modevalues[$mode]; if($add) { if($returndiff && !($this->modeflags & $flag)) { $modestradd .= $mode; if(self::$modes[$mode] == self::MODE_WITH_PARAMETER) { $paramstradd .= " ".$args[$c]; } } $this->modeflags |= $flag; if(self::$modes[$mode] == self::MODE_WITH_PARAMETER) { $this->modeparams[$mode] = $args[$c++]; } } else { if($returndiff && ($this->modeflags & $flag)) { $modestrdel .= $mode; } $this->modeflags &= ~$flag; } } if($returndiff) { $modediff = ($modestradd == "+" ? "" : $modestradd); $modediff .= ($modestrdel == "-" ? "" : $modestrdel); $modediff .= $paramstradd; return $modediff; } } public function getModeString() { $modestr = "+"; $paramstr = ""; foreach(self::$modevalues as $mode => $flag) { if(($this->modeflags & $flag)) { $modestr .= $mode; if(self::$modes[$mode] == self::MODE_WITH_PARAMETER) { $paramstr .= " ".$this->modeparams[$mode]; } } } return $modestr.$paramstr; } public function hasMode($mode) { if(!array_key_exists($mode, self::$modevalues)) { trigger_error("unknown mode (".$mode.") on setModes (".$modes.").", E_USER_WARNING); continue; } $flag = self::$modevalues[$mode]; if(self::$modes[$mode] == self::MODE_WITH_PARAMETER) { return (($this->modeflags & $flag) ? $this->modeparams[$mode] : false); } else return ($this->modeflags & $flag); } } ?>