cs_set.c

Go to the documentation of this file.
00001 /* ChanServ core functions
00002  *
00003  * (C) 2003-2007 Anope Team
00004  * Contact us at info@anope.org
00005  *
00006  * Please read COPYING and README for further details.
00007  *
00008  * Based on the original code of Epona by Lara.
00009  * Based on the original code of Services by Andy Church. 
00010  * 
00011  * $Id: cs_set.c 1275 2007-08-27 19:14:16Z drstein $
00012  *
00013  */
00014 /*************************************************************************/
00015 
00016 #include "module.h"
00017 #include "encrypt.h"
00018 
00019 int do_set(User * u);
00020 int do_set_founder(User * u, ChannelInfo * ci, char *param);
00021 int do_set_successor(User * u, ChannelInfo * ci, char *param);
00022 int do_set_password(User * u, ChannelInfo * ci, char *param);
00023 int do_set_desc(User * u, ChannelInfo * ci, char *param);
00024 int do_set_url(User * u, ChannelInfo * ci, char *param);
00025 int do_set_email(User * u, ChannelInfo * ci, char *param);
00026 int do_set_entrymsg(User * u, ChannelInfo * ci, char *param);
00027 int do_set_bantype(User * u, ChannelInfo * ci, char *param);
00028 int do_set_mlock(User * u, ChannelInfo * ci, char *param);
00029 int do_set_keeptopic(User * u, ChannelInfo * ci, char *param);
00030 int do_set_topiclock(User * u, ChannelInfo * ci, char *param);
00031 int do_set_private(User * u, ChannelInfo * ci, char *param);
00032 int do_set_secureops(User * u, ChannelInfo * ci, char *param);
00033 int do_set_securefounder(User * u, ChannelInfo * ci, char *param);
00034 int do_set_restricted(User * u, ChannelInfo * ci, char *param);
00035 int do_set_secure(User * u, ChannelInfo * ci, char *param);
00036 int do_set_signkick(User * u, ChannelInfo * ci, char *param);
00037 int do_set_opnotice(User * u, ChannelInfo * ci, char *param);
00038 int do_set_xop(User * u, ChannelInfo * ci, char *param);
00039 int do_set_peace(User * u, ChannelInfo * ci, char *param);
00040 int do_set_noexpire(User * u, ChannelInfo * ci, char *param);
00041 void myChanServHelp(User * u);
00042 
00049 int AnopeInit(int argc, char **argv)
00050 {
00051     Command *c;
00052 
00053     moduleAddAuthor("Anope");
00054     moduleAddVersion("$Id: cs_set.c 1275 2007-08-27 19:14:16Z drstein $");
00055     moduleSetType(CORE);
00056 
00057     c = createCommand("SET", do_set, NULL, CHAN_HELP_SET, -1, -1,
00058                       CHAN_SERVADMIN_HELP_SET, CHAN_SERVADMIN_HELP_SET);
00059     moduleAddCommand(CHANSERV, c, MOD_UNIQUE);
00060     c = createCommand("SET FOUNDER", NULL, NULL, CHAN_HELP_SET_FOUNDER, -1,
00061                       -1, -1, -1);
00062     moduleAddCommand(CHANSERV, c, MOD_UNIQUE);
00063     c = createCommand("SET SUCCESSOR", NULL, NULL, CHAN_HELP_SET_SUCCESSOR,
00064                       -1, -1, -1, -1);
00065     c->help_param1 = (char *) (long) CSMaxReg;
00066     moduleAddCommand(CHANSERV, c, MOD_UNIQUE);
00067     c = createCommand("SET PASSWORD", NULL, NULL, CHAN_HELP_SET_PASSWORD,
00068                       -1, -1, -1, -1);
00069     moduleAddCommand(CHANSERV, c, MOD_UNIQUE);
00070     c = createCommand("SET DESC", NULL, NULL, CHAN_HELP_SET_DESC, -1, -1,
00071                       -1, -1);
00072     moduleAddCommand(CHANSERV, c, MOD_UNIQUE);
00073     c = createCommand("SET URL", NULL, NULL, CHAN_HELP_SET_URL, -1, -1, -1,
00074                       -1);
00075     moduleAddCommand(CHANSERV, c, MOD_UNIQUE);
00076     c = createCommand("SET EMAIL", NULL, NULL, CHAN_HELP_SET_EMAIL, -1, -1,
00077                       -1, -1);
00078     moduleAddCommand(CHANSERV, c, MOD_UNIQUE);
00079     c = createCommand("SET ENTRYMSG", NULL, NULL, CHAN_HELP_SET_ENTRYMSG,
00080                       -1, -1, -1, -1);
00081     moduleAddCommand(CHANSERV, c, MOD_UNIQUE);
00082     c = createCommand("SET BANTYPE", NULL, NULL, CHAN_HELP_SET_BANTYPE, -1,
00083                       -1, -1, -1);
00084     moduleAddCommand(CHANSERV, c, MOD_UNIQUE);
00085     c = createCommand("SET PRIVATE", NULL, NULL, CHAN_HELP_SET_PRIVATE, -1,
00086                       -1, -1, -1);
00087     moduleAddCommand(CHANSERV, c, MOD_UNIQUE);
00088     c = createCommand("SET KEEPTOPIC", NULL, NULL, CHAN_HELP_SET_KEEPTOPIC,
00089                       -1, -1, -1, -1);
00090     moduleAddCommand(CHANSERV, c, MOD_UNIQUE);
00091     c = createCommand("SET TOPICLOCK", NULL, NULL, CHAN_HELP_SET_TOPICLOCK,
00092                       -1, -1, -1, -1);
00093     moduleAddCommand(CHANSERV, c, MOD_UNIQUE);
00094     c = createCommand("SET MLOCK", NULL, NULL, CHAN_HELP_SET_MLOCK, -1, -1,
00095                       -1, -1);
00096     moduleAddCommand(CHANSERV, c, MOD_UNIQUE);
00097     c = createCommand("SET RESTRICTED", NULL, NULL,
00098                       CHAN_HELP_SET_RESTRICTED, -1, -1, -1, -1);
00099     moduleAddCommand(CHANSERV, c, MOD_UNIQUE);
00100     c = createCommand("SET SECURE", NULL, NULL, CHAN_HELP_SET_SECURE, -1,
00101                       -1, -1, -1);
00102     c->help_param1 = s_NickServ;
00103     moduleAddCommand(CHANSERV, c, MOD_UNIQUE);
00104     c = createCommand("SET SECUREOPS", NULL, NULL, CHAN_HELP_SET_SECUREOPS,
00105                       -1, -1, -1, -1);
00106     moduleAddCommand(CHANSERV, c, MOD_UNIQUE);
00107     c = createCommand("SET SECUREFOUNDER", NULL, NULL,
00108                       CHAN_HELP_SET_SECUREFOUNDER, -1, -1, -1, -1);
00109     moduleAddCommand(CHANSERV, c, MOD_UNIQUE);
00110     c = createCommand("SET SIGNKICK", NULL, NULL, CHAN_HELP_SET_SIGNKICK,
00111                       -1, -1, -1, -1);
00112     moduleAddCommand(CHANSERV, c, MOD_UNIQUE);
00113     c = createCommand("SET OPNOTICE", NULL, NULL, CHAN_HELP_SET_OPNOTICE,
00114                       -1, -1, -1, -1);
00115     moduleAddCommand(CHANSERV, c, MOD_UNIQUE);
00116     c = createCommand("SET XOP", NULL, NULL, CHAN_HELP_SET_XOP, -1, -1, -1,
00117                       -1);
00118     moduleAddCommand(CHANSERV, c, MOD_UNIQUE);
00119     c = createCommand("SET PEACE", NULL, NULL, CHAN_HELP_SET_PEACE, -1, -1,
00120                       -1, -1);
00121     moduleAddCommand(CHANSERV, c, MOD_UNIQUE);
00122     c = createCommand("SET NOEXPIRE", NULL, NULL, -1, -1, -1,
00123                       CHAN_SERVADMIN_HELP_SET_NOEXPIRE,
00124                       CHAN_SERVADMIN_HELP_SET_NOEXPIRE);
00125     moduleAddCommand(CHANSERV, c, MOD_UNIQUE);
00126 
00127     moduleSetChanHelp(myChanServHelp);
00128 
00129     return MOD_CONT;
00130 }
00131 
00135 void AnopeFini(void)
00136 {
00137 
00138 }
00139 
00144 void myChanServHelp(User * u)
00145 {
00146     notice_lang(s_ChanServ, u, CHAN_HELP_CMD_SET);
00147 }
00148 
00155 /* Main SET routine.  Calls other routines as follows:
00156  *  do_set_command(User *command_sender, ChannelInfo *ci, char *param);
00157  * The parameter passed is the first space-delimited parameter after the
00158  * option name, except in the case of DESC, TOPIC, and ENTRYMSG, in which
00159  * it is the entire remainder of the line.  Additional parameters beyond
00160  * the first passed in the function call can be retrieved using
00161  * strtok(NULL, toks).
00162  */
00163 int do_set(User * u)
00164 {
00165     char *chan = strtok(NULL, " ");
00166     char *cmd = strtok(NULL, " ");
00167     char *param;
00168     ChannelInfo *ci;
00169     int is_servadmin = is_services_admin(u);
00170 
00171     if (readonly) {
00172         notice_lang(s_ChanServ, u, CHAN_SET_DISABLED);
00173         return MOD_CONT;
00174     }
00175 
00176     if (cmd) {
00177         if (stricmp(cmd, "DESC") == 0 || stricmp(cmd, "ENTRYMSG") == 0)
00178             param = strtok(NULL, "");
00179         else
00180             param = strtok(NULL, " ");
00181     } else {
00182         param = NULL;
00183     }
00184 
00185     if (!param && (!cmd || (stricmp(cmd, "SUCCESSOR") != 0 &&
00186                             stricmp(cmd, "URL") != 0 &&
00187                             stricmp(cmd, "EMAIL") != 0 &&
00188                             stricmp(cmd, "ENTRYMSG") != 0))) {
00189         syntax_error(s_ChanServ, u, "SET", CHAN_SET_SYNTAX);
00190     } else if (!(ci = cs_findchan(chan))) {
00191         notice_lang(s_ChanServ, u, CHAN_X_NOT_REGISTERED, chan);
00192     } else if (ci->flags & CI_VERBOTEN) {
00193         notice_lang(s_ChanServ, u, CHAN_X_FORBIDDEN, chan);
00194     } else if (!is_servadmin && !check_access(u, ci, CA_SET)) {
00195         notice_lang(s_ChanServ, u, ACCESS_DENIED);
00196     } else if (stricmp(cmd, "FOUNDER") == 0) {
00197         if (!is_servadmin
00198             && (ci->
00199                 flags & CI_SECUREFOUNDER ? !is_real_founder(u,
00200                                                             ci) :
00201                 !is_founder(u, ci))) {
00202             notice_lang(s_ChanServ, u, ACCESS_DENIED);
00203         } else {
00204             do_set_founder(u, ci, param);
00205         }
00206     } else if (stricmp(cmd, "SUCCESSOR") == 0) {
00207         if (!is_servadmin
00208             && (ci->
00209                 flags & CI_SECUREFOUNDER ? !is_real_founder(u,
00210                                                             ci) :
00211                 !is_founder(u, ci))) {
00212             notice_lang(s_ChanServ, u, ACCESS_DENIED);
00213         } else {
00214             do_set_successor(u, ci, param);
00215         }
00216     } else if (stricmp(cmd, "PASSWORD") == 0) {
00217         if (!is_servadmin
00218             && (ci->
00219                 flags & CI_SECUREFOUNDER ? !is_real_founder(u,
00220                                                             ci) :
00221                 !is_founder(u, ci))) {
00222             notice_lang(s_ChanServ, u, ACCESS_DENIED);
00223         } else {
00224             do_set_password(u, ci, param);
00225         }
00226     } else if (stricmp(cmd, "DESC") == 0) {
00227         do_set_desc(u, ci, param);
00228     } else if (stricmp(cmd, "URL") == 0) {
00229         do_set_url(u, ci, param);
00230     } else if (stricmp(cmd, "EMAIL") == 0) {
00231         do_set_email(u, ci, param);
00232     } else if (stricmp(cmd, "ENTRYMSG") == 0) {
00233         do_set_entrymsg(u, ci, param);
00234     } else if (stricmp(cmd, "TOPIC") == 0) {
00235         notice_lang(s_ChanServ, u, OBSOLETE_COMMAND, "TOPIC");
00236     } else if (stricmp(cmd, "BANTYPE") == 0) {
00237         do_set_bantype(u, ci, param);
00238     } else if (stricmp(cmd, "MLOCK") == 0) {
00239         do_set_mlock(u, ci, param);
00240     } else if (stricmp(cmd, "KEEPTOPIC") == 0) {
00241         do_set_keeptopic(u, ci, param);
00242     } else if (stricmp(cmd, "TOPICLOCK") == 0) {
00243         do_set_topiclock(u, ci, param);
00244     } else if (stricmp(cmd, "PRIVATE") == 0) {
00245         do_set_private(u, ci, param);
00246     } else if (stricmp(cmd, "SECUREOPS") == 0) {
00247         do_set_secureops(u, ci, param);
00248     } else if (stricmp(cmd, "SECUREFOUNDER") == 0) {
00249         if (!is_servadmin
00250             && (ci->
00251                 flags & CI_SECUREFOUNDER ? !is_real_founder(u,
00252                                                             ci) :
00253                 !is_founder(u, ci))) {
00254             notice_lang(s_ChanServ, u, ACCESS_DENIED);
00255         } else {
00256             do_set_securefounder(u, ci, param);
00257         }
00258     } else if (stricmp(cmd, "RESTRICTED") == 0) {
00259         do_set_restricted(u, ci, param);
00260     } else if (stricmp(cmd, "SECURE") == 0) {
00261         do_set_secure(u, ci, param);
00262     } else if (stricmp(cmd, "SIGNKICK") == 0) {
00263         do_set_signkick(u, ci, param);
00264     } else if (stricmp(cmd, "OPNOTICE") == 0) {
00265         do_set_opnotice(u, ci, param);
00266     } else if (stricmp(cmd, "XOP") == 0) {
00267         if (!(findModule("cs_xop"))) {
00268             notice_lang(s_ChanServ, u, CHAN_XOP_NOT_AVAILABLE, cmd);
00269         } else {
00270             do_set_xop(u, ci, param);
00271         }
00272     } else if (stricmp(cmd, "PEACE") == 0) {
00273         do_set_peace(u, ci, param);
00274     } else if (stricmp(cmd, "NOEXPIRE") == 0) {
00275         do_set_noexpire(u, ci, param);
00276     } else {
00277         notice_lang(s_ChanServ, u, CHAN_SET_UNKNOWN_OPTION, cmd);
00278         notice_lang(s_ChanServ, u, MORE_INFO, s_ChanServ, "SET");
00279     }
00280     return MOD_CONT;
00281 }
00282 
00283 /*************************************************************************/
00284 
00285 int do_set_founder(User * u, ChannelInfo * ci, char *param)
00286 {
00287     NickAlias *na = findnick(param);
00288     NickCore *nc, *nc0 = ci->founder;
00289 
00290     if (!na) {
00291         notice_lang(s_ChanServ, u, NICK_X_NOT_REGISTERED, param);
00292         return MOD_CONT;
00293     } else if (na->status & NS_VERBOTEN) {
00294         notice_lang(s_ChanServ, u, NICK_X_FORBIDDEN, param);
00295         return MOD_CONT;
00296     }
00297 
00298     nc = na->nc;
00299     if (nc->channelmax > 0 && nc->channelcount >= nc->channelmax
00300         && !is_services_admin(u)) {
00301         notice_lang(s_ChanServ, u, CHAN_SET_FOUNDER_TOO_MANY_CHANS, param);
00302         return MOD_CONT;
00303     }
00304 
00305     alog("%s: Changing founder of %s from %s to %s by %s!%s@%s",
00306          s_ChanServ, ci->name, ci->founder->display, nc->display, u->nick,
00307          u->username, u->host);
00308 
00309     /* Founder and successor must not be the same group */
00310     if (nc == ci->successor)
00311         ci->successor = NULL;
00312 
00313     nc0->channelcount--;
00314     ci->founder = nc;
00315     nc->channelcount++;
00316 
00317     notice_lang(s_ChanServ, u, CHAN_FOUNDER_CHANGED, ci->name, param);
00318     return MOD_CONT;
00319 }
00320 
00321 /*************************************************************************/
00322 
00323 int do_set_successor(User * u, ChannelInfo * ci, char *param)
00324 {
00325     NickAlias *na;
00326     NickCore *nc;
00327 
00328     if (param) {
00329         na = findnick(param);
00330 
00331         if (!na) {
00332             notice_lang(s_ChanServ, u, NICK_X_NOT_REGISTERED, param);
00333             return MOD_CONT;
00334         }
00335         if (na->status & NS_VERBOTEN) {
00336             notice_lang(s_ChanServ, u, NICK_X_FORBIDDEN, param);
00337             return MOD_CONT;
00338         }
00339         if (na->nc == ci->founder) {
00340             notice_lang(s_ChanServ, u, CHAN_SUCCESSOR_IS_FOUNDER, param,
00341                         ci->name);
00342             return MOD_CONT;
00343         }
00344         nc = na->nc;
00345 
00346     } else {
00347         nc = NULL;
00348     }
00349 
00350     alog("%s: Changing successor of %s from %s to %s by %s!%s@%s",
00351          s_ChanServ, ci->name,
00352          (ci->successor ? ci->successor->display : "none"),
00353          (nc ? nc->display : "none"), u->nick, u->username, u->host);
00354 
00355     ci->successor = nc;
00356 
00357     if (nc)
00358         notice_lang(s_ChanServ, u, CHAN_SUCCESSOR_CHANGED, ci->name,
00359                     param);
00360     else
00361         notice_lang(s_ChanServ, u, CHAN_SUCCESSOR_UNSET, ci->name);
00362     return MOD_CONT;
00363 }
00364 
00365 /*************************************************************************/
00366 
00367 int do_set_password(User * u, ChannelInfo * ci, char *param)
00368 {
00369     int len = strlen(param);
00370 
00371     if (stricmp(u->nick, param) == 0 || (StrictPasswords && len < 5)) {
00372         notice_lang(s_ChanServ, u, MORE_OBSCURE_PASSWORD);
00373         return MOD_CONT;
00374     }
00375 
00376     if (len > PASSMAX) {
00377         len = PASSMAX;
00378         param[len] = 0;
00379         notice_lang(s_ChanServ, u, PASSWORD_TRUNCATED, PASSMAX);
00380     }
00381 
00382     if (enc_encrypt(param, len, ci->founderpass, PASSMAX) < 0) {
00383         memset(param, 0, strlen(param));
00384         alog("%s: Failed to encrypt password for %s (set)", s_ChanServ,
00385              ci->name);
00386         notice_lang(s_ChanServ, u, CHAN_SET_PASSWORD_FAILED);
00387         return MOD_CONT;
00388     }
00389 
00390     memset(param, 0, strlen(param));
00391     notice_lang(s_ChanServ, u, CHAN_PASSWORD_CHANGED, ci->name);
00392 
00393     if (get_access(u, ci) < ACCESS_FOUNDER) {
00394         alog("%s: %s!%s@%s set password as Services admin for %s",
00395              s_ChanServ, u->nick, u->username, u->host, ci->name);
00396         if (WallSetpass)
00397             anope_cmd_global(s_ChanServ,
00398                              "\2%s\2 set password as Services admin for channel \2%s\2",
00399                              u->nick, ci->name);
00400     } else {
00401         alog("%s: %s!%s@%s changed password of %s (founder: %s)",
00402              s_ChanServ, u->nick, u->username, u->host,
00403              ci->name, ci->founder->display);
00404     }
00405     return MOD_CONT;
00406 }
00407 
00408 /*************************************************************************/
00409 
00410 int do_set_desc(User * u, ChannelInfo * ci, char *param)
00411 {
00412     if (ci->desc)
00413         free(ci->desc);
00414     ci->desc = sstrdup(param);
00415     notice_lang(s_ChanServ, u, CHAN_DESC_CHANGED, ci->name, param);
00416     return MOD_CONT;
00417 }
00418 
00419 /*************************************************************************/
00420 
00421 int do_set_url(User * u, ChannelInfo * ci, char *param)
00422 {
00423     if (ci->url)
00424         free(ci->url);
00425     if (param) {
00426         ci->url = sstrdup(param);
00427         notice_lang(s_ChanServ, u, CHAN_URL_CHANGED, ci->name, param);
00428     } else {
00429         ci->url = NULL;
00430         notice_lang(s_ChanServ, u, CHAN_URL_UNSET, ci->name);
00431     }
00432     return MOD_CONT;
00433 }
00434 
00435 /*************************************************************************/
00436 
00437 int do_set_email(User * u, ChannelInfo * ci, char *param)
00438 {
00439     if (ci->email)
00440         free(ci->email);
00441     if (param) {
00442         ci->email = sstrdup(param);
00443         notice_lang(s_ChanServ, u, CHAN_EMAIL_CHANGED, ci->name, param);
00444     } else {
00445         ci->email = NULL;
00446         notice_lang(s_ChanServ, u, CHAN_EMAIL_UNSET, ci->name);
00447     }
00448     return MOD_CONT;
00449 }
00450 
00451 /*************************************************************************/
00452 
00453 int do_set_entrymsg(User * u, ChannelInfo * ci, char *param)
00454 {
00455     if (ci->entry_message)
00456         free(ci->entry_message);
00457     if (param) {
00458         ci->entry_message = sstrdup(param);
00459         notice_lang(s_ChanServ, u, CHAN_ENTRY_MSG_CHANGED, ci->name,
00460                     param);
00461     } else {
00462         ci->entry_message = NULL;
00463         notice_lang(s_ChanServ, u, CHAN_ENTRY_MSG_UNSET, ci->name);
00464     }
00465     return MOD_CONT;
00466 }
00467 
00468 /*************************************************************************/
00469 
00470 int do_set_mlock(User * u, ChannelInfo * ci, char *param)
00471 {
00472     int add = -1;               /* 1 if adding, 0 if deleting, -1 if neither */
00473     unsigned char mode;
00474     CBMode *cbm;
00475 
00476     if (checkDefCon(DEFCON_NO_MLOCK_CHANGE)) {
00477         notice_lang(s_ChanServ, u, OPER_DEFCON_DENIED);
00478         return MOD_CONT;
00479     }
00480 
00481     /* Reinitialize everything */
00482     if (ircd->chanreg) {
00483         ci->mlock_on = ircd->regmode;
00484     } else {
00485         ci->mlock_on = 0;
00486     }
00487     ci->mlock_off = ci->mlock_limit = 0;
00488     ci->mlock_key = NULL;
00489     if (ircd->fmode) {
00490         ci->mlock_flood = NULL;
00491     }
00492     if (ircd->Lmode) {
00493         ci->mlock_redirect = NULL;
00494     }
00495 
00496     while ((mode = *param++)) {
00497         switch (mode) {
00498         case '+':
00499             add = 1;
00500             continue;
00501         case '-':
00502             add = 0;
00503             continue;
00504         default:
00505             if (add < 0)
00506                 continue;
00507         }
00508 
00509         if ((int) mode < 128 && (cbm = &cbmodes[(int) mode])->flag != 0) {
00510             if ((cbm->flags & CBM_NO_MLOCK)
00511                 || ((cbm->flags & CBM_NO_USER_MLOCK) && !is_oper(u))) {
00512                 notice_lang(s_ChanServ, u, CHAN_SET_MLOCK_IMPOSSIBLE_CHAR,
00513                             mode);
00514             } else if (add) {
00515                 ci->mlock_on |= cbm->flag;
00516                 ci->mlock_off &= ~cbm->flag;
00517                 if (cbm->cssetvalue)
00518                     cbm->cssetvalue(ci, strtok(NULL, " "));
00519             } else {
00520                 ci->mlock_off |= cbm->flag;
00521                 if (ci->mlock_on & cbm->flag) {
00522                     ci->mlock_on &= ~cbm->flag;
00523                     if (cbm->cssetvalue)
00524                         cbm->cssetvalue(ci, NULL);
00525                 }
00526             }
00527         } else {
00528             notice_lang(s_ChanServ, u, CHAN_SET_MLOCK_UNKNOWN_CHAR, mode);
00529         }
00530     }                           /* while (*param) */
00531 
00532     if (ircd->Lmode) {
00533         /* We can't mlock +L if +l is not mlocked as well. */
00534         if ((ci->mlock_on & ircd->chan_lmode)
00535             && !(ci->mlock_on & anope_get_limit_mode())) {
00536             ci->mlock_on &= ~ircd->chan_lmode;
00537             free(ci->mlock_redirect);
00538             notice_lang(s_ChanServ, u, CHAN_SET_MLOCK_L_REQUIRED);
00539         }
00540     }
00541 
00542     /* Some ircd we can't set NOKNOCK without INVITE */
00543     /* So check if we need there is a NOKNOCK MODE and that we need INVITEONLY */
00544     if (ircd->noknock && ircd->knock_needs_i) {
00545         if ((ci->mlock_on & ircd->noknock)
00546             && !(ci->mlock_on & anope_get_invite_mode())) {
00547             ci->mlock_on &= ~ircd->noknock;
00548             notice_lang(s_ChanServ, u, CHAN_SET_MLOCK_K_REQUIRED);
00549         }
00550     }
00551 
00552     /* Since we always enforce mode r there is no way to have no
00553      * mode lock at all.
00554      */
00555     if (get_mlock_modes(ci, 0)) {
00556         notice_lang(s_ChanServ, u, CHAN_MLOCK_CHANGED, ci->name,
00557                     get_mlock_modes(ci, 0));
00558     }
00559 
00560     /* Implement the new lock. */
00561     if (ci->c)
00562         check_modes(ci->c);
00563     return MOD_CONT;
00564 }
00565 
00566 /*************************************************************************/
00567 
00568 int do_set_bantype(User * u, ChannelInfo * ci, char *param)
00569 {
00570     char *endptr;
00571 
00572     int16 bantype = strtol(param, &endptr, 10);
00573 
00574     if (*endptr != 0 || bantype < 0 || bantype > 3) {
00575         notice_lang(s_ChanServ, u, CHAN_SET_BANTYPE_INVALID, param);
00576     } else {
00577         ci->bantype = bantype;
00578         notice_lang(s_ChanServ, u, CHAN_SET_BANTYPE_CHANGED, ci->name,
00579                     ci->bantype);
00580     }
00581     return MOD_CONT;
00582 }
00583 
00584 /*************************************************************************/
00585 
00586 int do_set_keeptopic(User * u, ChannelInfo * ci, char *param)
00587 {
00588     if (stricmp(param, "ON") == 0) {
00589         ci->flags |= CI_KEEPTOPIC;
00590         notice_lang(s_ChanServ, u, CHAN_SET_KEEPTOPIC_ON, ci->name);
00591     } else if (stricmp(param, "OFF") == 0) {
00592         ci->flags &= ~CI_KEEPTOPIC;
00593         notice_lang(s_ChanServ, u, CHAN_SET_KEEPTOPIC_OFF, ci->name);
00594     } else {
00595         syntax_error(s_ChanServ, u, "SET KEEPTOPIC",
00596                      CHAN_SET_KEEPTOPIC_SYNTAX);
00597     }
00598     return MOD_CONT;
00599 }
00600 
00601 /*************************************************************************/
00602 
00603 int do_set_topiclock(User * u, ChannelInfo * ci, char *param)
00604 {
00605     if (stricmp(param, "ON") == 0) {
00606         ci->flags |= CI_TOPICLOCK;
00607         notice_lang(s_ChanServ, u, CHAN_SET_TOPICLOCK_ON, ci->name);
00608     } else if (stricmp(param, "OFF") == 0) {
00609         ci->flags &= ~CI_TOPICLOCK;
00610         notice_lang(s_ChanServ, u, CHAN_SET_TOPICLOCK_OFF, ci->name);
00611     } else {
00612         syntax_error(s_ChanServ, u, "SET TOPICLOCK",
00613                      CHAN_SET_TOPICLOCK_SYNTAX);
00614     }
00615     return MOD_CONT;
00616 }
00617 
00618 /*************************************************************************/
00619 
00620 int do_set_private(User * u, ChannelInfo * ci, char *param)
00621 {
00622     if (stricmp(param, "ON") == 0) {
00623         ci->flags |= CI_PRIVATE;
00624         notice_lang(s_ChanServ, u, CHAN_SET_PRIVATE_ON, ci->name);
00625     } else if (stricmp(param, "OFF") == 0) {
00626         ci->flags &= ~CI_PRIVATE;
00627         notice_lang(s_ChanServ, u, CHAN_SET_PRIVATE_OFF, ci->name);
00628     } else {
00629         syntax_error(s_ChanServ, u, "SET PRIVATE",
00630                      CHAN_SET_PRIVATE_SYNTAX);
00631     }
00632     return MOD_CONT;
00633 }
00634 
00635 /*************************************************************************/
00636 
00637 int do_set_secureops(User * u, ChannelInfo * ci, char *param)
00638 {
00639     if (stricmp(param, "ON") == 0) {
00640         ci->flags |= CI_SECUREOPS;
00641         notice_lang(s_ChanServ, u, CHAN_SET_SECUREOPS_ON, ci->name);
00642     } else if (stricmp(param, "OFF") == 0) {
00643         ci->flags &= ~CI_SECUREOPS;
00644         notice_lang(s_ChanServ, u, CHAN_SET_SECUREOPS_OFF, ci->name);
00645     } else {
00646         syntax_error(s_ChanServ, u, "SET SECUREOPS",
00647                      CHAN_SET_SECUREOPS_SYNTAX);
00648     }
00649     return MOD_CONT;
00650 }
00651 
00652 /*************************************************************************/
00653 
00654 int do_set_securefounder(User * u, ChannelInfo * ci, char *param)
00655 {
00656     if (stricmp(param, "ON") == 0) {
00657         ci->flags |= CI_SECUREFOUNDER;
00658         notice_lang(s_ChanServ, u, CHAN_SET_SECUREFOUNDER_ON, ci->name);
00659     } else if (stricmp(param, "OFF") == 0) {
00660         ci->flags &= ~CI_SECUREFOUNDER;
00661         notice_lang(s_ChanServ, u, CHAN_SET_SECUREFOUNDER_OFF, ci->name);
00662     } else {
00663         syntax_error(s_ChanServ, u, "SET SECUREFOUNDER",
00664                      CHAN_SET_SECUREFOUNDER_SYNTAX);
00665     }
00666     return MOD_CONT;
00667 }
00668 
00669 /*************************************************************************/
00670 
00671 int do_set_restricted(User * u, ChannelInfo * ci, char *param)
00672 {
00673     if (stricmp(param, "ON") == 0) {
00674         ci->flags |= CI_RESTRICTED;
00675         if (ci->levels[CA_NOJOIN] < 0)
00676             ci->levels[CA_NOJOIN] = 0;
00677         notice_lang(s_ChanServ, u, CHAN_SET_RESTRICTED_ON, ci->name);
00678     } else if (stricmp(param, "OFF") == 0) {
00679         ci->flags &= ~CI_RESTRICTED;
00680         if (ci->levels[CA_NOJOIN] >= 0)
00681             ci->levels[CA_NOJOIN] = -2;
00682         notice_lang(s_ChanServ, u, CHAN_SET_RESTRICTED_OFF, ci->name);
00683     } else {
00684         syntax_error(s_ChanServ, u, "SET RESTRICTED",
00685                      CHAN_SET_RESTRICTED_SYNTAX);
00686     }
00687     return MOD_CONT;
00688 }
00689 
00690 /*************************************************************************/
00691 
00692 int do_set_secure(User * u, ChannelInfo * ci, char *param)
00693 {
00694     if (stricmp(param, "ON") == 0) {
00695         ci->flags |= CI_SECURE;
00696         notice_lang(s_ChanServ, u, CHAN_SET_SECURE_ON, ci->name);
00697     } else if (stricmp(param, "OFF") == 0) {
00698         ci->flags &= ~CI_SECURE;
00699         notice_lang(s_ChanServ, u, CHAN_SET_SECURE_OFF, ci->name);
00700     } else {
00701         syntax_error(s_ChanServ, u, "SET SECURE", CHAN_SET_SECURE_SYNTAX);
00702     }
00703     return MOD_CONT;
00704 }
00705 
00706 /*************************************************************************/
00707 
00708 int do_set_signkick(User * u, ChannelInfo * ci, char *param)
00709 {
00710     if (stricmp(param, "ON") == 0) {
00711         ci->flags |= CI_SIGNKICK;
00712         ci->flags &= ~CI_SIGNKICK_LEVEL;
00713         notice_lang(s_ChanServ, u, CHAN_SET_SIGNKICK_ON, ci->name);
00714     } else if (stricmp(param, "LEVEL") == 0) {
00715         ci->flags |= CI_SIGNKICK_LEVEL;
00716         ci->flags &= ~CI_SIGNKICK;
00717         notice_lang(s_ChanServ, u, CHAN_SET_SIGNKICK_LEVEL, ci->name);
00718     } else if (stricmp(param, "OFF") == 0) {
00719         ci->flags &= ~(CI_SIGNKICK | CI_SIGNKICK_LEVEL);
00720         notice_lang(s_ChanServ, u, CHAN_SET_SIGNKICK_OFF, ci->name);
00721     } else {
00722         syntax_error(s_ChanServ, u, "SET SIGNKICK",
00723                      CHAN_SET_SIGNKICK_SYNTAX);
00724     }
00725     return MOD_CONT;
00726 }
00727 
00728 /*************************************************************************/
00729 
00730 int do_set_opnotice(User * u, ChannelInfo * ci, char *param)
00731 {
00732     if (stricmp(param, "ON") == 0) {
00733         ci->flags |= CI_OPNOTICE;
00734         notice_lang(s_ChanServ, u, CHAN_SET_OPNOTICE_ON, ci->name);
00735     } else if (stricmp(param, "OFF") == 0) {
00736         ci->flags &= ~CI_OPNOTICE;
00737         notice_lang(s_ChanServ, u, CHAN_SET_OPNOTICE_OFF, ci->name);
00738     } else {
00739         syntax_error(s_ChanServ, u, "SET OPNOTICE",
00740                      CHAN_SET_OPNOTICE_SYNTAX);
00741     }
00742     return MOD_CONT;
00743 }
00744 
00745 /*************************************************************************/
00746 
00747 #define CHECKLEV(lev) ((ci->levels[(lev)] != ACCESS_INVALID) && (access->level >= ci->levels[(lev)]))
00748 
00749 int do_set_xop(User * u, ChannelInfo * ci, char *param)
00750 {
00751     if (stricmp(param, "ON") == 0) {
00752         if (!(ci->flags & CI_XOP)) {
00753             int i;
00754             ChanAccess *access;
00755 
00756             for (access = ci->access, i = 0; i < ci->accesscount;
00757                  access++, i++) {
00758                 if (!access->in_use)
00759                     continue;
00760                 /* This will probably cause wrong levels to be set, but hey,
00761                  * it's better than losing it altogether.
00762                  */
00763                 if (CHECKLEV(CA_AKICK) || CHECKLEV(CA_SET)) {
00764                     access->level = ACCESS_SOP;
00765                 } else if (CHECKLEV(CA_AUTOOP) || CHECKLEV(CA_OPDEOP)
00766                            || CHECKLEV(CA_OPDEOPME)) {
00767                     access->level = ACCESS_AOP;
00768                 } else if (ircd->halfop) {
00769                     if (CHECKLEV(CA_AUTOHALFOP) || CHECKLEV(CA_HALFOP)
00770                         || CHECKLEV(CA_HALFOPME)) {
00771                         access->level = ACCESS_HOP;
00772                     }
00773                 } else if (CHECKLEV(CA_AUTOVOICE) || CHECKLEV(CA_VOICE)
00774                            || CHECKLEV(CA_VOICEME)) {
00775                     access->level = ACCESS_VOP;
00776                 } else {
00777                     access->in_use = 0;
00778                     access->nc = NULL;
00779                 }
00780             }
00781 
00782             reset_levels(ci);
00783             ci->flags |= CI_XOP;
00784         }
00785 
00786         alog("%s: %s!%s@%s enabled XOP for %s", s_ChanServ, u->nick,
00787              u->username, u->host, ci->name);
00788         notice_lang(s_ChanServ, u, CHAN_SET_XOP_ON, ci->name);
00789     } else if (stricmp(param, "OFF") == 0) {
00790         ci->flags &= ~CI_XOP;
00791 
00792         alog("%s: %s!%s@%s disabled XOP for %s", s_ChanServ, u->nick,
00793              u->username, u->host, ci->name);
00794         notice_lang(s_ChanServ, u, CHAN_SET_XOP_OFF, ci->name);
00795     } else {
00796         syntax_error(s_ChanServ, u, "SET XOP", CHAN_SET_XOP_SYNTAX);
00797     }
00798     return MOD_CONT;
00799 }
00800 
00801 #undef CHECKLEV
00802 
00803 /*************************************************************************/
00804 
00805 int do_set_peace(User * u, ChannelInfo * ci, char *param)
00806 {
00807     if (stricmp(param, "ON") == 0) {
00808         ci->flags |= CI_PEACE;
00809         notice_lang(s_ChanServ, u, CHAN_SET_PEACE_ON, ci->name);
00810     } else if (stricmp(param, "OFF") == 0) {
00811         ci->flags &= ~CI_PEACE;
00812         notice_lang(s_ChanServ, u, CHAN_SET_PEACE_OFF, ci->name);
00813     } else {
00814         syntax_error(s_ChanServ, u, "SET PEACE", CHAN_SET_PEACE_SYNTAX);
00815     }
00816     return MOD_CONT;
00817 }
00818 
00819 /***************************