added P10_Channel.class.php and recv_burst
[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_WITH_PARAMETER) {
214                                         $paramstr .= " ".$this->modeparams[$mode];
215                                 }
216                         }
217                 }
218                 return $modestr.$paramstr;
219         }
220         
221 }
222
223 class P10_UserModeSet {
224         const MODE_WITHOUT_PARAMETER = 1, MODE_WITH_PARAMETER = 2;
225         private static $modes = array(
226                 "o" => self::MODE_WITHOUT_PARAMETER,
227                 "O" => self::MODE_WITHOUT_PARAMETER,
228                 "i" => self::MODE_WITHOUT_PARAMETER,
229                 "w" => self::MODE_WITHOUT_PARAMETER,
230                 "s" => self::MODE_WITHOUT_PARAMETER,
231                 "d" => self::MODE_WITHOUT_PARAMETER,
232                 "k" => self::MODE_WITHOUT_PARAMETER,
233                 "g" => self::MODE_WITH_PARAMETER,
234                 "r" => self::MODE_WITH_PARAMETER,
235                 "f" => self::MODE_WITH_PARAMETER,
236                 "n" => self::MODE_WITHOUT_PARAMETER,
237                 "I" => self::MODE_WITHOUT_PARAMETER,
238                 "X" => self::MODE_WITHOUT_PARAMETER,
239                 "S" => self::MODE_WITHOUT_PARAMETER,
240                 "H" => self::MODE_WITHOUT_PARAMETER,
241                 "c" => self::MODE_WITHOUT_PARAMETER,
242                 "W" => self::MODE_WITHOUT_PARAMETER,
243                 "t" => self::MODE_WITHOUT_PARAMETER,
244                 "D" => self::MODE_WITHOUT_PARAMETER,
245                 "x" => self::MODE_WITHOUT_PARAMETER
246         );
247         private static $modevalues = null;
248         private $modeflags = 0;
249         private $modeparams = array();
250         
251         public function __construct($modes) {
252                 if(self::$modevalues == null) {
253                         //build modevalues array
254                         $flag = 1;
255                         self::$modevalues = array();
256                         foreach(self::$modes as $mode => $type) {
257                                 self::$modevalues[$mode] = $flag;
258                                 $flag <<= 1;
259                         }
260                 }
261                 $this->parseModes($modes);
262         }
263         
264         public function parseModes($modes) {
265                 $args = explode(" ",$modes);
266                 $c = 1;
267                 for($i = 0; $i < strlen($args[0]); $i++) {
268                         $mode = $args[0][$i];
269                         if($mode == "+") continue;
270                         if($mode == "-") { //we have no - flag on parseModes???
271                                 trigger_error("unexpected MODE_DEL (-) on parseModes (".$modes.").", E_USER_WARNING);
272                                 break;
273                         }
274                         if(!array_key_exists($mode, self::$modevalues)) {
275                                 trigger_error("unknown mode (".$mode.") on parseModes (".$modes.").", E_USER_WARNING);
276                                 continue;
277                         }
278                         $flag = self::$modevalues[$mode];
279                         $this->modeflags |= $flag;
280                         if(self::$modevalues[$mode] == self::MODE_WITH_PARAMETER) {
281                                 $this->modeparams[$mode] = $args[$c++];
282                         }
283                 }
284         }
285         
286         public function setModes($modes, $returndiff = false) {
287                 $args = explode(" ",$modes);
288                 $c = 1;
289                 $add = true;
290                 $modestradd = "+";
291                 $paramstradd = "";
292                 $modestrdel = "-";
293                 for($i = 0; $i < strlen($args[0]); $i++) {
294                         $mode = $args[0][$i];
295                         if($mode == "+") {
296                                 $add = true;
297                                 continue;
298                         }
299                         if($mode == "-") { 
300                                 $add = false;
301                                 continue;
302                         }
303                         if(!array_key_exists($mode, self::$modevalues)) {
304                                 trigger_error("unknown mode (".$mode.") on setModes (".$modes.").", E_USER_WARNING);
305                                 continue;
306                         }
307                         $flag = self::$modevalues[$mode];
308                         if($add) {
309                                 if($returndiff && !($this->modeflags & $flag)) {
310                                         $modestradd .= $mode;
311                                         if(self::$modevalues[$mode] == self::MODE_WITH_PARAMETER) {
312                                                 $paramstradd .= " ".$args[$c];
313                                         }
314                                 }
315                                 $this->modeflags |= $flag;
316                                 if(self::$modevalues[$mode] == self::MODE_WITH_PARAMETER) {
317                                         $this->modeparams[$mode] = $args[$c++];
318                                 }
319                         } else {
320                                 if($returndiff && ($this->modeflags & $flag)) {
321                                         $modestrdel .= $mode;
322                                 }
323                                 $this->modeflags &= ~$flag;
324                         }
325                 }
326                 if($returndiff) {
327                         $modediff = ($modestradd == "+" ? "" : $modestradd);
328                         $modediff .= ($modestrdel == "-" ? "" : $modestrdel);
329                         $modediff .= $paramstradd;
330                         return $modediff;
331                 }
332         }
333         
334         public function getModeString() {
335                 $modestr = "+";
336                 $paramstr = "";
337                 foreach(self::$modevalues as $mode => $flag) {
338                         if(($this->modeflags & $flag)) {
339                                 $modestr .= $mode;
340                                 if(self::$modevalues[$mode] == self::MODE_WITH_PARAMETER) {
341                                         $paramstr .= " ".$this->modeparams[$mode];
342                                 }
343                         }
344                 }
345                 return $modestr.$paramstr;
346         }
347         
348 }
349
350 ?>