format
[PHP-P10.git] / Uplink / P10_ModeSets.class.php
index 52eed7d5eb75b9e59e7a06668a740a2a94b24667..aaaf8e73fb2e8c23a9bfe00052f4341ddb7d6fd0 100644 (file)
@@ -1,12 +1,10 @@
 <?php
-/********************************* PHP-P10 ******************************
- *    P10 uplink class by pk910   (c)2011 pk910                         *
- ************************************************************************
- *                          Version 2 (OOP)                             *
+/******************************* PHP-P10 v2 *****************************
+ * Copyright (C) 2011-2012  Philipp Kreil (pk910)                       *
  *                                                                      *
- * PHP-P10 is free software; you can redistribute it and/or modify      *
+ * 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 2 of the License, or    *
+ * 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,      *
  * GNU General Public License for more details.                         *
  *                                                                      *
  * You should have received a copy of the GNU General Public License    *
- * along with PHP-P10; if not, write to the Free Software Foundation,   *
- * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.       *
+ * along with this program. If not, see <http://www.gnu.org/licenses/>. *
  *                                                                      *
  ************************************************************************
- * 
+ *
  *  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 {
-       
-       public __construct($modes) {
-       
+       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 getModeString() {
-       
+
+       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);
+       }
+
 }
 
 ?>
\ No newline at end of file