added scripting interfaces (addUser, delUser, join, part, kick, privmsg, notice,...
[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::$modevalues[$mode] == self::MODE_TYPE_A) continue; //we shouldn't get such a mode on parseModes
112                         $this->modeflags |= $flag;
113                         if(self::$modevalues[$mode] == self::MODE_TYPE_B || self::$modevalues[$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::$modevalues[$mode] == self::MODE_TYPE_B || self::$modevalues[$mode] == self::MODE_TYPE_C) {
159                                                 $paramstradd .= " ".$args[$c];
160                                         }
161                                 }
162                                 $this->modeflags |= $flag;
163                                 if(self::$modevalues[$mode] == self::MODE_TYPE_B || self::$modevalues[$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::$modevalues[$mode] == self::MODE_TYPE_C) {
170                                                 $paramstrdel .= " ".$args[$c];
171                                         }
172                                 }
173                                 $this->modeflags &= ~$flag;
174                                 if(self::$modevalues[$mode] == self::MODE_TYPE_B || self::$modevalues[$mode] == self::MODE_TYPE_C) {
175                                         unset($this->modeparams[$mode]);
176                                 }
177                                 if(self::$modevalues[$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::$modevalues[$mode] == self::MODE_TYPE_B || self::$modevalues[$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                 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_WITH_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::$modevalues[$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::$modevalues[$mode] == self::MODE_WITH_PARAMETER) {
321                                                 $paramstradd .= " ".$args[$c];
322                                         }
323                                 }
324                                 $this->modeflags |= $flag;
325                                 if(self::$modevalues[$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::$modevalues[$mode] == self::MODE_WITH_PARAMETER) {
350                                         $paramstr .= " ".$this->modeparams[$mode];
351                                 }
352                         }
353                 }
354                 return $modestr.$paramstr;
355         }
356         
357 }
358
359 ?>