657b94a7e1cb399766d0bc144aea7bd80ddd01f6
[NeonServV5.git] / src / cmd_neonserv_resync.c
1 /* cmd_neonserv_resync.c - NeonServ v5.1
2  * Copyright (C) 2011  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] - usermask
22 * argv[1] - min access
23 * argv[2] - max access
24 */
25 static USERLIST_CALLBACK(neonserv_cmd_resync_userlist_lookup);
26 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);
27
28 struct neonserv_cmd_resync_cache {
29     struct ClientSocket *client, *textclient;
30     struct UserNode *user;
31     char *usermask;
32     int min_access;
33     int max_access;
34 };
35
36 CMD_BIND(neonserv_cmd_resync) {
37     int min_access = 0, max_access = 500;
38     char *usermask = NULL;
39     if(argc > 0)
40         usermask = argv[0];
41     if(argc > 2) {
42         min_access = atoi(argv[1]);
43         max_access = atoi(argv[2]);
44     }
45     struct neonserv_cmd_resync_cache *cache = malloc(sizeof(*cache));
46     if (!cache) {
47         perror("malloc() failed");
48         return;
49     }
50     cache->client = client;
51     cache->textclient = getTextBot();
52     cache->user = user;
53     cache->usermask = (usermask ? strdup(usermask) : NULL);
54     cache->min_access = min_access;
55     cache->max_access = max_access;
56     get_userlist_with_invisible(chan, neonserv_cmd_resync_userlist_lookup, cache);
57 }
58
59 static USERLIST_CALLBACK(neonserv_cmd_resync_userlist_lookup) {
60     struct neonserv_cmd_resync_cache *cache = data;
61     neonserv_cmd_resync_async1(cache->client, cache->textclient, cache->user, chan, cache->usermask, cache->min_access, cache->max_access);
62     if(cache->usermask)
63         free(cache->usermask);
64     free(cache);
65 }
66
67 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) {
68     MYSQL_RES *res;
69     MYSQL_ROW row, defaults = NULL;
70     int i;
71     int resync_op = 1;
72     int resync_voice = 1;
73     if(usermask && usermask[0] == '@') {
74         resync_voice = 0;
75         usermask++;
76         if(!*usermask) usermask = NULL;
77     } else if(usermask && usermask[0] == '+') {
78         resync_op = 0;
79         usermask++;
80         if(!*usermask) usermask = NULL;
81     }
82     struct ChanUser *chanuser;
83     int db_enfops, db_enfvoice;
84     printf_mysql_query("SELECT `channel_getop`, `channel_getvoice` FROM `channels` WHERE `channel_id` = '%d'", chan->channel_id);
85     row = mysql_fetch_row(mysql_use());
86     if(row[0] == NULL || row[1] == NULL) {
87         printf_mysql_query("SELECT `channel_getop`, `channel_getvoice` FROM `channels` WHERE `channel_name` = 'defaults'");
88         defaults = mysql_fetch_row(mysql_use());
89     }
90     db_enfops = atoi((row[0] ? row[0] : defaults[0]));
91     db_enfvoice = atoi((row[1] ? row[1] : defaults[1]));
92     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);
93     res = mysql_use();
94     char *db_users[mysql_num_rows(res)];
95     int db_access[mysql_num_rows(res)];
96     int db_flags[mysql_num_rows(res)];
97     int db_count = 0;
98     while ((row = mysql_fetch_row(res)) != NULL) {
99         db_users[db_count] = row[1];
100         db_access[db_count] = atoi(row[0]);
101         db_flags[db_count] = atoi(row[2]);
102         db_count++;
103     }
104     int caccess, cflags;
105     struct ModeBuffer *modeBuf;
106     modeBuf = initModeBuffer(client, chan);
107     for(chanuser = getChannelUsers(chan, NULL); chanuser; chanuser = getChannelUsers(chan, chanuser)) {
108         caccess = 0;
109         cflags = 0;
110         if((chanuser->user->flags & USERFLAG_ISAUTHED)) {
111             for(i = 0; i < db_count; i++) {
112                 if(!stricmp(db_users[i], chanuser->user->auth)) {
113                     caccess = db_access[i];
114                     cflags = db_flags[i];
115                     break;
116                 }
117             }
118         }
119         if((usermask && *usermask && match(usermask, row[1])) || caccess < min_access || caccess > max_access) continue;
120         if(caccess >= db_enfops) {
121             if(!(chanuser->flags & CHANUSERFLAG_OPPED) && resync_op)
122                 modeBufferOp(modeBuf, chanuser->user->nick);
123         } else if(caccess >= db_enfvoice) {
124             if((chanuser->flags & CHANUSERFLAG_OPPED) && resync_op && !(chanuser->user->flags & (USERFLAG_ISBOT | USERFLAG_ISIRCOP)))
125                 modeBufferDeop(modeBuf, chanuser->user->nick);
126             if(!(chanuser->flags & CHANUSERFLAG_VOICED) && resync_voice)
127                 modeBufferVoice(modeBuf, chanuser->user->nick);
128         } else {
129             if((chanuser->flags & CHANUSERFLAG_OPPED) && resync_op && !(chanuser->user->flags & (USERFLAG_ISBOT | USERFLAG_ISIRCOP)))
130                 modeBufferDeop(modeBuf, chanuser->user->nick);
131             if((chanuser->flags & CHANUSERFLAG_VOICED) && resync_voice && !(chanuser->user->flags & (USERFLAG_ISBOT | USERFLAG_ISIRCOP)))
132                 modeBufferDevoice(modeBuf, chanuser->user->nick);
133         }
134         
135     }
136     freeModeBuffer(modeBuf);
137     reply(textclient, user, "NS_RESYNC_DONE", chan->name);
138 }