static void cs_cmd_invite(struct sourceinfo *si, int parc, char *parv[]) { char *chan = parv[0]; struct mychan *mc; if (si->su == NULL) { command_fail(si, fault_noprivs, STR_IRC_COMMAND_ONLY, "INVITE"); return; } /* This command is not useful if the user is already in the channel, * ignore it if it is a fantasy command so users can program bots to * react on it without interference from ChanServ. */ if (si->c != NULL) return; if (!chan) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "INVITE"); command_fail(si, fault_needmoreparams, _("Syntax: INVITE <#channel>")); return; } if (!(mc = mychan_find(chan))) { command_fail(si, fault_nosuch_target, STR_IS_NOT_REGISTERED, chan); return; } if (metadata_find(mc, "private:close:closer")) { command_fail(si, fault_noprivs, STR_CHANNEL_IS_CLOSED, chan); return; } if (!chanacs_source_has_flag(mc, si, CA_INVITE)) { command_fail(si, fault_noprivs, STR_NOT_AUTHORIZED); return; } if (!mc->chan) { command_fail(si, fault_nosuch_target, STR_CHANNEL_IS_EMPTY, mc->name); return; } if (chanuser_find(mc->chan, si->su)) { command_fail(si, fault_noprivs, _("You're already on \2%s\2."), mc->name); return; } invite_sts(si->service->me, si->su, mc->chan); logcommand(si, CMDLOG_DO, "INVITE: \2%s\2", mc->name); command_success_nodata(si, _("You have been invited to \2%s\2."), mc->name); }
static void cs_cmd_set_keeptopic(sourceinfo_t *si, int parc, char *parv[]) { mychan_t *mc; if (!(mc = mychan_find(parv[0]))) { command_fail(si, fault_nosuch_target, _("Channel \2%s\2 is not registered."), parv[0]); return; } if (!parv[1]) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "SET KEEPTOPIC"); return; } if (!chanacs_source_has_flag(mc, si, CA_SET)) { command_fail(si, fault_noprivs, _("You are not authorized to perform this command.")); return; } if (!strcasecmp("ON", parv[1])) { if (MC_KEEPTOPIC & mc->flags) { command_fail(si, fault_nochange, _("The \2%s\2 flag is already set for channel \2%s\2."), "KEEPTOPIC", mc->name); return; } logcommand(si, CMDLOG_SET, "SET:KEEPTOPIC:ON: \2%s\2", mc->name); verbose(mc, _("\2%s\2 enabled the KEEPTOPIC flag"), get_source_name(si)); mc->flags |= MC_KEEPTOPIC; command_success_nodata(si, _("The \2%s\2 flag has been set for channel \2%s\2."), "KEEPTOPIC", mc->name); return; } else if (!strcasecmp("OFF", parv[1])) { if (!(MC_KEEPTOPIC & mc->flags)) { command_fail(si, fault_nochange, _("The \2%s\2 flag is not set for channel \2%s\2."), "KEEPTOPIC", mc->name); return; } logcommand(si, CMDLOG_SET, "SET:KEEPTOPIC:OFF: \2%s\2", mc->name); verbose(mc, _("\2%s\2 disabled the KEEPTOPIC flag"), get_source_name(si)); mc->flags &= ~(MC_KEEPTOPIC | MC_TOPICLOCK); command_success_nodata(si, _("The \2%s\2 flag has been removed for channel \2%s\2."), "KEEPTOPIC", mc->name); return; } else { command_fail(si, fault_badparams, STR_INVALID_PARAMS, "KEEPTOPIC"); return; } }
static void cs_cmd_devoice(sourceinfo_t *si, int parc, char *parv[]) { char *chan = parv[0]; char *nick = parv[1]; mychan_t *mc; user_t *tu; chanuser_t *cu; if (!chan) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "DEVOICE"); command_fail(si, fault_needmoreparams, _("Syntax: DEVOICE <#channel> [nickname]")); return; } mc = mychan_find(chan); if (!mc) { command_fail(si, fault_nosuch_target, _("Channel \2%s\2 is not registered."), chan); return; } if (!chanacs_source_has_flag(mc, si, CA_VOICE)) { command_fail(si, fault_noprivs, _("You are not authorized to perform this operation.")); return; } /* figure out who we're going to devoice */ if (!nick) tu = si->su; else { if (!(tu = user_find_named(nick))) { command_fail(si, fault_nosuch_target, _("\2%s\2 is not online."), nick); return; } } if (is_internal_client(tu)) return; cu = chanuser_find(mc->chan, tu); if (!cu) { command_fail(si, fault_nosuch_target, _("\2%s\2 is not on \2%s\2."), tu->nick, mc->name); return; } modestack_mode_param(chansvs.nick, mc->chan, MTYPE_DEL, 'v', CLIENT_NAME(tu)); cu->modes &= ~CSTATUS_VOICE; if (si->c == NULL && tu != si->su) change_notify(chansvs.nick, tu, "You have been devoiced on %s by %s", mc->name, get_source_name(si)); logcommand(si, CMDLOG_DO, "DEVOICE: \2%s!%s@%s\2 on \2%s\2", tu->nick, tu->user, tu->vhost, mc->name); if (!chanuser_find(mc->chan, si->su)) command_success_nodata(si, _("\2%s\2 has been devoiced on \2%s\2."), tu->nick, mc->name); }
static void funserv_cmd_requestbot(sourceinfo_t *si, int parc, char *parv[]) { char *name = parv[0]; mychan_t *mc; if (!name) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "REQUESTBOT"); command_fail(si, fault_needmoreparams, _("Syntax: REQUESTBOT <#channel>")); } if (*name != '#') { command_fail(si, fault_needmoreparams, STR_INVALID_PARAMS, "REQUESTBOT"); command_fail(si, fault_needmoreparams, _("Syntax: REQUESTBOT <#channel>")); } if (!(mc = mychan_find(name))) { command_fail(si, fault_nosuch_target, _("Channel \2%s\2 is not registered."), name); return; } if (!is_founder(mc, entity(si->smu))) { command_fail(si, fault_noprivs, _("You are not authorized to perform this operation.")); return; } myuser_notice(funserv->nick, myuser_find_ext(BOTNAME), "JOIN %s", name); command_success_nodata(si, "The bot should now be in %s.", name); }
static void bs_cmd_set_nobot(sourceinfo_t *si, int parc, char *parv[]) { char *channel = parv[0]; char *option = parv[1]; mychan_t *mc; metadata_t *md; if (parc < 2 || !channel || !option) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "SET NOBOT"); command_fail(si, fault_needmoreparams, _("Syntax: SET <#channel> NOBOT {ON|OFF}")); return; } mc = mychan_find(channel); if (!mc) { command_fail(si, fault_nosuch_target, _("Channel \2%s\2 is not registered."), channel); return; } if (!si->smu) { command_fail(si, fault_noprivs, _("You are not logged in.")); return; } if (!has_priv(si, PRIV_CHAN_ADMIN)) { command_fail(si, fault_noprivs, _("You are not authorized to perform this operation.")); return; } if (!irccasecmp(option, "ON")) { metadata_add(mc, "private:botserv:no-bot", "ON"); if ((md = metadata_find(mc, "private:botserv:bot-assigned")) != NULL) { if (mc->flags & MC_GUARD && (!config_options.leave_chans || (mc->chan != NULL && LIST_LENGTH(&mc->chan->members) > 1))) join(mc->name, chansvs.nick); part(mc->name, md->value); metadata_delete(mc, "private:botserv:bot-assigned"); metadata_delete(mc, "private:botserv:bot-handle-fantasy"); } command_success_nodata(si, _("No Bot mode is now \2ON\2 on channel %s."), mc->name); } else if(!irccasecmp(option, "OFF")) { metadata_delete(mc, "private:botserv:no-bot"); command_success_nodata(si, _("No Bot mode is now \2OFF\2 on channel %s."), mc->name); } else { command_fail(si, fault_badparams, STR_INVALID_PARAMS, "SET NOBOT"); command_fail(si, fault_badparams, _("Syntax: SET <#channel> NOBOT {ON|OFF}")); } }
static void cs_cmd_invite(sourceinfo_t *si, int parc, char *parv[]) { char *chan = parv[0]; mychan_t *mc; if (si->su == NULL) { command_fail(si, fault_noprivs, _("\2%s\2 can only be executed via IRC."), "INVITE"); return; } /* This command is not useful if the user is already in the channel, * ignore it if it is a fantasy command so users can program bots to * react on it without interference from ChanServ. */ if (si->c != NULL) return; if (!chan) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "INVITE"); command_fail(si, fault_needmoreparams, _("Syntax: INVITE <#channel>")); return; } mc = mychan_find(chan); if (!mc) { command_fail(si, fault_nosuch_target, _("Channel \2%s\2 is not registered."), chan); return; } if (metadata_find(mc, "private:close:closer")) { command_fail(si, fault_noprivs, _("\2%s\2 is closed."), chan); return; } if (!chanacs_source_has_flag(mc, si, CA_INVITE)) { command_fail(si, fault_noprivs, _("You are not authorized to perform this operation.")); return; } if (!mc->chan) { command_fail(si, fault_nosuch_target, _("\2%s\2 is currently empty."), mc->name); return; } if (chanuser_find(mc->chan, si->su)) { command_fail(si, fault_noprivs, _("You're already on \2%s\2."), mc->name); return; } invite_sts(si->service->me, si->su, mc->chan); logcommand(si, CMDLOG_DO, "INVITE: \2%s\2", mc->name); command_success_nodata(si, _("You have been invited to \2%s\2."), mc->name); }
static void cs_cmd_set_restricted(sourceinfo_t *si, int parc, char *parv[]) { mychan_t *mc; if (!(mc = mychan_find(parv[0]))) { command_fail(si, fault_nosuch_target, _("Channel \2%s\2 is not registered."), parv[0]); return; } if (!parv[1]) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "SET RESTRICTED"); return; } if (!chanacs_source_has_flag(mc, si, CA_SET)) { command_fail(si, fault_noprivs, STR_NOT_AUTHORIZED); return; } if (!strcasecmp("ON", parv[1])) { if (MC_RESTRICTED & mc->flags) { command_fail(si, fault_nochange, _("The \2%s\2 flag is already set for channel \2%s\2."), "RESTRICTED", mc->name); return; } logcommand(si, CMDLOG_SET, "SET:RESTRICTED:ON: \2%s\2", mc->name); verbose(mc, _("\2%s\2 enabled the RESTRICTED flag"), get_source_name(si)); mc->flags |= MC_RESTRICTED; command_success_nodata(si, _("The \2%s\2 flag has been set for channel \2%s\2."), "RESTRICTED", mc->name); return; } else if (!strcasecmp("OFF", parv[1])) { if (!(MC_RESTRICTED & mc->flags)) { command_fail(si, fault_nochange, _("The \2%s\2 flag is not set for channel \2%s\2."), "RESTRICTED", mc->name); return; } logcommand(si, CMDLOG_SET, "SET:RESTRICTED:OFF: \2%s\2", mc->name); verbose(mc, _("\2%s\2 disabled the RESTRICTED flag"), get_source_name(si)); mc->flags &= ~MC_RESTRICTED; command_success_nodata(si, _("The \2%s\2 flag has been removed for channel \2%s\2."), "RESTRICTED", mc->name); return; } else { command_fail(si, fault_badparams, STR_INVALID_PARAMS, "RESTRICTED"); return; } }
static chanacs_t *chanacs_ext_match_user(chanacs_t *ca, user_t *u) { chanacs_exttarget_t *ent; mychan_t *mc; unsigned int flags; ent = (chanacs_exttarget_t *) ca->entity; if (ent->checking > 4) /* arbitrary recursion limit? */ return NULL; if (!(mc = mychan_find(ent->channel))) return NULL; ent->checking++; flags = chanacs_user_flags(mc, u); ent->checking--; if (flags & CA_AKICK) return NULL; if (flags) return ca; return NULL; }
static struct chanacs * chanacs_ext_match_user(struct chanacs *ca, struct user *u) { struct this_exttarget *ent; struct mychan *mc; unsigned int flags; ent = (struct this_exttarget *) ca->entity; if (ent->checking > 4) // arbitrary recursion limit? return NULL; if (!(mc = mychan_find(ent->channel))) return NULL; ent->checking++; flags = chanacs_user_flags(mc, u); ent->checking--; if (flags & CA_AKICK) return NULL; if (flags) return ca; return NULL; }
static void cs_cmd_hold(char *origin) { char *target = strtok(NULL, " "); char *action = strtok(NULL, " "); mychan_t *mc; if (!target || !action) { notice(chansvs.nick, origin, STR_INSUFFICIENT_PARAMS, "HOLD"); notice(chansvs.nick, origin, "Usage: HOLD <#channel> <ON|OFF>"); return; } if (*target != '#') { notice(chansvs.nick, origin, STR_INVALID_PARAMS, "HOLD"); return; } if (!(mc = mychan_find(target))) { notice(chansvs.nick, origin, "\2%s\2 is not registered.", target); return; } if (!strcasecmp(action, "ON")) { if (mc->flags & MC_HOLD) { notice(chansvs.nick, origin, "\2%s\2 is already held.", target); return; } mc->flags |= MC_HOLD; wallops("%s set the HOLD option for the channel \2%s\2.", origin, target); logcommand(chansvs.me, user_find_named(origin), CMDLOG_ADMIN, "%s HOLD ON", mc->name); notice(chansvs.nick, origin, "\2%s\2 is now held.", target); } else if (!strcasecmp(action, "OFF")) { if (!(mc->flags & MC_HOLD)) { notice(chansvs.nick, origin, "\2%s\2 is not held.", target); return; } mc->flags &= ~MC_HOLD; wallops("%s removed the HOLD option on the channel \2%s\2.", origin, target); logcommand(chansvs.me, user_find_named(origin), CMDLOG_ADMIN, "%s HOLD OFF", mc->name); notice(chansvs.nick, origin, "\2%s\2 is no longer held.", target); } else { notice(chansvs.nick, origin, STR_INVALID_PARAMS, "HOLD"); notice(chansvs.nick, origin, "Usage: HOLD <#channel> <ON|OFF>"); } }
static void cs_cmd_set_pubacl(sourceinfo_t *si, int parc, char *parv[]) { mychan_t *mc; if (!(mc = mychan_find(parv[0]))) { command_fail(si, fault_nosuch_target, _("Channel \2%s\2 is not registered."), parv[0]); return; } if (!parv[1]) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "SET PUBACL"); return; } if (!chanacs_source_has_flag(mc, si, CA_SET)) { command_fail(si, fault_noprivs, _("You are not authorized to perform this command.")); return; } if (!strcasecmp("ON", parv[1])) { if (MC_PUBACL & mc->flags) { command_fail(si, fault_nochange, _("The \2%s\2 flag is already set for channel \2%s\2."), "PUBACL", mc->name); return; } logcommand(si, CMDLOG_SET, "SET:PUBACL:ON: \2%s\2", mc->name); mc->flags |= MC_PUBACL; command_success_nodata(si, _("The \2%s\2 flag has been set for channel \2%s\2."), "PUBACL", mc->name); return; } else if (!strcasecmp("OFF", parv[1])) { if (!(MC_PUBACL & mc->flags)) { command_fail(si, fault_nochange, _("The \2%s\2 flag is not set for channel \2%s\2."), "PUBACL", mc->name); return; } logcommand(si, CMDLOG_SET, "SET:PUBACL:OFF: \2%s\2", mc->name); mc->flags &= ~MC_PUBACL; command_success_nodata(si, _("The \2%s\2 flag has been removed for channel \2%s\2."), "PUBACL", mc->name); return; } else { command_fail(si, fault_badparams, STR_INVALID_PARAMS, "PUBACL"); return; } }
static void cs_fcmd_topicappend(char *origin, char *chan) { char *topic = strtok(NULL, ""); mychan_t *mc; user_t *u = user_find_named(origin); char topicbuf[BUFSIZE]; channel_t *c; if (!topic) { notice(chansvs.nick, origin, STR_INSUFFICIENT_PARAMS, "!TOPICAPPEND"); notice(chansvs.nick, origin, "Syntax: !TOPICAPPEND <topic>"); return; } c = channel_find(chan); if (!c) { notice(chansvs.nick, origin, "\2%s\2 is not registered.", chan); return; } mc = mychan_find(chan); if (!mc) { notice(chansvs.nick, origin, "Channel \2%s\2 is not registered.", chan); return; } if (!chanacs_user_has_flag(mc, u, CA_TOPIC)) { notice(chansvs.nick, origin, "You are not authorized to perform this operation."); return; } if (metadata_find(mc, METADATA_CHANNEL, "private:close:closer")) { notice(chansvs.nick, origin, "\2%s\2 is closed.", chan); return; } topicbuf[0] = '\0'; if (c->topic) { strlcpy(topicbuf, c->topic, BUFSIZE); strlcat(topicbuf, " | ", BUFSIZE); strlcat(topicbuf, topic, BUFSIZE); } else strlcpy(topicbuf, topic, BUFSIZE); handle_topic(c, origin, CURRTIME, topicbuf); topic_sts(chan, origin, CURRTIME, topicbuf); logcommand(chansvs.me, u, CMDLOG_SET, "%s TOPICAPPEND", mc->name); }
static void cs_cmd_drop(char *origin) { user_t *u = user_find_named(origin); mychan_t *mc; char *name = strtok(NULL, " "); if (!name) { notice(chansvs.nick, origin, STR_INSUFFICIENT_PARAMS, "DROP"); notice(chansvs.nick, origin, "Syntax: DROP <#channel>"); return; } if (*name != '#') { notice(chansvs.nick, origin, STR_INVALID_PARAMS, "DROP"); notice(chansvs.nick, origin, "Syntax: DROP <#channel>"); return; } if (!(mc = mychan_find(name))) { notice(chansvs.nick, origin, "\2%s\2 is not registered.", name); return; } if (!is_founder(mc, u->myuser) && !has_priv(u, PRIV_CHAN_ADMIN)) { notice(chansvs.nick, origin, "You are not authorized to perform this operation."); return; } if (metadata_find(mc, METADATA_CHANNEL, "private:close:closer") && !has_priv(u, PRIV_CHAN_ADMIN)) { logcommand(chansvs.me, u, CMDLOG_REGISTER, "%s failed DROP (closed)", mc->name); notice(chansvs.nick, origin, "The channel \2%s\2 is closed; it cannot be dropped.", mc->name); return; } if (!is_founder(mc, u->myuser)) { logcommand(chansvs.me, u, CMDLOG_ADMIN, "%s DROP", mc->name); wallops("%s dropped the channel \2%s\2", origin, name); } else logcommand(chansvs.me, u, CMDLOG_REGISTER, "%s DROP", mc->name); snoop("DROP: \2%s\2 by \2%s\2 as \2%s\2", mc->name, u->nick, u->myuser->name); hook_call_event("channel_drop", mc); if ((config_options.chan && irccasecmp(mc->name, config_options.chan)) || !config_options.chan) part(mc->name, chansvs.nick); mychan_delete(mc->name); notice(chansvs.nick, origin, "The channel \2%s\2 has been dropped.", name); return; }
static void bs_cmd_set_saycaller(struct sourceinfo *si, int parc, char *parv[]) { char *channel = parv[0]; char *option = parv[1]; struct mychan *mc; struct metadata *md; if (parc < 2 || !channel || !option) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "SET SAYCALLER"); command_fail(si, fault_needmoreparams, _("Syntax: SET <#channel> SAYCALLER {ON|OFF}")); return; } mc = mychan_find(channel); if (!mc) { command_fail(si, fault_nosuch_target, _("Channel \2%s\2 is not registered."), channel); return; } if (!chanacs_source_has_flag(mc, si, CA_SET)) { command_fail(si, fault_noprivs, _("You are not authorized to perform this operation.")); return; } if (metadata_find(mc, "private:frozen:freezer")) { command_fail(si, fault_noprivs, _("\2%s\2 is frozen."), mc->name); return; } if (!irccasecmp(option, "ON")) { if ((md = metadata_find(mc, "private:botserv:bot-assigned")) != NULL) metadata_add(mc, "private:botserv:saycaller", md->value); logcommand(si, CMDLOG_SET, "SET:SAYCALLER:ON: \2%s\2", mc->name); command_success_nodata(si, _("Say Caller is now \2ON\2 on channel %s."), mc->name); } else if(!irccasecmp(option, "OFF")) { metadata_delete(mc, "private:botserv:saycaller"); logcommand(si, CMDLOG_SET, "SET:SAYCALLER:OFF: \2%s\2", mc->name); command_success_nodata(si, _("Say Caller is now \2OFF\2 on channel %s."), mc->name); } else { command_fail(si, fault_badparams, STR_INVALID_PARAMS, "SET SAYCALLER"); command_fail(si, fault_badparams, _("Syntax: SET <#channel> SAYCALLER {ON|OFF}")); } }
static void bs_cmd_set_fantasy(sourceinfo_t *si, int parc, char *parv[]) { char *channel = parv[0]; char *option = parv[1]; mychan_t *mc; metadata_t *md; if (parc < 2 || !channel || !option) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "SET FANTASY"); command_fail(si, fault_needmoreparams, _("Syntax: SET <#channel> FANTASY {ON|OFF}")); return; } mc = mychan_find(channel); if (!mc) { command_fail(si, fault_nosuch_target, _("Channel \2%s\2 is not registered."), channel); return; } if (!si->smu) { command_fail(si, fault_noprivs, _("You are not logged in.")); return; } if (!chanacs_source_has_flag(mc, si, CA_SET)) { command_fail(si, fault_noprivs, _("You are not authorized to perform this operation.")); return; } if (!irccasecmp(option, "ON")) { if ((md = metadata_find(mc, "private:botserv:bot-assigned")) != NULL) metadata_add(mc, "private:botserv:bot-handle-fantasy", md->value); command_success_nodata(si, _("Fantasy mode is now \2ON\2 on channel %s."), mc->name); } else if(!irccasecmp(option, "OFF")) { metadata_delete(mc, "private:botserv:bot-handle-fantasy"); command_success_nodata(si, _("Fantasy mode is now \2OFF\2 on channel %s."), mc->name); } else { command_fail(si, fault_badparams, STR_INVALID_PARAMS, "SET FANTASY"); command_fail(si, fault_badparams, _("Syntax: SET <#channel> FANTASY {ON|OFF}")); } }
static void cs_cmd_topic(char *origin) { char *chan = strtok(NULL, " "); char *topic = strtok(NULL, ""); mychan_t *mc; channel_t *c; user_t *u; if (!chan || !topic) { notice(chansvs.nick, origin, STR_INSUFFICIENT_PARAMS, "TOPIC"); notice(chansvs.nick, origin, "Syntax: TOPIC <#channel> <topic>"); return; } c = channel_find(chan); if (!c) { notice(chansvs.nick, origin, "\2%s\2 is not registered.", chan); return; } mc = mychan_find(chan); if (!mc) { notice(chansvs.nick, origin, "Channel \2%s\2 is not registered.", chan); return; } if (metadata_find(mc, METADATA_CHANNEL, "private:close:closer")) { notice(chansvs.nick, origin, "\2%s\2 is closed.", chan); return; } u = user_find_named(origin); if (!chanacs_user_has_flag(mc, u, CA_TOPIC)) { notice(chansvs.nick, origin, "You are not authorized to perform this operation."); return; } handle_topic(c, origin, CURRTIME, topic); topic_sts(chan, origin, CURRTIME, topic); logcommand(chansvs.me, u, CMDLOG_SET, "%s TOPIC", mc->name); if (!chanuser_find(c, u)) notice(chansvs.nick, origin, "Topic set to \2%s\2 on \2%s\2.", topic, chan); }
static void bs_cmd_set_fantasy(struct sourceinfo *si, int parc, char *parv[]) { char *channel = parv[0]; char *option = parv[1]; struct mychan *mc; struct metadata *md; if (parc < 2 || !channel || !option) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "SET FANTASY"); command_fail(si, fault_needmoreparams, _("Syntax: SET <#channel> FANTASY {ON|OFF}")); return; } mc = mychan_find(channel); if (!mc) { command_fail(si, fault_nosuch_target, STR_IS_NOT_REGISTERED, channel); return; } if (!chanacs_source_has_flag(mc, si, CA_SET)) { command_fail(si, fault_noprivs, STR_NOT_AUTHORIZED); return; } if (!irccasecmp(option, "ON")) { if ((md = metadata_find(mc, "private:botserv:bot-assigned")) != NULL) metadata_add(mc, "private:botserv:bot-handle-fantasy", md->value); logcommand(si, CMDLOG_SET, "SET:FANTASY:ON: \2%s\2", mc->name); command_success_nodata(si, _("Fantasy mode is now \2ON\2 on channel %s."), mc->name); } else if(!irccasecmp(option, "OFF")) { metadata_delete(mc, "private:botserv:bot-handle-fantasy"); logcommand(si, CMDLOG_SET, "SET:FANTASY:OFF: \2%s\2", mc->name); command_success_nodata(si, _("Fantasy mode is now \2OFF\2 on channel %s."), mc->name); } else { command_fail(si, fault_badparams, STR_INVALID_PARAMS, "SET FANTASY"); command_fail(si, fault_badparams, _("Syntax: SET <#channel> FANTASY {ON|OFF}")); } }
static bool check_forward(const char *value, channel_t *c, mychan_t *mc, user_t *u, myuser_t *mu) { channel_t *target_c; mychan_t *target_mc; if (*value != '#' || strlen(value) > 50) return false; if (u == NULL && mu == NULL) return true; target_c = channel_find(value); target_mc = mychan_find(value); if (target_c == NULL && target_mc == NULL) return false; return true; }
static void bs_cmd_act(sourceinfo_t *si, int parc, char *parv[]) { char *channel = parv[0]; char *message = parv[1]; metadata_t *bs; user_t *bot; if (!channel || !message) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "ACT"); command_fail(si, fault_needmoreparams, _("Syntax: ACT <#channel> <msg>")); return; } channel_t *c = channel_find(channel); mychan_t *mc = mychan_find(channel); if (!mc) { command_fail(si, fault_nosuch_target, _("Channel \2%s\2 is not registered."), channel); return; } if (!c) { command_fail(si, fault_nosuch_target, _("\2%s\2 is currently empty."), channel); return; } if (!(chanacs_source_flags(mc, si) & (CA_OP | CA_AUTOOP))) { command_fail(si, fault_noprivs, STR_NOT_AUTHORIZED); return; } if ((bs = metadata_find(mc, "private:botserv:bot-assigned")) != NULL) bot = user_find_named(bs->value); else bot = NULL; if (bot == NULL) { command_fail(si, fault_nosuch_key, _("\2%s\2 does not have a bot assigned."), mc->name); return; } msg(bot->nick, channel, "\001ACTION %s\001", message); logcommand(si, CMDLOG_DO, "ACT:\2%s\2: \2%s\2", channel, message); }
static void cs_cmd_fdrop(sourceinfo_t *si, int parc, char *parv[]) { mychan_t *mc; char *name = parv[0]; if (!name) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "FDROP"); command_fail(si, fault_needmoreparams, _("Syntax: FDROP <#channel>")); return; } if (*name != '#') { command_fail(si, fault_badparams, STR_INVALID_PARAMS, "FDROP"); command_fail(si, fault_badparams, _("Syntax: FDROP <#channel>")); return; } if (!(mc = mychan_find(name))) { command_fail(si, fault_nosuch_target, _("Channel \2%s\2 is not registered."), name); return; } if (si->c != NULL) { command_fail(si, fault_noprivs, _("For security reasons, you may not drop a channel registration with a fantasy command.")); return; } if (mc->flags & MC_HOLD) { command_fail(si, fault_noprivs, _("The channel \2%s\2 is held; it cannot be dropped."), mc->name); return; } logcommand(si, CMDLOG_ADMIN | LG_REGISTER, "FDROP: \2%s\2", mc->name); wallops("%s dropped the channel \2%s\2", get_oper_name(si), name); verbose(mc, _("The channel has been dropped by %s administration"), me.netname); hook_call_channel_drop(mc); if (mc->chan != NULL && !(mc->chan->flags & CHAN_LOG)) part(mc->name, chansvs.nick); object_unref(mc); command_success_nodata(si, _("The channel \2%s\2 has been dropped."), name); return; }
static void cs_cmd_set_url(sourceinfo_t *si, int parc, char *parv[]) { mychan_t *mc; char *url = parv[1]; if (!(mc = mychan_find(parv[0]))) { command_fail(si, fault_nosuch_target, _("Channel \2%s\2 is not registered."), parv[0]); return; } if (!(chanacs_source_has_flag(mc, si, CA_SET) || chanacs_source_has_flag(mc, si, CA_FOUNDER))) { command_fail(si, fault_noprivs, _("You are not authorized to execute this command.")); return; } if (!url || !strcasecmp("OFF", url) || !strcasecmp("NONE", url)) { /* not in a namespace to allow more natural use of SET PROPERTY. * they may be able to introduce spaces, though. c'est la vie. */ if (metadata_find(mc, "url")) { metadata_delete(mc, "url"); logcommand(si, CMDLOG_SET, "SET:URL:NONE: \2%s\2", mc->name); verbose(mc, _("\2%s\2 cleared the channel URL."), get_source_name(si)); command_success_nodata(si, _("The URL for \2%s\2 has been cleared."), mc->name); notify_channel_set_change(si, si->smu, mc, "URL", "Cleared"); return; } command_fail(si, fault_nochange, _("The URL for \2%s\2 was not set."), mc->name); return; } /* we'll overwrite any existing metadata */ metadata_add(mc, "url", url); logcommand(si, CMDLOG_SET, "SET:URL: \2%s\2 \2%s\2", mc->name, url); verbose(mc, _("\2%s\2 set the channel URL to \2%s\2"), get_source_name(si), url); command_success_nodata(si, _("The URL of \2%s\2 has been set to: \2%s\2"), mc->name, url); notify_channel_set_change(si, si->smu, mc, "URL", url); }
static void cs_cmd_getkey(sourceinfo_t *si, int parc, char *parv[]) { char *chan = parv[0]; mychan_t *mc; if (!chan) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "GETKEY"); command_fail(si, fault_needmoreparams, _("Syntax: GETKEY <#channel>")); return; } mc = mychan_find(chan); if (!mc) { command_fail(si, fault_nosuch_target, _("Channel \2%s\2 is not registered."), chan); return; } if (metadata_find(mc, "private:close:closer")) { command_fail(si, fault_noprivs, _("\2%s\2 is closed."), chan); return; } if (!chanacs_source_has_flag(mc, si, CA_INVITE)) { command_fail(si, fault_noprivs, _("You are not authorized to perform this operation.")); return; } if (!mc->chan) { command_fail(si, fault_nosuch_target, _("\2%s\2 is currently empty."), mc->name); return; } if (!mc->chan->key) { command_fail(si, fault_nosuch_key, _("\2%s\2 is not keyed."), mc->name); return; } logcommand(si, CMDLOG_GET, "GETKEY: \2%s\2", mc->name); command_success_string(si, mc->chan->key, _("Channel \2%s\2 key is: %s"), mc->name, mc->chan->key); }
static void rs_cmd_info(sourceinfo_t *si, int parc, char *parv[]) { mychan_t *mc; metadata_t *md; if (parc < 1) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "INFO"); command_fail(si, fault_needmoreparams, _("Syntax: INFO <channel>")); return; } mc = mychan_find(parv[0]); if (!mc) { command_fail(si, fault_nosuch_target, _("Channel \2%s\2 is not registered."), parv[0]); return; } if (!metadata_find(mc, "private:rpgserv:enabled")) { command_fail(si, fault_nosuch_target, _("Channel \2%s\2 does not have RPGServ enabled."), parv[0]); return; } command_success_nodata(si, _("Information on \2%s\2:"), parv[0]); md = metadata_find(mc, "private:rpgserv:genre"); command_success_nodata(si, _("Genre : %s"), rs_prettyprint_keywords(md, genre_keys, genre_names, ARRAY_SIZE(genre_keys))); md = metadata_find(mc, "private:rpgserv:period"); command_success_nodata(si, _("Period : %s"), rs_prettyprint_keywords(md, period_keys, period_names, ARRAY_SIZE(period_keys))); md = metadata_find(mc, "private:rpgserv:ruleset"); command_success_nodata(si, _("Ruleset : %s"), rs_prettyprint_keywords(md, ruleset_keys, ruleset_names, ARRAY_SIZE(ruleset_keys))); md = metadata_find(mc, "private:rpgserv:rating"); command_success_nodata(si, _("Rating : %s"), rs_prettyprint_keywords(md, rating_keys, rating_names, ARRAY_SIZE(rating_keys))); md = metadata_find(mc, "private:rpgserv:system"); command_success_nodata(si, _("System : %s"), rs_prettyprint_keywords(md, system_keys, system_names, ARRAY_SIZE(system_keys))); md = metadata_find(mc, "private:rpgserv:setting"); command_success_nodata(si, _("Setting : %s"), md ? md->value : "<none>"); md = metadata_find(mc, "private:rpgserv:storyline"); command_success_nodata(si, _("Storyline: %s"), md ? md->value : "<none>"); md = metadata_find(mc, "private:rpgserv:summary"); command_success_nodata(si, _("Summary : %s"), md ? md->value : "<none>"); command_success_nodata(si, _("\2*** End of Info ***\2")); logcommand(si, CMDLOG_GET, "RPGSERV:INFO: \2%s\2", mc->name); }
static void cs_cmd_set_email(struct sourceinfo *si, int parc, char *parv[]) { struct mychan *mc; char *mail = parv[1]; if (!(mc = mychan_find(parv[0]))) { command_fail(si, fault_nosuch_target, _("Channel \2%s\2 is not registered."), parv[0]); return; } if (!chanacs_source_has_flag(mc, si, CA_SET)) { command_fail(si, fault_noprivs, _("You are not authorized to execute this command.")); return; } if (!mail || !strcasecmp(mail, "NONE") || !strcasecmp(mail, "OFF")) { if (metadata_find(mc, "email")) { metadata_delete(mc, "email"); command_success_nodata(si, _("The e-mail address for channel \2%s\2 was deleted."), mc->name); logcommand(si, CMDLOG_SET, "SET:EMAIL:NONE: \2%s\2", mc->name); return; } command_fail(si, fault_nochange, _("The e-mail address for channel \2%s\2 was not set."), mc->name); return; } if (!validemail(mail)) { command_fail(si, fault_badparams, _("\2%s\2 is not a valid e-mail address."), mail); return; } // we'll overwrite any existing metadata metadata_add(mc, "email", mail); logcommand(si, CMDLOG_SET, "SET:EMAIL: \2%s\2 \2%s\2", mc->name, mail); verbose(mc, _("\2%s\2 set the e-mail address for the channel to \2%s\2"), get_source_name(si), mail); command_success_nodata(si, _("The e-mail address for channel \2%s\2 has been set to \2%s\2."), parv[0], mail); }
static void cs_cmd_set_entrymsg(sourceinfo_t *si, int parc, char *parv[]) { mychan_t *mc; if (!(mc = mychan_find(parv[0]))) { command_fail(si, fault_nosuch_target, _("Channel \2%s\2 is not registered."), parv[0]); return; } if (!chanacs_source_has_flag(mc, si, CA_SET)) { command_fail(si, fault_noprivs, _("You are not authorized to execute this command.")); return; } if (!parv[1] || !strcasecmp("OFF", parv[1]) || !strcasecmp("NONE", parv[1])) { /* entrymsg is private because users won't see it if they're AKICKED, * if the channel is +i, or if the channel is RESTRICTED */ if (metadata_find(mc, "private:entrymsg")) { metadata_delete(mc, "private:entrymsg"); logcommand(si, CMDLOG_SET, "SET:ENTRYMSG:NONE: \2%s\2", mc->name); verbose(mc, _("\2%s\2 cleared the entry message"), get_source_name(si)); command_success_nodata(si, _("The entry message for \2%s\2 has been cleared."), parv[0]); return; } command_fail(si, fault_nochange, _("The entry message for \2%s\2 was not set."), parv[0]); return; } /* we'll overwrite any existing metadata. * Why is/was this even private? There are no size/content sanity checks * and even users with no channel access can see it. --jdhore */ metadata_add(mc, "private:entrymsg", parv[1]); logcommand(si, CMDLOG_SET, "SET:ENTRYMSG: \2%s\2 \2%s\2", mc->name, parv[1]); verbose(mc, _("\2%s\2 set the entry message for the channel to \2%s\2"), get_source_name(si), parv[1]); command_success_nodata(si, _("The entry message for \2%s\2 has been set to \2%s\2"), parv[0], parv[1]); }
static void cs_cmd_set_prefix(struct sourceinfo *si, int parc, char *parv[]) { struct mychan *mc; char *prefix = parv[1]; if (!(mc = mychan_find(parv[0]))) { command_fail(si, fault_nosuch_target, _("Channel \2%s\2 is not registered."), parv[0]); return; } if (!chanacs_source_has_flag(mc, si, CA_SET)) { command_fail(si, fault_noprivs, _("You are not authorized to execute this command.")); return; } if (!prefix || !strcasecmp(prefix, "DEFAULT")) { metadata_delete(mc, "private:prefix"); logcommand(si, CMDLOG_SET, "SET:PREFIX: \2%s\2 reset", mc->name); verbose(mc, _("The fantasy prefix for the channel has been reset by \2%s\2"), get_source_name(si)); command_success_nodata(si, _("The fantasy prefix for channel \2%s\2 has been reset."), parv[0]); return; } if (!goodprefix(prefix)) { command_fail(si, fault_badparams, _("Prefix '%s' is invalid. The prefix may " "contain only printable characters, and must contain at least " "one non-space character."), prefix); return; } metadata_add(mc, "private:prefix", prefix); logcommand(si, CMDLOG_SET, "SET:PREFIX: \2%s\2 \2%s\2", mc->name, prefix); verbose(mc, _("\2%s\2 set the fantasy prefix to \2%s\2"), get_source_name(si), prefix); command_success_nodata(si, _("The fantasy prefix for channel \2%s\2 has been set to \2%s\2."), parv[0], prefix); }
static void cs_cmd_set_fantasy(sourceinfo_t *si, int parc, char *parv[]) { mychan_t *mc; if (!(mc = mychan_find(parv[0]))) { command_fail(si, fault_nosuch_target, _("Channel \2%s\2 is not registered."), parv[0]); return; } if (!parv[1]) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "SET FANTASY"); return; } if (!chanacs_source_has_flag(mc, si, CA_SET)) { command_fail(si, fault_noprivs, _("You are not authorized to perform this command.")); return; } if (!strcasecmp("ON", parv[1])) { metadata_t *md = metadata_find(mc, "disable_fantasy"); if (!md) { command_fail(si, fault_nochange, _("The \2%s\2 flag is already set for channel \2%s\2."), "FANTASY", mc->name); return; } metadata_delete(mc, "disable_fantasy"); logcommand(si, CMDLOG_SET, "SET:FANTASY:ON: \2%s\2", mc->name); verbose(mc, _("\2%s\2 enabled the FANTASY flag"), get_source_name(si)); command_success_nodata(si, _("The \2%s\2 flag has been set for channel \2%s\2."), "FANTASY", mc->name); return; } else if (!strcasecmp("OFF", parv[1])) { metadata_t *md = metadata_find(mc, "disable_fantasy"); if (md) { command_fail(si, fault_nochange, _("The \2%s\2 flag is not set for channel \2%s\2."), "FANTASY", mc->name); return; } metadata_add(mc, "disable_fantasy", "on"); logcommand(si, CMDLOG_SET, "SET:FANTASY:OFF: \2%s\2", mc->name); verbose(mc, _("\2%s\2 disabled the FANTASY flag"), get_source_name(si)); command_success_nodata(si, _("The \2%s\2 flag has been removed for channel \2%s\2."), "FANTASY", mc->name); return; } else { command_fail(si, fault_badparams, STR_INVALID_PARAMS, "FANTASY"); return; } }
static void cs_cmd_unban(sourceinfo_t *si, int parc, char *parv[]) { const char *channel = parv[0]; const char *target = parv[1]; channel_t *c = channel_find(channel); mychan_t *mc = mychan_find(channel); user_t *tu; chanban_t *cb; if (si->su == NULL) { command_fail(si, fault_noprivs, _("\2%s\2 can only be executed via IRC."), "UNBAN"); return; } if (!channel) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "UNBAN"); command_fail(si, fault_needmoreparams, _("Syntax: UNBAN <#channel>")); return; } if (target && irccasecmp(target, si->su->nick)) { command_fail(si, fault_noprivs, _("You may only unban yourself via %s."), si->service->nick); if (validhostmask(target)) command_fail(si, fault_noprivs, _("Try \2/mode %s -b %s\2"), channel, target); return; } target = si->su->nick; if (!mc) { command_fail(si, fault_nosuch_target, _("Channel \2%s\2 is not registered."), channel); return; } if (!c) { command_fail(si, fault_nosuch_target, _("\2%s\2 is currently empty."), channel); return; } if (!si->smu) { command_fail(si, fault_noprivs, _("You are not logged in.")); return; } if (!chanacs_source_has_flag(mc, si, CA_REMOVE)) { command_fail(si, fault_noprivs, _("You are not authorized to perform this operation.")); return; } tu = si->su; { mowgli_node_t *n, *tn; char hostbuf2[BUFSIZE]; int count = 0; snprintf(hostbuf2, BUFSIZE, "%s!%s@%s", tu->nick, tu->user, tu->vhost); for (n = next_matching_ban(c, tu, 'b', c->bans.head); n != NULL; n = next_matching_ban(c, tu, 'b', tn)) { tn = n->next; cb = n->data; logcommand(si, CMDLOG_DO, "UNBAN: \2%s\2 \2%s\2 (for user \2%s\2)", mc->name, cb->mask, hostbuf2); modestack_mode_param(chansvs.nick, c, MTYPE_DEL, cb->type, cb->mask); chanban_delete(cb); count++; } if (count > 0) command_success_nodata(si, _("Unbanned \2%s\2 on \2%s\2 (%d ban%s removed)."), target, channel, count, (count != 1 ? "s" : "")); else command_success_nodata(si, _("No bans found matching \2%s\2 on \2%s\2."), target, channel); return; } }
static void cs_cmd_ban(sourceinfo_t *si, int parc, char *parv[]) { char *channel = parv[0]; char *target = parv[1]; char *newtarget; channel_t *c = channel_find(channel); mychan_t *mc = mychan_find(channel); user_t *tu; if (!channel || !target) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "BAN"); command_fail(si, fault_needmoreparams, _("Syntax: BAN <#channel> <nickname|hostmask>")); return; } if (!mc) { command_fail(si, fault_nosuch_target, _("Channel \2%s\2 is not registered."), channel); return; } if (!c) { command_fail(si, fault_nosuch_target, _("\2%s\2 is currently empty."), channel); return; } if (!chanacs_source_has_flag(mc, si, CA_REMOVE)) { command_fail(si, fault_noprivs, STR_NOT_AUTHORIZED); return; } if (metadata_find(mc, "private:close:closer")) { command_fail(si, fault_noprivs, _("\2%s\2 is closed."), channel); return; } if ((tu = user_find_named(target))) { char hostbuf[BUFSIZE]; hostbuf[0] = '\0'; mowgli_strlcat(hostbuf, "*!*@", BUFSIZE); mowgli_strlcat(hostbuf, tu->vhost, BUFSIZE); modestack_mode_param(chansvs.nick, c, MTYPE_ADD, 'b', hostbuf); chanban_add(c, hostbuf, 'b'); logcommand(si, CMDLOG_DO, "BAN: \2%s\2 on \2%s\2 (for user \2%s!%s@%s\2)", hostbuf, mc->name, tu->nick, tu->user, tu->vhost); if (si->su == NULL || !chanuser_find(mc->chan, si->su)) command_success_nodata(si, _("Banned \2%s\2 on \2%s\2."), target, channel); return; } else if ((is_extban(target) && (newtarget = target)) || ((newtarget = pretty_mask(target)) && validhostmask(newtarget))) { modestack_mode_param(chansvs.nick, c, MTYPE_ADD, 'b', newtarget); chanban_add(c, newtarget, 'b'); logcommand(si, CMDLOG_DO, "BAN: \2%s\2 on \2%s\2", newtarget, mc->name); if (si->su == NULL || !chanuser_find(mc->chan, si->su)) command_success_nodata(si, _("Banned \2%s\2 on \2%s\2."), newtarget, channel); return; } else { command_fail(si, fault_badparams, _("Invalid nickname/hostmask provided: \2%s\2"), target); command_fail(si, fault_badparams, _("Syntax: BAN <#channel> <nickname|hostmask>")); return; } }
static void cs_cmd_unban(sourceinfo_t *si, int parc, char *parv[]) { const char *channel = parv[0]; const char *target = parv[1]; channel_t *c = channel_find(channel); mychan_t *mc = mychan_find(channel); user_t *tu; chanban_t *cb; if (!channel) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "UNBAN"); command_fail(si, fault_needmoreparams, _("Syntax: UNBAN <#channel> <nickname|hostmask>")); return; } if (!target) { if (si->su == NULL) { command_fail(si, fault_needmoreparams, STR_INSUFFICIENT_PARAMS, "UNBAN"); command_fail(si, fault_needmoreparams, _("Syntax: UNBAN <#channel> <nickname|hostmask>")); return; } target = si->su->nick; } if (!mc) { command_fail(si, fault_nosuch_target, _("Channel \2%s\2 is not registered."), channel); return; } if (!c) { command_fail(si, fault_nosuch_target, _("\2%s\2 is currently empty."), channel); return; } if (!chanacs_source_has_flag(mc, si, CA_REMOVE) && (si->su == NULL || !chanacs_source_has_flag(mc, si, CA_EXEMPT) || irccasecmp(target, si->su->nick))) { command_fail(si, fault_noprivs, STR_NOT_AUTHORIZED); return; } if ((tu = user_find_named(target))) { mowgli_node_t *n, *tn; char hostbuf2[BUFSIZE]; int count = 0; snprintf(hostbuf2, BUFSIZE, "%s!%s@%s", tu->nick, tu->user, tu->vhost); for (n = next_matching_ban(c, tu, 'b', c->bans.head); n != NULL; n = next_matching_ban(c, tu, 'b', tn)) { tn = n->next; cb = n->data; logcommand(si, CMDLOG_DO, "UNBAN: \2%s\2 on \2%s\2 (for user \2%s\2)", cb->mask, mc->name, hostbuf2); modestack_mode_param(chansvs.nick, c, MTYPE_DEL, cb->type, cb->mask); chanban_delete(cb); count++; } if (count > 0) command_success_nodata(si, _("Unbanned \2%s\2 on \2%s\2 (%d ban%s removed)."), target, channel, count, (count != 1 ? "s" : "")); else command_success_nodata(si, _("No bans found matching \2%s\2 on \2%s\2."), target, channel); return; } else if ((cb = chanban_find(c, target, 'b')) != NULL || validhostmask(target)) { if (cb) { modestack_mode_param(chansvs.nick, c, MTYPE_DEL, 'b', target); chanban_delete(cb); logcommand(si, CMDLOG_DO, "UNBAN: \2%s\2 on \2%s\2", target, mc->name); if (si->su == NULL || !chanuser_find(mc->chan, si->su)) command_success_nodata(si, _("Unbanned \2%s\2 on \2%s\2."), target, channel); } else command_fail(si, fault_nosuch_key, _("No such ban \2%s\2 on \2%s\2."), target, channel); return; } else { command_fail(si, fault_badparams, _("Invalid nickname/hostmask provided: \2%s\2"), target); command_fail(si, fault_badparams, _("Syntax: UNBAN <#channel> [nickname|hostmask]")); return; } }