ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/ermyth/modules/chanserv/flags.C
Revision: 1.7
Committed: Thu Aug 30 19:56:20 2007 UTC (19 years, 1 month ago) by pippijn
Content type: text/plain
Branch: MAIN
Changes since 1.6: +34 -34 lines
Log Message:
- put faultcodes into their own namespace
- removed old files
- limited header garbage in atheme.h
- macros to inline bools for connection_t::is_*
- put some connection_t functions into the connection_t class

File Contents

# User Rev Content
1 pippijn 1.1 /*
2 pippijn 1.5 * Copyright © 2005-2007 William Pitcock, et al.
3 pippijn 1.2 * Rights to this code are as documented in doc/pod/license.pod.
4 pippijn 1.1 *
5 pippijn 1.5 * This file contains code for the ChanServ FLAGS functions.
6 pippijn 1.1 *
7 pippijn 1.7 * $Id: flags.C,v 1.6 2007-08-28 22:18:30 pippijn Exp $
8 pippijn 1.1 */
9    
10     #include "atheme.h"
11 pippijn 1.5 #include <ermyth/module.h>
12 pippijn 1.1 #include <account/mychan.h>
13     #include <account/myuser.h>
14     #include <account/chanacs.h>
15     #include "template.h"
16    
17 pippijn 1.7 static char const rcsid[] = "$Id: flags.C,v 1.6 2007-08-28 22:18:30 pippijn Exp $";
18 pippijn 1.1
19 pippijn 1.5 REGISTER_MODULE ("chanserv/flags", false, "The Ermyth Team <http://ermyth.schmorp.de>");
20 pippijn 1.1
21     static void cs_cmd_flags (sourceinfo_t *si, int parc, char *parv[]);
22    
23 pippijn 1.5 command_t const cs_flags = { "FLAGS", N_("Manipulates specific permissions on a channel."), AC_NONE, 3, cs_cmd_flags };
24 pippijn 1.1
25 pippijn 1.5 E cmdvec cs_cmdtree;
26     E helpvec cs_helptree;
27 pippijn 1.1
28 pippijn 1.5 bool
29     _modinit (module *m)
30 pippijn 1.1 {
31     cs_cmdtree << cs_flags;
32 pippijn 1.4 help_addentry (cs_helptree, "FLAGS", "help/chanserv/flags", NULL);
33 pippijn 1.5
34     return true;
35 pippijn 1.1 }
36    
37     void
38     _moddeinit ()
39     {
40     cs_cmdtree >> cs_flags;
41     help_delentry (cs_helptree, "FLAGS");
42     }
43    
44 pippijn 1.5 static char const * const
45 pippijn 1.1 get_template_name (mychan_t *mc, unsigned int level)
46     {
47 pippijn 1.7 metadata::item *md;
48 pippijn 1.5 char const *p, *q, *r;
49 pippijn 1.1 char *s;
50     char ss[40];
51     static char flagname[400];
52    
53     md = mc->find_metadata ("private:templates");
54     if (md != NULL)
55     {
56     p = md->value;
57     while (p != NULL)
58     {
59     while (*p == ' ')
60     p++;
61     q = strchr (p, '=');
62     if (q == NULL)
63     break;
64     r = strchr (q, ' ');
65     if (r != NULL && r < q)
66     break;
67     strlcpy (ss, q, sizeof ss);
68     if (r != NULL && r - q < (int) (sizeof ss - 1))
69     {
70     ss[r - q] = '\0';
71     }
72     if (level == flags_to_bitmask (ss, chanacs_flags, 0))
73     {
74     strlcpy (flagname, p, sizeof flagname);
75     s = strchr (flagname, '=');
76     if (s != NULL)
77     *s = '\0';
78     return flagname;
79     }
80     p = r;
81     }
82     }
83     if (level == chansvs.ca_sop)
84     return "SOP";
85     if (level == chansvs.ca_aop)
86     return "AOP";
87     /* if vop==hop, prefer vop */
88     if (level == chansvs.ca_vop)
89     return "VOP";
90     if (level == chansvs.ca_hop)
91     return "HOP";
92     return NULL;
93     }
94    
95     /* FLAGS <channel> [user] [flags] */
96     static void
97     cs_cmd_flags (sourceinfo_t *si, int parc, char *parv[])
98     {
99     chanacs_t *ca;
100     node_t *n;
101     int operoverride = 0;
102     char *channel = parv[0];
103     char *target = parv[1];
104 pippijn 1.5 char const *str1;
105     char const *str2;
106 pippijn 1.1 unsigned int addflags, removeflags, restrictflags;
107    
108     if (parc < 1)
109     {
110 pippijn 1.7 command_fail (si, fault::needmoreparams, STR_INSUFFICIENT_PARAMS, "FLAGS");
111     command_fail (si, fault::needmoreparams, _("Syntax: FLAGS <channel> [target] [flags]"));
112 pippijn 1.1 return;
113     }
114    
115     if (!target)
116     {
117 pippijn 1.7 mychan_t *mc = mychan_t::find (channel);
118 pippijn 1.1 unsigned int i = 1;
119    
120     if (!mc)
121     {
122 pippijn 1.7 command_fail (si, fault::nosuch_target, _("\2%s\2 is not registered."), channel);
123 pippijn 1.1 return;
124     }
125    
126     if (!chanacs_source_has_flag (mc, si, CA_ACLVIEW))
127     {
128     if (has_priv (si, PRIV_CHAN_AUSPEX))
129     operoverride = 1;
130     else
131     {
132 pippijn 1.7 command_fail (si, fault::noprivs, _("You are not authorized to perform this operation."));
133 pippijn 1.1 return;
134     }
135     }
136    
137     if (mc->find_metadata ("private:close:closer") && !has_priv (si, PRIV_CHAN_AUSPEX))
138     {
139 pippijn 1.7 command_fail (si, fault::noprivs, _("\2%s\2 is closed."), channel);
140 pippijn 1.1 return;
141     }
142    
143     command_success_nodata (si, _("Entry Nickname/Host Flags"));
144     command_success_nodata (si, "----- ---------------------- -----");
145    
146     LIST_FOREACH (n, mc->chanacs.head)
147     {
148     ca = static_cast<chanacs_t *> (n->data);
149     str1 = get_template_name (mc, ca->level);
150     str2 = ca->ts ? time_ago (ca->ts) : "?";
151     if (str1 != NULL)
152     command_success_nodata (si, _("%-5d %-22s %s (%s) [modified %s ago]"), i, ca->myuser ? ca->myuser->name : ca->host, bitmask_to_flags (ca->level, chanacs_flags), str1, str2);
153     else
154     command_success_nodata (si, _("%-5d %-22s %s [modified %s ago]"), i, ca->myuser ? ca->myuser->name : ca->host, bitmask_to_flags (ca->level, chanacs_flags), str2);
155     i++;
156     }
157    
158     command_success_nodata (si, "----- ---------------------- -----");
159     command_success_nodata (si, _("End of \2%s\2 FLAGS listing."), channel);
160     if (operoverride)
161     logcommand (si, CMDLOG_ADMIN, "%s FLAGS (oper override)", mc->name);
162     else
163     logcommand (si, CMDLOG_GET, "%s FLAGS", mc->name);
164     }
165     else
166     {
167 pippijn 1.7 mychan_t *mc = mychan_t::find (channel);
168 pippijn 1.1 myuser_t *tmu;
169     char *flagstr = parv[2];
170    
171     if (!si->smu)
172     {
173 pippijn 1.7 command_fail (si, fault::noprivs, _("You are not logged in."));
174 pippijn 1.1 return;
175     }
176    
177     if (!mc)
178     {
179 pippijn 1.7 command_fail (si, fault::nosuch_target, _("\2%s\2 is not registered."), channel);
180 pippijn 1.1 return;
181     }
182    
183     if (mc->find_metadata ("private:close:closer"))
184     {
185 pippijn 1.7 command_fail (si, fault::noprivs, _("\2%s\2 is closed."), channel);
186 pippijn 1.1 return;
187     }
188    
189     if (!target)
190     {
191 pippijn 1.7 command_fail (si, fault::needmoreparams, _("Usage: FLAGS %s [target] [flags]"), channel);
192 pippijn 1.1 return;
193     }
194    
195     if (!flagstr)
196     {
197     if (!chanacs_source_has_flag (mc, si, CA_ACLVIEW))
198     {
199 pippijn 1.7 command_fail (si, fault::noprivs, _("You are not authorized to execute this command."));
200 pippijn 1.1 return;
201     }
202     if (validhostmask (target))
203     ca = chanacs_find_host_literal (mc, target, 0);
204     else
205     {
206 pippijn 1.6 if (!(tmu = myuser_t::find_ext (target)))
207 pippijn 1.1 {
208 pippijn 1.7 command_fail (si, fault::nosuch_target, _("\2%s\2 is not registered."), target);
209 pippijn 1.1 return;
210     }
211     target = tmu->name;
212     ca = chanacs_find (mc, tmu, 0);
213     }
214     if (ca != NULL)
215     {
216     str1 = bitmask_to_flags2 (ca->level, 0, chanacs_flags);
217     command_success_string (si, str1, _("Flags for \2%s\2 in \2%s\2 are \2%s\2."), target, channel, str1);
218     }
219     else
220     command_success_string (si, "", _("No flags for \2%s\2 in \2%s\2."), target, channel);
221     logcommand (si, CMDLOG_GET, "%s FLAGS %s", mc->name, target);
222     return;
223     }
224    
225     /* founder may always set flags -- jilles */
226 pippijn 1.5 restrictflags = chanacs_source_flags (mc, si);
227     if (restrictflags & CA_FOUNDER)
228 pippijn 1.1 restrictflags = ca_all;
229     else
230     {
231     if (!(restrictflags & CA_FLAGS))
232     {
233     /* allow a user to remove their own access
234     * even without +f */
235     if (restrictflags & CA_AKICK || si->smu == NULL || irccasecmp (target, si->smu->name) || strcmp (flagstr, "-*"))
236     {
237 pippijn 1.7 command_fail (si, fault::noprivs, _("You are not authorized to execute this command."));
238 pippijn 1.1 return;
239     }
240     }
241     restrictflags = allow_flags (restrictflags);
242     }
243    
244     if (*flagstr == '+' || *flagstr == '-' || *flagstr == '=')
245     {
246     flags_make_bitmasks (flagstr, chanacs_flags, &addflags, &removeflags);
247     if (addflags == 0 && removeflags == 0)
248     {
249 pippijn 1.7 command_fail (si, fault::badparams, _("No valid flags given, use /%s%s HELP FLAGS for a list"), ircd->uses_rcommand ? "" : "msg ", chansvs.disp);
250 pippijn 1.1 return;
251     }
252     }
253     else
254     {
255     addflags = get_template_flags (mc, flagstr);
256     if (addflags == 0)
257     {
258     /* Hack -- jilles */
259     if (*target == '+' || *target == '-' || *target == '=')
260 pippijn 1.7 command_fail (si, fault::badparams, _("Usage: FLAGS %s [target] [flags]"), mc->name);
261 pippijn 1.1 else
262 pippijn 1.7 command_fail (si, fault::badparams, _("Invalid template name given, use /%s%s TEMPLATE %s for a list"), ircd->uses_rcommand ? "" : "msg ", chansvs.disp, mc->name);
263 pippijn 1.1 return;
264     }
265     removeflags = ca_all & ~addflags;
266     }
267    
268     if (!validhostmask (target))
269 pippijn 1.5 {
270 pippijn 1.6 if (!(tmu = myuser_t::find_ext (target)))
271 pippijn 1.5 {
272 pippijn 1.7 command_fail (si, fault::nosuch_target, _("\2%s\2 is not registered."), target);
273 pippijn 1.5 return;
274     }
275     target = tmu->name;
276    
277     ca = chanacs_open (mc, tmu, NULL, true);
278    
279     if (ca->level & CA_FOUNDER && removeflags & CA_FLAGS && !(removeflags & CA_FOUNDER))
280     {
281 pippijn 1.7 command_fail (si, fault::noprivs, _("You may not remove a founder's +f access."));
282 pippijn 1.5 return;
283     }
284 pippijn 1.7 if (ca->level & CA_FOUNDER && removeflags & CA_FOUNDER && mc->num_founders () == 1)
285 pippijn 1.5 {
286 pippijn 1.7 command_fail (si, fault::noprivs, _("You may not remove the last founder."));
287 pippijn 1.5 return;
288     }
289     if (!(ca->level & CA_FOUNDER) && addflags & CA_FOUNDER)
290     {
291 pippijn 1.7 if (mc->num_founders () >= chansvs.maxfounders)
292 pippijn 1.5 {
293 pippijn 1.7 command_fail (si, fault::noprivs, _("Only %d founders allowed per channel."), chansvs.maxfounders);
294 pippijn 1.5 chanacs_close (ca);
295     return;
296     }
297 pippijn 1.6 if ((tmu->num_channels () >= me.maxchans) && !has_priv_myuser (tmu, PRIV_REG_NOLIMIT))
298 pippijn 1.5 {
299 pippijn 1.7 command_fail (si, fault::toomany, _("\2%s\2 has too many channels registered."), tmu->name);
300 pippijn 1.5 return;
301     }
302     }
303     if (addflags & CA_FOUNDER)
304     addflags |= CA_FLAGS, removeflags &= ~CA_FLAGS;
305 pippijn 1.1
306     /* If NEVEROP is set, don't allow adding new entries
307     * except sole +b. Adding flags if the current level
308     * is +b counts as adding an entry.
309     * -- jilles */
310     if (MU_NEVEROP & tmu->flags && addflags != CA_AKICK && addflags != 0 && (ca->level == 0 || ca->level == CA_AKICK))
311     {
312 pippijn 1.7 command_fail (si, fault::noprivs, _("\2%s\2 does not wish to be added to access lists (NEVEROP set)."), tmu->name);
313 pippijn 1.1 chanacs_close (ca);
314     return;
315     }
316    
317     if (ca->level == 0 && chanacs_is_table_full (ca))
318     {
319 pippijn 1.7 command_fail (si, fault::toomany, _("Channel %s access list is full."), mc->name);
320 pippijn 1.1 chanacs_close (ca);
321     return;
322     }
323    
324     if (!chanacs_modify (ca, &addflags, &removeflags, restrictflags))
325     {
326 pippijn 1.7 command_fail (si, fault::noprivs, _("You are not allowed to set \2%s\2 on \2%s\2 in \2%s\2."), bitmask_to_flags2 (addflags, removeflags, chanacs_flags), tmu->name, mc->name);
327 pippijn 1.1 chanacs_close (ca);
328     return;
329     }
330     chanacs_close (ca);
331     }
332     else
333     {
334 pippijn 1.5 if (addflags & CA_FOUNDER)
335     {
336 pippijn 1.7 command_fail (si, fault::badparams, _("You may not set founder status on a hostmask."));
337 pippijn 1.5 return;
338     }
339     ca = chanacs_open (mc, NULL, target, true);
340     if (ca->level == 0 && chanacs_is_table_full (ca))
341 pippijn 1.1 {
342 pippijn 1.7 command_fail (si, fault::toomany, _("Channel %s access list is full."), mc->name);
343 pippijn 1.1 chanacs_close (ca);
344     return;
345     }
346     if (!chanacs_modify (ca, &addflags, &removeflags, restrictflags))
347     {
348 pippijn 1.7 command_fail (si, fault::noprivs, _("You are not allowed to set \2%s\2 on \2%s\2 in \2%s\2."), bitmask_to_flags2 (addflags, removeflags, chanacs_flags), target, mc->name);
349 pippijn 1.1 chanacs_close (ca);
350     return;
351     }
352     chanacs_close (ca);
353     }
354    
355     if ((addflags | removeflags) == 0)
356     {
357 pippijn 1.7 command_fail (si, fault::nochange, _("Channel access to \2%s\2 for \2%s\2 unchanged."), channel, target);
358 pippijn 1.1 return;
359     }
360     flagstr = bitmask_to_flags2 (addflags, removeflags, chanacs_flags);
361     command_success_nodata (si, _("Flags \2%s\2 were set on \2%s\2 in \2%s\2."), flagstr, target, channel);
362     logcommand (si, CMDLOG_SET, "%s FLAGS %s %s", mc->name, target, flagstr);
363     verbose (mc, "\2%s\2 set flags \2%s\2 on \2%s\2.", get_source_name (si), flagstr, target);
364     }
365     }
366    
367     /* vim:cinoptions=>s,e0,n0,f0,{0,}0,^0,=s,ps,t0,c3,+s,(2s,us,)20,*30,gs,hs
368     * vim:ts=8
369     * vim:sw=8
370     * vim:noexpandtab
371     */