ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/ermyth/modules/chanserv/template.C
Revision: 1.9
Committed: Sat Sep 22 14:27:27 2007 UTC (16 years, 8 months ago) by pippijn
Content type: text/plain
Branch: MAIN
CVS Tags: HEAD
Changes since 1.8: +3 -3 lines
Log Message:
split up ermyth into ermyth-modules, libermyth (currently just ermyth-util) and ermyth-core

File Contents

# Content
1 /**
2 * template.C: This file contains code for the ChanServ TEMPLATE 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-2006 Jilles Tjoelker, et al.
10 * Rights to this code are as documented in doc/pod/license.pod.
11 *
12 * $Id: template.C,v 1.8 2007-09-16 18:54:43 pippijn Exp $
13 */
14
15 #include "atheme.h"
16 #include <ermyth/module.h>
17 #include <account/myuser.h>
18 #include <account/mychan.h>
19 #include <account/chanacs.h>
20 #include "template.h"
21
22 static char const rcsid[] = "$Id: template.C,v 1.8 2007-09-16 18:54:43 pippijn Exp $";
23
24 REGISTER_MODULE ("chanserv/template", false, "The Ermyth Team <http://ermyth.xinutec.org>");
25
26 static void list_generic_flags (sourceinfo_t *si);
27
28 static void cs_cmd_template (sourceinfo_t *si, int parc, char *parv[]);
29
30 command_t const cs_flags = { "TEMPLATE", N_("Manipulates predefined sets of flags."), AC_NONE, 3, cs_cmd_template };
31
32 E cmdvec cs_cmdtree;
33 E helpvec cs_helptree;
34
35 bool
36 _modinit (module *m)
37 {
38 cs_cmdtree << cs_flags;
39 help_addentry (cs_helptree, "TEMPLATE", "help/chanserv/template", NULL);
40
41 return true;
42 }
43
44 void
45 _moddeinit ()
46 {
47 cs_cmdtree >> cs_flags;
48 help_delentry (cs_helptree, "TEMPLATE");
49 }
50
51 static void
52 list_generic_flags (sourceinfo_t *si)
53 {
54 command_success_nodata (si, "%-20s %s", _("Name"), _("Flags"));
55 command_success_nodata (si, "%-20s %s", "--------------------", "-----");
56 command_success_nodata (si, "%-20s %s", "SOP", bitmask_to_flags (chansvs.ca_sop, chanacs_flags));
57 command_success_nodata (si, "%-20s %s", "AOP", bitmask_to_flags (chansvs.ca_aop, chanacs_flags));
58 if (chansvs.ca_hop != chansvs.ca_vop)
59 command_success_nodata (si, "%-20s %s", "HOP", bitmask_to_flags (chansvs.ca_hop, chanacs_flags));
60 command_success_nodata (si, "%-20s %s", "VOP", bitmask_to_flags (chansvs.ca_vop, chanacs_flags));
61 command_success_nodata (si, "%-20s %s", "--------------------", "-----");
62 command_success_nodata (si, _("End of network wide template list."));
63 }
64
65 /* TEMPLATE [channel] [template] [flags] */
66 static void
67 cs_cmd_template (sourceinfo_t *si, int parc, char *parv[])
68 {
69 metadata *md;
70 int operoverride = 0, changechanacs = 0, l;
71 char *channel = parv[0];
72 char *target = parv[1];
73 mychan_t *mc = mychan_t::find (channel);
74 unsigned int oldflags, newflags = 0, addflags, removeflags, restrictflags;
75 char *p, *q, *r;
76 char ss[40], newstr[400];
77 bool found, denied;
78
79 if (!channel)
80 {
81 list_generic_flags (si);
82 logcommand (si, CMDLOG_GET, "TEMPLATE");
83 return;
84 }
85
86 mc = mychan_t::find (channel);
87 if (!mc)
88 {
89 command_fail (si, fault::nosuch_target, _("\2%s\2 is not registered."), channel);
90 return;
91 }
92
93 if (!target)
94 {
95 if (!chanacs_source_has_flag (mc, si, CA_ACLVIEW))
96 {
97 if (has_priv (si, PRIV_CHAN_AUSPEX))
98 operoverride = 1;
99 else
100 {
101 command_fail (si, fault::noprivs, _("You are not authorized to perform this operation."));
102 return;
103 }
104 }
105
106 if (mc->find_metadata ("private:close:closer") && !has_priv (si, PRIV_CHAN_AUSPEX))
107 {
108 command_fail (si, fault::noprivs, _("\2%s\2 is closed."), channel);
109 return;
110 }
111
112 md = mc->find_metadata ("private:templates");
113
114 if (md != NULL)
115 {
116 command_success_nodata (si, "%-20s %s", _("Name"), _("Flags"));
117 command_success_nodata (si, "%-20s %s", "--------------------", "-----");
118
119 p = md->value;
120 while (p != NULL)
121 {
122 while (*p == ' ')
123 p++;
124 q = strchr (p, '=');
125 if (q == NULL)
126 break;
127 r = strchr (q, ' ');
128 command_success_nodata (si, "%-20.*s %.*s", (q - p), p, r != NULL ? (r - q - 1) : (int) strlen (q + 1), q + 1);
129 p = r;
130 }
131
132 command_success_nodata (si, "%-20s %s", "--------------------", "-----");
133 command_success_nodata (si, _("End of \2%s\2 TEMPLATE listing."), mc->name);
134 }
135 else
136 command_success_nodata (si, _("No templates set on channel \2%s\2."), mc->name);
137 if (operoverride)
138 logcommand (si, CMDLOG_ADMIN, "%s TEMPLATE (oper override)", mc->name);
139 else
140 logcommand (si, CMDLOG_GET, "%s TEMPLATE", mc->name);
141 }
142 else
143 {
144 char *flagstr = parv[2];
145
146 if (!si->smu)
147 {
148 command_fail (si, fault::noprivs, _("You are not logged in."));
149 return;
150 }
151
152 /* probably no need to special-case founder here -- jilles */
153 /* founder may always set flags -- jilles */
154 restrictflags = chanacs_source_flags (mc, si);
155 if (restrictflags & CA_FOUNDER)
156 restrictflags = ca_all;
157 else
158 {
159 if (!(restrictflags & CA_FLAGS))
160 {
161 command_fail (si, fault::noprivs, _("You are not authorized to execute this command."));
162 return;
163 }
164 restrictflags = allow_flags (restrictflags);
165 }
166
167 if (mc->find_metadata ("private:close:closer"))
168 {
169 command_fail (si, fault::noprivs, _("\2%s\2 is closed."), channel);
170 return;
171 }
172
173 if (!target || !flagstr)
174 {
175 command_fail (si, fault::needmoreparams, _("Usage: TEMPLATE %s [target flags]"), channel);
176 return;
177 }
178
179 if (*target == '+' || *target == '-' || *target == '=')
180 {
181 command_fail (si, fault::badparams, _("Invalid template name \2%s\2."), target);
182 return;
183 }
184 l = strlen (target);
185
186 if (*flagstr == '!' && (flagstr[1] == '+' || flagstr[1] == '-' || flagstr[1] == '='))
187 {
188 changechanacs = 1;
189 flagstr++;
190 }
191
192 if (*flagstr == '+' || *flagstr == '-' || *flagstr == '=')
193 {
194 flags_make_bitmasks (flagstr, chanacs_flags, &addflags, &removeflags);
195 if (addflags == 0 && removeflags == 0)
196 {
197 command_fail (si, fault::badparams, _("No valid flags given, use /%s%s HELP FLAGS for a list"), ircd->uses_rcommand ? "" : "msg ", chansvs.disp);
198 return;
199 }
200 }
201 else
202 {
203 /* allow copying templates as well */
204 addflags = get_template_flags (mc, flagstr);
205 if (addflags == 0)
206 {
207 command_fail (si, fault::nosuch_key, _("Invalid template name given, use /%s%s TEMPLATE %s for a list"), ircd->uses_rcommand ? "" : "msg ", chansvs.disp, mc->name);
208 return;
209 }
210 removeflags = ca_all & ~addflags;
211 }
212
213 /* if adding +F, also add +f */
214 if (addflags & CA_FOUNDER)
215 addflags |= CA_FLAGS, removeflags &= ~CA_FLAGS;
216 /* if removing +f, also remove +F */
217 else if (removeflags & CA_FLAGS)
218 removeflags |= CA_FOUNDER, addflags &= ~CA_FOUNDER;
219
220 found = denied = false;
221 oldflags = 0;
222
223 md = mc->find_metadata ("private:templates");
224 if (md != NULL)
225 {
226 p = md->value;
227 strlcpy (newstr, p, sizeof newstr);
228 while (p != NULL)
229 {
230 while (*p == ' ')
231 p++;
232 q = strchr (p, '=');
233 if (q == NULL)
234 break;
235 r = strchr (q, ' ');
236 if (r != NULL && r < q)
237 break;
238 strlcpy (ss, q, sizeof ss);
239 if (r != NULL && r - q < (int) (sizeof ss - 1))
240 {
241 ss[r - q] = '\0';
242 }
243 if (q - p == l && !strncasecmp (target, p, q - p))
244 {
245 found = true;
246 oldflags = flags_to_bitmask (ss, chanacs_flags, 0);
247 addflags &= ~oldflags;
248 removeflags &= oldflags & ~addflags;
249 /* no change? */
250 if ((addflags | removeflags) == 0)
251 break;
252 /* attempting to add bad flag? */
253 /* attempting to remove bad flag? */
254 /* attempting to manipulate something with more privs? */
255 if (~restrictflags & addflags || ~restrictflags & removeflags || ~restrictflags & oldflags)
256 {
257 denied = true;
258 break;
259 }
260 newflags = (oldflags | addflags) & ~removeflags;
261 if (newflags == 0)
262 {
263 if (p == md->value)
264 /* removing first entry,
265 * zap the space after it */
266 strlcpy (newstr, r != NULL ? r + 1 : "", sizeof newstr);
267 else
268 {
269 /* otherwise, zap the space before it */
270 p--;
271 strlcpy (newstr + (p - md->value), r != NULL ? r : "", sizeof newstr - (p - md->value));
272 }
273 }
274 else
275 snprintf (newstr + (p - md->value), sizeof newstr - (p - md->value), "%s=%s%s", target, bitmask_to_flags (newflags, chanacs_flags), r != NULL ? r : "");
276 break;
277 }
278 p = r;
279 }
280 }
281 if (!found)
282 {
283 if (l == 3 && (!strcasecmp (target, "SOP") || !strcasecmp (target, "AOP") || !strcasecmp (target, "HOP") || !strcasecmp (target, "VOP")))
284 {
285 oldflags = get_template_flags (NULL, target);
286 addflags &= ~oldflags;
287 removeflags &= oldflags & ~addflags;
288 newflags = (oldflags | addflags) & ~removeflags;
289 if (newflags == 0)
290 removeflags = 0;
291 if ((addflags | removeflags) != 0)
292 command_success_nodata (si, _("Redefining built-in template \2%s\2."), target);
293 }
294 else
295 {
296 removeflags = 0;
297 newflags = addflags;
298 }
299 if ((addflags | removeflags) == 0)
300 ;
301 else if (~restrictflags & addflags || ~restrictflags & removeflags || ~restrictflags & oldflags)
302 denied = true;
303 else if (md != NULL)
304 snprintf (newstr + strlen (newstr), sizeof newstr - strlen (newstr), " %s=%s", target, bitmask_to_flags (newflags, chanacs_flags));
305 else
306 snprintf (newstr, sizeof newstr, "%s=%s", target, bitmask_to_flags (newflags, chanacs_flags));
307 }
308 if ((addflags | removeflags) == 0)
309 {
310 if (oldflags != 0)
311 command_fail (si, fault::nochange, _("Template \2%s\2 on \2%s\2 unchanged."), target, channel);
312 else
313 command_fail (si, fault::nosuch_key, _("No such template \2%s\2 on \2%s\2."), target, channel);
314 return;
315 }
316 if (denied)
317 {
318 command_fail (si, fault::noprivs, _("You are not allowed to set \2%s\2 on template \2%s\2 in \2%s\2."), bitmask_to_flags2 (addflags, removeflags, chanacs_flags), target, mc->name);
319 return;
320 }
321 if (strlen (newstr) >= 300)
322 {
323 command_fail (si, fault::toomany, _("Sorry, too many templates on \2%s\2."), channel);
324 return;
325 }
326 if (newstr[0] == '\0')
327 mc->del_metadata ("private:templates");
328 else
329 mc->add_metadata ("private:templates", newstr);
330 if (oldflags == 0)
331 command_success_nodata (si, _("Added template \2%s\2 with flags \2%s\2 in \2%s\2."), target, bitmask_to_flags (newflags, chanacs_flags), channel);
332 else if (newflags == 0)
333 command_success_nodata (si, _("Removed template \2%s\2 from \2%s\2."), target, channel);
334 else
335 command_success_nodata (si, _("Changed template \2%s\2 to \2%s\2 in \2%s\2."), target, bitmask_to_flags (newflags, chanacs_flags), channel);
336
337 flagstr = bitmask_to_flags2 (addflags, removeflags, chanacs_flags);
338 if (changechanacs)
339 {
340 node_t *n, *tn;
341 chanacs_t *ca;
342 int changes = 0, founderskipped = 0;
343 char flagstr2[128];
344
345 LIST_FOREACH_SAFE (n, tn, mc->chanacs.head)
346 {
347 ca = static_cast<chanacs_t *> (n->data);
348 if (ca->level != oldflags)
349 continue;
350 if ((addflags | removeflags) & CA_FOUNDER)
351 {
352 founderskipped++;
353 continue;
354 }
355 changes++;
356 chanacs_modify_simple (ca, newflags, ~newflags);
357 chanacs_close (ca);
358 }
359 logcommand (si, CMDLOG_SET, "%s TEMPLATE %s !%s (%d changes)", mc->name, target, flagstr, changes);
360 strlcpy (flagstr2, flagstr, sizeof flagstr2);
361 if (changes > 0)
362 verbose (mc, "\2%s\2 set \2%s\2 on %d access entries with flags \2%s\2.", get_source_name (si), flagstr2, changes, bitmask_to_flags (oldflags, chanacs_flags));
363 command_success_nodata (si, _("%d access entries updated accordingly."), changes);
364 if (founderskipped)
365 command_success_nodata (si, _("Not updating %d access entries involving founder status. Please do it manually."), founderskipped);
366 }
367 else
368 logcommand (si, CMDLOG_SET, "%s TEMPLATE %s %s", mc->name, target, flagstr);
369 /*verbose(mc, "Flags \2%s\2 were set on template \2%s\2 in \2%s\2.", flagstr, target, channel); */
370 }
371 }