f2ee0905cc48982dd2a1a8066d744d34812326c5
[NeonServV5.git] / src / cmd_neonserv_resync.c
1 /* cmd_neonserv_resync.c - NeonServ v5.3
2  * Copyright (C) 2011-2012  Philipp Kreil (pk910)
3  * 
4  * This program is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU General Public License as published by
6  * the Free Software Foundation, either version 3 of the License, or
7  * (at your option) any later version.
8  * 
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  * 
14  * You should have received a copy of the GNU General Public License 
15  * along with this program. If not, see <http://www.gnu.org/licenses/>. 
16  */
17
18 #include "cmd_neonserv.h"
19
20 /*
21 * argv[0] - (optional) usermask
22 * argv[1] - (optional) min access
23 * argv[2] - (optional) max access
24 * argv[1/3] - (optional) FORCE (override NoAutoOp)
25 */
26 static USERLIST_CALLBACK(neonserv_cmd_resync_userlist_lookup);
27 static void neonserv_cmd_resync_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *usermask, int min_access, int max_access, char override_noautoop);
28
29 struct neonserv_cmd_resync_cache {
30     struct ClientSocket *client, *textclient;
31     struct UserNode *user;
32     char *usermask;
33     int min_access;
34     int max_access;
35     char override_noautoop;
36 };
37
38 CMD_BIND(neonserv_cmd_resync) {
39     int min_access = 0, max_access = 500;
40     char *usermask = NULL;
41     char override_noautoop = 0;
42     if(argc > 0) {
43         usermask = argv[0];
44         if(argc > 2) {
45             min_access = atoi(argv[1]);
46             max_access = atoi(argv[2]);
47             if(argc > 3)
48                 override_noautoop = (!stricmp(argv[3], "FORCE") ? 1 : 0);
49         } else if(argc > 1)
50             override_noautoop = (!stricmp(argv[1], "FORCE") ? 1 : 0);
51     }
52     struct neonserv_cmd_resync_cache *cache = malloc(sizeof(*cache));
53     if (!cache) {
54         perror("malloc() failed");
55         return;
56     }
57     cache->client = client;
58     cache->textclient = getTextBot();
59     cache->user = user;
60     cache->usermask = (usermask ? strdup(usermask) : NULL);
61     cache->min_access = min_access;
62     cache->max_access = max_access;
63     cache->override_noautoop = override_noautoop;
64     get_userlist_with_invisible(chan, neonserv_cmd_resync_userlist_lookup, cache);
65 }
66
67 static USERLIST_CALLBACK(neonserv_cmd_resync_userlist_lookup) {
68     struct neonserv_cmd_resync_cache *cache = data;
69     neonserv_cmd_resync_async1(cache->client, cache->textclient, cache->user, chan, cache->usermask, cache->min_access, cache->max_access, cache->override_noautoop);
70     if(cache->usermask)
71         free(cache->usermask);
72     free(cache);
73 }
74
75 static void neonserv_cmd_resync_async1(struct ClientSocket *client, struct ClientSocket *textclient, struct UserNode *user, struct ChanNode *chan, char *usermask, int min_access, int max_access, char override_noautoop) {
76     MYSQL_RES *res;
77     MYSQL_ROW row, defaults = NULL;
78     int i;
79     int resync_op = 1;
80     int resync_voice = 1;
81     if(usermask && usermask[0] == '@') {
82         resync_voice = 0;
83         usermask++;
84         if(!*usermask) usermask = NULL;
85     } else if(usermask && usermask[0] == '+') {
86         resync_op = 0;
87         usermask++;
88         if(!*usermask) usermask = NULL;
89     }
90     struct ChanUser *chanuser;
91     int db_enfops, db_enfvoice;
92     printf_mysql_query("SELECT `channel_getop`, `channel_getvoice` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id);
93     row = mysql_fetch_row(mysql_use());
94     if(row[0] == NULL || row[1] == NULL) {
95         printf_mysql_query("SELECT `channel_getop`, `channel_getvoice` FROM `channels` WHERE `channel_name` = 'defaults'");
96         defaults = mysql_fetch_row(mysql_use());
97     }
98     db_enfops = atoi((row[0] ? row[0] : defaults[0]));
99     db_enfvoice = atoi((row[1] ? row[1] : defaults[1]));
100     printf_mysql_query("SELECT `chanuser_access`, `user_user`, `chanuser_flags` FROM `chanusers` LEFT JOIN `users` ON `chanuser_uid` = `user_id` WHERE `chanuser_cid` = '%d' ORDER BY `chanuser_access` DESC, `user_user` ASC", chan->channel_id);
101     res = mysql_use();
102     char *db_users[mysql_num_rows(res)];
103     int db_access[mysql_num_rows(res)];
104     int db_flags[mysql_num_rows(res)];
105     int db_count = 0;
106     while ((row = mysql_fetch_row(res)) != NULL) {
107         db_users[db_count] = row[1];
108         db_access[db_count] = atoi(row[0]);
109         db_flags[db_count] = atoi(row[2]);
110         db_count++;
111     }
112     int caccess, cflags;
113     struct ModeBuffer *modeBuf;
114     modeBuf = initModeBuffer(client, chan);
115     for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) {
116         caccess = 0;
117         cflags = 0;
118         if((chanuser->user->flags & USERFLAG_ISAUTHED)) {
119             for(i = 0; i < db_count; i++) {
120                 if(!stricmp(db_users[i], chanuser->user->auth)) {
121                     caccess = db_access[i];
122                     cflags = db_flags[i];
123                     if(cflags & DB_CHANUSER_SUSPENDED)
124                         caccess = 0;
125                     break;
126                 }
127             }
128         }
129         if((usermask && *usermask && match(usermask, chanuser->user->nick)) || caccess < min_access || caccess > max_access) continue;
130         if(caccess >= db_enfops) {
131             if(!(chanuser->flags & CHANUSERFLAG_OPPED) && resync_op && (override_noautoop || !(cflags & DB_CHANUSER_NOAUTOOP)))
132                 modeBufferOp(modeBuf, chanuser->user->nick);
133         } else if(caccess >= db_enfvoice) {
134             if((chanuser->flags & CHANUSERFLAG_OPPED) && resync_op && !(chanuser->user->flags & (USERFLAG_ISBOT | USERFLAG_ISIRCOP)))
135                 modeBufferDeop(modeBuf, chanuser->user->nick);
136             if(!(chanuser->flags & CHANUSERFLAG_VOICED) && resync_voice && (override_noautoop || !(cflags & DB_CHANUSER_NOAUTOOP)))
137                 modeBufferVoice(modeBuf, chanuser->user->nick);
138         } else {
139             if((chanuser->flags & CHANUSERFLAG_OPPED) && resync_op && !(chanuser->user->flags & (USERFLAG_ISBOT | USERFLAG_ISIRCOP)))
140                 modeBufferDeop(modeBuf, chanuser->user->nick);
141             if((chanuser->flags & CHANUSERFLAG_VOICED) && resync_voice && !(chanuser->user->flags & (USERFLAG_ISBOT | USERFLAG_ISIRCOP)))
142                 modeBufferDevoice(modeBuf, chanuser->user->nick);
143         }
144         
145     }
146     freeModeBuffer(modeBuf);
147     reply(textclient, user, "NS_RESYNC_DONE", chan->name);
148 }