1 |
/** |
2 |
* akick.C: This file contains code for the ChanServ AKICK functions. |
3 |
* |
4 |
* Copyright © 2007 Pippijn van Steenhoven / The Ermyth Team |
5 |
* Rights to this code are as documented in COPYING. |
6 |
* |
7 |
* |
8 |
* Portions of this file were derived from sources bearing the following license: |
9 |
* Copyright © 2005 William Pitcock, et al. |
10 |
* Rights to this code are as documented in doc/pod/license.pod. |
11 |
* |
12 |
* $Id: akick.C,v 1.9 2007-09-16 18:54:42 pippijn Exp $ |
13 |
*/ |
14 |
|
15 |
#include "atheme.h" |
16 |
#include <util/time.h> |
17 |
#include <ermyth/module.h> |
18 |
#include <account/myuser.h> |
19 |
#include <account/mychan.h> |
20 |
#include <account/chanacs.h> |
21 |
|
22 |
static void cs_cmd_akick (sourceinfo_t *si, int parc, char *parv[]); |
23 |
|
24 |
static char const rcsid[] = "$Id: akick.C,v 1.9 2007-09-16 18:54:42 pippijn Exp $"; |
25 |
|
26 |
REGISTER_MODULE ("chanserv/akick", false, "The Ermyth Team <http://ermyth.xinutec.org>"); |
27 |
|
28 |
command_t const cs_akick = { "AKICK", N_("Manipulates a channel's AKICK list."), AC_NONE, 4, cs_cmd_akick }; |
29 |
|
30 |
E cmdvec cs_cmdtree; |
31 |
E helpvec cs_helptree; |
32 |
|
33 |
void |
34 |
cs_cmd_akick (sourceinfo_t *si, int parc, char *parv[]) |
35 |
{ |
36 |
myuser_t *mu; |
37 |
mychan_t *mc; |
38 |
chanacs_t *ca, *ca2; |
39 |
metadata *md; |
40 |
node_t *n; |
41 |
int operoverride = 0; |
42 |
char *chan; |
43 |
char *cmd; |
44 |
char *uname = parv[2]; |
45 |
char *reason = parv[3]; |
46 |
|
47 |
if (parc < 2) |
48 |
{ |
49 |
command_fail (si, fault::needmoreparams, STR_INSUFFICIENT_PARAMS, "AKICK"); |
50 |
command_fail (si, fault::needmoreparams, _("Syntax: AKICK <#channel> ADD|DEL|LIST <nickname|hostmask> [reason]")); |
51 |
return; |
52 |
} |
53 |
|
54 |
if (parv[0][0] == '#') |
55 |
chan = parv[0], cmd = parv[1]; |
56 |
else if (parv[1][0] == '#') |
57 |
cmd = parv[0], chan = parv[1]; |
58 |
else |
59 |
{ |
60 |
command_fail (si, fault::badparams, STR_INVALID_PARAMS, "AKICK"); |
61 |
command_fail (si, fault::badparams, _("Syntax: AKICK <#channel> ADD|DEL|LIST <nickname|hostmask> [reason]")); |
62 |
return; |
63 |
} |
64 |
|
65 |
if ((strcasecmp ("LIST", cmd)) && (!uname)) |
66 |
{ |
67 |
command_fail (si, fault::needmoreparams, STR_INSUFFICIENT_PARAMS, "AKICK"); |
68 |
command_fail (si, fault::needmoreparams, _("Syntax: AKICK <#channel> ADD|DEL|LIST <nickname|hostmask> [reason]")); |
69 |
return; |
70 |
} |
71 |
|
72 |
/* make sure they're registered, logged in |
73 |
* and the founder of the channel before |
74 |
* we go any further. |
75 |
*/ |
76 |
if (!si->smu) |
77 |
{ |
78 |
/* if they're opers and just want to LIST, they don't have to log in */ |
79 |
if (!(has_priv (si, PRIV_CHAN_AUSPEX) && !strcasecmp ("LIST", cmd))) |
80 |
{ |
81 |
command_fail (si, fault::noprivs, _("You are not logged in.")); |
82 |
return; |
83 |
} |
84 |
} |
85 |
|
86 |
mc = mychan_t::find (chan); |
87 |
if (!mc) |
88 |
{ |
89 |
command_fail (si, fault::nosuch_target, _("\2%s\2 is not registered."), chan); |
90 |
return; |
91 |
} |
92 |
|
93 |
if (mc->find_metadata ("private:close:closer")) |
94 |
{ |
95 |
command_fail (si, fault::noprivs, _("\2%s\2 is closed."), chan); |
96 |
return; |
97 |
} |
98 |
|
99 |
/* ADD */ |
100 |
if (!strcasecmp ("ADD", cmd)) |
101 |
{ |
102 |
if ((chanacs_source_flags (mc, si) & (CA_FLAGS | CA_REMOVE)) != (CA_FLAGS | CA_REMOVE)) |
103 |
{ |
104 |
command_fail (si, fault::noprivs, _("You are not authorized to perform this operation.")); |
105 |
return; |
106 |
} |
107 |
|
108 |
mu = myuser_t::find_ext (uname); |
109 |
if (!mu) |
110 |
{ |
111 |
/* we might be adding a hostmask */ |
112 |
if (!validhostmask (uname)) |
113 |
{ |
114 |
command_fail (si, fault::badparams, _("\2%s\2 is neither a nickname nor a hostmask."), uname); |
115 |
return; |
116 |
} |
117 |
|
118 |
uname = collapse (uname); |
119 |
|
120 |
ca = chanacs_find_host_literal (mc, uname, 0); |
121 |
if (ca != NULL) |
122 |
{ |
123 |
if (ca->level & CA_AKICK) |
124 |
command_fail (si, fault::nochange, _("\2%s\2 is already on the AKICK list for \2%s\2"), uname, mc->name); |
125 |
else |
126 |
command_fail (si, fault::alreadyexists, _("\2%s\2 already has flags \2%s\2 on \2%s\2"), uname, bitmask_to_flags (ca->level, chanacs_flags), mc->name); |
127 |
return; |
128 |
} |
129 |
|
130 |
ca = chanacs_find_host (mc, uname, CA_AKICK); |
131 |
if (ca != NULL) |
132 |
{ |
133 |
command_fail (si, fault::nochange, _("The more general mask \2%s\2 is already on the AKICK list for \2%s\2"), ca->host, mc->name); |
134 |
return; |
135 |
} |
136 |
|
137 |
/* new entry */ |
138 |
ca2 = chanacs_open (mc, NULL, uname, true); |
139 |
if (chanacs_is_table_full (ca2)) |
140 |
{ |
141 |
command_fail (si, fault::toomany, _("Channel %s access list is full."), mc->name); |
142 |
chanacs_close (ca2); |
143 |
return; |
144 |
} |
145 |
chanacs_modify_simple (ca2, CA_AKICK, 0); |
146 |
if (reason != NULL) |
147 |
ca2->add_metadata ("reason", reason); |
148 |
|
149 |
ca2->callback.akick_add (ca2); |
150 |
chanacs_close (ca2); |
151 |
|
152 |
verbose (mc, "\2%s\2 added \2%s\2 to the AKICK list.", get_source_name (si), uname); |
153 |
logcommand (si, CMDLOG_SET, "%s AKICK ADD %s", mc->name, uname); |
154 |
|
155 |
command_success_nodata (si, _("\2%s\2 has been added to the AKICK list for \2%s\2."), uname, mc->name); |
156 |
|
157 |
return; |
158 |
} |
159 |
else |
160 |
{ |
161 |
if ((ca = chanacs_find (mc, mu, 0x0))) |
162 |
{ |
163 |
if (ca->level & CA_AKICK) |
164 |
command_fail (si, fault::nochange, _("\2%s\2 is already on the AKICK list for \2%s\2"), mu->name, mc->name); |
165 |
else |
166 |
command_fail (si, fault::alreadyexists, _("\2%s\2 already has flags \2%s\2 on \2%s\2"), mu->name, bitmask_to_flags (ca->level, chanacs_flags), mc->name); |
167 |
return; |
168 |
} |
169 |
|
170 |
/* new entry */ |
171 |
ca2 = chanacs_open (mc, mu, NULL, true); |
172 |
if (chanacs_is_table_full (ca2)) |
173 |
{ |
174 |
command_fail (si, fault::toomany, _("Channel %s access list is full."), mc->name); |
175 |
chanacs_close (ca2); |
176 |
return; |
177 |
} |
178 |
chanacs_modify_simple (ca2, CA_AKICK, 0); |
179 |
if (reason != NULL) |
180 |
ca2->add_metadata ("reason", reason); |
181 |
|
182 |
ca2->callback.akick_add (ca2); |
183 |
chanacs_close (ca2); |
184 |
|
185 |
command_success_nodata (si, _("\2%s\2 has been added to the AKICK list for \2%s\2."), mu->name, mc->name); |
186 |
|
187 |
verbose (mc, "\2%s\2 added \2%s\2 to the AKICK list.", get_source_name (si), mu->name); |
188 |
logcommand (si, CMDLOG_SET, "%s AKICK ADD %s", mc->name, mu->name); |
189 |
|
190 |
return; |
191 |
} |
192 |
} |
193 |
else if (!strcasecmp ("DEL", cmd)) |
194 |
{ |
195 |
if ((chanacs_source_flags (mc, si) & (CA_FLAGS | CA_REMOVE)) != (CA_FLAGS | CA_REMOVE)) |
196 |
{ |
197 |
command_fail (si, fault::noprivs, _("You are not authorized to perform this operation.")); |
198 |
return; |
199 |
} |
200 |
|
201 |
mu = myuser_t::find_ext (uname); |
202 |
if (!mu) |
203 |
{ |
204 |
/* we might be deleting a hostmask */ |
205 |
ca = chanacs_find_host_literal (mc, uname, CA_AKICK); |
206 |
if (ca == NULL) |
207 |
{ |
208 |
ca = chanacs_find_host (mc, uname, CA_AKICK); |
209 |
if (ca != NULL) |
210 |
command_fail (si, fault::nosuch_key, _("\2%s\2 is not on the AKICK list for \2%s\2, however \2%s\2 is."), uname, mc->name, ca->host); |
211 |
else |
212 |
command_fail (si, fault::nosuch_key, _("\2%s\2 is not on the AKICK list for \2%s\2."), uname, mc->name); |
213 |
return; |
214 |
} |
215 |
|
216 |
chanacs_modify_simple (ca, 0, CA_AKICK); |
217 |
chanacs_close (ca); |
218 |
|
219 |
verbose (mc, "\2%s\2 removed \2%s\2 from the AKICK list.", get_source_name (si), uname); |
220 |
logcommand (si, CMDLOG_SET, "%s AKICK DEL %s", mc->name, uname); |
221 |
|
222 |
command_success_nodata (si, _("\2%s\2 has been removed from the AKICK list for \2%s\2."), uname, mc->name); |
223 |
|
224 |
return; |
225 |
} |
226 |
|
227 |
if (!(ca = chanacs_find (mc, mu, CA_AKICK))) |
228 |
{ |
229 |
command_fail (si, fault::nosuch_key, _("\2%s\2 is not on the AKICK list for \2%s\2."), mu->name, mc->name); |
230 |
return; |
231 |
} |
232 |
|
233 |
chanacs_modify_simple (ca, 0, CA_AKICK); |
234 |
chanacs_close (ca); |
235 |
|
236 |
command_success_nodata (si, _("\2%s\2 has been removed from the AKICK list for \2%s\2."), mu->name, mc->name); |
237 |
logcommand (si, CMDLOG_SET, "%s AKICK DEL %s", mc->name, mu->name); |
238 |
|
239 |
verbose (mc, "\2%s\2 removed \2%s\2 from the AKICK list.", get_source_name (si), mu->name); |
240 |
|
241 |
return; |
242 |
} |
243 |
else if (!strcasecmp ("LIST", cmd)) |
244 |
{ |
245 |
int i = 0; |
246 |
|
247 |
if (!chanacs_source_has_flag (mc, si, CA_ACLVIEW)) |
248 |
{ |
249 |
if (has_priv (si, PRIV_CHAN_AUSPEX)) |
250 |
operoverride = 1; |
251 |
else |
252 |
{ |
253 |
command_fail (si, fault::noprivs, _("You are not authorized to perform this operation.")); |
254 |
return; |
255 |
} |
256 |
} |
257 |
command_success_nodata (si, _("AKICK list for \2%s\2:"), mc->name); |
258 |
|
259 |
LIST_FOREACH (n, mc->chanacs.head) |
260 |
{ |
261 |
ca = (chanacs_t *) n->data; |
262 |
|
263 |
if (ca->level == CA_AKICK) |
264 |
{ |
265 |
md = ca->find_metadata ("reason"); |
266 |
if (ca->myuser == NULL) |
267 |
command_success_nodata (si, _("%d: \2%s\2 %s [modified: %s ago]"), ++i, ca->host, md ? md->value : "", time_ago (ca->ts)); |
268 |
else if (!ca->myuser->logins.empty ()) |
269 |
command_success_nodata (si, _("%d: \2%s\2 (logged in) %s [modified: %s ago]"), ++i, ca->myuser->name, md ? md->value : "", time_ago (ca->ts)); |
270 |
else |
271 |
command_success_nodata (si, _("%d: \2%s\2 (not logged in) %s [modified: %s ago]"), ++i, ca->myuser->name, md ? md->value : "", time_ago (ca->ts)); |
272 |
} |
273 |
|
274 |
} |
275 |
|
276 |
command_success_nodata (si, _("Total of \2%d\2 %s in \2%s\2's AKICK list."), i, (i == 1) ? "entry" : "entries", mc->name); |
277 |
if (operoverride) |
278 |
logcommand (si, CMDLOG_ADMIN, "%s AKICK LIST (oper override)", mc->name); |
279 |
else |
280 |
logcommand (si, CMDLOG_GET, "%s AKICK LIST", mc->name); |
281 |
} |
282 |
else |
283 |
command_fail (si, fault::badparams, _("Invalid command. Use \2/%s%s help\2 for a command listing."), (ircd->uses_rcommand == false) ? "msg " : "", si->service->disp); |
284 |
} |
285 |
|
286 |
bool |
287 |
_modinit (module *m) |
288 |
{ |
289 |
cs_cmdtree << cs_akick; |
290 |
help_addentry (cs_helptree, "AKICK", "help/chanserv/akick", NULL); |
291 |
|
292 |
return true; |
293 |
} |
294 |
|
295 |
void |
296 |
_moddeinit () |
297 |
{ |
298 |
help_delentry (cs_helptree, "AKICK"); |
299 |
cs_cmdtree >> cs_akick; |
300 |
} |