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