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