ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/ircd-hybrid/contrib/m_flags.c
Revision: 76
Committed: Tue Oct 4 19:38:49 2005 UTC (19 years, 10 months ago) by adx
Content type: text/x-csrc
File size: 12868 byte(s)
Log Message:
- fixed contrib #includes

File Contents

# Content
1 /*
2 * m_flags.c: Implements comstud-style mode flags.
3 *
4 * Copyright 2002 by W. Campbell and the ircd-hybrid development team
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are
8 * met:
9 *
10 * 1.Redistributions of source code must retain the above copyright notice,
11 * this list of conditions and the following disclaimer.
12 * 2.Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 * 3.The name of the author may not be used to endorse or promote products
16 * derived from this software without specific prior written permission.
17 *
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
21 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
22 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
24 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
26 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
27 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
28 * POSSIBILITY OF SUCH DAMAGE.
29 *
30 * $Id$
31 */
32
33 /* List of ircd includes from ../include/ */
34 #include "stdinc.h"
35 #include "handlers.h"
36 #include "client.h"
37 #include "common.h" /* FALSE bleah */
38 #include "ircd.h"
39 #include "numeric.h"
40 #include "s_conf.h"
41 #include "s_serv.h"
42 #include "send.h"
43 #include "msg.h"
44 #include "parse.h"
45 #include "modules.h"
46 #include "s_user.h" /* send_umode_out() */
47
48 static void m_flags(struct Client *, struct Client *, int, char *[]);
49 static void mo_flags(struct Client *, struct Client *, int, char *[]);
50
51 static char *set_flags_to_string(struct Client *);
52 static char *unset_flags_to_string(struct Client *);
53
54 struct Message flags_msgtab = {
55 "FLAGS", 0, 0, 0, 0, MFLG_SLOW, 0,
56 {m_unregistered, m_flags, m_ignore, m_ignore, mo_flags, m_ignore}
57 };
58
59 #ifndef STATIC_MODULES
60 void
61 _modinit(void)
62 {
63 mod_add_cmd(&flags_msgtab);
64 }
65
66 void
67 _moddeinit(void)
68 {
69 mod_del_cmd(&flags_msgtab);
70 }
71
72 const char *_version = "$Revision$";
73 #endif
74
75 /* FLAGS requires it's own mini parser, since the last parameter in it can
76 * contain a number of FLAGS. CS handles FLAGS mode1 mode2 OR
77 * FLAGS :mode1 mode2, but not both mixed.
78 *
79 * The best way to match a flag to a mode is with a simple table
80 */
81
82 static struct FlagTable
83 {
84 const char *name;
85 unsigned int mode;
86 int oper;
87 } flag_table[] = {
88 /* name mode it represents oper only? */
89 { "OWALLOPS", UMODE_OPERWALL, 1 },
90 { "SWALLOPS", UMODE_WALLOP, 0 },
91 { "STATSNOTICES", UMODE_SPY, 1 },
92 /* We don't have a separate OKILL and SKILL modes */
93 { "OKILLS", UMODE_SKILL, 0 },
94 { "SKILLS", UMODE_SKILL, 0 },
95 { "SNOTICES", UMODE_SERVNOTICE, 0 },
96 /* We don't have separate client connect and disconnect modes */
97 { "CLICONNECTS", UMODE_CCONN, 1 },
98 { "CLIDISCONNECTS", UMODE_CCONN, 1 },
99 /* I'm taking a wild guess here... */
100 { "THROTTLES", UMODE_REJ, 1 },
101 #if 0
102 /* This one is special...controlled via an oper block option */
103 { "NICKCHANGES", UMODE_NCHANGE, 1 },
104 /* NICKCHANGES must be checked for separately */
105 #endif
106 /* I'm assuming this is correct... */
107 { "IPMISMATCHES", UMODE_UNAUTH, 1 },
108 { "LWALLOPS", UMODE_LOCOPS, 1 },
109 /* These aren't separate on Hybrid */
110 { "CONNECTS", UMODE_EXTERNAL, 1 },
111 { "SQUITS", UMODE_EXTERNAL, 1 },
112 /* Now we have our Hybrid specific flags */
113 { "FULL", UMODE_FULL, 1 },
114 /* Not in CS, but we might as well put it here */
115 { "INVISIBLE", UMODE_INVISIBLE, 0 },
116 { "BOTS", UMODE_BOTS, 1 },
117 { "CALLERID", UMODE_CALLERID, 0 },
118 { "UNAUTH", UMODE_UNAUTH, 1 },
119 { "DEBUG", UMODE_DEBUG, 1 },
120 { NULL, 0, 0 }
121 };
122
123 /* We won't control CALLERID or INVISIBLE in here */
124
125 #define FL_ALL_USER_FLAGS (UMODE_WALLOP | UMODE_SKILL | UMODE_SERVNOTICE )
126
127 /* and we don't control NCHANGES here either */
128
129 #define FL_ALL_OPER_FLAGS (FL_ALL_USER_FLAGS | UMODE_CCONN | UMODE_REJ |\
130 UMODE_FULL | UMODE_SPY | UMODE_DEBUG |\
131 UMODE_OPERWALL | UMODE_BOTS | UMODE_EXTERNAL |\
132 UMODE_UNAUTH | UMODE_LOCOPS )
133
134 /* m_flags()
135 *
136 * parv[0] = sender prefix
137 * parv[1] = parameter
138 */
139 static void
140 m_flags(struct Client *client_p, struct Client *source_p,
141 int parc, char *parv[])
142 {
143 int i,j;
144 int isadd;
145 int isgood;
146 unsigned int setflags;
147 char *p;
148 char *flag;
149
150 if (parc < 2)
151 {
152 /* Generate a list of what flags you have and what you are missing,
153 ** and send it to the user
154 */
155 sendto_one(source_p, ":%s NOTICE %s :Current flags:%s",
156 me.name, parv[0], set_flags_to_string(source_p));
157 sendto_one(source_p, ":%s NOTICE %s :Current missing flags:%s",
158 me.name, parv[0], unset_flags_to_string(source_p));
159 return;
160 }
161
162 /* Preserve the current flags */
163 setflags = source_p->umodes;
164
165 /* XXX - change this to support a multiple last parameter like ISON */
166
167 for (i = 1; i < parc; i++)
168 {
169 for (flag = strtoken(&p, parv[i], " "); flag;
170 flag = strtoken(&p, NULL, " "))
171 {
172 /* We default to being in ADD mode */
173 isadd = 1;
174
175 /* We default to being in BAD mode */
176 isgood = 0;
177
178 if (!isalpha(*flag))
179 {
180 if (*flag == '-')
181 isadd = 0;
182 else if (*flag == '+')
183 isadd = 1;
184 ++flag;
185 }
186
187 /* support ALL here */
188 if (!irccmp(flag, "ALL"))
189 {
190 if (isadd)
191 source_p->umodes |= FL_ALL_USER_FLAGS;
192 else
193 source_p->umodes &= ~FL_ALL_USER_FLAGS;
194 sendto_one(source_p, ":%s NOTICE %s :Current flags:%s",
195 me.name, parv[0], set_flags_to_string(source_p));
196 sendto_one(source_p, ":%s NOTICE %s :Current missing flags:%s",
197 me.name, parv[0], unset_flags_to_string(source_p));
198 send_umode_out(client_p, source_p, setflags);
199 return;
200 }
201
202 for (j = 0; flag_table[j].name; j++)
203 {
204 if (!flag_table[j].oper && !irccmp(flag, flag_table[j].name))
205 {
206 if (isadd)
207 source_p->umodes |= flag_table[j].mode;
208 else
209 source_p->umodes &= ~flag_table[j].mode;
210 isgood = 1;
211 continue;
212 }
213 }
214 /* This for ended without matching a valid FLAG, here is where
215 * I want to operate differently than ircd-comstud, and just ignore
216 * the invalid flag, send a warning and go on.
217 */
218 if (!isgood)
219 sendto_one(source_p, ":%s NOTICE %s :Invalid FLAGS: %s (IGNORING)",
220 me.name, parv[0], flag);
221 }
222 }
223
224 /* All done setting the flags, print the notices out to the user
225 * telling what flags they have and what flags they are missing
226 */
227 sendto_one(source_p, ":%s NOTICE %s :Current flags:%s",
228 me.name, parv[0], set_flags_to_string(source_p));
229 sendto_one(source_p, ":%s NOTICE %s :Current missing flags:%s",
230 me.name, parv[0], unset_flags_to_string(source_p));
231
232 send_umode_out(client_p, source_p, setflags);
233 }
234
235 /* mo_flags()
236 *
237 * parv[0] = sender prefix
238 * parv[1] = parameter
239 */
240 static void
241 mo_flags(struct Client *client_p, struct Client *source_p,
242 int parc, char *parv[])
243 {
244 int i,j;
245 int isadd;
246 int isgood;
247 unsigned int setflags;
248 char *p;
249 char *flag;
250
251 if (parc < 2)
252 {
253 /* Generate a list of what flags you have and what you are missing,
254 ** and send it to the user
255 */
256 sendto_one(source_p, ":%s NOTICE %s :Current flags:%s",
257 me.name, parv[0], set_flags_to_string(source_p));
258 sendto_one(source_p, ":%s NOTICE %s :Current missing flags:%s",
259 me.name, parv[0], unset_flags_to_string(source_p));
260 return;
261 }
262
263 /* Preserve the current flags */
264 setflags = source_p->umodes;
265
266 /* XXX - change this to support a multiple last parameter like ISON */
267
268 for (i = 1; i < parc; i++)
269 {
270 for (flag = strtoken(&p, parv[i], " "); flag;
271 flag = strtoken(&p, NULL, " "))
272 {
273 /* We default to being in ADD mode */
274 isadd = 1;
275
276 /* We default to being in BAD mode */
277 isgood = 0;
278
279 if (!isalpha(*flag))
280 {
281 if (*flag == '-')
282 isadd = 0;
283 else if (*flag == '+')
284 isadd = 1;
285 ++flag;
286 }
287
288 /* support ALL here */
289 if (!irccmp(flag, "ALL"))
290 {
291 if (isadd)
292 source_p->umodes |= FL_ALL_OPER_FLAGS;
293 else
294 source_p->umodes &= ~FL_ALL_OPER_FLAGS;
295 sendto_one(source_p, ":%s NOTICE %s :Current flags:%s",
296 me.name, parv[0], set_flags_to_string(source_p));
297 sendto_one(source_p, ":%s NOTICE %s :Current missing flags:%s",
298 me.name, parv[0], unset_flags_to_string(source_p));
299 send_umode_out(client_p, source_p, setflags);
300 return;
301 }
302
303 if (!irccmp(flag, "NICKCHANGES"))
304 {
305 if (!IsOperN(source_p))
306 {
307 sendto_one(source_p,
308 ":%s NOTICE %s :*** You have no nick_changes flag;",
309 me.name,parv[0]);
310 continue;
311 }
312 if (isadd)
313 source_p->umodes |= UMODE_NCHANGE;
314 else
315 source_p->umodes &= ~UMODE_NCHANGE;
316 isgood = 1;
317 continue;
318 }
319
320 for (j = 0; flag_table[j].name; j++)
321 {
322 if (!irccmp(flag, flag_table[j].name))
323 {
324 if (isadd)
325 source_p->umodes |= flag_table[j].mode;
326 else
327 source_p->umodes &= ~ (flag_table[j].mode);
328 isgood = 1;
329 continue;
330 }
331 }
332 /* This for ended without matching a valid FLAG, here is where
333 * I want to operate differently than ircd-comstud, and just ignore
334 * the invalid flag, send a warning and go on.
335 */
336 if (!isgood)
337 sendto_one(source_p, ":%s NOTICE %s :Invalid FLAGS: %s (IGNORING)",
338 me.name, parv[0], flag);
339 }
340 }
341
342 /* All done setting the flags, print the notices out to the user
343 ** telling what flags they have and what flags they are missing
344 */
345 sendto_one(source_p, ":%s NOTICE %s :Current flags:%s",
346 me.name, parv[0], set_flags_to_string(source_p));
347 sendto_one(source_p, ":%s NOTICE %s :Current missing flags:%s",
348 me.name, parv[0], unset_flags_to_string(source_p));
349
350 send_umode_out(client_p, source_p, setflags);
351 }
352
353 static char *
354 set_flags_to_string(struct Client *client_p)
355 {
356 /* XXX - list all flags that we have set on the client */
357 static char setflags[IRCD_BUFSIZE + 1];
358 int i;
359
360 /* Clear it to begin with, we'll be doing a lot of ircsprintf's */
361 setflags[0] = '\0';
362
363 /* Unlike unset_flags_to_string(), we don't have to care about oper
364 ** flags and not showing them
365 */
366
367 for (i = 0; flag_table[i].name; i++)
368 {
369 if (client_p->umodes & flag_table[i].mode)
370 {
371 ircsprintf(setflags, "%s %s", setflags, flag_table[i].name);
372 }
373 }
374
375 #if 0
376 if (IsOper(client_p) && IsOperN(client_p))
377 {
378 #endif
379 /* You can only be set +NICKCHANGES if you are an oper and
380 * IsOperN(client_p) is true
381 */
382 if (client_p->umodes & UMODE_NCHANGE)
383 {
384 ircsprintf(setflags, "%s %s", setflags, "NICKCHANGES");
385 }
386 #if 0
387 }
388 #endif
389 return setflags;
390 }
391
392 static char *
393 unset_flags_to_string(struct Client *client_p)
394 {
395 /* Inverse of above */
396 /* XXX - list all flags that we do NOT have set on the client */
397 static char setflags[IRCD_BUFSIZE + 1];
398 int i, isoper;
399
400 /* Clear it to begin with, we'll be doing a lot of ircsprintf's */
401 setflags[0] = '\0';
402
403 isoper = IsOper(client_p) != 0;
404
405 for (i = 0; flag_table[i].name; i++)
406 {
407 if (!(client_p->umodes & flag_table[i].mode))
408 {
409 if (!isoper && flag_table[i].oper)
410 continue;
411
412 ircsprintf(setflags, "%s %s", setflags,
413 flag_table[i].name);
414 }
415 }
416
417 if (IsOper(client_p) && IsOperN(client_p))
418 {
419 if (!(client_p->umodes & UMODE_NCHANGE))
420 {
421 ircsprintf(setflags, "%s %s", setflags, "NICKCHANGES");
422 }
423 }
424
425 return setflags;
426 }

Properties

Name Value
svn:eol-style native
svn:keywords Id Revision