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