*** VERSION 5.2.0 ***
[NeonServV5.git] / src / ModeNode.c
1 /* ModeNode.c - NeonServ v5.2
2  * Copyright (C) 2011  Philipp Kreil (pk910)
3  * 
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  * 
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  * 
14  * You should have received a copy of the GNU General Public License 
15  * along with this program. If not, see <http://www.gnu.org/licenses/>. 
16  */
17 #include "ModeNode.h"
18 #include "ChanNode.h"
19 #include "ChanUser.h"
20 #include "UserNode.h"
21 #include "BanNode.h"
22
23 static int modes_with_strarg, modes_with_intarg, modes_count;
24
25 unsigned int valid_modes[] = { /* Thats our mode list :P */
26     1,  'b', CHANNEL_MODE_TYPE_A,
27     2,  'o', CHANNEL_MODE_TYPE_A,
28     3,  'v', CHANNEL_MODE_TYPE_A,
29     4,  'k', CHANNEL_MODE_TYPE_B | CHANNEL_MODE_VALUE_STRING | CHANNEL_MODE_KEY,
30     5,  'a', CHANNEL_MODE_TYPE_C | CHANNEL_MODE_VALUE_INTEGER,
31     6,  'l', CHANNEL_MODE_TYPE_C | CHANNEL_MODE_VALUE_INTEGER,
32     7,  'f', CHANNEL_MODE_TYPE_C | CHANNEL_MODE_VALUE_STRING,
33     8,  'F', CHANNEL_MODE_TYPE_C | CHANNEL_MODE_VALUE_STRING,
34     9,  'c', CHANNEL_MODE_TYPE_D,
35     10, 'C', CHANNEL_MODE_TYPE_D,
36     11, 'i', CHANNEL_MODE_TYPE_D,
37     12, 'm', CHANNEL_MODE_TYPE_D,
38     13, 'M', CHANNEL_MODE_TYPE_D,
39     14, 'n', CHANNEL_MODE_TYPE_D,
40     15, 'N', CHANNEL_MODE_TYPE_D,
41     16, 'p', CHANNEL_MODE_TYPE_D,
42     17, 'r', CHANNEL_MODE_TYPE_D,
43     18, 's', CHANNEL_MODE_TYPE_D,
44     19, 't', CHANNEL_MODE_TYPE_D,
45     20, 'u', CHANNEL_MODE_TYPE_D,
46     21, 'D', CHANNEL_MODE_TYPE_D,
47     22, 'd', CHANNEL_MODE_TYPE_D,
48     23, 'R', CHANNEL_MODE_TYPE_D,
49     24, 'z', CHANNEL_MODE_TYPE_D,
50 //  ^ maximum is 32!!!
51     0x00, 0x00, 0x00
52 };
53
54 void init_ModeNode() {
55     unsigned int *mode, flag = 1;
56     modes_with_strarg = 0;
57     modes_with_intarg = 0;
58     modes_count = 0;
59     for (mode = valid_modes; mode[1]; mode += 3) {
60         if((mode[2] & CHANNEL_MODE_VALUE) == CHANNEL_MODE_VALUE_STRING) {
61             mode[2] |= modes_with_strarg << CHANNEL_MODE_VALUE_INDEX_SHIFT;
62             modes_with_strarg++;
63         }
64         if((mode[2] & CHANNEL_MODE_VALUE) == CHANNEL_MODE_VALUE_INTEGER) {
65             mode[2] |= modes_with_intarg << CHANNEL_MODE_VALUE_INDEX_SHIFT;
66             modes_with_intarg++;
67         }
68         modes_count++;
69         mode[0] = flag;
70         flag = flag << 1;
71     }
72 }
73
74 struct ModeNode *createModeNode(struct ChanNode *chan) {
75     struct ModeNode *modes = malloc(sizeof(*modes));
76     if (!modes)
77     {
78         perror("malloc() failed");
79         return NULL;
80     }
81     modes->chan = chan;
82     modes->modes = 0;
83     modes->allmodes = 0;
84     modes->mode_str_args = calloc(modes_with_strarg, sizeof(char*));
85     modes->mode_int_args = calloc(modes_with_intarg, sizeof(int));
86     return modes;
87 }
88
89 void freeModeNode(struct ModeNode *modes) {
90     int i;
91     for(i = 0; i < modes_with_strarg; i++) {
92         if(modes->mode_str_args[i])
93             free(modes->mode_str_args[i]);
94     }
95     free(modes->mode_str_args);
96     free(modes->mode_int_args);
97     free(modes);
98 }
99
100 static unsigned int* getModeOptions(char mode) {
101     unsigned int *cmode;
102     for (cmode = valid_modes; cmode[1]; cmode += 3) {
103         if(cmode[1] == mode)
104             return cmode;
105     }
106     return NULL;
107 }
108
109 int isModeSet(struct ModeNode* modes, char modeChar) {
110     unsigned int *modeOpt = getModeOptions(modeChar);
111     return (modes->modes & modeOpt[0]);
112 }
113
114 int isModeAffected(struct ModeNode* modes, char modeChar) {
115     unsigned int *modeOpt = getModeOptions(modeChar);
116     return (modes->allmodes & modeOpt[0]);
117 }
118
119 void* getModeValue(struct ModeNode* modes, char modeChar) {
120     #define MODE_VALUE_INDEX (modeOpt[2] & CHANNEL_MODE_VALUE_INDEX_MASK) >> CHANNEL_MODE_VALUE_INDEX_SHIFT
121     unsigned int *modeOpt = getModeOptions(modeChar);
122     if((modeOpt[2] & CHANNEL_MODE_VALUE) == CHANNEL_MODE_VALUE_STRING)
123         return modes->mode_str_args[MODE_VALUE_INDEX];
124     if((modeOpt[2] & CHANNEL_MODE_VALUE) == CHANNEL_MODE_VALUE_INTEGER)
125         return &modes->mode_int_args[MODE_VALUE_INDEX];
126     return NULL;
127     #undef MODE_VALUE_INDEX
128 }
129
130 unsigned int getModeType(struct ModeNode* modes, char modeChar) {
131     #define MODE_VALUE_INDEX (modeOpt[2] & CHANNEL_MODE_VALUE_INDEX_MASK) >> CHANNEL_MODE_VALUE_INDEX_SHIFT
132     unsigned int *modeOpt = getModeOptions(modeChar);
133     if(!modeOpt) return 0;
134     return modeOpt[2];
135     #undef MODE_VALUE_INDEX
136 }
137
138 static void parseModesUserPriv(struct ModeNode* modes, unsigned char flag, int add, char *nick) {
139     if(modes->chan == NULL) return;
140     struct UserNode *user = getUserByNick(nick);
141     if(user == NULL) return;
142     struct ChanUser *chanuser = getChanUser(user, modes->chan);
143     if(chanuser == NULL) return;
144     if(add)
145         chanuser->flags |= flag;
146     else
147         chanuser->flags &= ~flag;
148 }
149
150 static void parseModesBan(struct ModeNode* modes, int add, char *mask) {
151     if(modes->chan == NULL) return;
152     if(add)
153         addChannelBan(modes->chan, mask);
154     else
155         removeChannelBanMask(modes->chan, mask);
156 }
157
158 void parseModes(struct ModeNode* modes, char *modeStr, char **argv, int argc) {
159     int i, argpos = 0, add = 1;
160     #define MODE_TYPE (modeOpt[2] & CHANNEL_MODE_TYPE)
161     #define MODE_VALUE (modeOpt[2] & CHANNEL_MODE_VALUE)
162     #define MODE_VALUE_INDEX (modeOpt[2] & CHANNEL_MODE_VALUE_INDEX_MASK) >> CHANNEL_MODE_VALUE_INDEX_SHIFT
163     unsigned int *modeOpt;
164     for(i = 0; i < strlen(modeStr); i++) {
165         if(modeStr[i] == '+') {
166             add = 1;
167             continue;
168         }
169         if(modeStr[i] == '-') {
170             add = 0;
171             continue;
172         }
173         modeOpt = getModeOptions(modeStr[i]);
174         if(!modeOpt) continue; // unknown mode?
175         if(MODE_TYPE == CHANNEL_MODE_TYPE_A) {
176             if(argpos == argc) continue;
177             //special mode ;)
178             switch(modeStr[i]) {
179                 case 'o':
180                     parseModesUserPriv(modes, CHANUSERFLAG_OPPED, add, argv[argpos]);
181                     break;
182                 case 'v':
183                     parseModesUserPriv(modes, CHANUSERFLAG_VOICED, add, argv[argpos]);
184                     break;
185                 case 'b':
186                     parseModesBan(modes, add, argv[argpos]);
187                     break;
188                 default:
189                     //we have an unknown TYPE_A mode???
190                     break;
191             }
192             argpos++;
193             continue;
194         }
195         if(add) {
196             if(MODE_TYPE != CHANNEL_MODE_TYPE_D) { //all other types take parameters when set
197                 if(argpos == argc) continue;
198                 if(MODE_VALUE == CHANNEL_MODE_VALUE_STRING) {
199                     if(modes->mode_str_args[MODE_VALUE_INDEX])
200                         free(modes->mode_str_args[MODE_VALUE_INDEX]);
201                     modes->mode_str_args[MODE_VALUE_INDEX] = strdup(argv[argpos++]);
202                 } else if(MODE_VALUE == CHANNEL_MODE_VALUE_INTEGER)
203                     modes->mode_int_args[MODE_VALUE_INDEX] = atoi(argv[argpos++]);
204                 else
205                     argpos++; //we simply don't know what to do with the argument...
206             }
207             modes->modes |= modeOpt[0];
208             modes->allmodes |= modeOpt[0];
209         } else {
210             modes->modes &= ~modeOpt[0];
211             modes->allmodes |= modeOpt[0];
212             if(MODE_TYPE == CHANNEL_MODE_TYPE_B) {
213                 if(argpos == argc) continue;
214                 if(MODE_VALUE == CHANNEL_MODE_VALUE_STRING) {
215                     free(modes->mode_str_args[MODE_VALUE_INDEX]);
216                     modes->mode_str_args[MODE_VALUE_INDEX] = NULL;
217                 } else if(MODE_VALUE == CHANNEL_MODE_VALUE_INTEGER)
218                     modes->mode_int_args[MODE_VALUE_INDEX] = 0;
219                 argpos++; //we don't need the argument when unsetting a mode...
220             }
221         }
222     }
223     #undef MODE_TYPE
224     #undef MODE_VALUE
225     #undef MODE_VALUE_INDEX
226 }
227
228 void parseModeString(struct ModeNode* modes, char *modeStr) {
229     int argc = 0;
230     char *args[modes_count+1];
231     char *a, *b = modeStr;
232     do {
233         a = strstr(b, " ");
234         if(a) *a = '\0';
235         args[argc++] = b;
236         if(a) b = a+1;
237     } while(a);
238     parseModes(modes, args[0], args+1, argc-1);
239 }
240
241 int parseMode(struct ModeNode* modes, int add, char mode, char *param) {
242     #define MODE_TYPE (modeOpt[2] & CHANNEL_MODE_TYPE)
243     #define MODE_VALUE (modeOpt[2] & CHANNEL_MODE_VALUE)
244     #define MODE_VALUE_INDEX (modeOpt[2] & CHANNEL_MODE_VALUE_INDEX_MASK) >> CHANNEL_MODE_VALUE_INDEX_SHIFT
245     unsigned int *modeOpt = getModeOptions(mode);
246     if(!modeOpt) return 0;
247     if(MODE_TYPE == CHANNEL_MODE_TYPE_A) {
248         if(!param) return 0;
249         //special mode ;)
250         switch(mode) {
251             case 'o':
252                 parseModesUserPriv(modes, CHANUSERFLAG_OPPED, add, param);
253                 break;
254             case 'v':
255                 parseModesUserPriv(modes, CHANUSERFLAG_VOICED, add, param);
256                 break;
257             case 'b':
258                 parseModesBan(modes, add, param);
259                 break;
260             default:
261                 return 0; //we have an unknown TYPE_A mode???
262         }
263     }
264     if(add) {
265         if(MODE_TYPE != CHANNEL_MODE_TYPE_D) { //all other types take parameters when set
266             if(!param) return 0;
267             if(MODE_VALUE == CHANNEL_MODE_VALUE_STRING) {
268                 if(modes->mode_str_args[MODE_VALUE_INDEX])
269                     free(modes->mode_str_args[MODE_VALUE_INDEX]);
270                 modes->mode_str_args[MODE_VALUE_INDEX] = strdup(param);
271             } else if(MODE_VALUE == CHANNEL_MODE_VALUE_INTEGER)
272                 modes->mode_int_args[MODE_VALUE_INDEX] = atoi(param);
273         }
274         modes->modes |= modeOpt[0];
275         modes->allmodes |= modeOpt[0];
276     } else {
277         modes->modes &= ~modeOpt[0];
278         modes->allmodes |= modeOpt[0];
279         if(MODE_TYPE == CHANNEL_MODE_TYPE_B) {
280             if(!param) return 0;
281             if(MODE_VALUE == CHANNEL_MODE_VALUE_STRING) {
282                 free(modes->mode_str_args[MODE_VALUE_INDEX]);
283                 modes->mode_str_args[MODE_VALUE_INDEX] = NULL;
284             } else if(MODE_VALUE == CHANNEL_MODE_VALUE_INTEGER)
285                 modes->mode_int_args[MODE_VALUE_INDEX] = 0;
286         }
287     }
288     #undef MODE_TYPE
289     #undef MODE_VALUE
290     #undef MODE_VALUE_INDEX
291     return 1;
292 }
293
294 void getModeString(struct ModeNode* modes, char *modesStr) {
295     #define MODE_TYPE (mode[2] & CHANNEL_MODE_TYPE)
296     #define MODE_VALUE (mode[2] & CHANNEL_MODE_VALUE)
297     #define MODE_VALUE_INDEX (mode[2] & CHANNEL_MODE_VALUE_INDEX_MASK) >> CHANNEL_MODE_VALUE_INDEX_SHIFT
298     char paramStr[MAXLEN];
299     modesStr[0] = '+';
300     unsigned int *mode;
301     int modePos = 1;
302     int paramPos = 0;
303     for (mode = valid_modes; mode[1]; mode += 3) {
304         if(modes->modes & mode[0]) {
305             modesStr[modePos++] = (char) mode[1];
306             if(MODE_TYPE != CHANNEL_MODE_TYPE_D) {
307                 if(MODE_VALUE == CHANNEL_MODE_VALUE_STRING)
308                     paramPos += sprintf(paramStr + paramPos, " %s", modes->mode_str_args[MODE_VALUE_INDEX]);
309                 else if(MODE_VALUE == CHANNEL_MODE_VALUE_INTEGER)
310                     paramPos += sprintf(paramStr + paramPos, " %d", modes->mode_int_args[MODE_VALUE_INDEX]);
311             }
312         }
313     }
314     paramStr[paramPos] = '\0';
315     strcpy(modesStr + modePos, paramStr);
316     #undef MODE_TYPE
317     #undef MODE_VALUE
318     #undef MODE_VALUE_INDEX
319 }
320
321 void getFullModeString(struct ModeNode* modes, char *modesStr) {
322     #define MODE_TYPE (mode[2] & CHANNEL_MODE_TYPE)
323     #define MODE_VALUE (mode[2] & CHANNEL_MODE_VALUE)
324     #define MODE_VALUE_INDEX (mode[2] & CHANNEL_MODE_VALUE_INDEX_MASK) >> CHANNEL_MODE_VALUE_INDEX_SHIFT
325     char addMode[modes_count+1];
326     int addModePos = 0;
327     char addParams[MAXLEN];
328     addParams[0] = '\0';
329     int addParamsPos = 0;
330     char delMode[modes_count+1];
331     int delModePos = 0;
332     unsigned int *mode;
333     for (mode = valid_modes; mode[1]; mode += 3) {
334         if(modes->allmodes & mode[0]) {
335             if(modes->modes & mode[0]) {
336                 addMode[addModePos++] = (char) mode[1];
337                 if(MODE_TYPE != CHANNEL_MODE_TYPE_D) {
338                     if(MODE_VALUE == CHANNEL_MODE_VALUE_STRING)
339                         addParamsPos += sprintf(addParams + addParamsPos, " %s", modes->mode_str_args[MODE_VALUE_INDEX]);
340                     else if(MODE_VALUE == CHANNEL_MODE_VALUE_INTEGER)
341                         addParamsPos += sprintf(addParams + addParamsPos, " %d", modes->mode_int_args[MODE_VALUE_INDEX]);
342                 }
343             } else {
344                 delMode[delModePos++] = (char) mode[1];
345             }
346         }
347     }
348     addMode[addModePos] = '\0';
349     delMode[delModePos] = '\0';
350     addParams[addParamsPos] = '\0';
351     sprintf(modesStr, "%s%s%s%s%s", (addModePos ? "+" : ""), addMode, (delModePos ? "-" : ""), delMode, addParams);
352     if(*modesStr == '\0') {
353         sprintf(modesStr, "+");
354     }
355     #undef MODE_TYPE
356     #undef MODE_VALUE
357     #undef MODE_VALUE_INDEX
358 }