cs_set.c

Go to the documentation of this file.
00001 /* ChanServ core functions
00002  *
00003  * (C) 2003-2013 Anope Team
00004  * Contact us at team@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  *
00012  */
00013 /*************************************************************************/
00014 
00015 #include "module.h"
00016 #include "encrypt.h"
00017 
00018 static int do_set(User * u);
00019 static int do_set_founder(User * u, ChannelInfo * ci, char *param);
00020 static int do_set_successor(User * u, ChannelInfo * ci, char *param);
00021 static int do_set_password(User * u, ChannelInfo * ci, char *param);
00022 static int do_set_desc(User * u, ChannelInfo * ci, char *param);
00023 static int do_set_url(User * u, ChannelInfo * ci, char *param);
00024 static int do_set_email(User * u, ChannelInfo * ci, char *param);
00025 static int do_set_entrymsg(User * u, ChannelInfo * ci, char *param);
00026 static int do_set_bantype(User * u, ChannelInfo * ci, char *param);
00027 static int do_set_mlock(User * u, ChannelInfo * ci, char *param);
00028 static int do_set_keeptopic(User * u, ChannelInfo * ci, char *param);
00029 static int do_set_topiclock(User * u, ChannelInfo * ci, char *param);
00030 static int do_set_private(User * u, ChannelInfo * ci, char *param);
00031 static int do_set_secureops(User * u, ChannelInfo * ci, char *param);
00032 static int do_set_securefounder(User * u, ChannelInfo * ci, char *param);
00033 static int do_set_restricted(User * u, ChannelInfo * ci, char *param);
00034 static int do_set_secure(User * u, ChannelInfo * ci, char *param);
00035 static int do_set_signkick(User * u, ChannelInfo * ci, char *param);
00036 static int do_set_opnotice(User * u, ChannelInfo * ci, char *param);
00037 static int do_set_xop(User * u, ChannelInfo * ci, char *param);
00038 static int do_set_peace(User * u, ChannelInfo * ci, char *param);
00039 static int do_set_noexpire(User * u, ChannelInfo * ci, char *param);
00040 static void myChanServHelp(User * u);
00041 
00048 int AnopeInit(int argc, char **argv)
00049 {
00050     Command *c;
00051 
00052     moduleAddAuthor("Anope");
00053     moduleAddVersion(VERSION_STRING);
00054     moduleSetType(CORE);
00055 
00056     c = createCommand("SET", do_set, NULL, CHAN_HELP_SET, -1, -1,
00057                       CHAN_SERVADMIN_HELP_SET, CHAN_SERVADMIN_HELP_SET);
00058     moduleAddCommand(CHANSERV, c, MOD_UNIQUE);
00059     c = createCommand("SET FOUNDER", NULL, NULL, CHAN_HELP_SET_FOUNDER, -1,
00060                       -1, -1, -1);
00061     moduleAddCommand(CHANSERV, c, MOD_UNIQUE);
00062     c = createCommand("SET SUCCESSOR", NULL, NULL, CHAN_HELP_SET_SUCCESSOR,
00063                       -1, -1, -1, -1);
00064     c->help_param1 = (char *) (long) CSMaxReg;
00065     moduleAddCommand(CHANSERV, c, MOD_UNIQUE);
00066     c = createCommand("SET PASSWORD", NULL, NULL, CHAN_HELP_SET_PASSWORD,
00067                       -1, -1, -1, -1);
00068     moduleAddCommand(CHANSERV, c, MOD_UNIQUE);
00069     c = createCommand("SET DESC", NULL, NULL, CHAN_HELP_SET_DESC, -1, -1,
00070                       -1, -1);
00071     moduleAddCommand(CHANSERV, c, MOD_UNIQUE);
00072     c = createCommand("SET URL", NULL, NULL, CHAN_HELP_SET_URL, -1, -1, -1,
00073                       -1);
00074     moduleAddCommand(CHANSERV, c, MOD_UNIQUE);
00075     c = createCommand("SET EMAIL", NULL, NULL, CHAN_HELP_SET_EMAIL, -1, -1,
00076                       -1, -1);
00077     moduleAddCommand(CHANSERV, c, MOD_UNIQUE);
00078     c = createCommand("SET ENTRYMSG", NULL, NULL, CHAN_HELP_SET_ENTRYMSG,
00079                       -1, -1, -1, -1);
00080     moduleAddCommand(CHANSERV, c, MOD_UNIQUE);
00081     c = createCommand("SET BANTYPE", NULL, NULL, CHAN_HELP_SET_BANTYPE, -1,
00082                       -1, -1, -1);
00083     moduleAddCommand(CHANSERV, c, MOD_UNIQUE);
00084     c = createCommand("SET PRIVATE", NULL, NULL, CHAN_HELP_SET_PRIVATE, -1,
00085                       -1, -1, -1);
00086     moduleAddCommand(CHANSERV, c, MOD_UNIQUE);
00087     c = createCommand("SET KEEPTOPIC", NULL, NULL, CHAN_HELP_SET_KEEPTOPIC,
00088                       -1, -1, -1, -1);
00089     moduleAddCommand(CHANSERV, c, MOD_UNIQUE);
00090     c = createCommand("SET TOPICLOCK", NULL, NULL, CHAN_HELP_SET_TOPICLOCK,
00091                       -1, -1, -1, -1);
00092     moduleAddCommand(CHANSERV, c, MOD_UNIQUE);
00093     c = createCommand("SET MLOCK", NULL, NULL, CHAN_HELP_SET_MLOCK, -1, -1,
00094                       -1, -1);
00095     moduleAddCommand(CHANSERV, c, MOD_UNIQUE);
00096     c = createCommand("SET RESTRICTED", NULL, NULL,
00097                       CHAN_HELP_SET_RESTRICTED, -1, -1, -1, -1);
00098     moduleAddCommand(CHANSERV, c, MOD_UNIQUE);
00099     c = createCommand("SET SECURE", NULL, NULL, CHAN_HELP_SET_SECURE, -1,
00100                       -1, -1, -1);
00101     c->help_param1 = s_NickServ;
00102     moduleAddCommand(CHANSERV, c, MOD_UNIQUE);
00103     c = createCommand("SET SECUREOPS", NULL, NULL, CHAN_HELP_SET_SECUREOPS,
00104                       -1, -1, -1, -1);
00105     moduleAddCommand(CHANSERV, c, MOD_UNIQUE);
00106     c = createCommand("SET SECUREFOUNDER", NULL, NULL,
00107                       CHAN_HELP_SET_SECUREFOUNDER, -1, -1, -1, -1);
00108     moduleAddCommand(CHANSERV, c, MOD_UNIQUE);
00109     c = createCommand("SET SIGNKICK", NULL, NULL, CHAN_HELP_SET_SIGNKICK,
00110                       -1, -1, -1, -1);
00111     moduleAddCommand(CHANSERV, c, MOD_UNIQUE);
00112     c = createCommand("SET OPNOTICE", NULL, NULL, CHAN_HELP_SET_OPNOTICE,
00113                       -1, -1, -1, -1);
00114     moduleAddCommand(CHANSERV, c, MOD_UNIQUE);
00115     c = createCommand("SET XOP", NULL, NULL, CHAN_HELP_SET_XOP, -1, -1, -1,
00116                       -1);
00117     moduleAddCommand(CHANSERV, c, MOD_UNIQUE);
00118     c = createCommand("SET PEACE", NULL, NULL, CHAN_HELP_SET_PEACE, -1, -1,
00119                       -1, -1);
00120     moduleAddCommand(CHANSERV, c, MOD_UNIQUE);
00121     c = createCommand("SET NOEXPIRE", NULL, NULL, -1, -1, -1,
00122                       CHAN_SERVADMIN_HELP_SET_NOEXPIRE,
00123                       CHAN_SERVADMIN_HELP_SET_NOEXPIRE);
00124     moduleAddCommand(CHANSERV, c, MOD_UNIQUE);
00125 
00126     moduleSetChanHelp(myChanServHelp);
00127 
00128     return MOD_CONT;
00129 }
00130 
00134 void AnopeFini(void)
00135 {
00136 
00137 }
00138 
00143 static void myChanServHelp(User * u)
00144 {
00145     notice_lang(s_ChanServ, u, CHAN_HELP_CMD_SET);
00146 }
00147 
00154 /* Main SET routine.  Calls other routines as follows:
00155  *      do_set_command(User *command_sender, ChannelInfo *ci, char *param);
00156  * The parameter passed is the first space-delimited parameter after the
00157  * option name, except in the case of DESC, TOPIC, and ENTRYMSG, in which
00158  * it is the entire remainder of the line.  Additional parameters beyond
00159  * the first passed in the function call can be retrieved using
00160  * strtok(NULL, toks).
00161  */
00162 static int do_set(User * u)
00163 {
00164     char *chan = strtok(NULL, " ");
00165     char *cmd = strtok(NULL, " ");
00166     char *param;
00167     ChannelInfo *ci;
00168     int is_servadmin = is_services_admin(u);
00169 
00170     if (readonly) {
00171         notice_lang(s_ChanServ, u, CHAN_SET_DISABLED);
00172         return MOD_CONT;
00173     }
00174 
00175     if (cmd) {
00176         if (stricmp(cmd, "DESC") == 0 || stricmp(cmd, "ENTRYMSG") == 0)
00177             param = strtok(NULL, "");
00178         else
00179             param = strtok(NULL, " ");
00180     } else {
00181         param = NULL;
00182     }
00183 
00184     if (!param && (!cmd || (stricmp(cmd, "SUCCESSOR") != 0 &&
00185                             stricmp(cmd, "URL") != 0 &&
00186                             stricmp(cmd, "EMAIL") != 0 &&
00187                             stricmp(cmd, "ENTRYMSG") != 0 &&
00188                             stricmp(cmd, "MLOCK") != 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 static 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 static 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 static 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 (enc_encrypt_check_len(len ,PASSMAX - 1)) {
00377         notice_lang(s_ChanServ, u, PASSWORD_TOO_LONG);
00378         return MOD_CONT;
00379     }
00380 
00381     if (enc_encrypt(param, len, ci->founderpass, PASSMAX -1) < 0) {
00382         memset(param, 0, strlen(param));
00383         alog("%s: Failed to encrypt password for %s (set)", s_ChanServ,
00384              ci->name);
00385         notice_lang(s_ChanServ, u, CHAN_SET_PASSWORD_FAILED);
00386         return MOD_CONT;
00387     }
00388 
00389     memset(param, 0, strlen(param));
00390     notice_lang(s_ChanServ, u, CHAN_PASSWORD_CHANGED, ci->name);
00391 
00392     if (get_access(u, ci) < ACCESS_FOUNDER) {
00393         alog("%s: %s!%s@%s set password as Services admin for %s",
00394              s_ChanServ, u->nick, u->username, u->host, ci->name);
00395         if (WallSetpass)
00396             anope_cmd_global(s_ChanServ,
00397                              "\2%s\2 set password as Services admin for channel \2%s\2",
00398                              u->nick, ci->name);
00399     } else {
00400         alog("%s: %s!%s@%s changed password of %s (founder: %s)",
00401              s_ChanServ, u->nick, u->username, u->host,
00402              ci->name, ci->founder->display);
00403     }
00404     return MOD_CONT;
00405 }
00406 
00407 /*************************************************************************/
00408 
00409 static int do_set_desc(User * u, ChannelInfo * ci, char *param)
00410 {
00411     if (ci->desc)
00412         free(ci->desc);
00413     ci->desc = sstrdup(param);
00414     alog("%s: %s!%s@%s set description of %s to: %s",
00415          s_ChanServ, u->nick, u->username, u->host, ci->name, ci->desc);
00416     notice_lang(s_ChanServ, u, CHAN_DESC_CHANGED, ci->name, param);
00417     return MOD_CONT;
00418 }
00419 
00420 /*************************************************************************/
00421 
00422 static int do_set_url(User * u, ChannelInfo * ci, char *param)
00423 {
00424     if (ci->url)
00425         free(ci->url);
00426     if (param) {
00427         ci->url = sstrdup(param);
00428         alog("%s: %s!%s@%s set url for %s to: %s",
00429              s_ChanServ, u->nick, u->username, u->host, ci->name, ci->url);
00430         notice_lang(s_ChanServ, u, CHAN_URL_CHANGED, ci->name, param);
00431     } else {
00432         ci->url = NULL;
00433         alog("%s: %s!%s@%s unset url for %s",
00434              s_ChanServ, u->nick, u->username, u->host, ci->name);
00435         notice_lang(s_ChanServ, u, CHAN_URL_UNSET, ci->name);
00436     }
00437     return MOD_CONT;
00438 }
00439 
00440 /*************************************************************************/
00441 
00442 static int do_set_email(User * u, ChannelInfo * ci, char *param)
00443 {
00444     if (ci->email)
00445         free(ci->email);
00446     if (param) {
00447         ci->email = sstrdup(param);
00448         alog("%s: %s!%s@%s set email for %s to: %s",
00449              s_ChanServ, u->nick, u->username, u->host, ci->name, ci->email);
00450         notice_lang(s_ChanServ, u, CHAN_EMAIL_CHANGED, ci->name, param);
00451     } else {
00452         ci->email = NULL;
00453         alog("%s: %s!%s@%s unset email for %s",
00454              s_ChanServ, u->nick, u->username, u->host, ci->name);
00455         notice_lang(s_ChanServ, u, CHAN_EMAIL_UNSET, ci->name);
00456     }
00457     return MOD_CONT;
00458 }
00459 
00460 /*************************************************************************/
00461 
00462 static int do_set_entrymsg(User * u, ChannelInfo * ci, char *param)
00463 {
00464     if (ci->entry_message)
00465         free(ci->entry_message);
00466     if (param) {
00467         ci->entry_message = sstrdup(param);
00468         alog("%s: %s!%s@%s set entrymsg for %s to: %s",
00469              s_ChanServ, u->nick, u->username, u->host, ci->name, ci->entry_message);
00470         notice_lang(s_ChanServ, u, CHAN_ENTRY_MSG_CHANGED, ci->name,
00471                     param);
00472     } else {
00473         ci->entry_message = NULL;
00474         alog("%s: %s!%s@%s unset entrymsg for %s",
00475              s_ChanServ, u->nick, u->username, u->host, ci->name);
00476         notice_lang(s_ChanServ, u, CHAN_ENTRY_MSG_UNSET, ci->name);
00477     }
00478     return MOD_CONT;
00479 }
00480 
00481 /*************************************************************************/
00482 
00483 static int do_set_mlock(User * u, ChannelInfo * ci, char *param)
00484 {
00485     int add = -1;               /* 1 if adding, 0 if deleting, -1 if neither */
00486     unsigned char mode;
00487     CBMode *cbm;
00488 
00489     if (checkDefCon(DEFCON_NO_MLOCK_CHANGE)) {
00490         notice_lang(s_ChanServ, u, OPER_DEFCON_DENIED);
00491         return MOD_CONT;
00492     }
00493 
00494     /* Reinitialize everything */
00495     if (ircd->chanreg) {
00496         ci->mlock_on = ircd->regmode;
00497     } else {
00498         ci->mlock_on = 0;
00499     }
00500     ci->mlock_off = ci->mlock_limit = 0;
00501     ci->mlock_key = NULL;
00502     if (ircd->fmode) {
00503         ci->mlock_flood = NULL;
00504     }
00505     if (ircd->Lmode) {
00506         ci->mlock_redirect = NULL;
00507     }
00508 
00509     while (param && (mode = *param++)) {
00510         switch (mode) {
00511         case '+':
00512             add = 1;
00513             continue;
00514         case '-':
00515             add = 0;
00516             continue;
00517         default:
00518             if (add < 0)
00519                 continue;
00520         }
00521 
00522         if ((int) mode < 128 && (cbm = &cbmodes[(int) mode])->flag != 0) {
00523             if ((cbm->flags & CBM_NO_MLOCK)
00524                 || ((cbm->flags & CBM_NO_USER_MLOCK) && !is_oper(u))) {
00525                 notice_lang(s_ChanServ, u, CHAN_SET_MLOCK_IMPOSSIBLE_CHAR,
00526                             mode);
00527             } else if (add) {
00528                 ci->mlock_on |= cbm->flag;
00529                 ci->mlock_off &= ~cbm->flag;
00530                 if (cbm->cssetvalue)
00531                     cbm->cssetvalue(ci, strtok(NULL, " "));
00532             } else {
00533                 ci->mlock_off |= cbm->flag;
00534                 if (ci->mlock_on & cbm->flag) {
00535                     ci->mlock_on &= ~cbm->flag;
00536                     if (cbm->cssetvalue)
00537                         cbm->cssetvalue(ci, NULL);
00538                 }
00539             }
00540         } else {
00541             notice_lang(s_ChanServ, u, CHAN_SET_MLOCK_UNKNOWN_CHAR, mode);
00542         }
00543     }                           /* while (*param) */
00544 
00545     if (ircd->Lmode) {
00546         /* We can't mlock +L if +l is not mlocked as well. */
00547         if ((ci->mlock_on & ircd->chan_lmode)
00548             && !(ci->mlock_on & anope_get_limit_mode())) {
00549             ci->mlock_on &= ~ircd->chan_lmode;
00550             free(ci->mlock_redirect);
00551             notice_lang(s_ChanServ, u, CHAN_SET_MLOCK_L_REQUIRED);
00552         }
00553     }
00554 
00555     /* Some ircd we can't set NOKNOCK without INVITE */
00556     /* So check if we need there is a NOKNOCK MODE and that we need INVITEONLY */
00557     if (ircd->noknock && ircd->knock_needs_i) {
00558         if ((ci->mlock_on & ircd->noknock)
00559             && !(ci->mlock_on & anope_get_invite_mode())) {
00560             ci->mlock_on &= ~ircd->noknock;
00561             notice_lang(s_ChanServ, u, CHAN_SET_MLOCK_K_REQUIRED);
00562         }
00563     }
00564 
00565     /* Since we always enforce mode r there is no way to have no
00566      * mode lock at all.
00567      */
00568     if (get_mlock_modes(ci, 0)) {
00569         alog("%s: %s!%s@%s set mlock for %s to: %s",
00570              s_ChanServ, u->nick, u->username, u->host, ci->name, get_mlock_modes(ci, 0));
00571         notice_lang(s_ChanServ, u, CHAN_MLOCK_CHANGED, ci->name,
00572                     get_mlock_modes(ci, 0));
00573     }
00574 
00575     /* Implement the new lock. */
00576     if (ci->c)
00577         check_modes(ci->c);
00578     return MOD_CONT;
00579 }
00580 
00581 /*************************************************************************/
00582 
00583 static int do_set_bantype(User * u, ChannelInfo * ci, char *param)
00584 {
00585     char *endptr;
00586 
00587     int16 bantype = strtol(param, &endptr, 10);
00588 
00589     if (*endptr != 0 || bantype < 0 || bantype > 3) {
00590         notice_lang(s_ChanServ, u, CHAN_SET_BANTYPE_INVALID, param);
00591     } else {
00592         ci->bantype = bantype;
00593         alog("%s: %s!%s@%s set ban type for %s to: %d",
00594              s_ChanServ, u->nick, u->username, u->host, ci->name, ci->bantype);
00595         notice_lang(s_ChanServ, u, CHAN_SET_BANTYPE_CHANGED, ci->name,
00596                     ci->bantype);
00597     }
00598     return MOD_CONT;
00599 }
00600 
00601 /*************************************************************************/
00602 
00603 static int do_set_keeptopic(User * u, ChannelInfo * ci, char *param)
00604 {
00605     if (stricmp(param, "ON") == 0) {
00606         ci->flags |= CI_KEEPTOPIC;
00607         alog("%s: %s!%s@%s set keeptopic ON for %s",
00608              s_ChanServ, u->nick, u->username, u->host, ci->name);
00609         notice_lang(s_ChanServ, u, CHAN_SET_KEEPTOPIC_ON, ci->name);
00610     } else if (stricmp(param, "OFF") == 0) {
00611         ci->flags &= ~CI_KEEPTOPIC;
00612         alog("%s: %s!%s@%s set keeptopic OFF for %s",
00613              s_ChanServ, u->nick, u->username, u->host, ci->name);
00614         notice_lang(s_ChanServ, u, CHAN_SET_KEEPTOPIC_OFF, ci->name);
00615     } else {
00616         syntax_error(s_ChanServ, u, "SET KEEPTOPIC",
00617                      CHAN_SET_KEEPTOPIC_SYNTAX);
00618     }
00619     return MOD_CONT;
00620 }
00621 
00622 /*************************************************************************/
00623 
00624 static int do_set_topiclock(User * u, ChannelInfo * ci, char *param)
00625 {
00626     if (stricmp(param, "ON") == 0) {
00627         ci->flags |= CI_TOPICLOCK;
00628         alog("%s: %s!%s@%s set topiclock ON for %s",
00629              s_ChanServ, u->nick, u->username, u->host, ci->name);
00630         notice_lang(s_ChanServ, u, CHAN_SET_TOPICLOCK_ON, ci->name);
00631     } else if (stricmp(param, "OFF") == 0) {
00632         ci->flags &= ~CI_TOPICLOCK;
00633         alog("%s: %s!%s@%s set topiclock OFF for %s",
00634              s_ChanServ, u->nick, u->username, u->host, ci->name);
00635         notice_lang(s_ChanServ, u, CHAN_SET_TOPICLOCK_OFF, ci->name);
00636     } else {
00637         syntax_error(s_ChanServ, u, "SET TOPICLOCK",
00638                      CHAN_SET_TOPICLOCK_SYNTAX);
00639     }
00640     return MOD_CONT;
00641 }
00642 
00643 /*************************************************************************/
00644 
00645 static int do_set_private(User * u, ChannelInfo * ci, char *param)
00646 {
00647     if (stricmp(param, "ON") == 0) {
00648         ci->flags |= CI_PRIVATE;
00649         alog("%s: %s!%s@%s set private ON for %s",
00650              s_ChanServ, u->nick, u->username, u->host, ci->name);
00651         notice_lang(s_ChanServ, u, CHAN_SET_PRIVATE_ON, ci->name);
00652     } else if (stricmp(param, "OFF") == 0) {
00653         ci->flags &= ~CI_PRIVATE;
00654         alog("%s: %s!%s@%s set private OFF for %s",
00655              s_ChanServ, u->nick, u->username, u->host, ci->name);
00656         notice_lang(s_ChanServ, u, CHAN_SET_PRIVATE_OFF, ci->name);
00657     } else {
00658         syntax_error(s_ChanServ, u, "SET PRIVATE",
00659                      CHAN_SET_PRIVATE_SYNTAX);
00660     }
00661     return MOD_CONT;
00662 }
00663 
00664 /*************************************************************************/
00665 
00666 static int do_set_secureops(User * u, ChannelInfo * ci, char *param)
00667 {
00668     if (stricmp(param, "ON") == 0) {
00669         ci->flags |= CI_SECUREOPS;
00670         alog("%s: %s!%s@%s set secureops ON for %s",
00671              s_ChanServ, u->nick, u->username, u->host, ci->name);
00672         notice_lang(s_ChanServ, u, CHAN_SET_SECUREOPS_ON, ci->name);
00673     } else if (stricmp(param, "OFF") == 0) {
00674         ci->flags &= ~CI_SECUREOPS;
00675         alog("%s: %s!%s@%s set secureops OFF for %s",
00676              s_ChanServ, u->nick, u->username, u->host, ci->name);
00677         notice_lang(s_ChanServ, u, CHAN_SET_SECUREOPS_OFF, ci->name);
00678     } else {
00679         syntax_error(s_ChanServ, u, "SET SECUREOPS",
00680                      CHAN_SET_SECUREOPS_SYNTAX);
00681     }
00682     return MOD_CONT;
00683 }
00684 
00685 /*************************************************************************/
00686 
00687 static int do_set_securefounder(User * u, ChannelInfo * ci, char *param)
00688 {
00689     if (stricmp(param, "ON") == 0) {
00690         ci->flags |= CI_SECUREFOUNDER;
00691         alog("%s: %s!%s@%s set securefounder ON for %s",
00692              s_ChanServ, u->nick, u->username, u->host, ci->name);
00693         notice_lang(s_ChanServ, u, CHAN_SET_SECUREFOUNDER_ON, ci->name);
00694     } else if (stricmp(param, "OFF") == 0) {
00695         ci->flags &= ~CI_SECUREFOUNDER;
00696         alog("%s: %s!%s@%s set securefounder OFF for %s",
00697              s_ChanServ, u->nick, u->username, u->host, ci->name);
00698         notice_lang(s_ChanServ, u, CHAN_SET_SECUREFOUNDER_OFF, ci->name);
00699     } else {
00700         syntax_error(s_ChanServ, u, "SET SECUREFOUNDER",
00701                      CHAN_SET_SECUREFOUNDER_SYNTAX);
00702     }
00703     return MOD_CONT;
00704 }
00705 
00706 /*************************************************************************/
00707 
00708 static int do_set_restricted(User * u, ChannelInfo * ci, char *param)
00709 {
00710     if (stricmp(param, "ON") == 0) {
00711         ci->flags |= CI_RESTRICTED;
00712         if (ci->levels[CA_NOJOIN] < 0)
00713             ci->levels[CA_NOJOIN] = 0;
00714         alog("%s: %s!%s@%s set restricted ON for %s",
00715              s_ChanServ, u->nick, u->username, u->host, ci->name);
00716         notice_lang(s_ChanServ, u, CHAN_SET_RESTRICTED_ON, ci->name);
00717     } else if (stricmp(param, "OFF") == 0) {
00718         ci->flags &= ~CI_RESTRICTED;
00719         if (ci->levels[CA_NOJOIN] >= 0)
00720             ci->levels[CA_NOJOIN] = -2;
00721         alog("%s: %s!%s@%s set restricted OFF for %s",
00722              s_ChanServ, u->nick, u->username, u->host, ci->name);
00723         notice_lang(s_ChanServ, u, CHAN_SET_RESTRICTED_OFF, ci->name);
00724     } else {
00725         syntax_error(s_ChanServ, u, "SET RESTRICTED",
00726                      CHAN_SET_RESTRICTED_SYNTAX);
00727     }
00728     return MOD_CONT;
00729 }
00730 
00731 /*************************************************************************/
00732 
00733 static int do_set_secure(User * u, ChannelInfo * ci, char *param)
00734 {
00735     if (stricmp(param, "ON") == 0) {
00736         ci->flags |= CI_SECURE;
00737         alog("%s: %s!%s@%s set secure ON for %s",
00738              s_ChanServ, u->nick, u->username, u->host, ci->name);
00739         notice_lang(s_ChanServ, u, CHAN_SET_SECURE_ON, ci->name);
00740     } else if (stricmp(param, "OFF") == 0) {
00741         ci->flags &= ~CI_SECURE;
00742         alog("%s: %s!%s@%s set secure OFF for %s",
00743              s_ChanServ, u->nick, u->username, u->host, ci->name);
00744         notice_lang(s_ChanServ, u, CHAN_SET_SECURE_OFF, ci->name);
00745     } else {
00746         syntax_error(s_ChanServ, u, "SET SECURE", CHAN_SET_SECURE_SYNTAX);
00747     }
00748     return MOD_CONT;
00749 }
00750 
00751 /*************************************************************************/
00752 
00753 static int do_set_signkick(User * u, ChannelInfo * ci, char *param)
00754 {
00755     if (stricmp(param, "ON") == 0) {
00756         ci->flags |= CI_SIGNKICK;
00757         ci->flags &= ~CI_SIGNKICK_LEVEL;
00758         alog("%s: %s!%s@%s set signkick ON for %s",
00759              s_ChanServ, u->nick, u->username, u->host, ci->name);
00760         notice_lang(s_ChanServ, u, CHAN_SET_SIGNKICK_ON, ci->name);
00761     } else if (stricmp(param, "LEVEL") == 0) {
00762         ci->flags |= CI_SIGNKICK_LEVEL;
00763         ci->flags &= ~CI_SIGNKICK;
00764         alog("%s: %s!%s@%s set signkick LEVEL for %s",
00765              s_ChanServ, u->nick, u->username, u->host, ci->name);
00766         notice_lang(s_ChanServ, u, CHAN_SET_SIGNKICK_LEVEL, ci->name);
00767     } else if (stricmp(param, "OFF") == 0) {
00768         ci->flags &= ~(CI_SIGNKICK | CI_SIGNKICK_LEVEL);
00769         alog("%s: %s!%s@%s set signkick OFF for %s",
00770              s_ChanServ, u->nick, u->username, u->host, ci->name);
00771         notice_lang(s_ChanServ, u, CHAN_SET_SIGNKICK_OFF, ci->name);
00772     } else {
00773         syntax_error(s_ChanServ, u, "SET SIGNKICK",
00774                      CHAN_SET_SIGNKICK_SYNTAX);
00775     }
00776     return MOD_CONT;
00777 }
00778 
00779 /*************************************************************************/
00780 
00781 static int do_set_opnotice(User * u, ChannelInfo * ci, char *param)
00782 {
00783     if (stricmp(param, "ON") == 0) {
00784         ci->flags |= CI_OPNOTICE;
00785         alog("%s: %s!%s@%s set opnotice ON for %s",
00786              s_ChanServ, u->nick, u->username, u->host, ci->name);
00787         notice_lang(s_ChanServ, u, CHAN_SET_OPNOTICE_ON, ci->name);
00788     } else if (stricmp(param, "OFF") == 0) {
00789         ci->flags &= ~CI_OPNOTICE;
00790         alog("%s: %s!%s@%s set opnotice OFF for %s",
00791              s_ChanServ, u->nick, u->username, u->host, ci->name);
00792         notice_lang(s_ChanServ, u, CHAN_SET_OPNOTICE_OFF, ci->name);
00793     } else {
00794         syntax_error(s_ChanServ, u, "SET OPNOTICE",
00795                      CHAN_SET_OPNOTICE_SYNTAX);
00796     }
00797     return MOD_CONT;
00798 }
00799 
00800 /*************************************************************************/
00801 
00802 #define CHECKLEV(lev) ((ci->levels[(lev)] != ACCESS_INVALID) && (access->level >= ci->levels[(lev)]))
00803 
00804 static int do_set_xop(User * u, ChannelInfo * ci, char *param)
00805 {
00806     if (stricmp(param, "ON") == 0) {
00807         if (!(ci->flags & CI_XOP)) {
00808             int i;
00809             ChanAccess *access;
00810 
00811             for (access = ci->access, i = 0; i < ci->accesscount;
00812                  access++, i++) {
00813                 if (!access->in_use)
00814                     continue;
00815                 /* This will probably cause wrong levels to be set, but hey,
00816                  * it's better than losing it altogether.
00817                  */
00818                 if (CHECKLEV(CA_AKICK) || CHECKLEV(CA_SET)) {
00819                     access->level = ACCESS_SOP;
00820                 } else if (CHECKLEV(CA_AUTOOP) || CHECKLEV(CA_OPDEOP)
00821                            || CHECKLEV(CA_OPDEOPME)) {
00822                     access->level = ACCESS_AOP;
00823                 } else if (ircd->halfop && (CHECKLEV(CA_AUTOHALFOP) || CHECKLEV(CA_HALFOP)
00824                         || CHECKLEV(CA_HALFOPME))) {
00825                         access->level = ACCESS_HOP;
00826                 } else if (CHECKLEV(CA_AUTOVOICE) || CHECKLEV(CA_VOICE)
00827                            || CHECKLEV(CA_VOICEME)) {
00828                     access->level = ACCESS_VOP;
00829                 } else {
00830                     access->in_use = 0;
00831                     access->nc = NULL;
00832                 }
00833             }
00834             CleanAccess(ci);
00835 
00836             reset_levels(ci);
00837             ci->flags |= CI_XOP;
00838         }
00839 
00840         alog("%s: %s!%s@%s enabled XOP for %s", s_ChanServ, u->nick,
00841              u->username, u->host, ci->name);
00842         notice_lang(s_ChanServ, u, CHAN_SET_XOP_ON, ci->name);
00843     } else if (stricmp(param, "OFF") == 0) {
00844         ci->flags &= ~CI_XOP;
00845 
00846         alog("%s: %s!%s@%s disabled XOP for %s", s_ChanServ, u->nick,
00847              u->username, u->host, ci->name);
00848         notice_lang(s_ChanServ, u, CHAN_SET_XOP_OFF, ci->name);
00849     } else {
00850         syntax_error(s_ChanServ, u, "SET XOP", CHAN_SET_XOP_SYNTAX);
00851     }
00852     return MOD_CONT;
00853 }
00854 
00855 #undef CHECKLEV
00856 
00857 /*************************************************************************/
00858 
00859 static int do_set_peace(User * u, ChannelInfo * ci, char *param)
00860 {
00861     if (stricmp(param, "ON") == 0) {
00862         ci->flags |= CI_PEACE;
00863         alog("%s: %s!%s@%s set peace ON for %s",
00864              s_ChanServ, u->nick, u->username, u->host, ci->name);
00865         notice_lang(s_ChanServ, u, CHAN_SET_PEACE_ON, ci->name);
00866     } else if (stricmp(param, "OFF") == 0) {
00867         ci->flags &= ~CI_PEACE;
00868         alog("%s: %s!%s@%s set peace OFF for %s",
00869              s_ChanServ, u->nick, u->username, u->host, ci->name);
00870         notice_lang(s_ChanServ, u, CHAN_SET_PEACE_OFF, ci->name);
00871     } else {
00872         syntax_error(s_ChanServ, u, "SET PEACE", CHAN_SET_PEACE_SYNTAX);
00873     }
00874     return MOD_CONT;
00875 }
00876 
00877 /*************************************************************************/
00878 
00879 static int do_set_noexpire(User * u, ChannelInfo * ci, char *param)
00880 {
00881     if (!is_services_admin(u)) {
00882         notice_lang(s_ChanServ, u, PERMISSION_DENIED);
00883         return MOD_CONT;
00884     }
00885     if (stricmp(param, "ON") == 0) {
00886         ci->flags |= CI_NO_EXPIRE;
00887         alog("%s: %s!%s@%s set noexpire ON for %s",
00888              s_ChanServ, u->nick, u->username, u->host, ci->name);
00889         notice_lang(s_ChanServ, u, CHAN_SET_NOEXPIRE_ON, ci->name);
00890     } else if (stricmp(param, "OFF") == 0) {
00891         ci->flags &= ~CI_NO_EXPIRE;
00892         alog("%s: %s!%s@%s set noexpire OFF for %s",
00893              s_ChanServ, u->nick, u->username, u->host, ci->name);
00894         notice_lang(s_ChanServ, u, CHAN_SET_NOEXPIRE_OFF, ci->name);
00895     } else {
00896         syntax_error(s_ChanServ, u, "SET NOEXPIRE",
00897                      CHAN_SET_NOEXPIRE_SYNTAX);
00898     }
00899     return MOD_CONT;
00900 }