4 * argv[1-*] - parameters
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);
9 struct neonserv_cmd_mode_cache {
10 struct ClientSocket *client, *textclient;
11 struct UserNode *user;
16 static CMD_BIND(neonserv_cmd_mode) {
17 struct neonserv_cmd_mode_cache *cache = malloc(sizeof(*cache));
19 perror("malloc() failed");
22 cache->client = client;
23 cache->textclient = getTextBot();
26 cache->mode = strdup(merge_argv(argv, 0, argc));
27 get_userlist_with_invisible(chan, neonserv_cmd_mode_userlist_lookup, cache);
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);
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;
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());
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]));
56 parseModeString(modelock, row[4]);
58 parseModeString(modelock, defaults[4]);
59 int uaccess = getChannelAccess(user, chan, 0);
61 char *argv[MAXNUMPARAMS];
69 if(argc == MAXNUMPARAMS) break;
74 char *modeStr = argv[arg++];
75 for(i = 0; i < strlen(modeStr); i++) {
86 reply(textclient, user, "NS_MODE_INVALID", modeStr[i]);
90 if(uaccess < (modeStr[i] == 'o' ? db_canop : db_canvoice)) {
91 reply(textclient, user, "NS_MODE_ENFOPS", chan->name);
92 if(modeStr[i] == 'o') db_canop = -1;
93 else db_canvoice = -1;
96 if((modeStr[i] == 'o' ? db_canop : db_canvoice) == -1) break;
97 struct UserNode *cuser;
98 struct ChanUser *chanuser;
99 cuser = searchUserByNick(carg);
101 //check for an invisible user
102 for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) {
103 if(!stricmp(chanuser->user->nick, carg)) {
104 cuser = chanuser->user;
110 chanuser = getChanUser(cuser, chan);
113 if(!(add ^ (chanuser->flags & (modeStr[i] == 'o' ? CHANUSERFLAG_OPPED : CHANUSERFLAG_VOICED)))) break;
116 if(modeStr[i] == 'o' && isNetworkService(cuser)) {
117 reply(textclient, user, "NS_SERVICE_IMMUNE", cuser->nick);
120 if(isUserProtected(chan, cuser, user)) {
121 reply(textclient, user, "NS_USER_PROTECTED", cuser->nick);
125 modeBufferSet(modeBuf, add, modeStr[i], carg);
131 modetype = getModeType(modelock, modeStr[i]);
133 reply(textclient, user, "NS_MODE_INVALID", modeStr[i]);
136 if(isModeAffected(modelock, modeStr[i]) && add == !isModeSet(modelock, modeStr[i]) && uaccess < db_enfmodes) {
138 event->flags |= CMDFLAG_OPLOG;
140 getFullModeString(modelock, tmp);
141 reply(textclient, user, "NS_MODE_LOCKED", tmp, chan->name);
145 if(add && (modetype & CHANNEL_MODE_TYPE) != CHANNEL_MODE_TYPE_D) {
147 reply(textclient, user, "NS_MODE_INVALID", modeStr[i]);
151 if((modetype & CHANNEL_MODE_VALUE) == CHANNEL_MODE_VALUE_STRING && isModeSet(modelock, modeStr[i])) {
152 char *modelock_val = getModeValue(modelock, modeStr[i]);
153 if(stricmp(carg, modelock_val)) {
155 event->flags |= CMDFLAG_OPLOG;
157 getFullModeString(modelock, tmp);
158 reply(textclient, user, "NS_MODE_LOCKED", tmp, chan->name);
163 if((modetype & CHANNEL_MODE_VALUE) == CHANNEL_MODE_VALUE_STRING && isModeSet(modelock, modeStr[i])) {
164 int *modelock_val = getModeValue(modelock, modeStr[i]);
165 if(atoi(carg) != *modelock_val) {
167 event->flags |= CMDFLAG_OPLOG;
169 getFullModeString(modelock, tmp);
170 reply(textclient, user, "NS_MODE_LOCKED", tmp, chan->name);
177 if((modetype & CHANNEL_MODE_TYPE) == CHANNEL_MODE_TYPE_D && isModeSet(chan->modes, modeStr[i]) == add)
179 if(!isModeAffected(changemodes, modeStr[i])) {
180 if(!add && (modetype & CHANNEL_MODE_KEY)) {
181 if(isModeSet(chan->modes, modeStr[i])) {
182 char *current_val = getModeValue(chan->modes, modeStr[i]);
186 if(parseMode(changemodes, add, modeStr[i], carg)) {
188 if(add && (modetype & CHANNEL_MODE_KEY) && isModeSet(chan->modes, modeStr[i])) {
189 char *current_val = getModeValue(chan->modes, modeStr[i]);
190 modeBufferSet(modeBuf, 0, modeStr[i], current_val);
191 flushModeBuffer(modeBuf);
193 if(!add && !isModeSet(chan->modes, modeStr[i])) break;
194 modeBufferSet(modeBuf, add, modeStr[i], carg);
196 modeBufferSimpleMode(modeBuf, add, modeStr[i]);
199 reply(textclient, user, "NS_MODE_INVALID", modeStr[i]);
207 getFullModeString(changemodes, tmp);
208 freeModeBuffer(modeBuf);
210 reply(textclient, user, "NS_MODE_DONE", tmp);
213 freeModeNode(modelock);
214 freeModeNode(changemodes);