6ed9b530b89e7b5d42ae3c7e844925bd5bf398ca
[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     if((chanuser->flags & CHANUSERFLAG_OPPED_OR_VOICED) && (chanuser->flags & CHANUSERFLAG_INVISIBLE))
149         chanuser->flags &= ~CHANUSERFLAG_INVISIBLE;
150 }
151
152 static void parseModesBan(struct ModeNode* modes, int add, char *mask) {
153     if(modes->chan == NULL) return;
154     if(add)
155         addChannelBan(modes->chan, mask);
156     else
157         removeChannelBanMask(modes->chan, mask);
158 }
159
160 void parseModes(struct ModeNode* modes, char *modeStr, char **argv, int argc) {
161     int i, argpos = 0, add = 1;
162     #define MODE_TYPE (modeOpt[2] & CHANNEL_MODE_TYPE)
163     #define MODE_VALUE (modeOpt[2] & CHANNEL_MODE_VALUE)
164     #define MODE_VALUE_INDEX (modeOpt[2] & CHANNEL_MODE_VALUE_INDEX_MASK) >> CHANNEL_MODE_VALUE_INDEX_SHIFT
165     unsigned int *modeOpt;
166     for(i = 0; i < strlen(modeStr); i++) {
167         if(modeStr[i] == '+') {
168             add = 1;
169             continue;
170         }
171         if(modeStr[i] == '-') {
172             add = 0;
173             continue;
174         }
175         modeOpt = getModeOptions(modeStr[i]);
176         if(!modeOpt) continue; // unknown mode?
177         if(MODE_TYPE == CHANNEL_MODE_TYPE_A) {
178             if(argpos == argc) continue;
179             //special mode ;)
180             switch(modeStr[i]) {
181                 case 'o':
182                     parseModesUserPriv(modes, CHANUSERFLAG_OPPED, add, argv[argpos]);
183                     break;
184                 case 'v':
185                     parseModesUserPriv(modes, CHANUSERFLAG_VOICED, add, argv[argpos]);
186                     break;
187                 case 'b':
188                     parseModesBan(modes, add, argv[argpos]);
189                     break;
190                 default:
191                     //we have an unknown TYPE_A mode???
192                     break;
193             }
194             argpos++;
195             continue;
196         }
197         if(add) {
198             if(MODE_TYPE != CHANNEL_MODE_TYPE_D) { //all other types take parameters when set
199                 if(argpos == argc) continue;
200                 if(MODE_VALUE == CHANNEL_MODE_VALUE_STRING) {
201                     if(modes->mode_str_args[MODE_VALUE_INDEX])
202                         free(modes->mode_str_args[MODE_VALUE_INDEX]);
203                     modes->mode_str_args[MODE_VALUE_INDEX] = strdup(argv[argpos++]);
204                 } else if(MODE_VALUE == CHANNEL_MODE_VALUE_INTEGER)
205                     modes->mode_int_args[MODE_VALUE_INDEX] = atoi(argv[argpos++]);
206                 else
207                     argpos++; //we simply don't know what to do with the argument...
208             }
209             modes->modes |= modeOpt[0];
210             modes->allmodes |= modeOpt[0];
211         } else {
212             modes->modes &= ~modeOpt[0];
213             modes->allmodes |= modeOpt[0];
214             if(MODE_TYPE == CHANNEL_MODE_TYPE_B) {
215                 if(argpos == argc) continue;
216                 if(MODE_VALUE == CHANNEL_MODE_VALUE_STRING) {
217                     free(modes->mode_str_args[MODE_VALUE_INDEX]);
218                     modes->mode_str_args[MODE_VALUE_INDEX] = NULL;
219                 } else if(MODE_VALUE == CHANNEL_MODE_VALUE_INTEGER)
220                     modes->mode_int_args[MODE_VALUE_INDEX] = 0;
221                 argpos++; //we don't need the argument when unsetting a mode...
222             }
223         }
224     }
225     #undef MODE_TYPE
226     #undef MODE_VALUE
227     #undef MODE_VALUE_INDEX
228 }
229
230 void parseModeString(struct ModeNode* modes, char *modeStr) {
231     int argc = 0;
232     char *args[modes_count+1];
233     char *a, *b = modeStr;
234     do {
235         a = strstr(b, " ");
236         if(a) *a = '\0';
237         args[argc++] = b;
238         if(a) b = a+1;
239     } while(a);
240     parseModes(modes, args[0], args+1, argc-1);
241 }
242
243 int parseMode(struct ModeNode* modes, int add, char mode, char *param) {
244     #define MODE_TYPE (modeOpt[2] & CHANNEL_MODE_TYPE)
245     #define MODE_VALUE (modeOpt[2] & CHANNEL_MODE_VALUE)
246     #define MODE_VALUE_INDEX (modeOpt[2] & CHANNEL_MODE_VALUE_INDEX_MASK) >> CHANNEL_MODE_VALUE_INDEX_SHIFT
247     unsigned int *modeOpt = getModeOptions(mode);
248     if(!modeOpt) return 0;
249     if(MODE_TYPE == CHANNEL_MODE_TYPE_A) {
250         if(!param) return 0;
251         //special mode ;)
252         switch(mode) {
253             case 'o':
254                 parseModesUserPriv(modes, CHANUSERFLAG_OPPED, add, param);
255                 break;
256             case 'v':
257                 parseModesUserPriv(modes, CHANUSERFLAG_VOICED, add, param);
258                 break;
259             case 'b':
260                 parseModesBan(modes, add, param);
261                 break;
262             default:
263                 return 0; //we have an unknown TYPE_A mode???
264         }
265     }
266     if(add) {
267         if(MODE_TYPE != CHANNEL_MODE_TYPE_D) { //all other types take parameters when set
268             if(!param) return 0;
269             if(MODE_VALUE == CHANNEL_MODE_VALUE_STRING) {
270                 if(modes->mode_str_args[MODE_VALUE_INDEX])
271                     free(modes->mode_str_args[MODE_VALUE_INDEX]);
272                 modes->mode_str_args[MODE_VALUE_INDEX] = strdup(param);
273             } else if(MODE_VALUE == CHANNEL_MODE_VALUE_INTEGER)
274                 modes->mode_int_args[MODE_VALUE_INDEX] = atoi(param);
275         }
276         modes->modes |= modeOpt[0];
277         modes->allmodes |= modeOpt[0];
278     } else {
279         modes->modes &= ~modeOpt[0];
280         modes->allmodes |= modeOpt[0];
281         if(MODE_TYPE == CHANNEL_MODE_TYPE_B) {
282             if(!param) return 0;
283             if(MODE_VALUE == CHANNEL_MODE_VALUE_STRING) {
284                 free(modes->mode_str_args[MODE_VALUE_INDEX]);
285                 modes->mode_str_args[MODE_VALUE_INDEX] = NULL;
286             } else if(MODE_VALUE == CHANNEL_MODE_VALUE_INTEGER)
287                 modes->mode_int_args[MODE_VALUE_INDEX] = 0;
288         }
289     }
290     #undef MODE_TYPE
291     #undef MODE_VALUE
292     #undef MODE_VALUE_INDEX
293     return 1;
294 }
295
296 void getModeString(struct ModeNode* modes, char *modesStr) {
297     #define MODE_TYPE (mode[2] & CHANNEL_MODE_TYPE)
298     #define MODE_VALUE (mode[2] & CHANNEL_MODE_VALUE)
299     #define MODE_VALUE_INDEX (mode[2] & CHANNEL_MODE_VALUE_INDEX_MASK) >> CHANNEL_MODE_VALUE_INDEX_SHIFT
300     char paramStr[MAXLEN];
301     modesStr[0] = '+';
302     unsigned int *mode;
303     int modePos = 1;
304     int paramPos = 0;
305     for (mode = valid_modes; mode[1]; mode += 3) {
306         if(modes->modes & mode[0]) {
307             modesStr[modePos++] = (char) mode[1];
308             if(MODE_TYPE != CHANNEL_MODE_TYPE_D) {
309                 if(MODE_VALUE == CHANNEL_MODE_VALUE_STRING)
310                     paramPos += sprintf(paramStr + paramPos, " %s", modes->mode_str_args[MODE_VALUE_INDEX]);
311                 else if(MODE_VALUE == CHANNEL_MODE_VALUE_INTEGER)
312                     paramPos += sprintf(paramStr + paramPos, " %d", modes->mode_int_args[MODE_VALUE_INDEX]);
313             }
314         }
315     }
316     paramStr[paramPos] = '\0';
317     strcpy(modesStr + modePos, paramStr);
318     #undef MODE_TYPE
319     #undef MODE_VALUE
320     #undef MODE_VALUE_INDEX
321 }
322
323 void getFullModeString(struct ModeNode* modes, char *modesStr) {
324     #define MODE_TYPE (mode[2] & CHANNEL_MODE_TYPE)
325     #define MODE_VALUE (mode[2] & CHANNEL_MODE_VALUE)
326     #define MODE_VALUE_INDEX (mode[2] & CHANNEL_MODE_VALUE_INDEX_MASK) >> CHANNEL_MODE_VALUE_INDEX_SHIFT
327     char addMode[modes_count+1];
328     int addModePos = 0;
329     char addParams[MAXLEN];
330     addParams[0] = '\0';
331     int addParamsPos = 0;
332     char delMode[modes_count+1];
333     int delModePos = 0;
334     unsigned int *mode;
335     for (mode = valid_modes; mode[1]; mode += 3) {
336         if(modes->allmodes & mode[0]) {
337             if(modes->modes & mode[0]) {
338                 addMode[addModePos++] = (char) mode[1];
339                 if(MODE_TYPE != CHANNEL_MODE_TYPE_D) {
340                     if(MODE_VALUE == CHANNEL_MODE_VALUE_STRING)
341                         addParamsPos += sprintf(addParams + addParamsPos, " %s", modes->mode_str_args[MODE_VALUE_INDEX]);
342                     else if(MODE_VALUE == CHANNEL_MODE_VALUE_INTEGER)
343                         addParamsPos += sprintf(addParams + addParamsPos, " %d", modes->mode_int_args[MODE_VALUE_INDEX]);
344                 }
345             } else {
346                 delMode[delModePos++] = (char) mode[1];
347             }
348         }
349     }
350     addMode[addModePos] = '\0';
351     delMode[delModePos] = '\0';
352     addParams[addParamsPos] = '\0';
353     sprintf(modesStr, "%s%s%s%s%s", (addModePos ? "+" : ""), addMode, (delModePos ? "-" : ""), delMode, addParams);
354     if(*modesStr == '\0') {
355         sprintf(modesStr, "+");
356     }
357     #undef MODE_TYPE
358     #undef MODE_VALUE
359     #undef MODE_VALUE_INDEX
360 }