1 /* ModeNode.c - NeonServ v5.6
2 * Copyright (C) 2011-2012 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/>.
24 static int modes_with_strarg, modes_with_intarg, modes_count;
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,
57 void init_ModeNode() {
58 unsigned int *mode, flag = 1;
59 modes_with_strarg = 0;
60 modes_with_intarg = 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;
67 if((mode[2] & CHANNEL_MODE_VALUE) == CHANNEL_MODE_VALUE_INTEGER) {
68 mode[2] |= modes_with_intarg << CHANNEL_MODE_VALUE_INDEX_SHIFT;
77 struct ModeNode *createModeNode(struct ChanNode *chan) {
78 struct ModeNode *modes = malloc(sizeof(*modes));
81 printf_log("main", LOG_ERROR, "%s:%d malloc() failed", __FILE__, __LINE__);
87 modes->mode_str_args = calloc(modes_with_strarg, sizeof(char*));
88 modes->mode_int_args = calloc(modes_with_intarg, sizeof(int));
92 void freeModeNode(struct ModeNode *modes) {
94 for(i = 0; i < modes_with_strarg; i++) {
95 if(modes->mode_str_args[i])
96 free(modes->mode_str_args[i]);
98 free(modes->mode_str_args);
99 free(modes->mode_int_args);
103 static unsigned int* getModeOptions(char mode) {
105 for (cmode = valid_modes; cmode[1]; cmode += 3) {
112 int isModeSet(struct ModeNode* modes, char modeChar) {
113 unsigned int *modeOpt = getModeOptions(modeChar);
114 return (modes->modes & modeOpt[0]);
117 int isModeAffected(struct ModeNode* modes, char modeChar) {
118 unsigned int *modeOpt = getModeOptions(modeChar);
119 return (modes->allmodes & modeOpt[0]);
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];
130 #undef MODE_VALUE_INDEX
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;
138 #undef MODE_VALUE_INDEX
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;
148 chanuser->flags |= flag;
150 chanuser->flags &= ~flag;
151 if((chanuser->flags & CHANUSERFLAG_OPPED_OR_VOICED) && (chanuser->flags & CHANUSERFLAG_INVISIBLE))
152 chanuser->flags &= ~CHANUSERFLAG_INVISIBLE;
155 static void parseModesBan(struct ModeNode* modes, int add, char *mask) {
156 if(modes->chan == NULL) return;
158 addChannelBan(modes->chan, mask);
160 removeChannelBanMask(modes->chan, mask);
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] == '+') {
174 if(modeStr[i] == '-') {
178 modeOpt = getModeOptions(modeStr[i]);
179 if(!modeOpt) continue; // unknown mode?
180 if(MODE_TYPE == CHANNEL_MODE_TYPE_A) {
181 if(argpos == argc) continue;
185 parseModesUserPriv(modes, CHANUSERFLAG_OPPED, add, argv[argpos]);
188 parseModesUserPriv(modes, CHANUSERFLAG_HALFOPPED, add, argv[argpos]);
191 parseModesUserPriv(modes, CHANUSERFLAG_VOICED, add, argv[argpos]);
194 parseModesBan(modes, add, argv[argpos]);
197 //we have an unknown TYPE_A mode???
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++]);
213 argpos++; //we simply don't know what to do with the argument...
215 modes->modes |= modeOpt[0];
216 modes->allmodes |= modeOpt[0];
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...
233 #undef MODE_VALUE_INDEX
236 void parseModeString(struct ModeNode* modes, char *modeStr) {
238 char *args[modes_count+1];
239 char *a, *b = modeStr;
246 parseModes(modes, args[0], args+1, argc-1);
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) {
260 parseModesUserPriv(modes, CHANUSERFLAG_OPPED, add, param);
263 parseModesUserPriv(modes, CHANUSERFLAG_VOICED, add, param);
266 parseModesBan(modes, add, param);
269 return 0; //we have an unknown TYPE_A mode???
273 if(MODE_TYPE != CHANNEL_MODE_TYPE_D) { //all other types take parameters when set
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);
282 modes->modes |= modeOpt[0];
283 modes->allmodes |= modeOpt[0];
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;
298 #undef MODE_VALUE_INDEX
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];
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]);
322 paramStr[paramPos] = '\0';
323 strcpy(modesStr + modePos, paramStr);
326 #undef MODE_VALUE_INDEX
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];
335 char addParams[MAXLEN];
337 int addParamsPos = 0;
338 char delMode[modes_count+1];
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]);
352 delMode[delModePos++] = (char) mode[1];
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, "+");
365 #undef MODE_VALUE_INDEX