ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/cvsroot/ermyth/modules/chanserv/flags.C
Revision: 1.2
Committed: Sat Jul 21 01:29:08 2007 UTC (19 years, 2 months ago) by pippijn
Content type: text/plain
Branch: MAIN
Changes since 1.1: +2 -2 lines
Log Message:
- moved to new documentation system
- fixed small build error

File Contents

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