7 static struct ChanNode **chanList;
8 static int modes_with_strarg, modes_with_intarg;
10 //Types: http://www.irc.org/tech_docs/draft-brocklesby-irc-isupport-03.txt
11 #define CHANNEL_MODE_TYPE_A 0x01 /* ... special (addresses or users) ... */
12 #define CHANNEL_MODE_TYPE_B 0x02 /* These modes always take a parameter. */
13 #define CHANNEL_MODE_TYPE_C 0x03 /* These modes take a parameter only when set. */
14 #define CHANNEL_MODE_TYPE_D 0x04 /* These modes never take a parameter. */
15 #define CHANNEL_MODE_TYPE 0x07 /* bit mask to get the type */
17 #define CHANNEL_MODE_VALUE_STRING 0x10
18 #define CHANNEL_MODE_VALUE_INTEGER 0x20
19 #define CHANNEL_MODE_VALUE 0x30 /* bit mask to get the value */
21 #define CHANNEL_MODE_VALUE_INDEX_SHIFT 8
22 #define CHANNEL_MODE_VALUE_INDEX_MASK (0xff << CHANNEL_MODE_VALUE_INDEX_SHIFT) /* this "bitrange" is reserved for storing the array indexes of the mode values */
24 static unsigned int valid_modes[] = { /* Thats our mode list :P */
25 1, 'b', CHANNEL_MODE_TYPE_A,
26 2, 'o', CHANNEL_MODE_TYPE_A,
27 3, 'v', CHANNEL_MODE_TYPE_A,
28 4, 'k', CHANNEL_MODE_TYPE_B | CHANNEL_MODE_VALUE_STRING,
29 5, 'a', CHANNEL_MODE_TYPE_C | CHANNEL_MODE_VALUE_INTEGER,
30 6, 'l', CHANNEL_MODE_TYPE_C | CHANNEL_MODE_VALUE_INTEGER,
31 7, 'f', CHANNEL_MODE_TYPE_C | CHANNEL_MODE_VALUE_STRING,
32 8, 'F', CHANNEL_MODE_TYPE_C | CHANNEL_MODE_VALUE_STRING,
33 9, 'c', CHANNEL_MODE_TYPE_D,
34 10, 'C', CHANNEL_MODE_TYPE_D,
35 11, 'i', CHANNEL_MODE_TYPE_D,
36 12, 'm', CHANNEL_MODE_TYPE_D,
37 13, 'M', CHANNEL_MODE_TYPE_D,
38 14, 'n', CHANNEL_MODE_TYPE_D,
39 15, 'N', CHANNEL_MODE_TYPE_D,
40 16, 'p', CHANNEL_MODE_TYPE_D,
41 17, 'r', CHANNEL_MODE_TYPE_D,
42 18, 's', CHANNEL_MODE_TYPE_D,
43 19, 't', CHANNEL_MODE_TYPE_D,
44 20, 'u', CHANNEL_MODE_TYPE_D,
45 21, 'D', CHANNEL_MODE_TYPE_D,
46 22, 'd', CHANNEL_MODE_TYPE_D,
47 23, 'R', CHANNEL_MODE_TYPE_D,
48 24, 'z', CHANNEL_MODE_TYPE_D,
53 void init_ChanNode() {
59 1 46 *everything else*
60 ---------------------------
63 #define CHANNEL_LIST_SIZE 47
64 chanList = calloc(CHANNEL_LIST_SIZE, sizeof(*chanList));
65 unsigned int *mode, flag = 1;
66 modes_with_strarg = 0;
67 modes_with_intarg = 0;
68 for (mode = valid_modes; mode[1]; mode += 3) {
69 if((mode[2] & CHANNEL_MODE_VALUE) == CHANNEL_MODE_VALUE_STRING) {
70 mode[2] |= modes_with_strarg << CHANNEL_MODE_VALUE_INDEX_SHIFT;
73 if((mode[2] & CHANNEL_MODE_VALUE) == CHANNEL_MODE_VALUE_INTEGER) {
74 mode[2] |= modes_with_intarg << CHANNEL_MODE_VALUE_INDEX_SHIFT;
82 void free_ChanNode() {
83 //kamikaze free all channels and chanusers
85 struct ChanNode *chan, *next;
86 struct ChanUser *chanuser, *next_chanuser;
87 for(i = 0; i < CHANNEL_LIST_SIZE; i++) {
88 for(chan = chanList[i]; chan; chan = next) {
90 for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = next_chanuser) {
91 next_chanuser = getChannelUsers(chan, chanuser);
100 int is_valid_chan(const char *name) {
104 for (ii=1; name[ii]; ++ii) {
105 if ((name[ii] > 0) && (name[ii] <= 32))
109 if (name[ii] == '\xa0')
115 static int get_chanlist_entry(int name) {
116 if((name > 0 && name <= 32) || name == ',' || name == '\xa0') return -1; //invalid name
117 if(tolower(name) >= 97 && tolower(name) <= 122) {
118 return (tolower(name) - 97);
120 if(tolower(name) >= 48 && tolower(name) <= 57) {
121 return (tolower(name) - 48 + 26);
124 if(name == '{') return 36;
125 if(name == '|') return 37;
126 if(name == '}') return 38;
127 if(name == '~') return 39;
128 if(name == '[') return 40;
129 if(name == '\\') return 41;
130 if(name == ']') return 42;
131 if(name == '^') return 43;
132 if(name == '_') return 44;
133 if(name == '`') return 45;
137 struct ChanNode* getChanByName(const char *name) { //case insensitive
138 int chanListIndex = get_chanlist_entry(name[1]);
139 if(chanListIndex == -1 || chanList[chanListIndex] == NULL)
141 struct ChanNode *chan;
142 for(chan = chanList[chanListIndex]; chan; chan = chan->next) {
143 if(!stricmp(name, chan->name))
149 struct ChanNode* addChannel(const char *name) {
150 int chanListIndex = get_chanlist_entry(name[1]);
151 if(chanListIndex == -1 || !is_valid_chan(name))
153 struct ChanNode *chan = malloc(sizeof(*chan));
156 perror("malloc() failed");
159 strcpy(chan->name, name);
163 chan->chanbot = NULL;
168 chan->trigger = NULL;
169 chan->mode_str_args = calloc(modes_with_strarg, sizeof(char*));
170 chan->mode_int_args = calloc(modes_with_intarg, sizeof(int));
172 chan->next = chanList[chanListIndex];
173 chanList[chanListIndex] = chan;
177 int getChannelCount() {
179 struct ChanNode *chan;
180 for(i = 0; i < CHANNEL_LIST_SIZE; i++) {
181 for(chan = chanList[i]; chan; chan = chan->next) {
188 int getChanUserCount() {
190 struct ChanNode *chan;
191 for(i = 0; i < CHANNEL_LIST_SIZE; i++) {
192 for(chan = chanList[i]; chan; chan = chan->next) {
193 count += chan->usercount;
199 int getChanBanCount() {
201 struct ChanNode *chan;
203 for(i = 0; i < CHANNEL_LIST_SIZE; i++) {
204 for(chan = chanList[i]; chan; chan = chan->next) {
205 for(ban = chan->bans; ban; ban = ban->next)
212 void delChannel(struct ChanNode* chan, int freeChan) {
213 int chanListIndex = get_chanlist_entry(chan->name[1]);
214 if(chanListIndex == -1) return;
215 struct ChanNode *cchan, *last_chan = NULL;
216 for(cchan = chanList[chanListIndex]; cchan; cchan = cchan->next) {
219 last_chan->next = chan->next;
221 chanList[chanListIndex] = chan->next;
228 struct ChanUser *chanuser, *next;
229 for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = next) {
230 next = getChannelUsers(chan, chanuser);
231 removeChanUserFromLists(chanuser, 0, 1, 1);
240 void freeChanNode(struct ChanNode* chan) {
242 for(i = 0; i < modes_with_strarg; i++) {
243 if(chan->mode_str_args[i])
244 free(chan->mode_str_args[i]);
247 struct trigger_cache *trigger, *next_trigger;
248 for(trigger = chan->trigger; trigger; trigger = next_trigger) {
249 next_trigger = trigger->next;
250 free(trigger->trigger);
254 free(chan->mode_str_args);
255 free(chan->mode_int_args);
257 removeChannelBans(chan);
261 void checkChannelVisibility(struct ChanNode* chan) {
262 struct ChanUser *chanuser, *next;
263 for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) {
264 if(chanuser->user->flags & USERFLAG_ISBOT) {
265 chan->chanbot = chanuser->user;
269 //free the channel...
270 for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = next) {
271 next = getChannelUsers(chan, chanuser);
272 //remove the channel from the user's channel-list
273 removeChanUserFromLists(chanuser, 0, 1, 0);
274 if(!chanuser->user->channel) {
275 //free the user (no more channels)
276 delUser(chanuser->user, 1);
284 static unsigned int* getModeOptions(char mode) {
286 for (cmode = valid_modes; cmode[1]; cmode += 3) {
293 int isModeSet(struct ChanNode* chan, char modeChar) {
294 unsigned int *modeOpt = getModeOptions(modeChar);
295 return (chan->modes & modeOpt[0]);
298 void* getModeValue(struct ChanNode* chan, char modeChar) {
299 #define MODE_VALUE_INDEX (modeOpt[2] & CHANNEL_MODE_VALUE_INDEX_MASK) >> CHANNEL_MODE_VALUE_INDEX_SHIFT
300 unsigned int *modeOpt = getModeOptions(modeChar);
301 if((modeOpt[2] & CHANNEL_MODE_VALUE) == CHANNEL_MODE_VALUE_STRING)
302 return chan->mode_str_args[MODE_VALUE_INDEX];
303 if((modeOpt[2] & CHANNEL_MODE_VALUE) == CHANNEL_MODE_VALUE_INTEGER)
304 return &chan->mode_int_args[MODE_VALUE_INDEX];
306 #undef MODE_VALUE_INDEX
309 static void parseModesUserPriv(struct ChanNode* chan, unsigned char flag, int add, char *nick) {
310 struct UserNode *user = getUserByNick(nick);
311 if(user == NULL) return;
312 struct ChanUser *chanuser = getChanUser(user, chan);
313 if(chanuser == NULL) return;
315 chanuser->flags |= flag;
317 chanuser->flags &= ~flag;
320 static void parseModesBan(struct ChanNode* chan, int add, char *mask) {
322 addChannelBan(chan, mask);
324 removeChannelBanMask(chan, mask);
327 void parseModes(struct ChanNode* chan, char *modeStr, char **argv, int argc) {
328 int i, argpos = 0, add = 1;
329 #define MODE_TYPE (modeOpt[2] & CHANNEL_MODE_TYPE)
330 #define MODE_VALUE (modeOpt[2] & CHANNEL_MODE_VALUE)
331 #define MODE_VALUE_INDEX (modeOpt[2] & CHANNEL_MODE_VALUE_INDEX_MASK) >> CHANNEL_MODE_VALUE_INDEX_SHIFT
332 unsigned int *modeOpt;
333 for(i = 0; i < strlen(modeStr); i++) {
334 if(modeStr[i] == '+') {
338 if(modeStr[i] == '-') {
342 modeOpt = getModeOptions(modeStr[i]);
343 if(!modeOpt) continue; // unknown mode?
344 if(MODE_TYPE == CHANNEL_MODE_TYPE_A) {
345 if(argpos == argc) continue;
349 parseModesUserPriv(chan, CHANUSERFLAG_OPPED, add, argv[argpos]);
352 parseModesUserPriv(chan, CHANUSERFLAG_VOICED, add, argv[argpos]);
355 parseModesBan(chan, add, argv[argpos]);
358 //we have an unknown TYPE_A mode???
365 if(MODE_TYPE != CHANNEL_MODE_TYPE_D) { //all other types take parameters when set
366 if(argpos == argc) continue;
367 if(MODE_VALUE == CHANNEL_MODE_VALUE_STRING) {
368 if(chan->mode_str_args[MODE_VALUE_INDEX])
369 free(chan->mode_str_args[MODE_VALUE_INDEX]);
370 chan->mode_str_args[MODE_VALUE_INDEX] = strdup(argv[argpos++]);
371 } else if(MODE_VALUE == CHANNEL_MODE_VALUE_INTEGER)
372 chan->mode_int_args[MODE_VALUE_INDEX] = atoi(argv[argpos++]);
374 argpos++; //we simply don't know what to do with the argument...
376 chan->modes |= modeOpt[0];
378 chan->modes &= ~modeOpt[0];
379 if(MODE_TYPE == CHANNEL_MODE_TYPE_B) {
380 if(argpos == argc) continue;
381 if(MODE_VALUE == CHANNEL_MODE_VALUE_STRING) {
382 free(chan->mode_str_args[MODE_VALUE_INDEX]);
383 chan->mode_str_args[MODE_VALUE_INDEX] = NULL;
384 } else if(MODE_VALUE == CHANNEL_MODE_VALUE_INTEGER)
385 chan->mode_int_args[MODE_VALUE_INDEX] = 0;
386 argpos++; //we don't need the argument when unsetting a mode...
392 #undef MODE_VALUE_INDEX
395 void getModeString(struct ChanNode* chan, char *modesStr) {
396 #define MODE_TYPE (mode[2] & CHANNEL_MODE_TYPE)
397 #define MODE_VALUE (mode[2] & CHANNEL_MODE_VALUE)
398 #define MODE_VALUE_INDEX (mode[2] & CHANNEL_MODE_VALUE_INDEX_MASK) >> CHANNEL_MODE_VALUE_INDEX_SHIFT
399 char paramStr[MAXLEN];
404 for (mode = valid_modes; mode[1]; mode += 3) {
405 if(chan->modes & mode[0]) {
406 modesStr[modePos++] = (char) mode[1];
407 if(MODE_TYPE != CHANNEL_MODE_TYPE_D) {
408 if(MODE_VALUE == CHANNEL_MODE_VALUE_STRING)
409 paramPos += sprintf(paramStr + paramPos, " %s", chan->mode_str_args[MODE_VALUE_INDEX]);
410 else if(MODE_VALUE == CHANNEL_MODE_VALUE_INTEGER)
411 paramPos += sprintf(paramStr + paramPos, " %d", chan->mode_int_args[MODE_VALUE_INDEX]);
415 paramStr[paramPos] = '\0';
416 strcpy(modesStr + modePos, paramStr);
419 #undef MODE_VALUE_INDEX