7 static int modes_with_strarg, modes_with_intarg;
9 //Types: http://www.irc.org/tech_docs/draft-brocklesby-irc-isupport-03.txt
10 #define CHANNEL_MODE_TYPE_A 0x01 /* ... special (addresses or users) ... */
11 #define CHANNEL_MODE_TYPE_B 0x02 /* These modes always take a parameter. */
12 #define CHANNEL_MODE_TYPE_C 0x03 /* These modes take a parameter only when set. */
13 #define CHANNEL_MODE_TYPE_D 0x04 /* These modes never take a parameter. */
14 #define CHANNEL_MODE_TYPE 0x07 /* bit mask to get the type */
16 #define CHANNEL_MODE_VALUE_STRING 0x10
17 #define CHANNEL_MODE_VALUE_INTEGER 0x20
18 #define CHANNEL_MODE_VALUE 0x30 /* bit mask to get the value */
20 #define CHANNEL_MODE_VALUE_INDEX_SHIFT 8
21 #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 */
23 static unsigned int valid_modes[] = { /* Thats our mode list :P */
24 1, 'b', CHANNEL_MODE_TYPE_A,
25 2, 'o', CHANNEL_MODE_TYPE_A,
26 3, 'v', CHANNEL_MODE_TYPE_A,
27 4, 'k', CHANNEL_MODE_TYPE_B | CHANNEL_MODE_VALUE_STRING,
28 5, 'a', CHANNEL_MODE_TYPE_C | CHANNEL_MODE_VALUE_INTEGER,
29 6, 'l', CHANNEL_MODE_TYPE_C | CHANNEL_MODE_VALUE_INTEGER,
30 7, 'f', CHANNEL_MODE_TYPE_C | CHANNEL_MODE_VALUE_STRING,
31 8, 'F', CHANNEL_MODE_TYPE_C | CHANNEL_MODE_VALUE_STRING,
32 9, 'c', CHANNEL_MODE_TYPE_D,
33 10, 'C', CHANNEL_MODE_TYPE_D,
34 11, 'i', CHANNEL_MODE_TYPE_D,
35 12, 'm', CHANNEL_MODE_TYPE_D,
36 13, 'M', CHANNEL_MODE_TYPE_D,
37 14, 'n', CHANNEL_MODE_TYPE_D,
38 15, 'N', CHANNEL_MODE_TYPE_D,
39 16, 'p', CHANNEL_MODE_TYPE_D,
40 17, 'r', CHANNEL_MODE_TYPE_D,
41 18, 's', CHANNEL_MODE_TYPE_D,
42 19, 't', CHANNEL_MODE_TYPE_D,
43 20, 'u', CHANNEL_MODE_TYPE_D,
44 21, 'D', CHANNEL_MODE_TYPE_D,
45 22, 'd', CHANNEL_MODE_TYPE_D,
46 23, 'R', CHANNEL_MODE_TYPE_D,
47 24, 'z', CHANNEL_MODE_TYPE_D,
52 void init_ModeNode() {
53 unsigned int *mode, flag = 1;
54 modes_with_strarg = 0;
55 modes_with_intarg = 0;
56 for (mode = valid_modes; mode[1]; mode += 3) {
57 if((mode[2] & CHANNEL_MODE_VALUE) == CHANNEL_MODE_VALUE_STRING) {
58 mode[2] |= modes_with_strarg << CHANNEL_MODE_VALUE_INDEX_SHIFT;
61 if((mode[2] & CHANNEL_MODE_VALUE) == CHANNEL_MODE_VALUE_INTEGER) {
62 mode[2] |= modes_with_intarg << CHANNEL_MODE_VALUE_INDEX_SHIFT;
70 struct ModeNode *createModeNode(struct ChanNode *chan) {
71 struct ModeNode *modes = malloc(sizeof(*modes));
74 perror("malloc() failed");
79 modes->mode_str_args = calloc(modes_with_strarg, sizeof(char*));
80 modes->mode_int_args = calloc(modes_with_intarg, sizeof(int));
84 void freeModeNode(struct ModeNode *modes) {
86 for(i = 0; i < modes_with_strarg; i++) {
87 if(modes->mode_str_args[i])
88 free(modes->mode_str_args[i]);
90 free(modes->mode_str_args);
91 free(modes->mode_int_args);
95 static unsigned int* getModeOptions(char mode) {
97 for (cmode = valid_modes; cmode[1]; cmode += 3) {
104 int isModeSet(struct ModeNode* modes, char modeChar) {
105 unsigned int *modeOpt = getModeOptions(modeChar);
106 return (modes->modes & modeOpt[0]);
109 void* getModeValue(struct ModeNode* modes, char modeChar) {
110 #define MODE_VALUE_INDEX (modeOpt[2] & CHANNEL_MODE_VALUE_INDEX_MASK) >> CHANNEL_MODE_VALUE_INDEX_SHIFT
111 unsigned int *modeOpt = getModeOptions(modeChar);
112 if((modeOpt[2] & CHANNEL_MODE_VALUE) == CHANNEL_MODE_VALUE_STRING)
113 return modes->mode_str_args[MODE_VALUE_INDEX];
114 if((modeOpt[2] & CHANNEL_MODE_VALUE) == CHANNEL_MODE_VALUE_INTEGER)
115 return &modes->mode_int_args[MODE_VALUE_INDEX];
117 #undef MODE_VALUE_INDEX
120 static void parseModesUserPriv(struct ModeNode* modes, unsigned char flag, int add, char *nick) {
121 if(modes->chan == NULL) return;
122 struct UserNode *user = getUserByNick(nick);
123 if(user == NULL) return;
124 struct ChanUser *chanuser = getChanUser(user, modes->chan);
125 if(chanuser == NULL) return;
127 chanuser->flags |= flag;
129 chanuser->flags &= ~flag;
132 static void parseModesBan(struct ModeNode* modes, int add, char *mask) {
133 if(modes->chan == NULL) return;
135 addChannelBan(modes->chan, mask);
137 removeChannelBanMask(modes->chan, mask);
140 void parseModes(struct ModeNode* modes, char *modeStr, char **argv, int argc) {
141 int i, argpos = 0, add = 1;
142 #define MODE_TYPE (modeOpt[2] & CHANNEL_MODE_TYPE)
143 #define MODE_VALUE (modeOpt[2] & CHANNEL_MODE_VALUE)
144 #define MODE_VALUE_INDEX (modeOpt[2] & CHANNEL_MODE_VALUE_INDEX_MASK) >> CHANNEL_MODE_VALUE_INDEX_SHIFT
145 unsigned int *modeOpt;
146 for(i = 0; i < strlen(modeStr); i++) {
147 if(modeStr[i] == '+') {
151 if(modeStr[i] == '-') {
155 modeOpt = getModeOptions(modeStr[i]);
156 if(!modeOpt) continue; // unknown mode?
157 if(MODE_TYPE == CHANNEL_MODE_TYPE_A) {
158 if(argpos == argc) continue;
162 parseModesUserPriv(modes, CHANUSERFLAG_OPPED, add, argv[argpos]);
165 parseModesUserPriv(modes, CHANUSERFLAG_VOICED, add, argv[argpos]);
168 parseModesBan(modes, add, argv[argpos]);
171 //we have an unknown TYPE_A mode???
178 if(MODE_TYPE != CHANNEL_MODE_TYPE_D) { //all other types take parameters when set
179 if(argpos == argc) continue;
180 if(MODE_VALUE == CHANNEL_MODE_VALUE_STRING) {
181 if(modes->mode_str_args[MODE_VALUE_INDEX])
182 free(modes->mode_str_args[MODE_VALUE_INDEX]);
183 modes->mode_str_args[MODE_VALUE_INDEX] = strdup(argv[argpos++]);
184 } else if(MODE_VALUE == CHANNEL_MODE_VALUE_INTEGER)
185 modes->mode_int_args[MODE_VALUE_INDEX] = atoi(argv[argpos++]);
187 argpos++; //we simply don't know what to do with the argument...
189 modes->modes |= modeOpt[0];
191 modes->modes &= ~modeOpt[0];
192 if(MODE_TYPE == CHANNEL_MODE_TYPE_B) {
193 if(argpos == argc) continue;
194 if(MODE_VALUE == CHANNEL_MODE_VALUE_STRING) {
195 free(modes->mode_str_args[MODE_VALUE_INDEX]);
196 modes->mode_str_args[MODE_VALUE_INDEX] = NULL;
197 } else if(MODE_VALUE == CHANNEL_MODE_VALUE_INTEGER)
198 modes->mode_int_args[MODE_VALUE_INDEX] = 0;
199 argpos++; //we don't need the argument when unsetting a mode...
205 #undef MODE_VALUE_INDEX
208 void getModeString(struct ModeNode* modes, char *modesStr) {
209 #define MODE_TYPE (mode[2] & CHANNEL_MODE_TYPE)
210 #define MODE_VALUE (mode[2] & CHANNEL_MODE_VALUE)
211 #define MODE_VALUE_INDEX (mode[2] & CHANNEL_MODE_VALUE_INDEX_MASK) >> CHANNEL_MODE_VALUE_INDEX_SHIFT
212 char paramStr[MAXLEN];
217 for (mode = valid_modes; mode[1]; mode += 3) {
218 if(modes->modes & mode[0]) {
219 modesStr[modePos++] = (char) mode[1];
220 if(MODE_TYPE != CHANNEL_MODE_TYPE_D) {
221 if(MODE_VALUE == CHANNEL_MODE_VALUE_STRING)
222 paramPos += sprintf(paramStr + paramPos, " %s", modes->mode_str_args[MODE_VALUE_INDEX]);
223 else if(MODE_VALUE == CHANNEL_MODE_VALUE_INTEGER)
224 paramPos += sprintf(paramStr + paramPos, " %d", modes->mode_int_args[MODE_VALUE_INDEX]);
228 paramStr[paramPos] = '\0';
229 strcpy(modesStr + modePos, paramStr);
232 #undef MODE_VALUE_INDEX