5 static struct ChanNode **chanList;
6 static int modes_with_strarg, modes_with_intarg;
8 //Types: http://www.irc.org/tech_docs/draft-brocklesby-irc-isupport-03.txt
9 #define CHANNEL_MODE_TYPE_A 0x01 /* ... special (addresses or users) ... */
10 #define CHANNEL_MODE_TYPE_B 0x02 /* These modes always take a parameter. */
11 #define CHANNEL_MODE_TYPE_C 0x03 /* These modes take a parameter only when set. */
12 #define CHANNEL_MODE_TYPE_D 0x04 /* These modes never take a parameter. */
13 #define CHANNEL_MODE_TYPE 0x07 /* bit mask to get the type */
15 #define CHANNEL_MODE_VALUE_STRING 0x10
16 #define CHANNEL_MODE_VALUE_INTEGER 0x20
17 #define CHANNEL_MODE_VALUE 0x30 /* bit mask to get the value */
19 #define CHANNEL_MODE_VALUE_INDEX_SHIFT 8
20 #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 */
22 static unsigned int valid_modes[] = { /* Thats our mode list :P */
23 1, 'b', CHANNEL_MODE_TYPE_A,
24 2, 'o', CHANNEL_MODE_TYPE_A,
25 3, 'v', CHANNEL_MODE_TYPE_A,
26 4, 'k', CHANNEL_MODE_TYPE_B | CHANNEL_MODE_VALUE_STRING,
27 5, 'a', CHANNEL_MODE_TYPE_C | CHANNEL_MODE_VALUE_INTEGER,
28 6, 'l', CHANNEL_MODE_TYPE_C | CHANNEL_MODE_VALUE_INTEGER,
29 7, 'f', CHANNEL_MODE_TYPE_C | CHANNEL_MODE_VALUE_STRING,
30 8, 'F', CHANNEL_MODE_TYPE_C | CHANNEL_MODE_VALUE_STRING,
31 9, 'c', CHANNEL_MODE_TYPE_D,
32 10, 'C', CHANNEL_MODE_TYPE_D,
33 11, 'i', CHANNEL_MODE_TYPE_D,
34 12, 'm', CHANNEL_MODE_TYPE_D,
35 13, 'M', CHANNEL_MODE_TYPE_D,
36 14, 'n', CHANNEL_MODE_TYPE_D,
37 15, 'N', CHANNEL_MODE_TYPE_D,
38 16, 'p', CHANNEL_MODE_TYPE_D,
39 17, 'r', CHANNEL_MODE_TYPE_D,
40 18, 's', CHANNEL_MODE_TYPE_D,
41 19, 't', CHANNEL_MODE_TYPE_D,
42 20, 'u', CHANNEL_MODE_TYPE_D,
43 21, 'D', CHANNEL_MODE_TYPE_D,
44 22, 'd', CHANNEL_MODE_TYPE_D,
45 23, 'R', CHANNEL_MODE_TYPE_D,
46 24, 'z', CHANNEL_MODE_TYPE_D,
51 void init_ChanNode() {
57 1 46 *everything else*
58 ---------------------------
61 chanList = calloc(47, sizeof(*chanList));
62 unsigned int *mode, flag = 1;
63 modes_with_strarg = 0;
64 modes_with_intarg = 0;
65 for (mode = valid_modes; mode[1]; mode += 3) {
66 if((mode[2] & CHANNEL_MODE_VALUE) == CHANNEL_MODE_VALUE_STRING) {
67 mode[2] |= modes_with_strarg << CHANNEL_MODE_VALUE_INDEX_SHIFT;
70 if((mode[2] & CHANNEL_MODE_VALUE) == CHANNEL_MODE_VALUE_INTEGER) {
71 mode[2] |= modes_with_intarg << CHANNEL_MODE_VALUE_INDEX_SHIFT;
79 int is_valid_chan(const char *name) {
83 for (ii=1; name[ii]; ++ii) {
84 if ((name[ii] > 0) && (name[ii] <= 32))
88 if (name[ii] == '\xa0')
94 static int get_chanlist_entry(int name) {
95 if((name > 0 && name <= 32) || name == ',' || name == '\xa0') return -1; //invalid name
96 if(tolower(name) >= 97 && tolower(name) <= 122) {
97 return (tolower(name) - 97);
99 if(tolower(name) >= 48 && tolower(name) <= 57) {
100 return (tolower(name) - 48 + 26);
103 if(name == '{') return 36;
104 if(name == '|') return 37;
105 if(name == '}') return 38;
106 if(name == '~') return 39;
107 if(name == '[') return 40;
108 if(name == '\\') return 41;
109 if(name == ']') return 42;
110 if(name == '^') return 43;
111 if(name == '_') return 44;
112 if(name == '`') return 45;
116 struct ChanNode* getChanByName(const char *name) { //case insensitive
117 int chanListIndex = get_chanlist_entry(name[1]);
118 if(chanListIndex == -1 || chanList[chanListIndex] == NULL)
120 struct ChanNode *chan;
121 for(chan = chanList[chanListIndex]; chan; chan = chan->next) {
122 if(!stricmp(name, chan->name))
128 struct ChanNode* addChannel(const char *name) {
129 int chanListIndex = get_chanlist_entry(name[1]);
130 if(chanListIndex == -1 || !is_valid_chan(name))
132 struct ChanNode *chan = malloc(sizeof(*chan));
135 perror("malloc() failed");
138 strcpy(chan->name, name);
140 chan->chanbot = NULL;
144 chan->mode_str_args = calloc(modes_with_strarg, sizeof(char*));
145 chan->mode_int_args = calloc(modes_with_intarg, sizeof(int));
147 chan->next = chanList[chanListIndex];
148 chanList[chanListIndex] = chan;
152 void delChannel(struct ChanNode* chan, int freeChan) {
153 int chanListIndex = get_chanlist_entry(chan->name[1]);
154 if(chanListIndex == -1) return;
155 struct ChanNode *cchan, *last_chan = NULL;
156 for(cchan = chanList[chanListIndex]; cchan; cchan = cchan->next) {
159 last_chan->next = chan->next;
161 chanList[chanListIndex] = chan->next;
168 struct ChanUser *chanuser, *next;
169 for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = next) {
170 next = getChannelUsers(chan, chanuser);
171 removeChanUserFromLists(chanuser, 0, 1, 1);
180 void freeChanNode(struct ChanNode* chan) {
182 for(i = 0; i < modes_with_strarg; i++) {
183 if(chan->mode_str_args[i])
184 free(chan->mode_str_args[i]);
186 free(chan->mode_str_args);
187 free(chan->mode_int_args);
191 void checkChannelVisibility(struct ChanNode* chan) {
192 struct ChanUser *chanuser, *next;
193 for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) {
194 if(chanuser->user->flags & USERFLAG_ISBOT) {
195 chan->chanbot = chanuser->user;
199 //free the channel...
200 for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = next) {
201 next = getChannelUsers(chan, chanuser);
202 //remove the channel from the user's channel-list
203 removeChanUserFromLists(chanuser, 0, 1, 0);
204 if(!chanuser->user->channel) {
205 //free the user (no more channels)
206 delUser(chanuser->user, 1);
214 static unsigned int* getModeOptions(char mode) {
216 for (cmode = valid_modes; cmode[1]; cmode += 3) {
223 int isModeSet(struct ChanNode* chan, char modeChar) {
224 unsigned int *modeOpt = getModeOptions(modeChar);
225 return (chan->modes & modeOpt[0]);
228 void* getModeValue(struct ChanNode* chan, char modeChar) {
229 #define MODE_VALUE_INDEX (modeOpt[2] & CHANNEL_MODE_VALUE_INDEX_MASK) >> CHANNEL_MODE_VALUE_INDEX_SHIFT
230 unsigned int *modeOpt = getModeOptions(modeChar);
231 if((modeOpt[2] & CHANNEL_MODE_VALUE) == CHANNEL_MODE_VALUE_STRING)
232 return chan->mode_str_args[MODE_VALUE_INDEX];
233 if((modeOpt[2] & CHANNEL_MODE_VALUE) == CHANNEL_MODE_VALUE_INTEGER)
234 return &chan->mode_int_args[MODE_VALUE_INDEX];
236 #undef MODE_VALUE_INDEX
239 void parseModes(struct ChanNode* chan, char *modeStr, char **argv, int argc) {
240 int i, argpos = 0, add = 1;
241 #define MODE_TYPE (modeOpt[2] & CHANNEL_MODE_TYPE)
242 #define MODE_VALUE (modeOpt[2] & CHANNEL_MODE_VALUE)
243 #define MODE_VALUE_INDEX (modeOpt[2] & CHANNEL_MODE_VALUE_INDEX_MASK) >> CHANNEL_MODE_VALUE_INDEX_SHIFT
244 unsigned int *modeOpt;
245 for(i = 0; i < strlen(modeStr); i++) {
246 if(modeStr[i] == '+') {
250 if(modeStr[i] == '-') {
254 modeOpt = getModeOptions(modeStr[i]);
255 if(!modeOpt) continue; // unknown mode?
256 if(MODE_TYPE == CHANNEL_MODE_TYPE_A) {
261 if(MODE_TYPE != CHANNEL_MODE_TYPE_D) { //all other types take parameters when set
262 if(argpos == argc) continue;
263 if(MODE_VALUE == CHANNEL_MODE_VALUE_STRING) {
264 if(chan->mode_str_args[MODE_VALUE_INDEX])
265 free(chan->mode_str_args[MODE_VALUE_INDEX]);
266 chan->mode_str_args[MODE_VALUE_INDEX] = strdup(argv[argc++]);
267 } else if(MODE_VALUE == CHANNEL_MODE_VALUE_INTEGER)
268 chan->mode_int_args[MODE_VALUE_INDEX] = atoi(argv[argc++]);
270 argc++; //we simply don't know what to do with the argument...
272 chan->modes |= modeOpt[0];
274 chan->modes &= ~modeOpt[0];
275 if(MODE_TYPE == CHANNEL_MODE_TYPE_B) {
276 if(argpos == argc) continue;
277 if(MODE_VALUE == CHANNEL_MODE_VALUE_STRING) {
278 free(chan->mode_str_args[MODE_VALUE_INDEX]);
279 chan->mode_str_args[MODE_VALUE_INDEX] = NULL;
280 } else if(MODE_VALUE == CHANNEL_MODE_VALUE_INTEGER)
281 chan->mode_int_args[MODE_VALUE_INDEX] = 0;
282 argc++; //we don't need the argument when unsetting a mode...
288 #undef MODE_VALUE_INDEX