/** * set.C: This file contains routines to handle the NickServ SET command. * * Copyright © 2007 Pippijn van Steenhoven / The Ermyth Team * Rights to this code are as documented in COPYING. * * * Portions of this file were derived from sources bearing the following license: * Copyright © 2006 William Pitcock, et al. * Rights to this code are documented in doc/pod/license.pod. * * $Id: set.C,v 1.10 2007/09/22 14:27:28 pippijn Exp $ */ #include "atheme.h" #include #include #include #include static char const rcsid[] = "$Id: set.C,v 1.10 2007/09/22 14:27:28 pippijn Exp $"; REGISTER_MODULE ("nickserv/set", false, "The Ermyth Team "); static void ns_cmd_set (sourceinfo_t *si, int parc, char *parv[]); E cmdvec ns_cmdtree; E helpvec ns_helptree; command_t const ns_set = { "SET", N_("Sets various control flags."), AC_NONE, 2, ns_cmd_set }; cmdvec ns_set_cmdtree; /* HELP SET */ static void ns_help_set (sourceinfo_t *si) { command_success_nodata (si, _("Help for \2SET\2:")); command_success_nodata (si, " "); command_success_nodata (si, _("SET allows you to set various control flags")); if (nicksvs.no_nick_ownership) command_success_nodata (si, _("for accounts that change the way certain operations")); else command_success_nodata (si, _("for nicknames that change the way certain operations")); command_success_nodata (si, _("are performed on them.")); command_success_nodata (si, " "); command_help (si, ns_set_cmdtree); command_success_nodata (si, " "); command_success_nodata (si, _("For more information, use \2/msg %s HELP SET \37command\37\2."), nicksvs.nick); } /* SET */ static void ns_cmd_set (sourceinfo_t *si, int parc, char *parv[]) { char *setting = parv[0]; command_t const *c; if (si->smu == NULL) { command_fail (si, fault::noprivs, _("You are not logged in.")); return; } if (setting == NULL) { command_fail (si, fault::needmoreparams, STR_INSUFFICIENT_PARAMS, "SET"); command_fail (si, fault::needmoreparams, _("Syntax: SET ")); return; } /* take the command through the hash table */ if ((c = ns_set_cmdtree.find (setting))) c->exec (si->service, si, parc - 1, parv + 1); else command_fail (si, fault::badparams, _("Invalid set command. Use \2/%s%s HELP SET\2 for a command listing."), (ircd->uses_rcommand == false) ? "msg " : "", nicksvs.nick); } /* SET EMAIL */ static void ns_cmd_setemail (sourceinfo_t *si, int parc, char *parv[]) { char *email = parv[0]; if (si->smu == NULL) return; if (email == NULL) { command_fail (si, fault::needmoreparams, STR_INSUFFICIENT_PARAMS, "EMAIL"); command_fail (si, fault::needmoreparams, _("Syntax: SET EMAIL ")); return; } if (strlen (email) >= EMAILLEN) { command_fail (si, fault::badparams, STR_INVALID_PARAMS, "EMAIL"); return; } if (si->smu->flags & MU_WAITAUTH) { command_fail (si, fault::noprivs, _("Please verify your original registration before changing your e-mail address.")); return; } if (!validemail (email)) { command_fail (si, fault::badparams, _("\2%s\2 is not a valid email address."), email); return; } if (!strcasecmp (si->smu->email, email)) { command_fail (si, fault::nochange, _("The email address for \2%s\2 is already set to \2%s\2."), si->smu->name, si->smu->email); return; } snoop ("SET:EMAIL: \2%s\2 (\2%s\2 -> \2%s\2)", si->smu->name, si->smu->email, email); if (me.auth == AUTH_EMAIL) { unsigned long key = makekey (); si->smu->add_metadata ("private:verify:emailchg:key", itoa (key)); si->smu->add_metadata ("private:verify:emailchg:newemail", email); si->smu->add_metadata ("private:verify:emailchg:timestamp", itoa (NOW)); if (!sendemail (si->su != NULL ? si->su : si->service->me, EMAIL_SETEMAIL, si->smu, itoa (key))) { command_fail (si, fault::emailfail, _("Sending email failed, sorry! Your email address is unchanged.")); si->smu->del_metadata ("private:verify:emailchg:key"); si->smu->del_metadata ("private:verify:emailchg:newemail"); si->smu->del_metadata ("private:verify:emailchg:timestamp"); return; } logcommand (si, CMDLOG_SET, "SET EMAIL %s (awaiting verification)", email); command_success_nodata (si, _("An email containing email changing instructions has been sent to \2%s\2."), email); command_success_nodata (si, _("Your email address will not be changed until you follow these instructions.")); return; } strlcpy (si->smu->email, email, EMAILLEN); logcommand (si, CMDLOG_SET, "SET EMAIL %s", email); command_success_nodata (si, _("The email address for \2%s\2 has been changed to \2%s\2."), si->smu->name, si->smu->email); } command_t const ns_set_email = { "EMAIL", N_("Changes your e-mail address."), AC_NONE, 1, ns_cmd_setemail }; /* SET HIDEMAIL [ON|OFF] */ static void ns_cmd_sethidemail (sourceinfo_t *si, int parc, char *parv[]) { char *params = strtok (parv[0], " "); if (si->smu == NULL) return; if (params == NULL) { command_fail (si, fault::needmoreparams, STR_INSUFFICIENT_PARAMS, "HIDEMAIL"); return; } if (!strcasecmp ("ON", params)) { if (MU_HIDEMAIL & si->smu->flags) { command_fail (si, fault::nochange, _("The \2%s\2 flag is already set for \2%s\2."), "HIDEMAIL", si->smu->name); return; } logcommand (si, CMDLOG_SET, "SET HIDEMAIL ON"); si->smu->flags |= MU_HIDEMAIL; command_success_nodata (si, _("The \2%s\2 flag has been set for \2%s\2."), "HIDEMAIL", si->smu->name); return; } else if (!strcasecmp ("OFF", params)) { if (!(MU_HIDEMAIL & si->smu->flags)) { command_fail (si, fault::nochange, _("The \2%s\2 flag is not set for \2%s\2."), "HIDEMAIL", si->smu->name); return; } logcommand (si, CMDLOG_SET, "SET HIDEMAIL OFF"); si->smu->flags &= ~MU_HIDEMAIL; command_success_nodata (si, _("The \2%s\2 flag has been removed for \2%s\2."), "HIDEMAIL", si->smu->name); return; } else { command_fail (si, fault::badparams, STR_INVALID_PARAMS, "HIDEMAIL"); return; } } command_t const ns_set_hidemail = { "HIDEMAIL", N_("Hides your e-mail address."), AC_NONE, 1, ns_cmd_sethidemail }; static void ns_cmd_setemailmemos (sourceinfo_t *si, int parc, char *parv[]) { char *params = strtok (parv[0], " "); if (si->smu == NULL) return; if (si->smu->flags & MU_WAITAUTH) { command_fail (si, fault::noprivs, _("You have to verify your email address before you can enable emailing memos.")); return; } if (params == NULL) { command_fail (si, fault::needmoreparams, STR_INSUFFICIENT_PARAMS, "EMAILMEMOS"); return; } if (!strcasecmp ("ON", params)) { if (me.mta == NULL) { command_fail (si, fault::emailfail, _("Sending email is administratively disabled.")); return; } if (MU_EMAILMEMOS & si->smu->flags) { command_fail (si, fault::nochange, _("The \2%s\2 flag is already set for \2%s\2."), "EMAILMEMOS", si->smu->name); return; } logcommand (si, CMDLOG_SET, "SET EMAILMEMOS ON"); si->smu->flags |= MU_EMAILMEMOS; command_success_nodata (si, _("The \2%s\2 flag has been set for \2%s\2."), "EMAILMEMOS", si->smu->name); return; } else if (!strcasecmp ("OFF", params)) { if (!(MU_EMAILMEMOS & si->smu->flags)) { command_fail (si, fault::nochange, _("The \2%s\2 flag is not set for \2%s\2."), "EMAILMEMOS", si->smu->name); return; } logcommand (si, CMDLOG_SET, "SET EMAILMEMOS OFF"); si->smu->flags &= ~MU_EMAILMEMOS; command_success_nodata (si, _("The \2%s\2 flag has been removed for \2%s\2."), "EMAILMEMOS", si->smu->name); return; } else { command_fail (si, fault::badparams, STR_INVALID_PARAMS, "EMAILMEMOS"); return; } } command_t const ns_set_emailmemos = { "EMAILMEMOS", N_("Forwards incoming memos to your e-mail address."), AC_NONE, 1, ns_cmd_setemailmemos }; static void ns_cmd_setnomemo (sourceinfo_t *si, int parc, char *parv[]) { char *params = strtok (parv[0], " "); if (si->smu == NULL) return; if (params == NULL) { command_fail (si, fault::needmoreparams, STR_INSUFFICIENT_PARAMS, "NOMEMO"); return; } if (!strcasecmp ("ON", params)) { if (MU_NOMEMO & si->smu->flags) { command_fail (si, fault::nochange, _("The \2%s\2 flag is already set for \2%s\2."), "NOMEMO", si->smu->name); return; } logcommand (si, CMDLOG_SET, "SET NOMEMO ON"); si->smu->flags |= MU_NOMEMO; command_success_nodata (si, _("The \2%s\2 flag has been set for \2%s\2."), "NOMEMO", si->smu->name); return; } else if (!strcasecmp ("OFF", params)) { if (!(MU_NOMEMO & si->smu->flags)) { command_fail (si, fault::nochange, _("The \2%s\2 flag is not set for \2%s\2."), "NOMEMO", si->smu->name); return; } logcommand (si, CMDLOG_SET, "SET NOMEMO OFF"); si->smu->flags &= ~MU_NOMEMO; command_success_nodata (si, _("The \2%s\2 flag has been removed for \2%s\2."), "NOMEMO", si->smu->name); return; } else { command_fail (si, fault::badparams, STR_INVALID_PARAMS, "NOMEMO"); return; } } command_t const ns_set_nomemo = { "NOMEMO", N_("Disables the ability to recieve memos."), AC_NONE, 1, ns_cmd_setnomemo }; static void ns_cmd_setneverop (sourceinfo_t *si, int parc, char *parv[]) { char *params = strtok (parv[0], " "); if (si->smu == NULL) return; if (params == NULL) { command_fail (si, fault::needmoreparams, STR_INSUFFICIENT_PARAMS, "NEVEROP"); return; } if (!strcasecmp ("ON", params)) { if (MU_NEVEROP & si->smu->flags) { command_fail (si, fault::nochange, _("The \2%s\2 flag is already set for \2%s\2."), "NEVEROP", si->smu->name); return; } logcommand (si, CMDLOG_SET, "SET NEVEROP ON"); si->smu->flags |= MU_NEVEROP; command_success_nodata (si, _("The \2%s\2 flag has been set for \2%s\2."), "NEVEROP", si->smu->name); return; } else if (!strcasecmp ("OFF", params)) { if (!(MU_NEVEROP & si->smu->flags)) { command_fail (si, fault::nochange, _("The \2%s\2 flag is not set for \2%s\2."), "NEVEROP", si->smu->name); return; } logcommand (si, CMDLOG_SET, "SET NEVEROP OFF"); si->smu->flags &= ~MU_NEVEROP; command_success_nodata (si, _("The \2%s\2 flag has been removed for \2%s\2."), "NEVEROP", si->smu->name); return; } else { command_fail (si, fault::badparams, STR_INVALID_PARAMS, "NEVEROP"); return; } } command_t const ns_set_neverop = { "NEVEROP", N_("Prevents you from being added to access lists."), AC_NONE, 1, ns_cmd_setneverop }; static void ns_cmd_setnoop (sourceinfo_t *si, int parc, char *parv[]) { char *params = strtok (parv[0], " "); if (si->smu == NULL) return; if (params == NULL) { command_fail (si, fault::needmoreparams, STR_INSUFFICIENT_PARAMS, "NOOP"); return; } if (!strcasecmp ("ON", params)) { if (MU_NOOP & si->smu->flags) { command_fail (si, fault::nochange, _("The \2%s\2 flag is already set for \2%s\2."), "NOOP", si->smu->name); return; } logcommand (si, CMDLOG_SET, "SET NOOP ON"); si->smu->flags |= MU_NOOP; command_success_nodata (si, _("The \2%s\2 flag has been set for \2%s\2."), "NOOP", si->smu->name); return; } else if (!strcasecmp ("OFF", params)) { if (!(MU_NOOP & si->smu->flags)) { command_fail (si, fault::nochange, _("The \2%s\2 flag is not set for \2%s\2."), "NOOP", si->smu->name); return; } logcommand (si, CMDLOG_SET, "SET NOOP OFF"); si->smu->flags &= ~MU_NOOP; command_success_nodata (si, _("The \2%s\2 flag has been removed for \2%s\2."), "NOOP", si->smu->name); return; } else { command_fail (si, fault::badparams, STR_INVALID_PARAMS, "NOOP"); return; } } command_t const ns_set_noop = { "NOOP", N_("Prevents services from setting modes upon you automatically."), AC_NONE, 1, ns_cmd_setnoop }; static void ns_cmd_setproperty (sourceinfo_t *si, int parc, char *parv[]) { char *tok[2] = { 0 }; sjtoken (parv[0], ' ', tok, 2); char *property = tok[0]; char *value = tok[1]; if (si->smu == NULL) return; if (!property) { command_fail (si, fault::needmoreparams, _("Syntax: SET PROPERTY [value]")); return; } if (strchr (property, ':') && !has_priv (si, PRIV_METADATA)) { command_fail (si, fault::badparams, _("Invalid property name.")); return; } if (strchr (property, ':')) snoop ("SET:PROPERTY: \2%s\2: \2%s\2/\2%s\2", si->smu->name, property, value); if (si->smu->mdmap.size () >= me.mdlimit) { command_fail (si, fault::toomany, _("Cannot add \2%s\2 to \2%s\2 metadata table, it is full."), property, si->smu->name); return; } if (!value) { metadata *md = si->smu->find_metadata (property); if (!md) { command_fail (si, fault::nosuch_target, _("Metadata entry \2%s\2 was not set."), property); return; } si->smu->del_metadata (property); logcommand (si, CMDLOG_SET, "SET PROPERTY %s (deleted)", property); command_success_nodata (si, _("Metadata entry \2%s\2 has been deleted."), property); return; } if (strlen (property) > 32 || strlen (value) > 300) { command_fail (si, fault::badparams, _("Parameters are too long. Aborting.")); return; } si->smu->add_metadata (property, value); logcommand (si, CMDLOG_SET, "SET PROPERTY %s to %s", property, value); command_success_nodata (si, _("Metadata entry \2%s\2 added."), property); } command_t const ns_set_property = { "PROPERTY", N_("Manipulates metadata entries associated with a nickname."), AC_NONE, 2, ns_cmd_setproperty }; static void ns_cmd_setqproperty (sourceinfo_t *si, int parc, char *parv[]) { char *property = strtok (parv[0], " "); char *value = strtok (NULL, ""); if (si->smu == NULL) return; if (!property) { command_fail (si, fault::needmoreparams, _("Syntax: SET PROPERTY [value]")); return; } if (strchr (property, ':') && !has_priv (si, PRIV_METADATA)) { command_fail (si, fault::badparams, _("Invalid property name.")); return; } if (strchr (property, ':')) snoop ("SET:PROPERTY: \2%s\2: \2%s\2/\2%s\2", si->smu->name, property, value); if (si->smu->mdmap.size () >= me.mdlimit) { command_fail (si, fault::toomany, _("Cannot add \2%s\2 to \2%s\2 metadata table, it is full."), property, si->smu->name); return; } if (!value) { metadata *md = si->smu->find_metadata (property); if (!md) { command_fail (si, fault::nosuch_target, _("Metadata entry \2%s\2 was not set."), property); return; } si->smu->del_metadata (property); logcommand (si, CMDLOG_SET, "SET PROPERTY %s (deleted)", property); return; } if (strlen (property) > 32 || strlen (value) > 300) return; si->smu->add_metadata (property, value); logcommand (si, CMDLOG_SET, "SET QPROPERTY %s to %s", property, value); } command_t const ns_set_qproperty = { "QPROPERTY", N_("Quietly manipulates metadata entries associated with a nickname."), AC_NONE, 2, ns_cmd_setqproperty }; static void ns_cmd_setpassword (sourceinfo_t *si, int parc, char *parv[]) { char *password = strtok (parv[0], " "); if (si->smu == NULL) return; if (password == NULL) { command_fail (si, fault::needmoreparams, STR_INSUFFICIENT_PARAMS, "PASSWORD"); return; } if (strlen (password) > 32) { command_fail (si, fault::badparams, STR_INVALID_PARAMS, "PASSWORD"); return; } if (!strcasecmp (password, si->smu->name)) { command_fail (si, fault::badparams, _("You cannot use your nickname as a password.")); command_fail (si, fault::badparams, _("Syntax: SET PASSWORD ")); return; } /*snoop("SET:PASSWORD: \2%s\2 as \2%s\2 for \2%s\2", si->su->user, si->smu->name, si->smu->name); */ logcommand (si, CMDLOG_SET, "SET PASSWORD"); si->smu->set_password (password); command_success_nodata (si, _("The password for \2%s\2 has been changed to \2%s\2. Please write this down for future reference."), si->smu->name, password); return; } command_t const ns_set_password = { "PASSWORD", N_("Changes the password associated with your nickname."), AC_NONE, 1, ns_cmd_setpassword }; static void ns_cmd_setwhois (sourceinfo_t *si, int parc, char *parv[]) { char const * const value = parv[0]; if (si->smu == NULL) return; if (value == NULL) { command_fail (si, fault::needmoreparams, STR_INSUFFICIENT_PARAMS, "WHOIS"); return; } else if (!strcasecmp (value, "UNSET")) { phandler->mdchange (si->su->nick, "swhois", ""); si->smu->del_metadata ("private:swhois"); command_success_nodata (si, _("Your description has been removed.")); return; } phandler->mdchange (si->su->nick, "swhois", value); si->smu->add_metadata ("private:swhois", value); command_success_nodata (si, _("Your description is now set to: \2%s\2"), value); return; } command_t const ns_set_whois = { "WHOIS", N_("Sets your WHOIS description."), AC_NONE, 1, ns_cmd_setwhois }; static void whois_on_identify (user_t *u) { metadata *md; if ((md = u->myuser->find_metadata ("private:swhois")) != NULL) phandler->mdchange (u->nick, "swhois", md->value); } command_t const *ns_set_commands[] = { &ns_set_email, &ns_set_emailmemos, &ns_set_hidemail, &ns_set_nomemo, &ns_set_noop, &ns_set_neverop, &ns_set_password, &ns_set_property, &ns_set_qproperty, &ns_set_whois, NULL }; bool _modinit (module *m) { user_t::callback.identify.attach (whois_on_identify); ns_cmdtree << ns_set; help_addentry (ns_helptree, "SET", NULL, ns_help_set); help_addentry (ns_helptree, "SET EMAIL", "help/nickserv/set_email", NULL); help_addentry (ns_helptree, "SET EMAILMEMOS", "help/nickserv/set_emailmemos", NULL); help_addentry (ns_helptree, "SET HIDEMAIL", "help/nickserv/set_hidemail", NULL); help_addentry (ns_helptree, "SET NOMEMO", "help/nickserv/set_nomemo", NULL); help_addentry (ns_helptree, "SET NEVEROP", "help/nickserv/set_neverop", NULL); help_addentry (ns_helptree, "SET NOOP", "help/nickserv/set_noop", NULL); help_addentry (ns_helptree, "SET PASSWORD", "help/nickserv/set_password", NULL); help_addentry (ns_helptree, "SET PROPERTY", "help/nickserv/set_property", NULL); help_addentry (ns_helptree, "SET WHOIS", "help/nickserv/set_whois", NULL); /* populate ns_set_cmdtree */ ns_set_cmdtree << ns_set_commands; return true; } void _moddeinit () { user_t::callback.identify.detach (whois_on_identify); ns_cmdtree >> ns_set; help_delentry (ns_helptree, "SET"); help_delentry (ns_helptree, "SET EMAIL"); help_delentry (ns_helptree, "SET EMAILMEMOS"); help_delentry (ns_helptree, "SET HIDEMAIL"); help_delentry (ns_helptree, "SET NOMEMO"); help_delentry (ns_helptree, "SET NEVEROP"); help_delentry (ns_helptree, "SET NOOP"); help_delentry (ns_helptree, "SET PASSWORD"); help_delentry (ns_helptree, "SET PROPERTY"); help_delentry (ns_helptree, "SET WHOIS"); /* clear ns_set_cmdtree */ ns_set_cmdtree >> ns_set_commands; }