changed file headers & added AUTHORS file
[PHP-P10.git] / Uplink / P10_ModeSets.class.php
1 <?php
2 /******************************* PHP-P10 v2 *****************************
3  * Copyright (C) 2011  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                 
71                 //special behavior
72                 "o" => self::MODE_TYPE_B,
73                 "v" => self::MODE_TYPE_B
74         );
75         private static $modevalues = null;
76         private $modeflags = 0;
77         private $modeparams = array();
78         private $channel;
79         
80         public function __construct($channel) {
81                 if(self::$modevalues == null) {
82                         //build modevalues array
83                         $flag = 1;
84                         self::$modevalues = array();
85                         foreach(self::$modes as $mode => $type) {
86                                 self::$modevalues[$mode] = $flag;
87                                 $flag <<= 1;
88                         }
89                 }
90                 $this->channel = $channel;
91         }
92         
93         public function parseModes($modes) {
94                 $args = explode(" ",$modes);
95                 $c = 1;
96                 for($i = 0; $i < strlen($args[0]); $i++) {
97                         $mode = $args[0][$i];
98                         if($mode == "+") continue;
99                         if($mode == "-") { //we have no - flag on parseModes???
100                                 trigger_error("unexpected MODE_DEL (-) on parseModes (".$modes.").", E_USER_WARNING);
101                                 break;
102                         }
103                         if(!array_key_exists($mode, self::$modevalues)) {
104                                 trigger_error("unknown mode (".$mode.") on parseModes (".$modes.").", E_USER_WARNING);
105                                 continue;
106                         }
107                         $flag = self::$modevalues[$mode];
108                         if(self::$modes[$mode] == self::MODE_TYPE_A) continue; //we shouldn't get such a mode on parseModes
109                         $this->modeflags |= $flag;
110                         if(self::$modes[$mode] == self::MODE_TYPE_B || self::$modes[$mode] == self::MODE_TYPE_C) {
111                                 $this->modeparams[$mode] = $args[$c++];
112                         }
113                 }
114                 return $c-1;
115         }
116         
117         public function setModes($modes, $returndiff = false) {
118                 $args = explode(" ",$modes);
119                 $c = 1;
120                 $add = true;
121                 $modestradd = "+";
122                 $paramstradd = "";
123                 $modestrdel = "-";
124                 $paramstrdel = "";
125                 for($i = 0; $i < strlen($args[0]); $i++) {
126                         $mode = $args[0][$i];
127                         if($mode == "+") {
128                                 $add = true;
129                                 continue;
130                         }
131                         if($mode == "-") { 
132                                 $add = false;
133                                 continue;
134                         }
135                         if(!array_key_exists($mode, self::$modevalues)) {
136                                 trigger_error("unknown mode (".$mode.") on setModes (".$modes.").", E_USER_WARNING);
137                                 continue;
138                         }
139                         if($mode == "o" || $mode == "v") {
140                                 if($this->setPrivs($add, $mode, $args[$c++])) {
141                                         if($returndiff && $add) {
142                                                 $modestradd .= $mode;
143                                                 $paramstradd .= " ".$args[$c-1];
144                                         } else if($returndiff && !$add) {
145                                                 $modestrdel .= $mode;
146                                                 $paramstrdel .= " ".$args[$c-1];
147                                         }
148                                 }
149                                 continue;
150                         }
151                         $flag = self::$modevalues[$mode];
152                         if($add) {
153                                 if($returndiff && !($this->modeflags & $flag)) {
154                                         $modestradd .= $mode;
155                                         if(self::$modes[$mode] == self::MODE_TYPE_B || self::$modes[$mode] == self::MODE_TYPE_C) {
156                                                 $paramstradd .= " ".$args[$c];
157                                         }
158                                 }
159                                 $this->modeflags |= $flag;
160                                 if(self::$modes[$mode] == self::MODE_TYPE_B || self::$modes[$mode] == self::MODE_TYPE_C) {
161                                         $this->modeparams[$mode] = $args[$c++];
162                                 }
163                         } else {
164                                 if($returndiff && ($this->modeflags & $flag)) {
165                                         $modestrdel .= $mode;
166                                         if(self::$modes[$mode] == self::MODE_TYPE_C) {
167                                                 $paramstrdel .= " ".$args[$c];
168                                         }
169                                 }
170                                 $this->modeflags &= ~$flag;
171                                 if(self::$modes[$mode] == self::MODE_TYPE_B || self::$modes[$mode] == self::MODE_TYPE_C) {
172                                         unset($this->modeparams[$mode]);
173                                 }
174                                 if(self::$modes[$mode] == self::MODE_TYPE_C) $c++;
175                         }
176                 }
177                 if($returndiff) {
178                         $modediff = ($modestradd == "+" ? "" : $modestradd);
179                         $modediff .= ($modestrdel == "-" ? "" : $modestrdel);
180                         $modediff .= $paramstradd.$paramstrdel;
181                         return $modediff;
182                 }
183         }
184         
185         private function setPrivs($add, $mode, $user) {
186                 $user = P10_User::getUserByNum($user);
187                 if($user == null) {
188                         trigger_error("Tried to set privs on a User that does not exist.", E_USER_ERROR);
189                         return;
190                 }
191                 $privs = $this->channel->getUserPrivs($user);
192                 $privFlag = 0;
193                 if($mode == "o") $privFlag = P10_Channel::USERPRIV_OPED;
194                 if($mode == "v") $privFlag = P10_Channel::USERPRIV_VOICE;
195                 if(!($add xor ($privs & $privFlag)))
196                         return false;
197                 if($add) $privs |= $privFlag;
198                 else $privs &= ~$privFlag;
199                 $this->channel->setUserPrivs($user, $privs);
200                 return true;
201                 
202         }
203         
204         public function getModeString() {
205                 $modestr = "+";
206                 $paramstr = "";
207                 foreach(self::$modevalues as $mode => $flag) {
208                         if(($this->modeflags & $flag)) {
209                                 $modestr .= $mode;
210                                 if(self::$modes[$mode] == self::MODE_TYPE_B || self::$modes[$mode] == self::MODE_TYPE_C) {
211                                         $paramstr .= " ".$this->modeparams[$mode];
212                                 }
213                         }
214                 }
215                 return $modestr.$paramstr;
216         }
217         
218         public function hasMode($mode) {
219                 if(!array_key_exists($mode, self::$modevalues)) {
220                         trigger_error("unknown mode (".$mode.") on setModes (".$modes.").", E_USER_WARNING);
221                         continue;
222                 }
223                 $flag = self::$modevalues[$mode];
224                 if(self::$modes[$mode] == self::MODE_TYPE_B || self::$modes[$mode] == self::MODE_TYPE_C) {
225                         return (($this->modeflags & $flag) ? $this->modeparams[$mode] : false);
226                 } else
227                         return ($this->modeflags & $flag);
228         }
229         
230 }
231
232 class P10_UserModeSet {
233         const MODE_WITHOUT_PARAMETER = 1, MODE_WITH_PARAMETER = 2;
234         private static $modes = array(
235                 "o" => self::MODE_WITHOUT_PARAMETER,
236                 "O" => self::MODE_WITHOUT_PARAMETER,
237                 "i" => self::MODE_WITHOUT_PARAMETER,
238                 "w" => self::MODE_WITHOUT_PARAMETER,
239                 "s" => self::MODE_WITHOUT_PARAMETER,
240                 "d" => self::MODE_WITHOUT_PARAMETER,
241                 "k" => self::MODE_WITHOUT_PARAMETER,
242                 "g" => self::MODE_WITHOUT_PARAMETER,
243                 "r" => self::MODE_WITH_PARAMETER,
244                 "f" => self::MODE_WITH_PARAMETER,
245                 "n" => self::MODE_WITHOUT_PARAMETER,
246                 "I" => self::MODE_WITHOUT_PARAMETER,
247                 "X" => self::MODE_WITHOUT_PARAMETER,
248                 "S" => self::MODE_WITHOUT_PARAMETER,
249                 "H" => self::MODE_WITHOUT_PARAMETER,
250                 "c" => self::MODE_WITHOUT_PARAMETER,
251                 "W" => self::MODE_WITHOUT_PARAMETER,
252                 "t" => self::MODE_WITHOUT_PARAMETER,
253                 "D" => self::MODE_WITHOUT_PARAMETER,
254                 "x" => self::MODE_WITHOUT_PARAMETER
255         );
256         private static $modevalues = null;
257         private $modeflags = 0;
258         private $modeparams = array();
259         
260         public function __construct($modes) {
261                 if(self::$modevalues == null) {
262                         //build modevalues array
263                         $flag = 1;
264                         self::$modevalues = array();
265                         foreach(self::$modes as $mode => $type) {
266                                 self::$modevalues[$mode] = $flag;
267                                 $flag <<= 1;
268                         }
269                 }
270                 $this->parseModes($modes);
271         }
272         
273         public function parseModes($modes) {
274                 $args = explode(" ",$modes);
275                 $c = 1;
276                 for($i = 0; $i < strlen($args[0]); $i++) {
277                         $mode = $args[0][$i];
278                         if($mode == "+") continue;
279                         if($mode == "-") { //we have no - flag on parseModes???
280                                 trigger_error("unexpected MODE_DEL (-) on parseModes (".$modes.").", E_USER_WARNING);
281                                 break;
282                         }
283                         if(!array_key_exists($mode, self::$modevalues)) {
284                                 trigger_error("unknown mode (".$mode.") on parseModes (".$modes.").", E_USER_WARNING);
285                                 continue;
286                         }
287                         $flag = self::$modevalues[$mode];
288                         $this->modeflags |= $flag;
289                         if(self::$modes[$mode] == self::MODE_WITH_PARAMETER) {
290                                 $this->modeparams[$mode] = $args[$c++];
291                         }
292                 }
293         }
294         
295         public function setModes($modes, $returndiff = false) {
296                 $args = explode(" ",$modes);
297                 $c = 1;
298                 $add = true;
299                 $modestradd = "+";
300                 $paramstradd = "";
301                 $modestrdel = "-";
302                 for($i = 0; $i < strlen($args[0]); $i++) {
303                         $mode = $args[0][$i];
304                         if($mode == "+") {
305                                 $add = true;
306                                 continue;
307                         }
308                         if($mode == "-") { 
309                                 $add = false;
310                                 continue;
311                         }
312                         if(!array_key_exists($mode, self::$modevalues)) {
313                                 trigger_error("unknown mode (".$mode.") on setModes (".$modes.").", E_USER_WARNING);
314                                 continue;
315                         }
316                         $flag = self::$modevalues[$mode];
317                         if($add) {
318                                 if($returndiff && !($this->modeflags & $flag)) {
319                                         $modestradd .= $mode;
320                                         if(self::$modes[$mode] == self::MODE_WITH_PARAMETER) {
321                                                 $paramstradd .= " ".$args[$c];
322                                         }
323                                 }
324                                 $this->modeflags |= $flag;
325                                 if(self::$modes[$mode] == self::MODE_WITH_PARAMETER) {
326                                         $this->modeparams[$mode] = $args[$c++];
327                                 }
328                         } else {
329                                 if($returndiff && ($this->modeflags & $flag)) {
330                                         $modestrdel .= $mode;
331                                 }
332                                 $this->modeflags &= ~$flag;
333                         }
334                 }
335                 if($returndiff) {
336                         $modediff = ($modestradd == "+" ? "" : $modestradd);
337                         $modediff .= ($modestrdel == "-" ? "" : $modestrdel);
338                         $modediff .= $paramstradd;
339                         return $modediff;
340                 }
341         }
342         
343         public function getModeString() {
344                 $modestr = "+";
345                 $paramstr = "";
346                 foreach(self::$modevalues as $mode => $flag) {
347                         if(($this->modeflags & $flag)) {
348                                 $modestr .= $mode;
349                                 if(self::$modes[$mode] == self::MODE_WITH_PARAMETER) {
350                                         $paramstr .= " ".$this->modeparams[$mode];
351                                 }
352                         }
353                 }
354                 return $modestr.$paramstr;
355         }
356         
357         public function hasMode($mode) {
358                 if(!array_key_exists($mode, self::$modevalues)) {
359                         trigger_error("unknown mode (".$mode.") on setModes (".$modes.").", E_USER_WARNING);
360                         continue;
361                 }
362                 $flag = self::$modevalues[$mode];
363                 if(self::$modes[$mode] == self::MODE_WITH_PARAMETER) {
364                         return (($this->modeflags & $flag) ? $this->modeparams[$mode] : false);
365                 } else
366                         return ($this->modeflags & $flag);
367         }
368         
369 }
370
371 ?>