ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/hybrid-ircservices-1/modules/chanserv/set.c
Revision: 1209
Committed: Thu Aug 25 19:05:49 2011 UTC (14 years, 11 months ago) by michael
Content type: text/x-csrc
File size: 21471 byte(s)
Log Message:
- run everything thru indent
  "-bli0 -di1 -npcs -nut -cdw -bls -nbbo -bap"

File Contents

# Content
1 /* SET command handling.
2 *
3 * IRC Services is copyright (c) 1996-2009 Andrew Church.
4 * E-mail: <achurch@achurch.org>
5 * Parts written by Andrew Kempe and others.
6 * This program is free but copyrighted software; see the file GPL.txt for
7 * details.
8 */
9
10 #include "services.h"
11 #include "modules.h"
12 #include "language.h"
13 #include "encrypt.h"
14 #include "modules/nickserv/nickserv.h"
15 #include "modules/operserv/operserv.h"
16
17 #include "chanserv.h"
18 #include "cs-local.h"
19
20 /*************************************************************************/
21
22 static int cb_set = -1;
23 static int cb_set_mlock = -1;
24 static int cb_unset = -1;
25
26 /*************************************************************************/
27
28 static void do_set_founder(User * u, ChannelInfo * ci, char *param);
29 static void do_set_successor(User * u, ChannelInfo * ci, char *param);
30 static void do_set_password(User * u, ChannelInfo * ci, char *param);
31 static void do_set_desc(User * u, ChannelInfo * ci, char *param);
32 static void do_set_url(User * u, ChannelInfo * ci, char *param);
33 static void do_set_email(User * u, ChannelInfo * ci, char *param);
34 static void do_set_entrymsg(User * u, ChannelInfo * ci, char *param);
35 static void do_set_mlock(User * u, ChannelInfo * ci, char *param);
36 static void do_set_hide(User * u, ChannelInfo * ci, char *param, char *extra);
37 static void do_set_boolean(User * u, ChannelInfo * ci, ChanOpt * co,
38 char *param);
39
40 /*************************************************************************/
41 /*************************************************************************/
42
43 /* Main SET routine. Calls other routines as follows:
44 * do_set_command(User *command_sender, ChannelInfo *ci, char *param);
45 * The parameter passed is the first space-delimited parameter after the
46 * option name, except in the case of DESC, TOPIC, and ENTRYMSG, in which
47 * it is the entire remainder of the line. Additional parameters beyond
48 * the first passed in the function call can be retrieved using
49 * strtok(NULL, toks).
50 *
51 * do_set_boolean, the default handler, is an exception to this in that it
52 * also takes the ChanOpt structure for the selected option as a parameter.
53 */
54
55 void
56 do_set(User * u)
57 {
58 char *chan = strtok(NULL, " ");
59 char *cmd = strtok(NULL, " ");
60 char *param = NULL, *extra = NULL;
61 ChannelInfo *ci = NULL;
62 int is_servadmin = is_services_admin(u);
63 int used_privs = 0;
64
65 if (readonly)
66 {
67 notice_lang(s_ChanServ, u, CHAN_SET_DISABLED);
68 return;
69 }
70
71 if (chan && cmd)
72 {
73 if (stricmp(cmd, "DESC") == 0 || stricmp(cmd, "TOPIC") == 0
74 || stricmp(cmd, "ENTRYMSG") == 0)
75 param = strtok_remaining();
76 else
77 param = strtok(NULL, " ");
78 if (stricmp(cmd, "HIDE") == 0)
79 extra = strtok(NULL, " ");
80 }
81 else
82 {
83 param = NULL;
84 }
85
86 if (!param || (stricmp(cmd, "MLOCK") != 0 && strtok_remaining()))
87 {
88 syntax_error(s_ChanServ, u, "SET", CHAN_SET_SYNTAX);
89 }
90 else if (!(ci = get_channelinfo(chan)))
91 {
92 notice_lang(s_ChanServ, u, CHAN_X_NOT_REGISTERED, chan);
93 }
94 else if (ci->flags & CF_VERBOTEN)
95 {
96 notice_lang(s_ChanServ, u, CHAN_X_FORBIDDEN, chan);
97 }
98 else if (!check_access_cmd(u, ci, "SET", cmd)
99 && (used_privs = 1, !is_servadmin))
100 {
101 notice_lang(s_ChanServ, u, ACCESS_DENIED);
102 }
103 else if (call_callback_4(cb_set, u, ci, cmd, param) > 0)
104 {
105 return;
106 }
107 else if (stricmp(cmd, "FOUNDER") == 0)
108 {
109 used_privs = 0;
110 if (!is_founder(u, ci) && (used_privs = 1, !is_servadmin))
111 {
112 notice_lang(s_ChanServ, u, CHAN_IDENTIFY_REQUIRED, s_ChanServ, chan);
113 }
114 else
115 {
116 if (WallAdminPrivs && used_privs)
117 {
118 wallops(s_ChanServ, "\2%s\2 used SET FOUNDER as Services"
119 " admin on \2%s\2", u->nick, ci->name);
120 }
121 do_set_founder(u, ci, param);
122 }
123 }
124 else if (stricmp(cmd, "SUCCESSOR") == 0)
125 {
126 used_privs = 0;
127 if (!is_founder(u, ci) && (used_privs = 1, !is_servadmin))
128 {
129 notice_lang(s_ChanServ, u, CHAN_IDENTIFY_REQUIRED, s_ChanServ, chan);
130 }
131 else
132 {
133 if (WallAdminPrivs && used_privs)
134 {
135 wallops(s_ChanServ, "\2%s\2 used SET SUCCESSOR as Services"
136 " admin on \2%s\2", u->nick, ci->name);
137 }
138 do_set_successor(u, ci, param);
139 }
140 }
141 else if (stricmp(cmd, "PASSWORD") == 0)
142 {
143 if (!is_servadmin && !is_founder(u, ci))
144 {
145 notice_lang(s_ChanServ, u, CHAN_IDENTIFY_REQUIRED, s_ChanServ, chan);
146 }
147 else
148 {
149 if (WallAdminPrivs && used_privs)
150 {
151 wallops(s_ChanServ, "\2%s\2 used SET PASSWORD as Services"
152 " admin on \2%s\2", u->nick, ci->name);
153 }
154 do_set_password(u, ci, param);
155 }
156 }
157 else if (stricmp(cmd, "DESC") == 0)
158 {
159 if (WallAdminPrivs && used_privs)
160 {
161 wallops(s_ChanServ, "\2%s\2 used SET DESC as Services admin"
162 " on \2%s\2", u->nick, ci->name);
163 }
164 do_set_desc(u, ci, param);
165 }
166 else if (stricmp(cmd, "URL") == 0)
167 {
168 if (WallAdminPrivs && used_privs)
169 {
170 wallops(s_ChanServ, "\2%s\2 used SET URL as Services admin"
171 " on \2%s\2", u->nick, ci->name);
172 }
173 do_set_url(u, ci, param);
174 }
175 else if (stricmp(cmd, "EMAIL") == 0)
176 {
177 if (WallAdminPrivs && used_privs)
178 {
179 wallops(s_ChanServ, "\2%s\2 used SET EMAIL as Services admin"
180 " on \2%s\2", u->nick, ci->name);
181 }
182 do_set_email(u, ci, param);
183 }
184 else if (stricmp(cmd, "ENTRYMSG") == 0)
185 {
186 if (WallAdminPrivs && used_privs)
187 {
188 wallops(s_ChanServ, "\2%s\2 used SET ENTRYMSG as Services admin"
189 " on \2%s\2", u->nick, ci->name);
190 }
191 do_set_entrymsg(u, ci, param);
192 }
193 else if (stricmp(cmd, "MLOCK") == 0)
194 {
195 if (WallAdminPrivs && used_privs)
196 {
197 wallops(s_ChanServ, "\2%s\2 used SET MLOCK as Services admin"
198 " on \2%s\2", u->nick, ci->name);
199 }
200 do_set_mlock(u, ci, param);
201 }
202 else if (stricmp(cmd, "HIDE") == 0)
203 {
204 if (WallAdminPrivs && used_privs)
205 {
206 wallops(s_ChanServ, "\2%s\2 used SET HIDE as Services admin"
207 " on \2%s\2", u->nick, ci->name);
208 }
209 do_set_hide(u, ci, param, extra);
210 }
211 else
212 {
213 ChanOpt *co = chanopt_from_name(cmd);
214 if (co && co->flag == CF_NOEXPIRE && (used_privs = 1, !is_servadmin))
215 co = NULL;
216 if (co)
217 {
218 if (WallAdminPrivs && used_privs)
219 {
220 wallops(s_ChanServ, "\2%s\2 used SET %s as Services admin"
221 " on \2%s\2", u->nick, co->name, ci->name);
222 }
223 do_set_boolean(u, ci, co, param);
224 }
225 else
226 {
227 notice_lang(s_ChanServ, u, CHAN_SET_UNKNOWN_OPTION, strupper(cmd));
228 notice_lang(s_ChanServ, u, MORE_INFO, s_ChanServ, "SET");
229 }
230 }
231 put_channelinfo(ci);
232 }
233
234 /*************************************************************************/
235
236 /* Handler for UNSET. */
237
238 void
239 do_unset(User * u)
240 {
241 char *chan = strtok(NULL, " ");
242 char *cmd = strtok(NULL, " ");
243 ChannelInfo *ci = NULL;
244 int is_servadmin = is_services_admin(u);
245 int used_privs = 0;
246
247 if (readonly)
248 {
249 notice_lang(s_ChanServ, u, CHAN_SET_DISABLED);
250 return;
251 }
252
253 if (!chan || !cmd)
254 {
255 syntax_error(s_ChanServ, u, "UNSET", CHAN_UNSET_SYNTAX);
256 }
257 else if (!(ci = get_channelinfo(chan)))
258 {
259 notice_lang(s_ChanServ, u, CHAN_X_NOT_REGISTERED, chan);
260 }
261 else if (ci->flags & CF_VERBOTEN)
262 {
263 notice_lang(s_ChanServ, u, CHAN_X_FORBIDDEN, chan);
264 }
265 else if (!check_access_cmd(u, ci, "SET", cmd)
266 && (used_privs = 1, !is_servadmin))
267 {
268 notice_lang(s_ChanServ, u, ACCESS_DENIED);
269 }
270 else if (call_callback_3(cb_unset, u, ci, cmd) > 0)
271 {
272 return;
273 }
274 else if (stricmp(cmd, "SUCCESSOR") == 0)
275 {
276 if (!is_servadmin && !is_founder(u, ci))
277 {
278 notice_lang(s_ChanServ, u, CHAN_IDENTIFY_REQUIRED, s_ChanServ, chan);
279 }
280 else
281 {
282 if (WallAdminPrivs && !is_founder(u, ci))
283 {
284 wallops(s_ChanServ, "\2%s\2 used UNSET SUCCESSOR as"
285 " Services admin on \2%s\2", u->nick, ci->name);
286 }
287 do_set_successor(u, ci, NULL);
288 }
289 }
290 else if (stricmp(cmd, "URL") == 0)
291 {
292 if (WallAdminPrivs && used_privs)
293 {
294 wallops(s_ChanServ, "\2%s\2 used UNSET URL as Services admin"
295 " on \2%s\2", u->nick, ci->name);
296 }
297 do_set_url(u, ci, NULL);
298 }
299 else if (stricmp(cmd, "EMAIL") == 0)
300 {
301 if (WallAdminPrivs && used_privs)
302 {
303 wallops(s_ChanServ, "\2%s\2 used UNSET EMAIL as Services admin"
304 " on \2%s\2", u->nick, ci->name);
305 }
306 do_set_email(u, ci, NULL);
307 }
308 else if (stricmp(cmd, "ENTRYMSG") == 0)
309 {
310 if (WallAdminPrivs && used_privs)
311 {
312 wallops(s_ChanServ, "\2%s\2 used UNSET ENTRYMSG as Services admin"
313 " on \2%s\2", u->nick, ci->name);
314 }
315 do_set_entrymsg(u, ci, NULL);
316 }
317 else
318 {
319 syntax_error(s_ChanServ, u, "UNSET", CHAN_UNSET_SYNTAX);
320 }
321 put_channelinfo(ci);
322 }
323
324 /*************************************************************************/
325 /*************************************************************************/
326
327 static void
328 do_set_founder(User * u, ChannelInfo * ci, char *param)
329 {
330 NickInfo *ni = get_nickinfo(param);
331 NickGroupInfo *ngi, *oldngi;
332
333 if (!ni)
334 {
335 notice_lang(s_ChanServ, u, NICK_X_NOT_REGISTERED, param);
336 return;
337 }
338 else if (ni->status & NS_VERBOTEN)
339 {
340 notice_lang(s_ChanServ, u, NICK_X_FORBIDDEN, param);
341 put_nickinfo(ni);
342 return;
343 }
344 else if (!(ngi = get_ngi(ni)))
345 {
346 notice_lang(s_ChanServ, u, INTERNAL_ERROR);
347 put_nickinfo(ni);
348 return;
349 }
350 put_nickinfo(ni);
351 if ((!is_services_admin(u) && check_channel_limit(ngi, NULL) >= 0)
352 || ngi->channels_count >= MAX_CHANNELCOUNT)
353 {
354 notice_lang(s_ChanServ, u, CHAN_SET_FOUNDER_TOO_MANY_CHANS, param);
355 return;
356 }
357 uncount_chan(ci);
358 oldngi = get_ngi_id(ci->founder);
359 module_log("Changing founder of %s from %s to %s by %s!%s@%s", ci->name,
360 oldngi ? ngi_mainnick(oldngi) : "<unknown>", param, u->nick,
361 u->username, u->host);
362 put_nickgroupinfo(oldngi);
363 ci->founder = ngi->id;
364 put_nickgroupinfo(ngi);
365 count_chan(ci);
366 if (ci->successor == ci->founder)
367 {
368 module_log("Successor for %s is same as new founder, clearing", ci->name);
369 ci->successor = 0;
370 }
371 notice_lang(s_ChanServ, u, CHAN_FOUNDER_CHANGED, ci->name, param);
372 }
373
374 /*************************************************************************/
375
376 static void
377 do_set_successor(User * u, ChannelInfo * ci, char *param)
378 {
379 if (param)
380 {
381 NickInfo *ni;
382 NickGroupInfo *ngi;
383
384 ni = get_nickinfo(param);
385 if (!ni)
386 {
387 notice_lang(s_ChanServ, u, NICK_X_NOT_REGISTERED, param);
388 return;
389 }
390 else if (ni->status & NS_VERBOTEN)
391 {
392 notice_lang(s_ChanServ, u, NICK_X_FORBIDDEN, param);
393 put_nickinfo(ni);
394 return;
395 }
396 else if (!(ngi = get_ngi(ni)))
397 {
398 notice_lang(s_ChanServ, u, INTERNAL_ERROR);
399 put_nickinfo(ni);
400 return;
401 }
402 put_nickinfo(ni);
403 if (ngi->id == ci->founder)
404 {
405 notice_lang(s_ChanServ, u, CHAN_SUCCESSOR_IS_FOUNDER);
406 put_nickgroupinfo(ngi);
407 return;
408 }
409 if (ci->successor)
410 {
411 NickGroupInfo *oldngi = get_ngi_id(ci->successor);
412 module_log("Changing successor of %s from %s to %s by %s!%s@%s",
413 ci->name,
414 oldngi ? ngi_mainnick(oldngi) : "<unknown>", param,
415 u->nick, u->username, u->host);
416 put_nickgroupinfo(oldngi);
417 }
418 else
419 {
420 module_log("Setting successor of %s to %s by %s!%s@%s",
421 ci->name, param, u->nick, u->username, u->host);
422 }
423 ci->successor = ngi->id;
424 put_nickgroupinfo(ngi);
425 notice_lang(s_ChanServ, u, CHAN_SUCCESSOR_CHANGED, ci->name, param);
426 }
427 else
428 {
429 module_log("Clearing successor of %s by %s!%s@%s",
430 ci->name, u->nick, u->username, u->host);
431 ci->successor = 0;
432 notice_lang(s_ChanServ, u, CHAN_SUCCESSOR_UNSET, ci->name);
433 }
434 }
435
436 /*************************************************************************/
437
438 static void
439 do_set_password(User * u, ChannelInfo * ci, char *param)
440 {
441 Password passbuf;
442 User *u2;
443
444 if (!(NoAdminPasswordCheck && is_services_admin(u))
445 && (stricmp(param, ci->name) == 0
446 || stricmp(param, ci->name + 1) == 0
447 || stricmp(param, u->nick) == 0
448 || (StrictPasswords && strlen(param) < 5)))
449 {
450 notice_lang(s_ChanServ, u, MORE_OBSCURE_PASSWORD);
451 return;
452 }
453
454 init_password(&passbuf);
455 if (encrypt_password(param, strlen(param), &passbuf) != 0)
456 {
457 clear_password(&passbuf);
458 memset(param, 0, strlen(param));
459 module_log("Failed to encrypt password for %s (set)", ci->name);
460 notice_lang(s_ChanServ, u, CHAN_SET_PASSWORD_FAILED);
461 return;
462 }
463 copy_password(&ci->founderpass, &passbuf);
464 clear_password(&passbuf);
465 if (CSShowPassword)
466 notice_lang(s_ChanServ, u, CHAN_PASSWORD_CHANGED_TO, ci->name, param);
467 else
468 notice_lang(s_ChanServ, u, CHAN_PASSWORD_CHANGED, ci->name);
469 memset(param, 0, strlen(param));
470 if (!is_founder(u, ci))
471 {
472 module_log("%s!%s@%s set password as Services admin for %s",
473 u->nick, u->username, u->host, ci->name);
474 }
475 /* Clear founder privileges from all other users who might have
476 * identified earlier. */
477 for (u2 = first_user(); u2; u2 = next_user())
478 {
479 if (u2 != u)
480 {
481 struct u_chaninfolist *c, *c2;
482 LIST_FOREACH_SAFE(c, u2->id_chans, c2)
483 {
484 if (irc_stricmp(c->chan, ci->name) == 0)
485 {
486 LIST_REMOVE(c, u2->id_chans);
487 free(c);
488 }
489 }
490 }
491 }
492 }
493
494 /*************************************************************************/
495
496 static void
497 do_set_desc(User * u, ChannelInfo * ci, char *param)
498 {
499 free(ci->desc);
500 ci->desc = sstrdup(param);
501 notice_lang(s_ChanServ, u, CHAN_DESC_CHANGED, ci->name, param);
502 }
503
504 /*************************************************************************/
505
506 static void
507 do_set_url(User * u, ChannelInfo * ci, char *param)
508 {
509 if (param && !valid_url(param))
510 {
511 notice_lang(s_ChanServ, u, BAD_URL);
512 return;
513 }
514
515 free(ci->url);
516 if (param)
517 {
518 ci->url = sstrdup(param);
519 notice_lang(s_ChanServ, u, CHAN_URL_CHANGED, ci->name, param);
520 }
521 else
522 {
523 ci->url = NULL;
524 notice_lang(s_ChanServ, u, CHAN_URL_UNSET, ci->name);
525 }
526 }
527
528 /*************************************************************************/
529
530 static void
531 do_set_email(User * u, ChannelInfo * ci, char *param)
532 {
533 if (param && !valid_email(param))
534 {
535 notice_lang(s_ChanServ, u, BAD_EMAIL);
536 return;
537 }
538 if (param && rejected_email(param))
539 {
540 notice_lang(s_NickServ, u, REJECTED_EMAIL);
541 return;
542 }
543
544 free(ci->email);
545 if (param)
546 {
547 ci->email = sstrdup(param);
548 notice_lang(s_ChanServ, u, CHAN_EMAIL_CHANGED, ci->name, param);
549 }
550 else
551 {
552 ci->email = NULL;
553 notice_lang(s_ChanServ, u, CHAN_EMAIL_UNSET, ci->name);
554 }
555 }
556
557 /*************************************************************************/
558
559 static void
560 do_set_entrymsg(User * u, ChannelInfo * ci, char *param)
561 {
562 free(ci->entry_message);
563 if (param)
564 {
565 ci->entry_message = sstrdup(param);
566 notice_lang(s_ChanServ, u, CHAN_ENTRY_MSG_CHANGED, ci->name);
567 }
568 else
569 {
570 ci->entry_message = NULL;
571 notice_lang(s_ChanServ, u, CHAN_ENTRY_MSG_UNSET, ci->name);
572 }
573 }
574
575 /*************************************************************************/
576
577 static void
578 do_set_mlock(User * u, ChannelInfo * ci, char *param)
579 {
580 char *s, modebuf[40], *end, c;
581 int ac = 0;
582 char *av[MAX_MLOCK_PARAMS];
583 char **avptr = &av[0];
584 int add = -1; /* 1 if adding, 0 if deleting, -1 if neither */
585 int32 flag;
586 int params;
587 ModeLock oldlock;
588
589 oldlock = ci->mlock;
590 memset(&ci->mlock, 0, sizeof(ci->mlock));
591
592 while (ac < MAX_MLOCK_PARAMS && (s = strtok(NULL, " ")) != NULL)
593 av[ac++] = s;
594
595 while (*param)
596 {
597 if (*param == '+')
598 {
599 add = 1;
600 param++;
601 continue;
602 }
603 else if (*param == '-')
604 {
605 add = 0;
606 param++;
607 continue;
608 }
609 else if (add < 0)
610 {
611 notice_lang(s_ChanServ, u, CHAN_SET_MLOCK_NEED_PLUS_MINUS);
612 goto fail;
613 }
614 c = *param++;
615 flag = mode_char_to_flag(c, MODE_CHANNEL);
616 params = mode_char_to_params(c, MODE_CHANNEL);
617 if (!flag)
618 {
619 notice_lang(s_ChanServ, u, CHAN_SET_MLOCK_UNKNOWN_CHAR, c);
620 continue;
621 }
622 else if (flag == MODE_INVALID)
623 {
624 notice_lang(s_ChanServ, u, CHAN_SET_MLOCK_CANNOT_LOCK, c);
625 continue;
626 }
627 /* "Off" locks never take parameters (they prevent the mode from
628 * ever being set in the first place) */
629 params = add ? (params >> 8) & 0xFF : 0;
630 if (params > ac)
631 {
632 notice_lang(s_ChanServ, u, CHAN_SET_MLOCK_NEED_PARAM, c);
633 goto fail;
634 }
635 if (flag & chanmode_reg)
636 notice_lang(s_ChanServ, u, CHAN_SET_MLOCK_MODE_REG_BAD, c);
637 else if (add)
638 ci->mlock.on |= flag, ci->mlock.off &= ~flag;
639 else
640 ci->mlock.off |= flag, ci->mlock.on &= ~flag;
641 switch (c)
642 {
643 case 'k':
644 if (add)
645 {
646 free(ci->mlock.key);
647 ci->mlock.key = sstrdup(avptr[0]);
648 }
649 else
650 {
651 free(ci->mlock.key);
652 ci->mlock.key = NULL;
653 }
654 break;
655 case 'l':
656 if (add)
657 {
658 ci->mlock.limit = atol(avptr[0]);
659 if (ci->mlock.limit <= 0)
660 {
661 notice_lang(s_ChanServ, u, CHAN_SET_MLOCK_NEED_POSITIVE, 'l');
662 goto fail;
663 }
664 }
665 else
666 {
667 ci->mlock.limit = 0;
668 }
669 break;
670 } /* switch */
671 if (call_callback_5(cb_set_mlock, u, ci, c, add, avptr) > 0)
672 goto fail;
673 ac -= params;
674 avptr += params;
675 } /* while (*param) */
676
677 /* Make sure there are no problems. */
678 if (call_callback_5(cb_set_mlock, u, ci, 0, 0, NULL) > 0)
679 goto fail;
680
681 /* Tell the user about the new mode lock. */
682 end = modebuf;
683 *end = 0;
684 if (ci->mlock.on || ci->mlock.key || ci->mlock.limit)
685 end += snprintf(end, sizeof(modebuf) - (end - modebuf), "+%s",
686 mode_flags_to_string(ci->mlock.on, MODE_CHANNEL));
687 if (ci->mlock.off)
688 end += snprintf(end, sizeof(modebuf) - (end - modebuf), "-%s",
689 mode_flags_to_string(ci->mlock.off, MODE_CHANNEL));
690 if (*modebuf)
691 {
692 notice_lang(s_ChanServ, u, CHAN_MLOCK_CHANGED, ci->name, modebuf);
693 }
694 else
695 {
696 notice_lang(s_ChanServ, u, CHAN_MLOCK_REMOVED, ci->name);
697 }
698
699 /* Clean up, implement the new lock and return. */
700 free(oldlock.key);
701 free(oldlock.link);
702 free(oldlock.flood);
703 check_modes(ci->c);
704 return;
705
706 fail:
707 /* Failure; restore the old mode lock. */
708 free(ci->mlock.key);
709 free(ci->mlock.link);
710 free(ci->mlock.flood);
711 ci->mlock = oldlock;
712 }
713
714 /*************************************************************************/
715
716 #define HIDE(x) do { \
717 flag = CF_HIDE_##x; \
718 onmsg = CHAN_SET_HIDE_##x##_ON; \
719 offmsg = CHAN_SET_HIDE_##x##_OFF; \
720 } while (0)
721
722 static void
723 do_set_hide(User * u, ChannelInfo * ci, char *param, char *extra)
724 {
725 int32 flag;
726 int onmsg, offmsg;
727
728 if (!extra)
729 {
730 syntax_error(s_ChanServ, u, "SET HIDE", CHAN_SET_HIDE_SYNTAX);
731 return;
732 }
733 if (stricmp(param, "EMAIL") == 0)
734 {
735 HIDE(EMAIL);
736 }
737 else if (stricmp(param, "TOPIC") == 0)
738 {
739 HIDE(TOPIC);
740 }
741 else if (stricmp(param, "MLOCK") == 0)
742 {
743 HIDE(MLOCK);
744 }
745 else
746 {
747 syntax_error(s_ChanServ, u, "SET HIDE", CHAN_SET_HIDE_SYNTAX);
748 return;
749 }
750 if (stricmp(extra, "ON") == 0)
751 {
752 ci->flags |= flag;
753 notice_lang(s_ChanServ, u, onmsg, ci->name, s_ChanServ);
754 }
755 else if (stricmp(extra, "OFF") == 0)
756 {
757 ci->flags &= ~flag;
758 notice_lang(s_ChanServ, u, offmsg, ci->name, s_ChanServ);
759 }
760 else
761 {
762 syntax_error(s_ChanServ, u, "SET HIDE", CHAN_SET_HIDE_SYNTAX);
763 }
764 }
765
766 #undef HIDE
767
768 /*************************************************************************/
769
770 static void
771 do_set_boolean(User * u, ChannelInfo * ci, ChanOpt * co, char *param)
772 {
773 if (stricmp(param, "ON") == 0)
774 {
775 ci->flags |= co->flag;
776 notice_lang(s_ChanServ, u, co->onstr, ci->name);
777 }
778 else if (stricmp(param, "OFF") == 0)
779 {
780 ci->flags &= ~co->flag;
781 notice_lang(s_ChanServ, u, co->offstr, ci->name);
782 }
783 else
784 {
785 char buf[BUFSIZE];
786 snprintf(buf, sizeof(buf), "SET %s", co->name);
787 syntax_error(s_ChanServ, u, buf, co->syntaxstr);
788 return;
789 }
790 }
791
792 /*************************************************************************/
793 /*************************************************************************/
794
795 int
796 init_set(void)
797 {
798 cb_set = register_callback("SET");
799 cb_set_mlock = register_callback("SET MLOCK");
800 cb_unset = register_callback("UNSET");
801 if (cb_set < 0 || cb_set_mlock < 0 || cb_unset < 0)
802 {
803 module_log("set: Unable to register callbacks");
804 exit_set();
805 return 0;
806 }
807 return 1;
808 }
809
810 /*************************************************************************/
811
812 void
813 exit_set()
814 {
815 unregister_callback(cb_unset);
816 unregister_callback(cb_set_mlock);
817 unregister_callback(cb_set);
818 }
819
820 /*************************************************************************/
821
822 /*
823 * Local variables:
824 * c-file-style: "stroustrup"
825 * c-file-offsets: ((case-label . *) (statement-case-intro . *))
826 * indent-tabs-mode: nil
827 * End:
828 *
829 * vim: expandtab shiftwidth=4:
830 */