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