added cmd_mode and added some useful functions to ModeNode.c
[NeonServV5.git] / cmd_neonserv_mode.c
1
2 /*
3 * argv[0] - modes
4 * argv[1-*] - parameters
5 */
6 static USERLIST_CALLBACK(neonserv_cmd_mode_userlist_lookup);
7 static void neonserv_cmd_mode_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *mode);
8
9 struct neonserv_cmd_mode_cache {
10     struct ClientSocket *client, *textclient;
11     struct UserNode *user;
12     struct Event *event;
13     char *mode;
14 };
15
16 static CMD_BIND(neonserv_cmd_mode) {
17     struct neonserv_cmd_mode_cache *cache = malloc(sizeof(*cache));
18     if (!cache) {
19         perror("malloc() failed");
20         return;
21     }
22     cache->client = client;
23     cache->textclient = getTextBot();
24     cache->user = user;
25     cache->event = event;
26     cache->mode = strdup(merge_argv(argv, 0, argc));
27     get_userlist_with_invisible(chan, neonserv_cmd_mode_userlist_lookup, cache);
28 }
29
30 static USERLIST_CALLBACK(neonserv_cmd_mode_userlist_lookup) {
31     struct neonserv_cmd_mode_cache *cache = data;
32     neonserv_cmd_mode_async1(cache->client, cache->textclient, cache->user, chan, cache->event, cache->mode);
33     free(cache->mode);
34     free(cache);
35 }
36
37 static void neonserv_cmd_mode_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, struct Event *event, char *mode) {
38     MYSQL_ROW row, defaults = NULL;
39     int i, arg, add = 1;
40     unsigned int modetype;
41     int db_canop, db_canvoice, db_canban, db_enfmodes;
42     struct ModeNode *modelock = createModeNode(NULL), *changemodes = createModeNode(NULL);
43     struct ModeBuffer *modeBuf;
44     modeBuf = initModeBuffer(client, chan);
45     printf_mysql_query("SELECT `channel_canop`, `channel_canvoice`, `channel_canban`, `channel_enfmodes`, `channel_modes` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id);
46     row = mysql_fetch_row(mysql_use());
47     if(row[0] == NULL || row[1] == NULL || row[2] == NULL || row[3] == NULL) {
48         printf_mysql_query("SELECT `channel_canop`, `channel_canvoice`, `channel_canban`, `channel_enfmodes`, `channel_modes` FROM `channels` WHERE `channel_name` = 'defaults'");
49         defaults = mysql_fetch_row(mysql_use());
50     }
51     db_canop = atoi((row[0] ? row[0] : defaults[0]));
52     db_canvoice = atoi((row[1] ? row[1] : defaults[1]));
53     db_canban = atoi((row[2] ? row[2] : defaults[2]));
54     db_enfmodes = atoi((row[3] ? row[3] : defaults[3]));
55     if(row[4])
56         parseModeString(modelock, row[4]);
57     else if(defaults[4])
58         parseModeString(modelock, defaults[4]);
59     int uaccess = getChannelAccess(user, chan, 0);
60     char *a, *b = mode;
61     char *argv[MAXNUMPARAMS];
62     char *carg;
63     char tmp[MAXLEN];
64     int argc = 0;
65     do {
66         a = strstr(b, " ");
67         if(a) *a = '\0';
68         argv[argc++] = b;
69         if(argc == MAXNUMPARAMS) break;
70         if(a) b = a+1;
71     } while(a);
72     arg = 0;
73     while(arg < argc) {
74         char *modeStr = argv[arg++];
75         for(i = 0; i < strlen(modeStr); i++) {
76             switch(modeStr[i]) {
77                 case '+':
78                     add = 1;
79                     break;
80                 case '-':
81                     add = 0;
82                     break;
83                 case 'o':
84                     
85                     break;
86                 case 'v':
87                     
88                     break;
89                 case 'b':
90                     
91                     break;
92                 default:
93                     modetype = getModeType(modelock, modeStr[i]);
94                     if(modetype == 0) {
95                         reply(textclient, user, "NS_MODE_INVALID", modeStr[i]);
96                         return;
97                     }
98                     if(isModeAffected(modelock, modeStr[i]) && add == !isModeSet(modelock, modeStr[i]) && uaccess < db_enfmodes) {
99                         if(isGodMode(user))
100                             event->flags |= CMDFLAG_OPLOG;
101                         else {
102                             getFullModeString(modelock, tmp);
103                             reply(textclient, user, "NS_MODE_LOCKED", tmp, chan->name);
104                             return;
105                         }
106                     }
107                     if(add && (modetype & CHANNEL_MODE_TYPE) != CHANNEL_MODE_TYPE_D) {
108                         if(arg == argc) {
109                             reply(textclient, user, "NS_MODE_INVALID", modeStr[i]);
110                             return;
111                         }
112                         carg = argv[arg++];
113                         if((modetype & CHANNEL_MODE_VALUE) == CHANNEL_MODE_VALUE_STRING && isModeSet(modelock, modeStr[i])) {
114                             char *modelock_val = getModeValue(modelock, modeStr[i]);
115                             if(stricmp(carg, modelock_val)) {
116                                 if(isGodMode(user))
117                                     event->flags |= CMDFLAG_OPLOG;
118                                 else {
119                                     getFullModeString(modelock, tmp);
120                                     reply(textclient, user, "NS_MODE_LOCKED", tmp, chan->name);
121                                     return;
122                                 }
123                             }
124                         }
125                         if((modetype & CHANNEL_MODE_VALUE) == CHANNEL_MODE_VALUE_STRING && isModeSet(modelock, modeStr[i])) {
126                             int *modelock_val = getModeValue(modelock, modeStr[i]);
127                             if(atoi(carg) != *modelock_val) {
128                                 if(isGodMode(user))
129                                     event->flags |= CMDFLAG_OPLOG;
130                                 else {
131                                     getFullModeString(modelock, tmp);
132                                     reply(textclient, user, "NS_MODE_LOCKED", tmp, chan->name);
133                                     return;
134                                 }
135                             }
136                         }
137                     } else
138                         carg = NULL;
139                     if((modetype & CHANNEL_MODE_TYPE) == CHANNEL_MODE_TYPE_D && isModeSet(chan->modes, modeStr[i]) == add)
140                         continue;
141                     if(!isModeAffected(changemodes, modeStr[i])) {
142                         if(!add && (modetype & CHANNEL_MODE_KEY)) {
143                             if(isModeSet(chan->modes, modeStr[i])) {
144                                 char *current_val = getModeValue(chan->modes, modeStr[i]);
145                                 carg = current_val;
146                             }
147                         }
148                         if(parseMode(changemodes, add, modeStr[i], carg)) {
149                             if(carg) {
150                                 if(add && (modetype & CHANNEL_MODE_KEY) && isModeSet(chan->modes, modeStr[i])) {
151                                     char *current_val = getModeValue(chan->modes, modeStr[i]);
152                                     modeBufferSet(modeBuf, 0, modeStr[i], current_val);
153                                     flushModeBuffer(modeBuf);
154                                 }
155                                 if(!add && !isModeSet(chan->modes, modeStr[i])) continue;
156                                 modeBufferSet(modeBuf, add, modeStr[i], carg);
157                             } else {
158                                 modeBufferSimpleMode(modeBuf, add, modeStr[i]);
159                             }
160                         } else {
161                             reply(textclient, user, "NS_MODE_INVALID", modeStr[i]);
162                             return;
163                         }
164                     }
165                     break;
166             }
167         }
168     }
169     getFullModeString(changemodes, tmp);
170     freeModeBuffer(modeBuf);
171     reply(textclient, user, "NS_MODE_DONE", tmp);
172     logEvent(event);
173     freeModeNode(modelock);
174     freeModeNode(changemodes);
175 }