612ee65fa739ceef377e3e7086a45fd7c954e95c
[PHP-P10.git] / Uplink / P10_ModeSets.class.php
1 <?php
2 /********************************* PHP-P10 ******************************
3  *    P10 uplink class by pk910   (c)2011 pk910                         *
4  ************************************************************************
5  *                          Version 2 (OOP)                             *
6  *                                                                      *
7  * PHP-P10 is free software; you can redistribute it and/or modify      *
8  * it under the terms of the GNU General Public License as published by *
9  * the Free Software Foundation; either version 2 of the License, or    *
10  * (at your option) any later version.                                  *
11  *                                                                      *
12  * This program is distributed in the hope that it will be useful,      *
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of       *
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the        *
15  * GNU General Public License for more details.                         *
16  *                                                                      *
17  * You should have received a copy of the GNU General Public License    *
18  * along with PHP-P10; if not, write to the Free Software Foundation,   *
19  * Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA.       *
20  *                                                                      *
21  ************************************************************************
22  * 
23  *  Uplink/P10_ModeSets.class.php
24  *
25  * classes to parse and store channel or user modes
26  *
27  */
28
29 class P10_ChannelModeSet {
30         const MODE_TYPE_A = 1, MODE_TYPE_B = 2, MODE_TYPE_C = 3, MODE_TYPE_D = 4;
31         /** http://www.irc.org/tech_docs/draft-brocklesby-irc-isupport-03.txt
32          * Section 3.3 CHANMODES
33          *
34          * Type A: Modes that add or remove an address to or from a list.
35          *   These modes always take a parameter when sent by the server to a
36          *   client; when sent by a client, they may be specified without a
37          *   parameter, which requests the server to display the current
38          *   contents of the corresponding list on the channel to the client.
39          *
40          * Type B: Modes that change a setting on the channel.  These modes
41          *   always take a parameter.
42          *
43          * Type C: Modes that change a setting on the channel. These modes
44          *   take a parameter only when set; the parameter is absent when the
45          *   mode is removed both in the client's and server's MODE command.
46          *
47          * Type D: Modes that change a setting on the channel. These modes
48          *   never take a parameter.
49          **/
50         private static $modes = array(
51                 "b" => self::MODE_TYPE_A,
52                 "k" => self::MODE_TYPE_B,
53                 "a" => self::MODE_TYPE_C,
54                 "l" => self::MODE_TYPE_C,
55                 "f" => self::MODE_TYPE_C,
56                 "F" => self::MODE_TYPE_C,
57                 "c" => self::MODE_TYPE_D,
58                 "C" => self::MODE_TYPE_D,
59                 "i" => self::MODE_TYPE_D,
60                 "m" => self::MODE_TYPE_D,
61                 "M" => self::MODE_TYPE_D,
62                 "n" => self::MODE_TYPE_D,
63                 "N" => self::MODE_TYPE_D,
64                 "p" => self::MODE_TYPE_D,
65                 "r" => self::MODE_TYPE_D,
66                 "s" => self::MODE_TYPE_D,
67                 "t" => self::MODE_TYPE_D,
68                 "u" => self::MODE_TYPE_D,
69                 "D" => self::MODE_TYPE_D,
70                 "d" => self::MODE_TYPE_D,
71                 "R" => self::MODE_TYPE_D,
72                 "z" => self::MODE_TYPE_D,
73                 
74                 //special behavior
75                 "o" => self::MODE_TYPE_B,
76                 "v" => self::MODE_TYPE_B
77         );
78         private static $modevalues = null;
79         private $modeflags = 0;
80         private $modeparams = array();
81         private $channel;
82         
83         public function __construct($channel) {
84                 if(self::$modevalues == null) {
85                         //build modevalues array
86                         $flag = 1;
87                         self::$modevalues = array();
88                         foreach(self::$modes as $mode => $type) {
89                                 self::$modevalues[$mode] = $flag;
90                                 $flag <<= 1;
91                         }
92                 }
93                 $this->channel = $channel;
94         }
95         
96         public function parseModes($modes) {
97                 $args = explode(" ",$modes);
98                 $c = 1;
99                 for($i = 0; $i < strlen($args[0]); $i++) {
100                         $mode = $args[0][$i];
101                         if($mode == "+") continue;
102                         if($mode == "-") { //we have no - flag on parseModes???
103                                 trigger_error("unexpected MODE_DEL (-) on parseModes (".$modes.").", E_USER_WARNING);
104                                 break;
105                         }
106                         if(!array_key_exists($mode, self::$modevalues)) {
107                                 trigger_error("unknown mode (".$mode.") on parseModes (".$modes.").", E_USER_WARNING);
108                                 continue;
109                         }
110                         $flag = self::$modevalues[$mode];
111                         if(self::$modes[$mode] == self::MODE_TYPE_A) continue; //we shouldn't get such a mode on parseModes
112                         $this->modeflags |= $flag;
113                         if(self::$modes[$mode] == self::MODE_TYPE_B || self::$modes[$mode] == self::MODE_TYPE_C) {
114                                 $this->modeparams[$mode] = $args[$c++];
115                         }
116                 }
117                 return $c-1;
118         }
119         
120         public function setModes($modes, $returndiff = false) {
121                 $args = explode(" ",$modes);
122                 $c = 1;
123                 $add = true;
124                 $modestradd = "+";
125                 $paramstradd = "";
126                 $modestrdel = "-";
127                 $paramstrdel = "";
128                 for($i = 0; $i < strlen($args[0]); $i++) {
129                         $mode = $args[0][$i];
130                         if($mode == "+") {
131                                 $add = true;
132                                 continue;
133                         }
134                         if($mode == "-") { 
135                                 $add = false;
136                                 continue;
137                         }
138                         if(!array_key_exists($mode, self::$modevalues)) {
139                                 trigger_error("unknown mode (".$mode.") on setModes (".$modes.").", E_USER_WARNING);
140                                 continue;
141                         }
142                         if($mode == "o" || $mode == "v") {
143                                 if($this->setPrivs($add, $mode, $args[$c++])) {
144                                         if($returndiff && $add) {
145                                                 $modestradd .= $mode;
146                                                 $paramstradd .= " ".$args[$c-1];
147                                         } else if($returndiff && !$add) {
148                                                 $modestrdel .= $mode;
149                                                 $paramstrdel .= " ".$args[$c-1];
150                                         }
151                                 }
152                                 continue;
153                         }
154                         $flag = self::$modevalues[$mode];
155                         if($add) {
156                                 if($returndiff && !($this->modeflags & $flag)) {
157                                         $modestradd .= $mode;
158                                         if(self::$modes[$mode] == self::MODE_TYPE_B || self::$modes[$mode] == self::MODE_TYPE_C) {
159                                                 $paramstradd .= " ".$args[$c];
160                                         }
161                                 }
162                                 $this->modeflags |= $flag;
163                                 if(self::$modes[$mode] == self::MODE_TYPE_B || self::$modes[$mode] == self::MODE_TYPE_C) {
164                                         $this->modeparams[$mode] = $args[$c++];
165                                 }
166                         } else {
167                                 if($returndiff && ($this->modeflags & $flag)) {
168                                         $modestrdel .= $mode;
169                                         if(self::$modes[$mode] == self::MODE_TYPE_C) {
170                                                 $paramstrdel .= " ".$args[$c];
171                                         }
172                                 }
173                                 $this->modeflags &= ~$flag;
174                                 if(self::$modes[$mode] == self::MODE_TYPE_B || self::$modes[$mode] == self::MODE_TYPE_C) {
175                                         unset($this->modeparams[$mode]);
176                                 }
177                                 if(self::$modes[$mode] == self::MODE_TYPE_C) $c++;
178                         }
179                 }
180                 if($returndiff) {
181                         $modediff = ($modestradd == "+" ? "" : $modestradd);
182                         $modediff .= ($modestrdel == "-" ? "" : $modestrdel);
183                         $modediff .= $paramstradd.$paramstrdel;
184                         return $modediff;
185                 }
186         }
187         
188         private function setPrivs($add, $mode, $user) {
189                 $user = P10_User::getUserByNum($user);
190                 if($user == null) {
191                         trigger_error("Tried to set privs on a User that does not exist.", E_USER_ERROR);
192                         return;
193                 }
194                 $privs = $this->channel->getUserPrivs($user);
195                 $privFlag = 0;
196                 if($mode == "o") $privFlag = P10_Channel::USERPRIV_OPED;
197                 if($mode == "v") $privFlag = P10_Channel::USERPRIV_VOICE;
198                 if(!($add xor ($privs & $privFlag)))
199                         return false;
200                 if($add) $privs |= $privFlag;
201                 else $privs &= ~$privFlag;
202                 $this->channel->setUserPrivs($user, $privs);
203                 return true;
204                 
205         }
206         
207         public function getModeString() {
208                 $modestr = "+";
209                 $paramstr = "";
210                 foreach(self::$modevalues as $mode => $flag) {
211                         if(($this->modeflags & $flag)) {
212                                 $modestr .= $mode;
213                                 if(self::$modes[$mode] == self::MODE_TYPE_B || self::$modes[$mode] == self::MODE_TYPE_C) {
214                                         $paramstr .= " ".$this->modeparams[$mode];
215                                 }
216                         }
217                 }
218                 return $modestr.$paramstr;
219         }
220         
221         public function hasMode($mode) {
222                 if(!array_key_exists($mode, self::$modevalues)) {
223                         trigger_error("unknown mode (".$mode.") on setModes (".$modes.").", E_USER_WARNING);
224                         continue;
225                 }
226                 $flag = self::$modevalues[$mode];
227                 if(self::$modes[$mode] == self::MODE_TYPE_B || self::$modes[$mode] == self::MODE_TYPE_C) {
228                         return (($this->modeflags & $flag) ? $this->modeparams[$mode] : false);
229                 } else
230                         return ($this->modeflags & $flag);
231         }
232         
233 }
234
235 class P10_UserModeSet {
236         const MODE_WITHOUT_PARAMETER = 1, MODE_WITH_PARAMETER = 2;
237         private static $modes = array(
238                 "o" => self::MODE_WITHOUT_PARAMETER,
239                 "O" => self::MODE_WITHOUT_PARAMETER,
240                 "i" => self::MODE_WITHOUT_PARAMETER,
241                 "w" => self::MODE_WITHOUT_PARAMETER,
242                 "s" => self::MODE_WITHOUT_PARAMETER,
243                 "d" => self::MODE_WITHOUT_PARAMETER,
244                 "k" => self::MODE_WITHOUT_PARAMETER,
245                 "g" => self::MODE_WITHOUT_PARAMETER,
246                 "r" => self::MODE_WITH_PARAMETER,
247                 "f" => self::MODE_WITH_PARAMETER,
248                 "n" => self::MODE_WITHOUT_PARAMETER,
249                 "I" => self::MODE_WITHOUT_PARAMETER,
250                 "X" => self::MODE_WITHOUT_PARAMETER,
251                 "S" => self::MODE_WITHOUT_PARAMETER,
252                 "H" => self::MODE_WITHOUT_PARAMETER,
253                 "c" => self::MODE_WITHOUT_PARAMETER,
254                 "W" => self::MODE_WITHOUT_PARAMETER,
255                 "t" => self::MODE_WITHOUT_PARAMETER,
256                 "D" => self::MODE_WITHOUT_PARAMETER,
257                 "x" => self::MODE_WITHOUT_PARAMETER
258         );
259         private static $modevalues = null;
260         private $modeflags = 0;
261         private $modeparams = array();
262         
263         public function __construct($modes) {
264                 if(self::$modevalues == null) {
265                         //build modevalues array
266                         $flag = 1;
267                         self::$modevalues = array();
268                         foreach(self::$modes as $mode => $type) {
269                                 self::$modevalues[$mode] = $flag;
270                                 $flag <<= 1;
271                         }
272                 }
273                 $this->parseModes($modes);
274         }
275         
276         public function parseModes($modes) {
277                 $args = explode(" ",$modes);
278                 $c = 1;
279                 for($i = 0; $i < strlen($args[0]); $i++) {
280                         $mode = $args[0][$i];
281                         if($mode == "+") continue;
282                         if($mode == "-") { //we have no - flag on parseModes???
283                                 trigger_error("unexpected MODE_DEL (-) on parseModes (".$modes.").", E_USER_WARNING);
284                                 break;
285                         }
286                         if(!array_key_exists($mode, self::$modevalues)) {
287                                 trigger_error("unknown mode (".$mode.") on parseModes (".$modes.").", E_USER_WARNING);
288                                 continue;
289                         }
290                         $flag = self::$modevalues[$mode];
291                         $this->modeflags |= $flag;
292                         if(self::$modes[$mode] == self::MODE_WITH_PARAMETER) {
293                                 $this->modeparams[$mode] = $args[$c++];
294                         }
295                 }
296         }
297         
298         public function setModes($modes, $returndiff = false) {
299                 $args = explode(" ",$modes);
300                 $c = 1;
301                 $add = true;
302                 $modestradd = "+";
303                 $paramstradd = "";
304                 $modestrdel = "-";
305                 for($i = 0; $i < strlen($args[0]); $i++) {
306                         $mode = $args[0][$i];
307                         if($mode == "+") {
308                                 $add = true;
309                                 continue;
310                         }
311                         if($mode == "-") { 
312                                 $add = false;
313                                 continue;
314                         }
315                         if(!array_key_exists($mode, self::$modevalues)) {
316                                 trigger_error("unknown mode (".$mode.") on setModes (".$modes.").", E_USER_WARNING);
317                                 continue;
318                         }
319                         $flag = self::$modevalues[$mode];
320                         if($add) {
321                                 if($returndiff && !($this->modeflags & $flag)) {
322                                         $modestradd .= $mode;
323                                         if(self::$modes[$mode] == self::MODE_WITH_PARAMETER) {
324                                                 $paramstradd .= " ".$args[$c];
325                                         }
326                                 }
327                                 $this->modeflags |= $flag;
328                                 if(self::$modes[$mode] == self::MODE_WITH_PARAMETER) {
329                                         $this->modeparams[$mode] = $args[$c++];
330                                 }
331                         } else {
332                                 if($returndiff && ($this->modeflags & $flag)) {
333                                         $modestrdel .= $mode;
334                                 }
335                                 $this->modeflags &= ~$flag;
336                         }
337                 }
338                 if($returndiff) {
339                         $modediff = ($modestradd == "+" ? "" : $modestradd);
340                         $modediff .= ($modestrdel == "-" ? "" : $modestrdel);
341                         $modediff .= $paramstradd;
342                         return $modediff;
343                 }
344         }
345         
346         public function getModeString() {
347                 $modestr = "+";
348                 $paramstr = "";
349                 foreach(self::$modevalues as $mode => $flag) {
350                         if(($this->modeflags & $flag)) {
351                                 $modestr .= $mode;
352                                 if(self::$modes[$mode] == self::MODE_WITH_PARAMETER) {
353                                         $paramstr .= " ".$this->modeparams[$mode];
354                                 }
355                         }
356                 }
357                 return $modestr.$paramstr;
358         }
359         
360         public function hasMode($mode) {
361                 if(!array_key_exists($mode, self::$modevalues)) {
362                         trigger_error("unknown mode (".$mode.") on setModes (".$modes.").", E_USER_WARNING);
363                         continue;
364                 }
365                 $flag = self::$modevalues[$mode];
366                 if(self::$modes[$mode] == self::MODE_WITH_PARAMETER) {
367                         return (($this->modeflags & $flag) ? $this->modeparams[$mode] : false);
368                 } else
369                         return ($this->modeflags & $flag);
370         }
371         
372 }
373
374 ?>