1 /* ModeNode.c - NeonServ v5.2
2 * Copyright (C) 2011 Philipp Kreil (pk910)
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.
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.
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/>.
23 static int modes_with_strarg, modes_with_intarg, modes_count;
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,
54 void init_ModeNode() {
55 unsigned int *mode, flag = 1;
56 modes_with_strarg = 0;
57 modes_with_intarg = 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;
64 if((mode[2] & CHANNEL_MODE_VALUE) == CHANNEL_MODE_VALUE_INTEGER) {
65 mode[2] |= modes_with_intarg << CHANNEL_MODE_VALUE_INDEX_SHIFT;
74 struct ModeNode *createModeNode(struct ChanNode *chan) {
75 struct ModeNode *modes = malloc(sizeof(*modes));
78 perror("malloc() failed");
84 modes->mode_str_args = calloc(modes_with_strarg, sizeof(char*));
85 modes->mode_int_args = calloc(modes_with_intarg, sizeof(int));
89 void freeModeNode(struct ModeNode *modes) {
91 for(i = 0; i < modes_with_strarg; i++) {
92 if(modes->mode_str_args[i])
93 free(modes->mode_str_args[i]);
95 free(modes->mode_str_args);
96 free(modes->mode_int_args);
100 static unsigned int* getModeOptions(char mode) {
102 for (cmode = valid_modes; cmode[1]; cmode += 3) {
109 int isModeSet(struct ModeNode* modes, char modeChar) {
110 unsigned int *modeOpt = getModeOptions(modeChar);
111 return (modes->modes & modeOpt[0]);
114 int isModeAffected(struct ModeNode* modes, char modeChar) {
115 unsigned int *modeOpt = getModeOptions(modeChar);
116 return (modes->allmodes & modeOpt[0]);
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];
127 #undef MODE_VALUE_INDEX
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;
135 #undef MODE_VALUE_INDEX
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;
145 chanuser->flags |= flag;
147 chanuser->flags &= ~flag;
148 if((chanuser->flags & CHANUSERFLAG_OPPED_OR_VOICED) && (chanuser->flags & CHANUSERFLAG_INVISIBLE))
149 chanuser->flags &= ~CHANUSERFLAG_INVISIBLE;
152 static void parseModesBan(struct ModeNode* modes, int add, char *mask) {
153 if(modes->chan == NULL) return;
155 addChannelBan(modes->chan, mask);
157 removeChannelBanMask(modes->chan, mask);
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] == '+') {
171 if(modeStr[i] == '-') {
175 modeOpt = getModeOptions(modeStr[i]);
176 if(!modeOpt) continue; // unknown mode?
177 if(MODE_TYPE == CHANNEL_MODE_TYPE_A) {
178 if(argpos == argc) continue;
182 parseModesUserPriv(modes, CHANUSERFLAG_OPPED, add, argv[argpos]);
185 parseModesUserPriv(modes, CHANUSERFLAG_VOICED, add, argv[argpos]);
188 parseModesBan(modes, add, argv[argpos]);
191 //we have an unknown TYPE_A mode???
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++]);
207 argpos++; //we simply don't know what to do with the argument...
209 modes->modes |= modeOpt[0];
210 modes->allmodes |= modeOpt[0];
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...
227 #undef MODE_VALUE_INDEX
230 void parseModeString(struct ModeNode* modes, char *modeStr) {
232 char *args[modes_count+1];
233 char *a, *b = modeStr;
240 parseModes(modes, args[0], args+1, argc-1);
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) {
254 parseModesUserPriv(modes, CHANUSERFLAG_OPPED, add, param);
257 parseModesUserPriv(modes, CHANUSERFLAG_VOICED, add, param);
260 parseModesBan(modes, add, param);
263 return 0; //we have an unknown TYPE_A mode???
267 if(MODE_TYPE != CHANNEL_MODE_TYPE_D) { //all other types take parameters when set
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);
276 modes->modes |= modeOpt[0];
277 modes->allmodes |= modeOpt[0];
279 modes->modes &= ~modeOpt[0];
280 modes->allmodes |= modeOpt[0];
281 if(MODE_TYPE == CHANNEL_MODE_TYPE_B) {
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;
292 #undef MODE_VALUE_INDEX
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];
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]);
316 paramStr[paramPos] = '\0';
317 strcpy(modesStr + modePos, paramStr);
320 #undef MODE_VALUE_INDEX
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];
329 char addParams[MAXLEN];
331 int addParamsPos = 0;
332 char delMode[modes_count+1];
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]);
346 delMode[delModePos++] = (char) mode[1];
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, "+");
359 #undef MODE_VALUE_INDEX